KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > codeassist > impl > Engine


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.codeassist.impl;
12
13 import java.util.Map JavaDoc;
14
15 import org.eclipse.jdt.core.compiler.CharOperation;
16 import org.eclipse.jdt.internal.compiler.*;
17 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18 import org.eclipse.jdt.internal.compiler.env.*;
19
20 import org.eclipse.jdt.internal.compiler.ast.*;
21 import org.eclipse.jdt.internal.compiler.lookup.*;
22 import org.eclipse.jdt.internal.compiler.parser.*;
23 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
24 import org.eclipse.jdt.internal.compiler.impl.*;
25 import org.eclipse.jdt.internal.core.NameLookup;
26 import org.eclipse.jdt.internal.core.SearchableEnvironment;
27
28 public abstract class Engine implements ITypeRequestor {
29
30     public LookupEnvironment lookupEnvironment;
31
32     protected CompilationUnitScope unitScope;
33     public SearchableEnvironment nameEnvironment;
34
35     public AssistOptions options;
36     public CompilerOptions compilerOptions;
37     public boolean forbiddenReferenceIsError;
38     public boolean discouragedReferenceIsError;
39
40     public boolean importCachesInitialized = false;
41     public char[][][] importsCache;
42     public ImportBinding[] onDemandImportsCache;
43     public int importCacheCount = 0;
44     public int onDemandImportCacheCount = 0;
45     public char[] currentPackageName = null;
46
47     public Engine(Map JavaDoc settings){
48         this.options = new AssistOptions(settings);
49         this.compilerOptions = new CompilerOptions(settings);
50         this.forbiddenReferenceIsError =
51             (this.compilerOptions.getSeverity(CompilerOptions.ForbiddenReference) & ProblemSeverities.Error) != 0;
52         this.discouragedReferenceIsError =
53             (this.compilerOptions.getSeverity(CompilerOptions.DiscouragedReference) & ProblemSeverities.Error) != 0;
54     }
55
56     /**
57      * Add an additional binary type
58      */

59     public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
60         lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
61     }
62
63     /**
64      * Add an additional compilation unit.
65      */

66     public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
67         CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
68         CompilationUnitDeclaration parsedUnit =
69             this.getParser().dietParse(sourceUnit, result);
70
71         lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
72         lookupEnvironment.completeTypeBindings(parsedUnit, true);
73     }
74
75     /**
76      * Add additional source types (the first one is the requested type, the rest is formed by the
77      * secondary types defined in the same compilation unit).
78      */

79     public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
80         CompilationResult result =
81             new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
82         CompilationUnitDeclaration unit =
83             SourceTypeConverter.buildCompilationUnit(
84                 sourceTypes,//sourceTypes[0] is always toplevel here
85
SourceTypeConverter.FIELD_AND_METHOD // need field and methods
86
| SourceTypeConverter.MEMBER_TYPE, // need member types
87
// no need for field initialization
88
lookupEnvironment.problemReporter,
89                 result);
90
91         if (unit != null) {
92             lookupEnvironment.buildTypeBindings(unit, accessRestriction);
93             lookupEnvironment.completeTypeBindings(unit, true);
94         }
95     }
96
97     public abstract AssistParser getParser();
98
99     public void initializeImportCaches() {
100         ImportBinding[] importBindings = this.unitScope.imports;
101         int length = importBindings == null ? 0 : importBindings.length;
102
103         this.currentPackageName = CharOperation.concatWith(unitScope.fPackage.compoundName, '.');
104
105         for (int i = 0; i < length; i++) {
106             ImportBinding importBinding = importBindings[i];
107             if(importBinding.onDemand) {
108                 if(this.onDemandImportsCache == null) {
109                     this.onDemandImportsCache = new ImportBinding[length - i];
110                 }
111                 this.onDemandImportsCache[this.onDemandImportCacheCount++] =
112                     importBinding;
113             } else {
114                 if(!(importBinding.resolvedImport instanceof MethodBinding) ||
115                         importBinding instanceof ImportConflictBinding) {
116                     if(this.importsCache == null) {
117                         this.importsCache = new char[length - i][][];
118                     }
119                     this.importsCache[this.importCacheCount++] = new char[][]{
120                             importBinding.compoundName[importBinding.compoundName.length - 1],
121                             CharOperation.concatWith(importBinding.compoundName, '.')
122                         };
123                 }
124             }
125         }
126
127         this.importCachesInitialized = true;
128     }
129
130     protected boolean mustQualifyType(
131         char[] packageName,
132         char[] typeName,
133         char[] enclosingTypeNames,
134         int modifiers) {
135
136         // If there are no types defined into the current CU yet.
137
if (unitScope == null)
138             return true;
139
140         if(!this.importCachesInitialized) {
141             this.initializeImportCaches();
142         }
143
144         for (int i = 0; i < this.importCacheCount; i++) {
145             char[][] importName = this.importsCache[i];
146             if(CharOperation.equals(typeName, importName[0])) {
147                 char[] fullyQualifiedTypeName =
148                     enclosingTypeNames == null || enclosingTypeNames.length == 0
149                             ? CharOperation.concat(
150                                     packageName,
151                                     typeName,
152                                     '.')
153                             : CharOperation.concat(
154                                     CharOperation.concat(
155                                         packageName,
156                                         enclosingTypeNames,
157                                         '.'),
158                                     typeName,
159                                     '.');
160                 return !CharOperation.equals(fullyQualifiedTypeName, importName[1]);
161             }
162         }
163
164         if ((enclosingTypeNames == null || enclosingTypeNames.length == 0 ) && CharOperation.equals(this.currentPackageName, packageName))
165             return false;
166
167         char[] fullyQualifiedEnclosingTypeName = null;
168
169         for (int i = 0; i < this.onDemandImportCacheCount; i++) {
170             ImportBinding importBinding = this.onDemandImportsCache[i];
171             Binding resolvedImport = importBinding.resolvedImport;
172
173             char[][] importName = importBinding.compoundName;
174             char[] importFlatName = CharOperation.concatWith(importName, '.');
175
176             boolean isFound = false;
177             // resolvedImport is a ReferenceBindng or a PackageBinding
178
if(resolvedImport instanceof ReferenceBinding) {
179                 if(enclosingTypeNames != null && enclosingTypeNames.length != 0) {
180                     if(fullyQualifiedEnclosingTypeName == null) {
181                         fullyQualifiedEnclosingTypeName =
182                             CharOperation.concat(
183                                     packageName,
184                                     enclosingTypeNames,
185                                     '.');
186                     }
187                     if(CharOperation.equals(fullyQualifiedEnclosingTypeName, importFlatName)) {
188                         if(importBinding.isStatic()) {
189                             isFound = (modifiers & ClassFileConstants.AccStatic) != 0;
190                         } else {
191                             isFound = true;
192                         }
193                     }
194                 }
195             } else {
196                 if(enclosingTypeNames == null || enclosingTypeNames.length == 0) {
197                     if(CharOperation.equals(packageName, importFlatName)) {
198                         if(importBinding.isStatic()) {
199                             isFound = (modifiers & ClassFileConstants.AccStatic) != 0;
200                         } else {
201                             isFound = true;
202                         }
203                     }
204                 }
205             }
206
207             // find potential conflict with another import
208
if(isFound) {
209                 for (int j = 0; j < this.onDemandImportCacheCount; j++) {
210                     if(i != j) {
211                         ImportBinding conflictingImportBinding = this.onDemandImportsCache[j];
212                         if(conflictingImportBinding.resolvedImport instanceof ReferenceBinding) {
213                             ReferenceBinding refBinding =
214                                 (ReferenceBinding) conflictingImportBinding.resolvedImport;
215                             if (refBinding.getMemberType(typeName) != null) {
216                                 return true;
217                             }
218                         } else {
219                             char[] conflictingImportName =
220                                 CharOperation.concatWith(conflictingImportBinding.compoundName, '.');
221
222                             if (this.nameEnvironment.nameLookup.findType(
223                                     String.valueOf(typeName),
224                                     String.valueOf(conflictingImportName),
225                                     false,
226                                     NameLookup.ACCEPT_ALL,
227                                     false/*don't check restrictions*/) != null) {
228                                 return true;
229                             }
230                         }
231                     }
232                 }
233                 return false;
234             }
235         }
236         return true;
237     }
238
239     /*
240      * Find the node (a field, a method or an initializer) at the given position
241      * and parse its block statements if it is a method or an initializer.
242      * Returns the node or null if not found
243      */

244     protected ASTNode parseBlockStatements(CompilationUnitDeclaration unit, int position) {
245         int length = unit.types.length;
246         for (int i = 0; i < length; i++) {
247             TypeDeclaration type = unit.types[i];
248             if (type.declarationSourceStart < position
249                 && type.declarationSourceEnd >= position) {
250                 getParser().scanner.setSource(unit.compilationResult);
251                 return parseBlockStatements(type, unit, position);
252             }
253         }
254         return null;
255     }
256
257     private ASTNode parseBlockStatements(
258         TypeDeclaration type,
259         CompilationUnitDeclaration unit,
260         int position) {
261         //members
262
TypeDeclaration[] memberTypes = type.memberTypes;
263         if (memberTypes != null) {
264             int length = memberTypes.length;
265             for (int i = 0; i < length; i++) {
266                 TypeDeclaration memberType = memberTypes[i];
267                 if (memberType.bodyStart > position)
268                     continue;
269                 if (memberType.declarationSourceEnd >= position) {
270                     return parseBlockStatements(memberType, unit, position);
271                 }
272             }
273         }
274         //methods
275
AbstractMethodDeclaration[] methods = type.methods;
276         if (methods != null) {
277             int length = methods.length;
278             for (int i = 0; i < length; i++) {
279                 AbstractMethodDeclaration method = methods[i];
280                 if (method.bodyStart > position)
281                     continue;
282
283                 if(method.isDefaultConstructor())
284                     continue;
285
286                 if (method.declarationSourceEnd >= position) {
287
288                     getParser().parseBlockStatements(method, unit);
289                     return method;
290                 }
291             }
292         }
293         //initializers
294
FieldDeclaration[] fields = type.fields;
295         if (fields != null) {
296             int length = fields.length;
297             for (int i = 0; i < length; i++) {
298                 FieldDeclaration field = fields[i];
299                 if (field.sourceStart > position)
300                     continue;
301                 if (field.declarationSourceEnd >= position) {
302                     if (field instanceof Initializer) {
303                         getParser().parseBlockStatements((Initializer)field, type, unit);
304                     }
305                     return field;
306                 }
307             }
308         }
309         return null;
310     }
311
312     protected void reset() {
313         lookupEnvironment.reset();
314     }
315
316     public static char[] getTypeSignature(TypeBinding typeBinding) {
317         return typeBinding.signature();
318     }
319     public static char[] getSignature(Binding binding) {
320         char[] result = null;
321         if ((binding.kind() & Binding.TYPE) != 0) {
322             TypeBinding typeBinding = (TypeBinding)binding;
323             result = typeBinding.genericTypeSignature();
324         } else if ((binding.kind() & Binding.METHOD) != 0) {
325             MethodBinding methodBinding = (MethodBinding)binding;
326             int oldMod = methodBinding.modifiers;
327             //TODO remove the next line when method from binary type will be able to generate generic siganute
328
methodBinding.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
329             result = methodBinding.genericSignature();
330             if(result == null) {
331                 result = methodBinding.signature();
332             }
333             methodBinding.modifiers = oldMod;
334         }
335         if (result != null) {
336             result = CharOperation.replaceOnCopy(result, '/', '.');
337         }
338         return result;
339     }
340
341     public static char[][] getSignatures(Binding[] bindings) {
342         int length = bindings == null ? 0 : bindings.length;
343         char[][] signatures = new char[length][];
344         for (int i = 0; i < length; i++) {
345             signatures[i] = getSignature(bindings[i]);
346         }
347         return signatures;
348     }
349 }
350
Popular Tags