5f0406da60b4adc32b71ac1fd1a0949eec62620d
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / codeassist / impl / Engine.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.codeassist.impl;
12
13 import java.util.Map;
14
15 import net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment;
16 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
17 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
18 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
19 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
21 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
22 import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
23 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
24 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
25 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
26 import net.sourceforge.phpdt.internal.compiler.impl.ITypeRequestor;
27 import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
28 import net.sourceforge.phpdt.internal.compiler.lookup.ImportBinding;
29 import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
30 import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
31 import net.sourceforge.phpdt.internal.compiler.parser.SourceTypeConverter;
32 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
33
34
35 public abstract class Engine implements ITypeRequestor {
36
37         public LookupEnvironment lookupEnvironment;
38         
39         protected CompilationUnitScope unitScope;
40         protected ISearchableNameEnvironment nameEnvironment;
41
42         public AssistOptions options;
43         public CompilerOptions compilerOptions; 
44         
45         public Engine(Map settings){
46                 this.options = new AssistOptions(settings);
47                 this.compilerOptions = new CompilerOptions(settings);
48         }
49         
50         /**
51          * Add an additional binary type
52          */
53         public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
54                 lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
55         }
56
57         /**
58          * Add an additional compilation unit.
59          */
60         public void accept(ICompilationUnit sourceUnit) {
61                 CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
62                 CompilationUnitDeclaration parsedUnit =
63                         this.getParser().dietParse(sourceUnit, result);
64
65
66                 lookupEnvironment.buildTypeBindings(parsedUnit);
67                 lookupEnvironment.completeTypeBindings(parsedUnit, true);
68         }
69
70         /**
71          * Add additional source types (the first one is the requested type, the rest is formed by the
72          * secondary types defined in the same compilation unit).
73          */
74         public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
75                 CompilationResult result =
76                         new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
77                 CompilationUnitDeclaration unit =
78                         SourceTypeConverter.buildCompilationUnit(
79                                 sourceTypes,
80                                 true,
81                                 true,
82                                 lookupEnvironment.problemReporter,
83                                 result);
84
85                 if (unit != null) {
86                         lookupEnvironment.buildTypeBindings(unit);
87                         lookupEnvironment.completeTypeBindings(unit, true);
88                 }
89         }
90
91         public abstract AssistParser getParser();
92         
93         protected boolean mustQualifyType(
94                 char[] packageName,
95                 char[] typeName) {
96
97                 // If there are no types defined into the current CU yet.
98                 if (unitScope == null)
99                         return true;
100                         
101                 char[][] compoundPackageName = CharOperation.splitOn('.', packageName);
102                 char[] readableTypeName = CharOperation.concat(packageName, typeName, '.');
103
104                 if (CharOperation.equals(unitScope.fPackage.compoundName, compoundPackageName))
105                         return false;
106
107                 ImportBinding[] imports = unitScope.imports;
108                 if (imports != null){
109                         for (int i = 0, length = imports.length; i < length; i++) {
110                                 if (imports[i].onDemand) {
111                                         if (CharOperation.equals(imports[i].compoundName, compoundPackageName)) {
112                                                 for (int j = 0; j < imports.length; j++) {
113                                                         if(i != j){
114                                                                 if(imports[j].onDemand) {
115                                                                         if(nameEnvironment.findType(typeName, imports[j].compoundName) != null){
116                                                                                 return true;
117                                                                         }
118                                                                 } else {
119                                                                         if(CharOperation.equals(CharOperation.lastSegment(imports[j].readableName(), '.'), typeName)) {
120                                                                                 return true;    
121                                                                         }
122                                                                 }
123                                                         }
124                                                 }
125                                                 return false; // how do you match p1.p2.A.* ?
126                                         }
127         
128                                 } else
129         
130                                         if (CharOperation.equals(imports[i].readableName(), readableTypeName)) {
131                                                 return false;
132                                         }
133                         }
134                 }
135                 return true;
136         }
137
138         protected void parseMethod(CompilationUnitDeclaration unit, int position) {
139                 for (int i = unit.types.length; --i >= 0;) {
140                         TypeDeclaration type = unit.types[i];
141                         if (type.declarationSourceStart < position
142                                 && type.declarationSourceEnd >= position) {
143                                 getParser().scanner.setSource(
144                                         unit.compilationResult.compilationUnit.getContents());
145                                 parseMethod(type, unit, position);
146                                 return;
147                         }
148                 }
149         }
150
151         private void parseMethod(
152                 TypeDeclaration type,
153                 CompilationUnitDeclaration unit,
154                 int position) {
155                 //members
156                 TypeDeclaration[] memberTypes = type.memberTypes;
157                 if (memberTypes != null) {
158                         for (int i = memberTypes.length; --i >= 0;) {
159                                 TypeDeclaration memberType = memberTypes[i];
160                                 if (memberType.bodyStart > position)
161                                         continue;
162                                 if (memberType.declarationSourceEnd >= position) {
163                                         parseMethod(memberType, unit, position);
164                                         return;
165                                 }
166                         }
167                 }
168                 //methods
169                 AbstractMethodDeclaration[] methods = type.methods;
170                 if (methods != null) {
171                         for (int i = methods.length; --i >= 0;) {
172                                 AbstractMethodDeclaration method = methods[i];
173                                 if (method.bodyStart > position)
174                                         continue;
175                                 if (method.declarationSourceEnd >= position) {
176                                         getParser().parseBlockStatements(method, unit);
177                                         return;
178                                 }
179                         }
180                 }
181                 //initializers
182                 FieldDeclaration[] fields = type.fields;
183                 if (fields != null) {
184                         for (int i = fields.length; --i >= 0;) {
185                                 if (!(fields[i] instanceof Initializer))
186                                         continue;
187                                 Initializer initializer = (Initializer) fields[i];
188                                 if (initializer.bodyStart > position)
189                                         continue;
190                                 if (initializer.declarationSourceEnd >= position) {
191                                         getParser().parseBlockStatements(initializer, type, unit);
192                                         return;
193                                 }
194                         }
195                 }
196         }
197
198         protected void reset() {
199                 lookupEnvironment.reset();
200         }
201 }