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
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.codeassist;
13 import java.util.Locale;
16 import net.sourceforge.phpdt.core.compiler.IProblem;
17 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
18 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
19 import net.sourceforge.phpdt.internal.codeassist.impl.AssistParser;
20 import net.sourceforge.phpdt.internal.codeassist.impl.Engine;
21 import net.sourceforge.phpdt.internal.codeassist.select.SelectionNodeFound;
22 import net.sourceforge.phpdt.internal.codeassist.select.SelectionOnImportReference;
23 import net.sourceforge.phpdt.internal.codeassist.select.SelectionOnPackageReference;
24 import net.sourceforge.phpdt.internal.codeassist.select.SelectionOnQualifiedTypeReference;
25 import net.sourceforge.phpdt.internal.codeassist.select.SelectionOnSingleTypeReference;
26 import net.sourceforge.phpdt.internal.codeassist.select.SelectionParser;
27 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
28 import net.sourceforge.phpdt.internal.compiler.DefaultErrorHandlingPolicies;
29 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
30 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
31 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
32 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
33 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
34 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
35 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
36 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
37 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
38 import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
39 import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
40 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
41 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
42 import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
43 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
44 import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
45 import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReferenceBinding;
46 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
47 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
48 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
49 import net.sourceforge.phpdt.internal.compiler.parser.SourceTypeConverter;
50 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
51 import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
52 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
53 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
56 * The selection engine is intended to infer the nature of a selected name in some
57 * source code. This name can be qualified.
59 * Selection is resolving context using a name environment (no need to search), assuming
60 * the source where selection occurred is correct and will not perform any completion
61 * attempt. If this was the desired behavior, a call to the CompletionEngine should be
64 public final class SelectionEngine extends Engine implements ISearchRequestor {
66 public static boolean DEBUG = false;
68 SelectionParser parser;
69 ISelectionRequestor requestor;
71 boolean acceptedAnswer;
73 private int actualSelectionStart;
74 private int actualSelectionEnd;
75 private char[] qualifiedSelection;
76 private char[] selectedIdentifier;
78 private char[][][] acceptedClasses;
79 private char[][][] acceptedInterfaces;
80 int acceptedClassesCount;
81 int acceptedInterfacesCount;
84 * The SelectionEngine is responsible for computing the selected object.
86 * It requires a searchable name environment, which supports some
87 * specific search APIs, and a requestor to feed back the results to a UI.
89 * @param nameEnvironment net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment
90 * used to resolve type/package references and search for types/packages
91 * based on partial names.
93 * @param requestor net.sourceforge.phpdt.internal.codeassist.ISelectionRequestor
94 * since the engine might produce answers of various forms, the engine
95 * is associated with a requestor able to accept all possible completions.
97 * @param settings java.util.Map
98 * set of options used to configure the code assist engine.
100 public SelectionEngine(
101 ISearchableNameEnvironment nameEnvironment,
102 ISelectionRequestor requestor,
107 this.requestor = requestor;
108 this.nameEnvironment = nameEnvironment;
110 ProblemReporter problemReporter =
112 DefaultErrorHandlingPolicies.proceedWithAllProblems(),
113 this.compilerOptions,
114 new DefaultProblemFactory(Locale.getDefault())) {
115 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
116 unitResult.record(problem, referenceContext);
117 SelectionEngine.this.requestor.acceptError(problem);
120 this.parser = new SelectionParser(problemReporter, this.compilerOptions.assertMode);
121 this.lookupEnvironment =
122 new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
126 * One result of the search consists of a new class.
127 * @param packageName char[]
128 * @param className char[]
129 * @param modifiers int
131 * NOTE - All package and type names are presented in their readable form:
132 * Package names are in the form "a.b.c".
133 * Nested type names are in the qualified form "A.M".
134 * The default package is represented by an empty array.
136 public void acceptClass(char[] packageName, char[] className, int modifiers) {
137 if (CharOperation.equals(className, selectedIdentifier)) {
138 if (qualifiedSelection != null
139 && !CharOperation.equals(
141 CharOperation.concat(packageName, className, '.'))) {
145 if(mustQualifyType(packageName, className)) {
146 char[][] acceptedClass = new char[2][];
147 acceptedClass[0] = packageName;
148 acceptedClass[1] = className;
150 if(acceptedClasses == null) {
151 acceptedClasses = new char[10][][];
152 acceptedClassesCount = 0;
154 int length = acceptedClasses.length;
155 if(length == acceptedClassesCount) {
156 System.arraycopy(acceptedClasses, 0, acceptedClasses = new char[(length + 1)* 2][][], 0, length);
158 acceptedClasses[acceptedClassesCount++] = acceptedClass;
161 requestor.acceptClass(
165 acceptedAnswer = true;
171 * One result of the search consists of a new interface.
173 * NOTE - All package and type names are presented in their readable form:
174 * Package names are in the form "a.b.c".
175 * Nested type names are in the qualified form "A.I".
176 * The default package is represented by an empty array.
178 public void acceptInterface(
180 char[] interfaceName,
183 if (CharOperation.equals(interfaceName, selectedIdentifier)) {
184 if (qualifiedSelection != null
185 && !CharOperation.equals(
187 CharOperation.concat(packageName, interfaceName, '.'))) {
191 if(mustQualifyType(packageName, interfaceName)) {
192 char[][] acceptedInterface= new char[2][];
193 acceptedInterface[0] = packageName;
194 acceptedInterface[1] = interfaceName;
196 if(acceptedInterfaces == null) {
197 acceptedInterfaces = new char[10][][];
198 acceptedInterfacesCount = 0;
200 int length = acceptedInterfaces.length;
201 if(length == acceptedInterfacesCount) {
202 System.arraycopy(acceptedInterfaces, 0, acceptedInterfaces = new char[(length + 1) * 2][][], 0, length);
204 acceptedInterfaces[acceptedInterfacesCount++] = acceptedInterface;
207 requestor.acceptInterface(
211 acceptedAnswer = true;
217 * One result of the search consists of a new package.
218 * @param packageName char[]
220 * NOTE - All package names are presented in their readable form:
221 * Package names are in the form "a.b.c".
222 * The default package is represented by an empty array.
224 public void acceptPackage(char[] packageName) {
227 private void acceptQualifiedTypes() {
228 if(acceptedClasses != null){
229 acceptedAnswer = true;
230 for (int i = 0; i < acceptedClassesCount; i++) {
231 requestor.acceptClass(
232 acceptedClasses[i][0],
233 acceptedClasses[i][1],
236 acceptedClasses = null;
237 acceptedClassesCount = 0;
239 if(acceptedInterfaces != null){
240 acceptedAnswer = true;
241 for (int i = 0; i < acceptedInterfacesCount; i++) {
242 requestor.acceptInterface(
243 acceptedInterfaces[i][0],
244 acceptedInterfaces[i][1],
247 acceptedInterfaces = null;
248 acceptedInterfacesCount = 0;
253 * One result of the search consists of a new type.
254 * @param packageName char[]
255 * @param typeName char[]
257 * NOTE - All package and type names are presented in their readable form:
258 * Package names are in the form "a.b.c".
259 * Nested type names are in the qualified form "A.M".
260 * The default package is represented by an empty array.
262 public void acceptType(char[] packageName, char[] typeName) {
263 acceptClass(packageName, typeName, 0);
266 private boolean checkSelection(
271 Scanner scanner = new Scanner();
272 scanner.setSource(source);
274 int lastIdentifierStart = -1;
275 int lastIdentifierEnd = -1;
276 char[] lastIdentifier = null;
277 int token, identCount = 0;
278 StringBuffer entireSelection = new StringBuffer(selectionEnd - selectionStart + 1);
280 if(selectionStart > selectionEnd){
282 // compute start position of current line
283 int currentPosition = selectionStart - 1;
284 int nextCharacterPosition = selectionStart;
285 char currentCharacter = ' ';
287 while(currentPosition > 0 || currentCharacter == '\r' || currentCharacter == '\n'){
289 if(source[currentPosition] == '\\' && source[currentPosition+1] == 'u') {
290 int pos = currentPosition + 2;
291 int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
292 while (source[pos] == 'u') {
295 if ((c1 = Character.getNumericValue(source[pos++])) > 15
297 || (c2 = Character.getNumericValue(source[pos++])) > 15
299 || (c3 = Character.getNumericValue(source[pos++])) > 15
301 || (c4 = Character.getNumericValue(source[pos++])) > 15
305 currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
306 nextCharacterPosition = pos;
309 currentCharacter = source[currentPosition];
310 nextCharacterPosition = currentPosition+1;
313 if(currentCharacter == '\r' || currentCharacter == '\n') {
319 catch (ArrayIndexOutOfBoundsException e) {
323 // compute start and end of the last token
324 scanner.resetTo(nextCharacterPosition, selectionEnd);
327 token = scanner.getNextToken();
328 } catch (InvalidInputException e) {
332 // token == ITerminalSymbols.TokenNamethis ||
333 // token == ITerminalSymbols.TokenNamesuper ||
334 token == ITerminalSymbols.TokenNameIdentifier) &&
335 scanner.startPosition <= selectionStart &&
336 selectionStart <= scanner.currentPosition) {
337 lastIdentifierStart = scanner.startPosition;
338 lastIdentifierEnd = scanner.currentPosition - 1;
339 lastIdentifier = scanner.getCurrentTokenSource();
341 } while (token != ITerminalSymbols.TokenNameEOF);
343 scanner.resetTo(selectionStart, selectionEnd);
345 boolean expectingIdentifier = true;
349 token = scanner.getNextToken();
350 } catch (InvalidInputException e) {
354 // case ITerminalSymbols.TokenNamethis :
355 // case ITerminalSymbols.TokenNamesuper :
356 case ITerminalSymbols.TokenNameIdentifier :
357 if (!expectingIdentifier)
359 lastIdentifier = scanner.getCurrentTokenSource();
360 lastIdentifierStart = scanner.startPosition;
361 lastIdentifierEnd = scanner.currentPosition - 1;
362 if(lastIdentifierEnd > selectionEnd) {
363 lastIdentifierEnd = selectionEnd;
364 lastIdentifier = CharOperation.subarray(lastIdentifier, 0,lastIdentifierEnd - lastIdentifierStart + 1);
366 entireSelection.append(lastIdentifier);
369 expectingIdentifier = false;
371 case ITerminalSymbols.TokenNameDOT :
372 if (expectingIdentifier)
374 entireSelection.append('.');
375 expectingIdentifier = true;
377 case ITerminalSymbols.TokenNameEOF :
378 if (expectingIdentifier)
384 } while (token != ITerminalSymbols.TokenNameEOF);
386 if (lastIdentifierStart > 0) {
387 actualSelectionStart = lastIdentifierStart;
388 actualSelectionEnd = lastIdentifierEnd;
389 selectedIdentifier = lastIdentifier;
391 qualifiedSelection = entireSelection.toString().toCharArray();
397 public AssistParser getParser() {
402 * Ask the engine to compute the selection at the specified position
403 * of the given compilation unit.
405 * @param sourceUnit net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit
406 * the source of the current compilation unit.
408 * @param selectionSourceStart int
409 * @param selectionSourceEnd int
410 * a range in the source where the selection is.
413 ICompilationUnit sourceUnit,
414 int selectionSourceStart,
415 int selectionSourceEnd) {
417 char[] source = sourceUnit.getContents();
420 System.out.print("SELECTION IN "); //$NON-NLS-1$
421 System.out.print(sourceUnit.getFileName());
422 System.out.print(" FROM "); //$NON-NLS-1$
423 System.out.print(selectionSourceStart);
424 System.out.print(" TO "); //$NON-NLS-1$
425 System.out.println(selectionSourceEnd);
426 System.out.println("SELECTION - Source :"); //$NON-NLS-1$
427 System.out.println(source);
429 if (!checkSelection(source, selectionSourceStart, selectionSourceEnd))
432 acceptedAnswer = false;
433 CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
434 CompilationUnitDeclaration parsedUnit =
435 parser.dietParse(sourceUnit, result, actualSelectionStart, actualSelectionEnd);
437 if (parsedUnit != null) {
439 System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
440 System.out.println(parsedUnit.toString());
443 // scan the package & import statements first
444 if (parsedUnit.currentPackage instanceof SelectionOnPackageReference) {
446 ((SelectionOnPackageReference) parsedUnit.currentPackage).tokens;
447 requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
450 ImportReference[] imports = parsedUnit.imports;
451 if (imports != null) {
452 for (int i = 0, length = imports.length; i < length; i++) {
453 ImportReference importReference = imports[i];
454 if (importReference instanceof SelectionOnImportReference) {
455 char[][] tokens = ((SelectionOnImportReference) importReference).tokens;
456 requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
457 nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), this);
458 // accept qualified types only if no unqualified type was accepted
459 if(!acceptedAnswer) {
460 acceptQualifiedTypes();
461 if (!acceptedAnswer) {
462 nameEnvironment.findTypes(selectedIdentifier, this);
463 // try with simple type name
464 if(!acceptedAnswer) {
465 acceptQualifiedTypes();
473 if (parsedUnit.types != null) {
474 lookupEnvironment.buildTypeBindings(parsedUnit);
475 if ((this.unitScope = parsedUnit.scope) != null) {
477 lookupEnvironment.completeTypeBindings(parsedUnit, true);
478 parsedUnit.scope.faultInTypes();
479 selectDeclaration(parsedUnit);
480 parseMethod(parsedUnit, selectionSourceStart);
482 System.out.println("SELECTION - AST :"); //$NON-NLS-1$
483 System.out.println(parsedUnit.toString());
485 parsedUnit.resolve();
486 } catch (SelectionNodeFound e) {
487 if (e.binding != null) {
489 System.out.println("SELECTION - Selection binding:"); //$NON-NLS-1$
490 System.out.println(e.binding.toString());
492 // if null then we found a problem in the selection node
493 selectFrom(e.binding);
499 // only reaches here if no selection could be derived from the parsed tree
500 // thus use the selected source and perform a textual type search
501 if (!acceptedAnswer) {
502 nameEnvironment.findTypes(selectedIdentifier, this);
504 // accept qualified types only if no unqualified type was accepted
505 if(!acceptedAnswer) {
506 acceptQualifiedTypes();
509 } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
510 } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
516 private void selectFrom(Binding binding) {
517 if (binding instanceof ReferenceBinding) {
518 ReferenceBinding typeBinding = (ReferenceBinding) binding;
519 if (qualifiedSelection != null
520 && !CharOperation.equals(qualifiedSelection, typeBinding.readableName())) {
523 if (typeBinding.isInterface()) {
524 requestor.acceptInterface(
525 typeBinding.qualifiedPackageName(),
526 typeBinding.qualifiedSourceName(),
528 } else if(typeBinding instanceof ProblemReferenceBinding){
529 ProblemReferenceBinding problemBinding = (ProblemReferenceBinding)typeBinding;
530 if(problemBinding.original == null
531 || !(problemBinding.original instanceof ReferenceBinding)) {
534 ReferenceBinding original = (ReferenceBinding) problemBinding.original;
536 requestor.acceptClass(
537 original.qualifiedPackageName(),
538 original.qualifiedSourceName(),
541 requestor.acceptClass(
542 typeBinding.qualifiedPackageName(),
543 typeBinding.qualifiedSourceName(),
546 acceptedAnswer = true;
548 if (binding instanceof MethodBinding) {
549 MethodBinding methodBinding = (MethodBinding) binding;
550 TypeBinding[] parameterTypes = methodBinding.parameters;
551 int length = parameterTypes.length;
552 char[][] parameterPackageNames = new char[length][];
553 char[][] parameterTypeNames = new char[length][];
554 for (int i = 0; i < length; i++) {
555 parameterPackageNames[i] = parameterTypes[i].qualifiedPackageName();
556 parameterTypeNames[i] = parameterTypes[i].qualifiedSourceName();
558 requestor.acceptMethod(
559 methodBinding.declaringClass.qualifiedPackageName(),
560 methodBinding.declaringClass.qualifiedSourceName(),
561 methodBinding.isConstructor()
562 ? methodBinding.declaringClass.sourceName()
563 : methodBinding.selector,
564 parameterPackageNames,
566 methodBinding.isConstructor());
567 acceptedAnswer = true;
569 if (binding instanceof FieldBinding) {
570 FieldBinding fieldBinding = (FieldBinding) binding;
571 if (fieldBinding.declaringClass != null) { // arraylength
572 requestor.acceptField(
573 fieldBinding.declaringClass.qualifiedPackageName(),
574 fieldBinding.declaringClass.qualifiedSourceName(),
576 acceptedAnswer = true;
579 if (binding instanceof LocalVariableBinding) {
580 selectFrom(((LocalVariableBinding) binding).type);
581 // open on the type of the variable
583 if (binding instanceof ArrayBinding) {
584 selectFrom(((ArrayBinding) binding).leafComponentType);
585 // open on the type of the array
587 if (binding instanceof PackageBinding) {
588 PackageBinding packageBinding = (PackageBinding) binding;
589 requestor.acceptPackage(packageBinding.readableName());
590 acceptedAnswer = true;
592 if(binding instanceof BaseTypeBinding) {
593 acceptedAnswer = true;
598 * Asks the engine to compute the selection of the given type
599 * from the source type.
601 * @param sourceType net.sourceforge.phpdt.internal.compiler.env.ISourceType
602 * a source form of the current type in which code assist is invoked.
604 * @param typeName char[]
605 * a type name which is to be resolved in the context of a compilation unit.
606 * NOTE: the type name is supposed to be correctly reduced (no whitespaces, no unicodes left)
608 * @param searchInEnvironment
609 * if <code>true</code> and no selection could be found in context then search type in environment.
611 public void selectType(ISourceType sourceType, char[] typeName, boolean searchInEnvironment) {
613 acceptedAnswer = false;
615 // find the outer most type
616 ISourceType outerType = sourceType;
617 ISourceType parent = sourceType.getEnclosingType();
618 while (parent != null) {
620 parent = parent.getEnclosingType();
622 // compute parse tree for this most outer type
623 CompilationResult result = new CompilationResult(outerType.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
624 CompilationUnitDeclaration parsedUnit =
626 .buildCompilationUnit(
627 new ISourceType[] { outerType },
629 // don't need field and methods
630 true, // by default get member types
631 this.parser.problemReporter(), result);
633 if (parsedUnit != null && parsedUnit.types != null) {
635 System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
636 System.out.println(parsedUnit.toString());
638 // find the type declaration that corresponds to the original source type
639 char[] packageName = sourceType.getPackageName();
640 char[] sourceTypeName = sourceType.getQualifiedName();
641 // the fully qualified name without the package name
642 if (packageName != null) {
643 // remove the package name if necessary
645 CharOperation.subarray(
646 sourceType.getQualifiedName(),
647 packageName.length + 1,
648 sourceTypeName.length);
650 TypeDeclaration typeDecl =
651 parsedUnit.declarationOfType(CharOperation.splitOn('.', sourceTypeName));
652 if (typeDecl != null) {
654 // add fake field with the type we're looking for
655 // note: since we didn't ask for fields above, there is no field defined yet
656 FieldDeclaration field = new FieldDeclaration();
658 if ((dot = CharOperation.lastIndexOf('.', typeName)) == -1) {
659 this.selectedIdentifier = typeName;
660 field.type = new SelectionOnSingleTypeReference(typeName, -1);
663 qualifiedSelection = typeName;
664 char[][] previousIdentifiers = CharOperation.splitOn('.', typeName, 0, dot - 1);
665 char[] selectionIdentifier =
666 CharOperation.subarray(typeName, dot + 1, typeName.length);
667 this.selectedIdentifier = selectionIdentifier;
669 new SelectionOnQualifiedTypeReference(
672 new long[previousIdentifiers.length + 1]);
674 field.name = "<fakeField>".toCharArray(); //$NON-NLS-1$
675 typeDecl.fields = new FieldDeclaration[] { field };
678 lookupEnvironment.buildTypeBindings(parsedUnit);
679 if ((this.unitScope = parsedUnit.scope) != null) {
682 // note: this builds fields only in the parsed unit (the buildFieldsAndMethods flag is not passed along)
683 this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
686 parsedUnit.scope.faultInTypes();
687 parsedUnit.resolve();
688 } catch (SelectionNodeFound e) {
689 if (e.binding != null) {
691 System.out.println("SELECTION - Selection binding :"); //$NON-NLS-1$
692 System.out.println(e.binding.toString());
694 // if null then we found a problem in the selection node
695 selectFrom(e.binding);
701 // only reaches here if no selection could be derived from the parsed tree
702 // thus use the selected source and perform a textual type search
703 if (!acceptedAnswer && searchInEnvironment) {
704 if (this.selectedIdentifier != null) {
705 nameEnvironment.findTypes(typeName, this);
707 // accept qualified types only if no unqualified type was accepted
708 if(!acceptedAnswer) {
709 acceptQualifiedTypes();
713 } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
715 qualifiedSelection = null;
720 // Check if a declaration got selected in this unit
721 private void selectDeclaration(CompilationUnitDeclaration compilationUnit){
723 // the selected identifier is not identical to the parser one (equals but not identical),
724 // for traversing the parse tree, the parser assist identifier is necessary for identitiy checks
725 char[] assistIdentifier = this.getParser().assistIdentifier();
726 if (assistIdentifier == null) return;
728 // iterate over the types
729 TypeDeclaration[] types = compilationUnit.types;
730 for (int i = 0, length = types == null ? 0 : types.length; i < length; i++){
731 selectDeclaration(types[i], assistIdentifier);
735 // Check if a declaration got selected in this type
736 private void selectDeclaration(TypeDeclaration typeDeclaration, char[] assistIdentifier){
738 if (typeDeclaration.name == assistIdentifier){
739 throw new SelectionNodeFound(typeDeclaration.binding);
741 TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
742 for (int i = 0, length = memberTypes == null ? 0 : memberTypes.length; i < length; i++){
743 selectDeclaration(memberTypes[i], assistIdentifier);
745 FieldDeclaration[] fields = typeDeclaration.fields;
746 for (int i = 0, length = fields == null ? 0 : fields.length; i < length; i++){
747 if (fields[i].name == assistIdentifier){
748 throw new SelectionNodeFound(fields[i].binding);
751 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
752 for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++){
753 AbstractMethodDeclaration method = methods[i];
754 if (method.selector == assistIdentifier){
755 if(method.binding != null) {
756 throw new SelectionNodeFound(method.binding);
758 if(method.scope != null) {
759 throw new SelectionNodeFound(new MethodBinding(method.modifiers, method.selector, null, null, null, method.scope.referenceType().binding));