diff options
author | cjaun | 2011-07-19 18:43:24 +0000 |
---|---|---|
committer | cjaun | 2011-07-19 18:43:24 +0000 |
commit | d0955507da6b3e6b66399057ef5bf1f18f3492d9 (patch) | |
tree | 1974ada51fdef7f417017211e7e66bfd5c6e53e5 | |
parent | a4461dd23e125b95a7520e7a810a4bc6256840f1 (diff) | |
download | webtools.jsdt.core-d0955507da6b3e6b66399057ef5bf1f18f3492d9.tar.gz webtools.jsdt.core-d0955507da6b3e6b66399057ef5bf1f18f3492d9.tar.xz webtools.jsdt.core-d0955507da6b3e6b66399057ef5bf1f18f3492d9.zip |
[351448] [Content Assist] No parameters populated for constructor for code completion
39 files changed, 2057 insertions, 1986 deletions
diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionProposal.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionProposal.java index 5e873cda..4b67b5a3 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionProposal.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionProposal.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -639,6 +639,41 @@ public final class CompletionProposal extends InternalCompletionProposal { * */ public static final int TYPE_IMPORT = 23; + + /** + * Completion is a reference to a constructor. + * This kind of completion might occur in a context like + * <code>"new Lis"</code> and complete it to + * <code>"new List();"</code> if List is a class that is not abstract. + * <p> + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + * <ul> + * <li>{@link #getDeclarationSignature()} - + * the type signature of the type that declares the constructor that is referenced + * </li> + * <li>{@link #getFlags()} - + * the modifiers flags of the constructor that is referenced + * </li> + * <li>{@link #getName()} - + * the simple name of the constructor that is referenced + * </li> + * <li>{@link #getSignature()} - + * the method signature of the constructor that is referenced + * </li> + * </ul> + * </p> + * <p> + * This kind of proposal could require a long computation, so they are computed only if completion operation is called with a {@link IProgressMonitor} + * (e.g. {@link ICodeAssist#codeComplete(int, CompletionRequestor, IProgressMonitor)}).<br> + * This kind of proposal is always is only proposals with a {@link #TYPE_REF} required proposal, so this kind of required proposal must be allowed: + * <code>requestor.setAllowsRequiredProposals(CONSTRUCTOR_INVOCATION, TYPE_REF, true)</code>. + * </p> + * + * @see #getKind() + * @see CompletionRequestor#setAllowsRequiredProposals(int, int, boolean) + */ + public static final int CONSTRUCTOR_INVOCATION = 26; /** * First valid completion kind. @@ -650,7 +685,7 @@ public final class CompletionProposal extends InternalCompletionProposal { * Last valid completion kind. * */ - protected static final int LAST_KIND = TYPE_IMPORT; + protected static final int LAST_KIND = CONSTRUCTOR_INVOCATION; /** * Kind of completion request. @@ -1799,6 +1834,33 @@ public final class CompletionProposal extends InternalCompletionProposal { this.parameterNames = parameterNames; this.parameterNamesComputed = true; } + + /** + * @return <code>true</code> if this proposal includes parameters, + * <code>false</code> if it does not + */ + public boolean hasParameters() { + return this.parameterNames != null && this.parameterNames.length > 0; + } + + /** + * @return parameter names for this proposal, or <code>null</code> if they are not set + * + * @see #findParameterNames(IProgressMonitor) + * @see #setParameterNames(char[][]) + */ + public char[][] getParamaterNames() { + return this.parameterNames; + } + + /** + * @return type names of the parameters for this proposal, or <code>null</code> none are set + * + * @see org.eclipse.wst.jsdt.internal.codeassist.InternalCompletionProposal#getParameterTypeNames() + */ + public char[][] getParameterTypeNames() { + return this.parameterTypeNames; + } /** * Returns the accessibility of the proposal. diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Signature.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Signature.java index 7374af75..07c2dbb1 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Signature.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Signature.java @@ -1312,7 +1312,12 @@ private static int appendTypeSignature(char[] string, int start, boolean fullyQu buffer.append(VOID); return start; default : - throw new IllegalArgumentException(); + /* either the string is not formated as a signature, or we do not know + * how to handle it, so just return it, this is preferable to throwing + * an unnecessary exception + */ + buffer.append(string); + return start; } } } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CharOperation.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CharOperation.java index 55d71791..4dc1e2d7 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CharOperation.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CharOperation.java @@ -1039,12 +1039,49 @@ public static final char[] fixLibPackageTail(char[] packageName) { * => result = { } * </pre></li> * </ol> + * + * <p><b>NOTE:</b> This implementation ignores any elements in the given array that are empty.</p> * * @param array the given array * @param separator the given separator + * * @return the concatenation of the given array parts using the given separator between each part + * + * @see #concatWith(char[][], char, boolean) */ public static final char[] concatWith(char[][] array, char separator) { + return concatWith(array, separator, true); +} + +/** + * Answers the concatenation of the given array parts using the given separator between each part. + * <br> + * <br> + * For example:<br> + * <ol> + * <li><pre> + * array = { { 'a' }, { 'b' } } + * separator = '.' + * => result = { 'a', '.', 'b' } + * </pre> + * </li> + * <li><pre> + * array = null + * separator = '.' + * => result = { } + * </pre></li> + * </ol> + * + * <p>This implementation allows the caller to decide if empty elements in the array should be skipped or not</p> + * + * @param array char string array to concatenate with itself + * @param separator the separator to use between each element of the char string array + * @param ignoreEmptyElements <code>true</code> to skip any empty elements in the char string array, + * <code>false</code> to include an empty element in the return char string + * + * @return the concatenation of the given array parts using the given separator between each part + */ +public static final char[] concatWith(char[][] array, char separator, boolean ignoreEmptyElements) { int length = array == null ? 0 : array.length; if (length == 0) return CharOperation.NO_CHAR; @@ -1052,7 +1089,7 @@ public static final char[] concatWith(char[][] array, char separator) { int size = length - 1; int index = length; while (--index >= 0) { - if (array[index].length == 0) + if (array[index].length == 0 && ignoreEmptyElements) size--; else size += array[index].length; @@ -1063,7 +1100,7 @@ public static final char[] concatWith(char[][] array, char separator) { index = length; while (--index >= 0) { length = array[index].length; - if (length > 0) { + if (length > 0 || (length == 0 && !ignoreEmptyElements)) { System.arraycopy( array[index], 0, diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTConverter.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTConverter.java index db7e4622..89d623fb 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTConverter.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTConverter.java @@ -27,6 +27,7 @@ import org.eclipse.wst.jsdt.core.compiler.InvalidInputException; import org.eclipse.wst.jsdt.core.dom.Modifier.ModifierKeyword; import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.Argument; +import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.ForeachStatement; import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArgumentExpression; import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference; @@ -364,8 +365,11 @@ class ASTConverter { } } org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall explicitConstructorCall = null; - if (isConstructor) { - org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration constructorDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration) methodDeclaration; + /* need this check because a constructor could have been made a constructor after the + * method declaration was created, and thus it is not a ConstructorDeclaration + */ + if (isConstructor && methodDeclaration instanceof ConstructorDeclaration) { + ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration; explicitConstructorCall = constructorDeclaration.constructorCall; switch(this.ast.apiLevel) { case AST.JLS2_INTERNAL : diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferEngine.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferEngine.java index 644bfc28..2bd9a475 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferEngine.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferEngine.java @@ -722,9 +722,8 @@ public class InferEngine extends ASTVisitor implements IInferEngine { this.currentContext.currentType=type; type.isDefinition=true; int nameStart = assignment.getLeftHandSide().sourceStart(); -// InferredMethod method = type.addConstructorMethod(type.name, methodDeclaration, nameStart); - type.updatePositions(assignment.getLeftHandSide().sourceStart(), assignment.getExpression().sourceEnd()); + type.updatePositions(nameStart, assignment.getExpression().sourceEnd()); } } @@ -844,7 +843,7 @@ public class InferEngine extends ASTVisitor implements IInferEngine { type.isDefinition=true; int nameStart = localDeclaration.sourceStart(); type.addConstructorMethod(type.name, methodDeclaration, nameStart); - type.updatePositions(localDeclaration.sourceStart(), localDeclaration.getInitialization().sourceEnd()); + type.updatePositions(nameStart, localDeclaration.getInitialization().sourceEnd()); } keepVisiting = false; @@ -1442,6 +1441,11 @@ public class InferEngine extends ASTVisitor implements IInferEngine { this.isTopLevelAnonymousFunction=false; char[] methodName = methodDeclaration.getName(); + //if declaration didn't have name get name from inferred method if there is one + if(methodName == null && methodDeclaration.getInferredMethod() != null) { + methodName = methodDeclaration.getInferredMethod().name; + } + if (passNumber==1) { buildDefinedMembers((ProgramElement[])methodDeclaration.getStatements(),(Argument[])methodDeclaration.getArguments()); @@ -1504,9 +1508,7 @@ public class InferEngine extends ASTVisitor implements IInferEngine { this.currentContext.currentType = type; type.isDefinition = true; int nameStart = methodDeclaration.sourceStart(); - InferredMethod method = type.addConstructorMethod(methodName, methodDeclaration, nameStart); - method.isConstructor = true; - //methodDeclaration.setInferredType(type); + type.addConstructorMethod(methodName, methodDeclaration, nameStart); } } } @@ -1521,8 +1523,7 @@ public class InferEngine extends ASTVisitor implements IInferEngine { protected void handleJSDocConstructor(InferredType type,IFunctionDeclaration methodDeclaration, int nameStart) { Javadoc javadoc = (Javadoc)methodDeclaration.getJsDoc(); type.isDefinition=true; - InferredMethod method = type.addConstructorMethod(type.name, methodDeclaration, nameStart); - method.isConstructor=true; + type.addConstructorMethod(type.name, methodDeclaration, nameStart); if (javadoc.extendsType!=null) { diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredType.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredType.java index 7e9fed30..90f3eae6 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredType.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2010 IBM Corporation and others. + * Copyright (c) 2005, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -212,7 +212,9 @@ public class InferredType extends ASTNode { */ public InferredMethod addConstructorMethod(char [] methodName, IFunctionDeclaration functionDeclaration, int nameStart) { InferredMethod method = this.addMethod(methodName, functionDeclaration, nameStart, true); + method.isConstructor = true; this.setNameStart(nameStart); + method.getFunctionDeclaration().setInferredType(this); return method; } @@ -239,8 +241,7 @@ public class InferredType extends ASTNode { private InferredMethod addMethod(char [] methodName, IFunctionDeclaration functionDeclaration, int nameStart, boolean isConstructor) { MethodDeclaration methodDeclaration = (MethodDeclaration)functionDeclaration; InferredMethod method = findMethod(methodName, methodDeclaration); - if (method==null) - { + if (method==null) { method=new InferredMethod(methodName,methodDeclaration,this); if (methodDeclaration.inferredMethod==null) methodDeclaration.inferredMethod = method; @@ -263,11 +264,13 @@ public class InferredType extends ASTNode { if( !isAnonymous ) this.updatePositions(methodDeclaration.sourceStart, methodDeclaration.sourceEnd); method.isConstructor=isConstructor; - } - else - if (methodDeclaration.inferredMethod==null) + method.nameStart = nameStart; + } else { + if (methodDeclaration.inferredMethod==null) { methodDeclaration.inferredMethod=method; - method.nameStart = nameStart; + } + } + return method; } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/CompletionEngine.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/CompletionEngine.java index bce29a25..f0406b4e 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/CompletionEngine.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/CompletionEngine.java @@ -30,6 +30,8 @@ import org.eclipse.wst.jsdt.core.UnimplementedException; import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.core.compiler.IProblem; +import org.eclipse.wst.jsdt.core.infer.InferredMethod; +import org.eclipse.wst.jsdt.core.infer.InferredType; import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants; import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionNodeFound; import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnArgumentName; @@ -95,8 +97,10 @@ import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend; import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.OperatorExpression; import org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds; +import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement; import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference; +import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.wst.jsdt.internal.compiler.ast.SuperReference; import org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement; import org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement; @@ -110,7 +114,6 @@ import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType; import org.eclipse.wst.jsdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext; import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding; -import org.eclipse.wst.jsdt.internal.compiler.lookup.BaseTypeBinding; import org.eclipse.wst.jsdt.internal.compiler.lookup.BinaryTypeBinding; import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding; import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope; @@ -319,8 +322,6 @@ public final class CompletionEngine private final static char[] CLASS = "Class".toCharArray(); //$NON-NLS-1$ private final static char[] VOID = "void".toCharArray(); //$NON-NLS-1$ -// private final static char[] INT = "int".toCharArray(); //$NON-NLS-1$ -// private final static char[] INT_SIGNATURE = new char[]{Signature.C_INT}; private final static char[] VARARGS = "...".toCharArray(); //$NON-NLS-1$ @@ -385,50 +386,12 @@ public final class CompletionEngine HashtableOfObject knownPkgs = new HashtableOfObject(10); HashtableOfObject knownTypes = new HashtableOfObject(10); Scanner nameScanner; - - /* - static final char[][] mainDeclarations = - new char[][] { - "package".toCharArray(), - "import".toCharArray(), - "abstract".toCharArray(), - "final".toCharArray(), - "public".toCharArray(), - "class".toCharArray(), - "interface".toCharArray()}; - - static final char[][] modifiers = // may want field, method, type & member type modifiers - new char[][] { - "abstract".toCharArray(), - "final".toCharArray(), - "native".toCharArray(), - "public".toCharArray(), - "protected".toCharArray(), - "private".toCharArray(), - "static".toCharArray(), - "strictfp".toCharArray(), - "synchronized".toCharArray(), - "transient".toCharArray(), - "volatile".toCharArray()}; - */ - static final BaseTypeBinding[] BASE_TYPES = { -// TypeBinding.BOOLEAN, -// TypeBinding.BYTE, -// TypeBinding.CHAR, -// TypeBinding.DOUBLE, -// TypeBinding.FLOAT, -// TypeBinding.INT, -// TypeBinding.LONG, -// TypeBinding.SHORT, -// TypeBinding.VOID - }; - static final int BASE_TYPES_LENGTH = BASE_TYPES.length; - static final char[][] BASE_TYPE_NAMES = new char[BASE_TYPES_LENGTH][]; - static { - for (int i=0; i<BASE_TYPES_LENGTH; i++) { - BASE_TYPE_NAMES[i] = BASE_TYPES[i].simpleName; - } - } + + /** + * <p>Constructors accepted by {@link #acceptConstructor(int, char[], int, char[], char[][], char[][], String, AccessRestriction)} + * to be processed by {@link #acceptConstructors(Scope)}</p> + */ + private ObjectVector acceptedConstructors; static final char[] classField = "class".toCharArray(); //$NON-NLS-1$ static final char[] lengthField = "length".toCharArray(); //$NON-NLS-1$ @@ -445,9 +408,13 @@ public final class CompletionEngine public int sourceStart() { return 0; } public int sourceEnd() { return 0; } }; - - private ObjectVector acceptedTypes; - + + /** + * When performing an index search for binding matches this is + * where the results will be stored + */ + private ObjectVector acceptedBindings; + /** * The CompletionEngine is responsible for computing source completions. * @@ -542,14 +509,14 @@ public final class CompletionEngine } } - if(acceptedTypes == null) { - acceptedTypes = new ObjectVector(); + if(this.acceptedBindings == null) { + this.acceptedBindings = new ObjectVector(); } char[] fullyQualifiedName = simpleTypeName; if(CharOperation.indexOf('.', simpleTypeName) < 0) { fullyQualifiedName = CharOperation.concat(packageName, simpleTypeName, '.'); } - acceptedTypes.add(new AcceptedBinding(packageName, fullyQualifiedName, enclosingTypeNames, modifiers, accessibility)); + this.acceptedBindings.add(new AcceptedBinding(packageName, fullyQualifiedName, enclosingTypeNames, modifiers, accessibility)); } public void acceptBinding( @@ -560,57 +527,52 @@ public final class CompletionEngine int modifiers, AccessRestriction accessRestriction) { -// char [][]pkgName=new char[][]{packageName}; -// PackageBinding packageBinding = (PackageBinding) this.unitScope.getBinding(name, mask, invocationSite, needResolve)getPackage(pkgName); -// Binding binding = packageBinding.getBinding(simpleTypeName, bindingType); - if (this.options.checkDeprecation && (modifiers & ClassFileConstants.AccDeprecated) != 0) return; - - if (this.options.checkVisibility) { - if((modifiers & ClassFileConstants.AccPublic) == 0) { - if((modifiers & ClassFileConstants.AccPrivate) != 0) return; + if (this.options.checkDeprecation && (modifiers & ClassFileConstants.AccDeprecated) != 0) return; - char[] currentPackage = CharOperation.concatWith(this.unitScope.getDefaultPackage().compoundName, '.'); - if(!CharOperation.equals(packageName, currentPackage)) return; - } - } + if (this.options.checkVisibility) { + if((modifiers & ClassFileConstants.AccPublic) == 0) { + if((modifiers & ClassFileConstants.AccPrivate) != 0) return; - int accessibility = IAccessRule.K_ACCESSIBLE; - if(accessRestriction != null) { - switch (accessRestriction.getProblemId()) { - case IProblem.ForbiddenReference: - if (this.options.checkForbiddenReference) { - return; - } - accessibility = IAccessRule.K_NON_ACCESSIBLE; - break; - case IProblem.DiscouragedReference: - if (this.options.checkDiscouragedReference) { - return; - } - accessibility = IAccessRule.K_DISCOURAGED; - break; - } + char[] currentPackage = CharOperation.concatWith(this.unitScope.getDefaultPackage().compoundName, '.'); + if(!CharOperation.equals(packageName, currentPackage)) return; } + } - if(acceptedTypes == null) { - acceptedTypes = new ObjectVector(); + int accessibility = IAccessRule.K_ACCESSIBLE; + if(accessRestriction != null) { + switch (accessRestriction.getProblemId()) { + case IProblem.ForbiddenReference: + if (this.options.checkForbiddenReference) { + return; + } + accessibility = IAccessRule.K_NON_ACCESSIBLE; + break; + case IProblem.DiscouragedReference: + if (this.options.checkDiscouragedReference) { + return; + } + accessibility = IAccessRule.K_DISCOURAGED; + break; } - acceptedTypes.add(new AcceptedBinding(bindingType,packageName, simpleTypeName, modifiers, accessibility)); } - + if(acceptedBindings == null) { + acceptedBindings = new ObjectVector(); + } + acceptedBindings.add(new AcceptedBinding(bindingType,packageName, simpleTypeName, modifiers, accessibility)); + } private void acceptTypes(Scope scope) { - if(this.acceptedTypes == null) return; + if(this.acceptedBindings == null) return; - int length = this.acceptedTypes.size(); + int length = this.acceptedBindings.size(); if(length == 0) return; HashtableOfObject onDemandFound = new HashtableOfObject(); next : for (int i = 0; i < length; i++) { - AcceptedBinding acceptedType = (AcceptedBinding)this.acceptedTypes.elementAt(i); + AcceptedBinding acceptedType = (AcceptedBinding)this.acceptedBindings.elementAt(i); if (acceptedType.bindingType!=Binding.TYPE) continue; char[] packageName = acceptedType.packageName; @@ -689,91 +651,6 @@ public final class CompletionEngine fullyQualifiedName, true,scope); continue next; - -// } else { -// char[] fullyQualifiedEnclosingTypeOrPackageName = null; -// -// AcceptedBinding foundType = null; -// if((foundType = (AcceptedBinding)onDemandFound.get(simpleTypeName)) == null) { -// for (int j = 0; j < this.onDemandImportCacheCount; j++) { -// ImportBinding importBinding = this.onDemandImportsCache[j]; -// -// char[][] importName = importBinding.compoundName; -// char[] importFlatName = CharOperation.concatWith(importName, '.'); -// -// if(fullyQualifiedEnclosingTypeOrPackageName == null) { -// if(enclosingTypeNames != null && enclosingTypeNames.length != 0) { -// fullyQualifiedEnclosingTypeOrPackageName = -// CharOperation.concat( -// packageName, -// flatEnclosingTypeNames, -// '.'); -// } else { -// fullyQualifiedEnclosingTypeOrPackageName = -// packageName; -// } -// } -// if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) { -// if(importBinding.isStatic()) { -// if((modifiers & ClassFileConstants.AccStatic) != 0) { -// acceptedType.qualifiedTypeName = typeName; -// acceptedType.fullyQualifiedName = fullyQualifiedName; -// onDemandFound.put( -// simpleTypeName, -// acceptedType); -// continue next; -// } -// } else { -// acceptedType.qualifiedTypeName = typeName; -// acceptedType.fullyQualifiedName = fullyQualifiedName; -// onDemandFound.put( -// simpleTypeName, -// acceptedType); -// continue next; -// } -// } -// } -// } else if(!foundType.mustBeQualified){ -// done : for (int j = 0; j < this.onDemandImportCacheCount; j++) { -// ImportBinding importBinding = this.onDemandImportsCache[j]; -// -// char[][] importName = importBinding.compoundName; -// char[] importFlatName = CharOperation.concatWith(importName, '.'); -// -// if(fullyQualifiedEnclosingTypeOrPackageName == null) { -// if(enclosingTypeNames != null && enclosingTypeNames.length != 0) { -// fullyQualifiedEnclosingTypeOrPackageName = -// CharOperation.concat( -// packageName, -// flatEnclosingTypeNames, -// '.'); -// } else { -// fullyQualifiedEnclosingTypeOrPackageName = -// packageName; -// } -// } -// if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) { -// if(importBinding.isStatic()) { -// if((modifiers & ClassFileConstants.AccStatic) != 0) { -// foundType.mustBeQualified = true; -// break done; -// } -// } else { -// foundType.mustBeQualified = true; -// break done; -// } -// } -// } -// } -// proposeType( -// packageName, -// simpleTypeName, -// modifiers, -// accessibility, -// typeName, -// fullyQualifiedName, -// true); -// } } } char[][] keys = onDemandFound.keyTable; @@ -794,7 +671,78 @@ public final class CompletionEngine } } } - this.acceptedTypes = null; // reset + this.acceptedBindings = null; // reset + } + + /** + * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptConstructor( + * int, char[], int, char[][], char[][], java.lang.String, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction) + */ + public void acceptConstructor( + int modifiers, + char[] typeName, + int parameterCount, + char[][] parameterTypes, + char[][] parameterNames, + String path, + AccessRestriction accessRestriction) { + + int accessibility = IAccessRule.K_ACCESSIBLE; + if(accessRestriction != null) { + switch (accessRestriction.getProblemId()) { + case IProblem.ForbiddenReference: + if (this.options.checkForbiddenReference) { + return; + } + accessibility = IAccessRule.K_NON_ACCESSIBLE; + break; + case IProblem.DiscouragedReference: + if (this.options.checkDiscouragedReference) { + return; + } + accessibility = IAccessRule.K_DISCOURAGED; + break; + } + } + + if(this.acceptedConstructors == null) { + this.acceptedConstructors = new ObjectVector(); + } + this.acceptedConstructors.add( + new AcceptedConstructor( + modifiers, + typeName, + parameterCount, + parameterTypes, + parameterNames, + accessibility)); + } + + /** + * <p>Creates proposals for all of the constructors accepted by + * {@link #acceptConstructor(int, char[], int, char[][], char[][], String, AccessRestriction)}.</p> + * + * @see #acceptConstructor(int, char[], int, char[][], char[][], String, AccessRestriction) + */ + private void acceptConstructors() { + int length; + if(this.acceptedConstructors != null && (length = this.acceptedConstructors.size()) > 0) { + for (int i = 0; i < length; i++) { + AcceptedConstructor acceptedConstructor = (AcceptedConstructor)this.acceptedConstructors.elementAt(i); + + //decide if constructor should be proposed based on visibility rules + boolean proposeConstructor = true; + if (this.options.checkVisibility) { + final int modifiers = acceptedConstructor.modifiers; + proposeConstructor = !(((modifiers & ClassFileConstants.AccPublic) == 0) && + ((modifiers & ClassFileConstants.AccPrivate) != 0)); + } + + if (proposeConstructor) { + proposeConstructor(acceptedConstructor); + } + } + } } public void acceptUnresolvedName(char[] name) { @@ -823,21 +771,28 @@ public final class CompletionEngine } + /** + * <p>When doing an index search for bindings this is where the results end up.</p> + * + * @param name the name of the binding + * @param exactMatch <code>true</code> if an exact match is needed, <code>false</code> otherwise + * @param prefixRequired + */ private void acceptBindings(char[] name,boolean exactMatch, boolean prefixRequired) { - if(this.acceptedTypes == null) return; + + if(this.acceptedBindings == null) return; - int length = this.acceptedTypes.size(); + int length = this.acceptedBindings.size(); if(length == 0) return; for (int i = 0; i < length; i++) { - AcceptedBinding acceptedType = (AcceptedBinding)this.acceptedTypes.elementAt(i); + AcceptedBinding acceptedType = (AcceptedBinding)this.acceptedBindings.elementAt(i); char[] packageName = acceptedType.packageName; char[] bindingName = acceptedType.simpleTypeName; char[][] enclosingTypeNames = acceptedType.enclosingTypeNames; int modifiers = acceptedType.modifiers; -// int accessibility = acceptedType.accessibility; if (packageName==null) packageName=new char[0]; @@ -873,24 +828,25 @@ public final class CompletionEngine if (binding2 instanceof MethodBinding && binding2.isValidBinding()) { MethodBinding method = (MethodBinding) binding2; + + int relevance = computeBaseRelevance(); relevance += computeRelevanceForInterestingProposal(); if (name != null) relevance += computeRelevanceForCaseMatching(name, bindingName); relevance += computeRelevanceForExpectingType(method.returnType); -// relevance += computeRelevanceForStatic(onlyStaticMethods, method.isStatic()); relevance += computeRelevanceForQualification(prefixRequired); relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); - + + //figure out the parameters int parametersLength=method.original().parameters.length; char[][] parameterPackageNames = new char[parametersLength][]; - char[][] parameterTypeNames = new char[parametersLength][]; - + char[][] parameterFullTypeNames = new char[parametersLength][]; for (int j = 0; j < parametersLength; j++) { - TypeBinding type = method.original().parameters[j]; - parameterPackageNames[i] = type.qualifiedPackageName(); - parameterTypeNames[i] = type.qualifiedSourceName(); + TypeBinding type = method.parameters[j]; + parameterPackageNames[j] = type.qualifiedPackageName(); + parameterFullTypeNames[j] = type.qualifiedSourceName(); } -// char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); + char[][] parameterNames = findMethodParameterNames(method, parameterFullTypeNames); this.noProposal = false; // Standard proposal @@ -905,7 +861,7 @@ public final class CompletionEngine proposal.setDeclarationPackageName(packageName); proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); proposal.setParameterPackageNames(parameterPackageNames); - proposal.setParameterTypeNames(parameterTypeNames); + proposal.setParameterTypeNames(parameterFullTypeNames); if(method.returnType!=null) { proposal.setPackageName(method.returnType.qualifiedPackageName()); @@ -920,7 +876,8 @@ public final class CompletionEngine proposal.setFlags(modifiers); proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); proposal.setRelevance(relevance); - if(enclosingTypeNames != null) proposal.setParameterNames(enclosingTypeNames); + if(parameterNames != null) proposal.setParameterNames(parameterNames); + proposal.setIsContructor(method.isConstructor()); this.requestor.accept(proposal); if(DEBUG) { this.printDebug(proposal); @@ -940,7 +897,7 @@ public final class CompletionEngine proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); proposal.setParameterPackageNames(parameterPackageNames); - proposal.setParameterTypeNames(parameterTypeNames); + proposal.setParameterTypeNames(parameterFullTypeNames); proposal.setPackageName(method.returnType.qualifiedPackageName()); proposal.setTypeName(method.returnType.qualifiedSourceName()); proposal.setName(bindingName); @@ -949,22 +906,19 @@ public final class CompletionEngine int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); proposal.setRelevance(relevance+R_INLINE_TAG); - if(enclosingTypeNames != null) proposal.setParameterNames(enclosingTypeNames); + if(parameterNames != null) proposal.setParameterNames(parameterNames); + proposal.setIsContructor(method.isConstructor()); this.requestor.accept(proposal); if(DEBUG) { this.printDebug(proposal); } } - - - } + }//end if method binding else { int relevance = computeBaseRelevance(); relevance += computeRelevanceForInterestingProposal(); if (name != null) relevance += computeRelevanceForCaseMatching(name, bindingName); -// relevance += computeRelevanceForExpectingType(method.returnType); -// relevance += computeRelevanceForStatic(onlyStaticMethods, method.isStatic()); relevance += computeRelevanceForQualification(prefixRequired); relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); @@ -973,19 +927,8 @@ public final class CompletionEngine // Standard proposal if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); -// proposal.setDeclarationSignature(getSignature(method.declaringClass)); -// proposal.setSignature(getSignature(method)); proposal.setSignature(defaultSignature); -// FunctionBinding original = method.original(); -// if(original != method) { -// proposal.setOriginalSignature(getSignature(original)); -// } proposal.setDeclarationPackageName(packageName); -// proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); -// proposal.setParameterPackageNames(parameterPackageNames); -// proposal.setParameterTypeNames(parameterTypeNames); -// proposal.setPackageName(method.returnType.qualifiedPackageName()); -// proposal.setTypeName(method.returnType.qualifiedSourceName()); proposal.setName(bindingName); proposal.setCompletion(completion); proposal.setFlags(modifiers); @@ -1002,18 +945,6 @@ public final class CompletionEngine if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_METHOD_REF)) { char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK); CompletionProposal proposal = this.createProposal(CompletionProposal.JSDOC_METHOD_REF, this.actualCompletionPosition); -// proposal.setDeclarationSignature(getSignature(method.declaringClass)); -// proposal.setSignature(getSignature(method)); -// FunctionBinding original = method.original(); -// if(original != method) { -// proposal.setOriginalSignature(getSignature(original)); -// } -// proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); -// proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); -// proposal.setParameterPackageNames(parameterPackageNames); -// proposal.setParameterTypeNames(parameterTypeNames); -// proposal.setPackageName(method.returnType.qualifiedPackageName()); -// proposal.setTypeName(method.returnType.qualifiedSourceName()); proposal.setName(bindingName); proposal.setCompletion(javadocCompletion); proposal.setFlags( modifiers); @@ -1044,7 +975,6 @@ public final class CompletionEngine relevance += computeRelevanceForInterestingProposal(variableBinding); if (name != null) relevance += computeRelevanceForCaseMatching(name, variableBinding.name); relevance += computeRelevanceForExpectingType(variableBinding.type); -// relevance += computeRelevanceForStatic(onlyStaticFields, field.isStatic()); relevance += computeRelevanceForQualification(prefixRequired); relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); @@ -1058,8 +988,6 @@ public final class CompletionEngine proposal.setDeclarationSignature(getSignature(compilationUnitScope.referenceContext.compilationUnitBinding)); } proposal.setSignature(getSignature(variableBinding.type)); -// proposal.setDeclarationPackageName(packageName); -// proposal.setDeclarationTypeName(variableBinding.declaringClass.qualifiedSourceName()); proposal.setDeclarationTypeName(packageName); proposal.setPackageName(variableBinding.type.qualifiedPackageName()); proposal.setTypeName(variableBinding.type.qualifiedSourceName()); @@ -1078,10 +1006,8 @@ public final class CompletionEngine if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_FIELD_REF)) { char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK); CompletionProposal proposal = this.createProposal(CompletionProposal.JSDOC_FIELD_REF, this.actualCompletionPosition); -// proposal.setDeclarationSignature(getSignature(variableBinding.declaringClass)); proposal.setSignature(getSignature(variableBinding.type)); proposal.setDeclarationPackageName(packageName); -// proposal.setDeclarationTypeName(variableBinding.declaringClass.qualifiedSourceName()); proposal.setPackageName(variableBinding.type.qualifiedPackageName()); proposal.setTypeName(variableBinding.type.qualifiedSourceName()); proposal.setName(variableBinding.name); @@ -1105,7 +1031,7 @@ public final class CompletionEngine break; } } - this.acceptedTypes = null; // reset + this.acceptedBindings = null; // reset } @@ -1141,6 +1067,137 @@ public final class CompletionEngine return false; return true; } + + /** + * <p>Propose a constructor based on an {@link AcceptedConstructor}.</p> + * + * @param acceptedConstructor {@link AcceptedConstructor} to create a proposal for + */ + private void proposeConstructor(AcceptedConstructor acceptedConstructor) { + proposeConstructor( + acceptedConstructor.typeName, + acceptedConstructor.parameterCount, + acceptedConstructor.parameterTypes, + acceptedConstructor.parameterNames, + acceptedConstructor.modifiers, + acceptedConstructor.accessibility); + } + + /** + * <p>Create a constructor proposal based on the given information.</p> + * + * @param typeName Name of the type the constructor is for + * @param parameterCount Number of parameters for the constructor, or -1 for a default constructor + * @param parameterTypes Type names of the parameters, should be same length as parameterCount + * @param parameterNames Type names of the parameters, should be same length as parameterCount + * @param modifiers Type names of the parameters, should be same length as parameterCount + * @param accessibility Accessibility of the constructor + * + * @see Flags + * @see IAccessRule + */ + private void proposeConstructor( + char[] typeName, + int parameterCount, + char[][] parameterTypes, + char[][] parameterNames, + int modifiers, + int accessibility) { + + int relevance = computeBaseRelevance(); + relevance += computeRelevanceForResolution(); + relevance += computeRelevanceForInterestingProposal(); + relevance += computeRelevanceForRestrictions(accessibility); + relevance += computeRelevanceForCaseMatching(this.completionToken, typeName); + relevance += computeRelevanceForClass(); + relevance += computeRelevanceForException(typeName); + + char[] completion; + if (this.source != null + && this.source.length > this.endPosition + && this.source[this.endPosition] == '(') { + completion = CharOperation.NO_CHAR; + } else { + completion = new char[] { '(', ')' }; + } + + //NOTE: currently all constructors are assumed to be public + int flags = modifiers; + flags |= Flags.AccPublic; + + switch (parameterCount) { + case -1: {// default constructor + flags = Flags.AccPublic; + this.noProposal = false; + if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) { + CompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition); + proposal.setDeclarationSignature(createNonGenericTypeSignature(typeName)); + proposal.setDeclarationTypeName(typeName); + proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR); + proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR); + proposal.setParameterNames(CharOperation.NO_CHAR_CHAR); + proposal.setName(typeName); + proposal.setIsContructor(true); + proposal.setCompletion(completion); + proposal.setFlags(flags); + proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); + proposal.setRelevance(relevance); + this.requestor.accept(proposal); + } + break; + } + case 0: {// constructor with no parameter + this.noProposal = false; + if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) { + CompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition); + proposal.setDeclarationSignature(createNonGenericTypeSignature(typeName)); + proposal.setDeclarationTypeName(typeName); + proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR); + proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR); + proposal.setParameterNames(CharOperation.NO_CHAR_CHAR); + proposal.setName(typeName); + proposal.setIsContructor(true); + proposal.setCompletion(completion); + proposal.setFlags(flags); + proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); + proposal.setRelevance(relevance); + this.requestor.accept(proposal); + + } + break; + } + default: {// constructor with parameter + int parameterNamesLength = parameterNames == null ? 0 : parameterNames.length; + if (parameterCount != parameterNamesLength) { + parameterNames = null; + } + + + this.noProposal = false; + if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) { + CompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition); + proposal.setDeclarationSignature(createNonGenericTypeSignature(typeName)); + proposal.setDeclarationTypeName(typeName); + proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR); + if(parameterTypes != null) { + proposal.setParameterTypeNames(parameterTypes); + } + if (parameterNames != null) { + proposal.setParameterNames(parameterNames); + } + proposal.setName(typeName); + proposal.setIsContructor(true); + proposal.setCompletion(completion); + proposal.setFlags(flags); + proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); + proposal.setRelevance(relevance); + + this.requestor.accept(proposal); + } + break; + } + } + } private void proposeType(char[] packageName, char[] simpleTypeName, int modifiers, int accessibility, char[] typeName, char[] fullyQualifiedName, boolean isQualified, Scope scope) { char[] completionName = fullyQualifiedName; @@ -1197,14 +1254,14 @@ public final class CompletionEngine // completion = packageName; // } -// int relevance = computeBaseRelevance(); -// relevance += computeRelevanceForResolution(); -// relevance += computeRelevanceForInterestingProposal(); -// relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, packageName); -// if(!this.resolvingImports) { -// relevance += computeRelevanceForQualification(true); -// } -// relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); + int relevance = computeBaseRelevance(); + relevance += computeRelevanceForResolution(); + relevance += computeRelevanceForInterestingProposal(); + relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, packageName); + if(!this.resolvingImports) { + relevance += computeRelevanceForQualification(true); + } + relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); this.noProposal = false; // if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { @@ -2462,18 +2519,6 @@ public final class CompletionEngine } return argTypes; } - -// private TypeBinding[] computeTypesIfCorrect(Expression[] arguments) { -// if (arguments == null) return null; -// int argsLength = arguments.length; -// TypeBinding[] argTypes = new TypeBinding[argsLength]; -// for (int a = argsLength; --a >= 0;) { -// TypeBinding typeBinding = arguments[a].resolvedType; -// if(typeBinding == null || !typeBinding.isValidBinding()) return null; -// argTypes[a] = typeBinding; -// } -// return argTypes; -// } private void findAnonymousType( ReferenceBinding currentType, @@ -2509,9 +2554,7 @@ public final class CompletionEngine CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); //proposal.setDeclarationSignature(null); char[] signature = - createNonGenericTypeSignature( - CharOperation.concatWith(JAVA_LANG, '.'), - CLASS); + createNonGenericTypeSignature(CLASS); if (this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4) { // add type argument char[] typeArgument = getTypeSignature(receiverType); @@ -2852,7 +2895,16 @@ public final class CompletionEngine } char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames); - char[] completion = CharOperation.NO_CHAR; + char[] bindingName = constructor.selector; + char[] completion = bindingName; + if (this.source != null + && this.source.length > this.endPosition + && this.source[this.endPosition] == '(') { + completion = bindingName; + } else { + completion = CharOperation.concat(bindingName, new char[] { '(', ')' }); + } + if(forAnonymousType){ int relevance = computeBaseRelevance(); relevance += computeRelevanceForResolution(); @@ -2959,14 +3011,11 @@ public final class CompletionEngine proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); proposal.setParameterPackageNames(parameterPackageNames); proposal.setParameterTypeNames(parameterTypeNames); - //proposal.setPackageName(null); - //proposal.setTypeName(null); proposal.setName(currentType.sourceName()); proposal.setIsContructor(true); proposal.setCompletion(completion); proposal.setFlags(constructor.modifiers); - int start = (this.assistNodeInJavadoc > 0) ? this.startPosition : this.endPosition; - proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); + proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); proposal.setRelevance(relevance); if(parameterNames != null) proposal.setParameterNames(parameterNames); this.requestor.accept(proposal); @@ -3009,37 +3058,6 @@ public final class CompletionEngine } } -// private char[][] findEnclosingTypeNames(Scope scope){ -// char[][] excludedNames = new char[10][]; -// int excludedNameCount = 0; -// -// Scope currentScope = scope; -// while(currentScope != null) { -// switch (currentScope.kind) { -// case Scope.CLASS_SCOPE : -// ClassScope classScope = (ClassScope) currentScope; -// -// TypeDeclaration typeDeclaration = classScope.referenceContext; -// -// if(excludedNameCount == excludedNames.length) { -// System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount); -// } -// excludedNames[excludedNameCount++] = typeDeclaration.name; -// break; -// case Scope.METHOD_SCOPE : -// break; -// } -// -// currentScope = currentScope.parent; -// } -// -// if(excludedNameCount == 0) { -// return CharOperation.NO_CHAR_CHAR; -// } -// System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount][], 0, excludedNameCount); -// return excludedNames; -// } - // Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean) private void findFields( char[] fieldName, @@ -3291,135 +3309,14 @@ public final class CompletionEngine boolean proposeMethod = !this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null); ObjectVector methodsFound = new ObjectVector(); - -// if (receiverType.isArrayType()) { -// if (proposeField -// && token.length <= lengthField.length -// && CharOperation.prefixEquals(token, lengthField, false /* ignore case */ -// )) { -// -// int relevance = computeBaseRelevance(); -// relevance += computeRelevanceForResolution(); -// relevance += computeRelevanceForInterestingProposal(); -// relevance += computeRelevanceForCaseMatching(token,lengthField); -// relevance += computeRelevanceForExpectingType(TypeBinding.INT); -// relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for length field -// if (missingElements != null) { -// relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); -// } -// this.noProposal = false; -// if(!isIgnored(CompletionProposal.FIELD_REF, missingElements != null)) { -// CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); -// proposal.setDeclarationSignature(getSignature(receiverType)); -// proposal.setSignature(INT_SIGNATURE); -// //proposal.setDeclarationPackageName(null); -// //proposal.setDeclarationTypeName(null); -// //proposal.setPackageName(null); -// proposal.setTypeName(INT); -// proposal.setName(lengthField); -// if (missingElements != null) { -// CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; -// for (int i = 0; i < missingElements.length; i++) { -// subProposals[i] = -// createRequiredTypeProposal( -// missingElements[i], -// missingElementsStarts[i], -// missingElementsEnds[i], -// relevance); -// } -// proposal.setRequiredProposals(subProposals); -// } -// proposal.setCompletion(lengthField); -// proposal.setFlags(Flags.AccPublic); -// proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); -// proposal.setRelevance(relevance); -// this.requestor.accept(proposal); -// if(DEBUG) { -// this.printDebug(proposal); -// } -// } -// } -// if (proposeMethod -// && token.length <= cloneMethod.length -// && CharOperation.prefixEquals(token, cloneMethod, false /* ignore case */) -// ) { -// ReferenceBinding objectRef = scope.getJavaLangObject(); -// -// int relevance = computeBaseRelevance(); -// relevance += computeRelevanceForResolution(); -// relevance += computeRelevanceForInterestingProposal(); -// relevance += computeRelevanceForCaseMatching(token, cloneMethod); -// relevance += computeRelevanceForExpectingType(objectRef); -// relevance += computeRelevanceForStatic(false, false); -// relevance += computeRelevanceForQualification(false); -// relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for clone() method -// if (missingElements != null) { -// relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); -// } -// char[] completion; -// if (this.source != null -// && this.source.length > this.endPosition -// && this.source[this.endPosition] == '(') { -// completion = cloneMethod; -// } else { -// completion = CharOperation.concat(cloneMethod, new char[] { '(', ')' }); -// } -// this.noProposal = false; -// if (!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null)) { -// CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); -// proposal.setDeclarationSignature(getSignature(receiverType)); -// proposal.setSignature( -// this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4 && receiverType.isArrayType() ? -// createMethodSignature( -// CharOperation.NO_CHAR_CHAR, -// CharOperation.NO_CHAR_CHAR, -// getSignature(receiverType)) : -// createMethodSignature( -// CharOperation.NO_CHAR_CHAR, -// CharOperation.NO_CHAR_CHAR, -// CharOperation.concatWith(JAVA_LANG, '.'), -// OBJECT)); -// //proposal.setOriginalSignature(null); -// //proposal.setDeclarationPackageName(null); -// //proposal.setDeclarationTypeName(null); -// //proposal.setParameterPackageNames(null); -// //proposal.setParameterTypeNames(null); -// proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.')); -// proposal.setTypeName(OBJECT); -// proposal.setName(cloneMethod); -// if (missingElements != null) { -// CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; -// for (int i = 0; i < missingElements.length; i++) { -// subProposals[i] = -// createRequiredTypeProposal( -// missingElements[i], -// missingElementsStarts[i], -// missingElementsEnds[i], -// relevance); -// } -// proposal.setRequiredProposals(subProposals); -// } -// proposal.setCompletion(completion); -// proposal.setFlags(Flags.AccPublic); -// proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); -// proposal.setRelevance(relevance); -// this.requestor.accept(proposal); -// if(DEBUG) { -// this.printDebug(proposal); -// } -// } -// methodsFound.add(new Object[]{objectRef.getMethods(cloneMethod)[0], objectRef}); -// } -// -// receiverType = scope.getJavaLangObject(); -// } - + ObjectVector fieldsFound = new ObjectVector(); + if(proposeField) { findFields( token, (ReferenceBinding) receiverType, scope, - new ObjectVector(), + fieldsFound, new ObjectVector(), staticsOnly, invocationSite, @@ -3536,7 +3433,7 @@ public final class CompletionEngine InvocationSite invocationSite, boolean insideTypeAnnotation) { -// boolean staticsOnly = false; + boolean staticsOnly = false; Scope currentScope = scope; done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found @@ -3544,10 +3441,10 @@ public final class CompletionEngine switch (currentScope.kind) { case Scope.METHOD_SCOPE : -// // handle the error case inside an explicit constructor call (see MethodScope>>findField) -// MethodScope methodScope = (MethodScope) currentScope; -// staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; -// + // handle the error case inside an explicit constructor call (see MethodScope>>findField) + MethodScope methodScope = (MethodScope) currentScope; + staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; + case Scope.BLOCK_SCOPE : break; @@ -3574,7 +3471,7 @@ public final class CompletionEngine } } } -// staticsOnly |= enclosingType.isStatic(); + staticsOnly |= enclosingType.isStatic(); insideTypeAnnotation = false; break; case Scope.COMPILATION_UNIT_SCOPE : @@ -3591,7 +3488,7 @@ public final class CompletionEngine InvocationSite invocationSite, boolean insideTypeAnnotation) { -// boolean staticsOnly = false; + boolean staticsOnly = false; Scope currentScope = scope; done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found @@ -3599,10 +3496,10 @@ public final class CompletionEngine switch (currentScope.kind) { case Scope.METHOD_SCOPE : -// // handle the error case inside an explicit constructor call (see MethodScope>>findField) -// MethodScope methodScope = (MethodScope) currentScope; -// staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; -// + // handle the error case inside an explicit constructor call (see MethodScope>>findField) + MethodScope methodScope = (MethodScope) currentScope; + staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; + case Scope.BLOCK_SCOPE : break; @@ -3654,7 +3551,7 @@ public final class CompletionEngine } } } -// staticsOnly |= enclosingType.isStatic(); + staticsOnly |= enclosingType.isStatic(); insideTypeAnnotation = false; break; case Scope.COMPILATION_UNIT_SCOPE : @@ -3912,136 +3809,6 @@ public final class CompletionEngine } } -// private void findImportsOfStaticFields(char[] fieldName, ReferenceBinding ref) { -// FieldBinding[] fields = ref.fields(); -// -// int fieldLength = fieldName.length; -// next : for (int m = fields.length; --m >= 0;) { -// FieldBinding field = fields[m]; -// -// if (fieldLength > field.name.length) -// continue next; -// -// if (!field.isStatic()) -// continue next; -// -// if (!CharOperation.prefixEquals(fieldName, field.name, false/* ignore case */) -// && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) -// continue next; -// -// if (this.options.checkDeprecation && field.isViewedAsDeprecated()) continue next; -// -// if (this.options.checkVisibility -// && !field.canBeSeenBy(this.unitScope.getDefaultPackage())) -// continue next; -// -// char[] completionName = CharOperation.concat(field.name, SEMICOLON); -// -// int relevance = computeBaseRelevance(); -// relevance += computeRelevanceForResolution(); -// relevance += computeRelevanceForInterestingProposal(); -// relevance += computeRelevanceForCaseMatching(fieldName, field.name); -// relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); -// -// this.noProposal = false; -// if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { -// CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); -// proposal.setDeclarationSignature(getSignature(field.declaringClass)); -// proposal.setSignature(getSignature(field.type)); -// proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); -// proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); -// proposal.setPackageName(field.type.qualifiedPackageName()); -// proposal.setTypeName(field.type.qualifiedSourceName()); -// proposal.setName(field.name); -// proposal.setCompletion(completionName); -// proposal.setFlags(field.modifiers); -// proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); -// proposal.setRelevance(relevance); -// this.requestor.accept(proposal); -// if(DEBUG) { -// this.printDebug(proposal); -// } -// } -// } -// } -// -// private void findImportsOfStaticMethods(char[] methodName, ReferenceBinding ref) { -// MethodBinding[] methods = ref.methods(); -// -// int methodLength = methodName.length; -// next : for (int m = methods.length; --m >= 0;) { -// MethodBinding method = methods[m]; -// -// if (method.isDefaultAbstract()) continue next; -// -// if (method.isConstructor()) continue next; -// -// if (!method.isStatic()) continue next; -// -// if (this.options.checkDeprecation && method.isViewedAsDeprecated()) continue next; -// -// if (this.options.checkVisibility -// && !method.canBeSeenBy(this.unitScope.getDefaultPackage())) continue next; -// -// if (methodLength > method.selector.length) -// continue next; -// -// if (!CharOperation.prefixEquals(methodName, method.selector, false/* ignore case */) -// && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) -// continue next; -// -// int length = method.parameters.length; -// char[][] parameterPackageNames = new char[length][]; -// char[][] parameterTypeNames = new char[length][]; -// -// for (int i = 0; i < length; i++) { -// TypeBinding type = method.original().parameters[i]; -// parameterPackageNames[i] = type.qualifiedPackageName(); -// parameterTypeNames[i] = type.qualifiedSourceName(); -// } -// char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); -// -// -// char[] completionName = CharOperation.concat( -// method.declaringClass.qualifiedPackageName(), -// '.', -// method.declaringClass.qualifiedSourceName(), -// '.', -// method.selector); -// -// completionName = CharOperation.concat(completionName, SEMICOLON); -// -// int relevance = computeBaseRelevance(); -// relevance += computeRelevanceForResolution(); -// relevance += computeRelevanceForInterestingProposal(); -// relevance += computeRelevanceForCaseMatching(methodName, method.selector); -// relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); -// -// this.noProposal = false; -// if(!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) { -// CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_NAME_REFERENCE, this.actualCompletionPosition); -// proposal.setDeclarationSignature(getSignature(method.declaringClass)); -// proposal.setSignature(getSignature(method)); -// proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); -// proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); -// proposal.setParameterPackageNames(parameterPackageNames); -// proposal.setParameterTypeNames(parameterTypeNames); -// proposal.setPackageName(method.returnType.qualifiedPackageName()); -// proposal.setTypeName(method.returnType.qualifiedSourceName()); -// proposal.setName(method.selector); -// proposal.setCompletion(completionName); -// proposal.setFlags(method.modifiers); -// proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); -// proposal.setRelevance(relevance); -// if(parameterNames != null) proposal.setParameterNames(parameterNames); -// this.requestor.accept(proposal); -// if(DEBUG) { -// this.printDebug(proposal); -// } -// } -// } -// } - /* * Find javadoc block tags for a given completion javadoc tag node */ @@ -4261,116 +4028,6 @@ public final class CompletionEngine findKeywords(token, keywords, false, false); } - // Helper method for findMemberTypes(char[], ReferenceBinding, Scope) -// private void findMemberTypes( -// char[] typeName, -// ReferenceBinding[] memberTypes, -// ObjectVector typesFound, -// ReferenceBinding receiverType, -// SourceTypeBinding invocationType, -// boolean staticOnly, -// boolean staticFieldsAndMethodOnly, -// boolean fromStaticImport, -// boolean checkQualification, -// Scope scope) { -// -// // Inherited member types which are hidden by subclasses are filtered out -// // No visibility checks can be performed without the scope & invocationSite -// int typeLength = typeName.length; -// next : for (int m = memberTypes.length; --m >= 0;) { -// ReferenceBinding memberType = memberTypes[m]; -// // if (!wantClasses && memberType.isClass()) continue next; -// // if (!wantInterfaces && memberType.isInterface()) continue next; -// -// if (staticOnly && !memberType.isStatic()) continue next; -// -// if (isForbidden(memberType)) continue next; -// -// if (typeLength > memberType.sourceName.length) -// continue next; -// -// if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false/* ignore case */) -// && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, memberType.sourceName))) -// continue next; -// -// if (this.options.checkDeprecation && -// memberType.isViewedAsDeprecated() && -// !scope.isDefinedInSameUnit(memberType)) -// continue next; -// -// if (this.options.checkVisibility) { -// if (invocationType != null && !memberType.canBeSeenBy(receiverType, invocationType)) { -// continue next; -// } else if(invocationType == null && !memberType.canBeSeenBy(this.unitScope.getDefaultPackage())) { -// continue next; -// } -// } -// -// for (int i = typesFound.size; --i >= 0;) { -// ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i); -// -// if (memberType == otherType) -// continue next; -// -// if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) { -// -// if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType())) -// continue next; -// } -// } -// -// typesFound.add(memberType); -// -// if(!this.insideQualifiedReference) { -// if(this.assistNodeIsClass) { -// if(!memberType.isClass()) continue next; -// } -// } -// -// char[] completionName = memberType.sourceName(); -// -// boolean isQualified = false; -// if(checkQualification && !fromStaticImport) { -// char[] memberPackageName = memberType.qualifiedPackageName(); -// char[] memberTypeName = memberType.sourceName(); -// char[] memberEnclosingTypeNames = memberType.enclosingType().qualifiedSourceName(); -// if (mustQualifyType(memberPackageName, memberTypeName, memberEnclosingTypeNames, memberType.modifiers)) { -// if (memberPackageName == null || memberPackageName.length == 0) -// if (this.unitScope != null && this.unitScope.getDefaultPackage().compoundName != CharOperation.NO_CHAR_CHAR) -// break next; // ignore types from the default package from outside it -// isQualified = true; -// completionName = -// CharOperation.concat( -// memberPackageName, -// CharOperation.concat( -// memberEnclosingTypeNames, -// memberTypeName, -// '.'), -// '.'); -// } -// } -// -// int relevance = computeBaseRelevance(); -// relevance += computeRelevanceForResolution(); -// relevance += computeRelevanceForInterestingProposal(); -// relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName); -// relevance += computeRelevanceForExpectingType(memberType); -// relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); -// if(!insideQualifiedReference) { -// relevance += computeRelevanceForQualification(isQualified); -// } -// if (staticFieldsAndMethodOnly && this.insideQualifiedReference) relevance += R_NON_INHERITED; // This criterion doesn't concern types and is added to be balanced with field and method relevance. -// -// if (memberType.isClass()) { -// relevance += computeRelevanceForClass(); -// relevance += computeRelevanceForException(memberType.sourceName); -// } -// -// this.noProposal = false; -// createTypeProposal(memberType, memberType.qualifiedSourceName(), IAccessRule.K_ACCESSIBLE, completionName, relevance); -// } -// } - private void findMemberTypes( char[] typeName, ReferenceBinding receiverType, @@ -4785,6 +4442,8 @@ public final class CompletionEngine proposal.setPackageName(method.returnType.qualifiedPackageName()); proposal.setTypeName(method.returnType.qualifiedSourceName()); proposal.setName(method.selector); + proposal.setIsContructor(method.isConstructor()); + if (missingElements != null) { CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; for (int i = 0; i < missingElements.length; i++) { @@ -5617,6 +5276,18 @@ public final class CompletionEngine if ((parsedType = ((CompilationUnitScope)sourceType.scope).referenceContext) != null){ AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method.original()); + if(methodDecl == null && method.isConstructor()) { + //if its a constructor we know the return type is the type the method is defined on + InferredType type = parsedType.findInferredType(method.returnType.qualifiedSourceName()); + if(type != null) { + InferredMethod infMethod = type.findMethod(method.selector, null); + + if(infMethod.getFunctionDeclaration() instanceof AbstractMethodDeclaration) { + methodDecl = (AbstractMethodDeclaration)infMethod.getFunctionDeclaration(); + } + } + } + if (methodDecl != null){ Argument[] arguments = methodDecl.arguments; parameterNames = new char[length][]; @@ -5786,43 +5457,31 @@ public final class CompletionEngine scope = scope.parent; } } - -// private void findPackages(CompletionOnPackageReference packageStatement) { -// -// this.completionToken = CharOperation.concatWith(packageStatement.tokens, '.'); -// if (this.completionToken.length == 0) -// return; -// -// setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd); -// this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this); -// } private void findTypesAndPackages(char[] token, Scope scope, ObjectVector typesFound) { if (token == null) return; - - // do not propose type if completion token is empty - boolean skip = false; - if (token.length == 0 && NO_TYPE_COMPLETION_ON_EMPTY_TOKEN) { - if(!assistNodeIsConstructor && (this.assistNodeInJavadoc & CompletionOnJavadoc.EXCEPTION) == 0) { - return; - } - skip = true; - } - + boolean proposeType = !this.requestor.isIgnored(CompletionProposal.TYPE_REF) || - ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_TYPE_REF)); + ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0); + boolean proposeAllMemberTypes = !this.assistNodeIsConstructor; + + boolean proposeConstructor = + this.assistNodeIsConstructor && + (!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)); + - if (!skip && proposeType && scope.enclosingSourceType() != null) { + if ((proposeType || proposeConstructor) && scope.enclosingSourceType() != null) { findNestedTypes(token, scope.enclosingSourceType(), scope, proposeAllMemberTypes, typesFound); } - boolean isEmptyPrefix = token.length == 0; + boolean isEmptyPrefix = token.length == 0; - if (!skip && proposeType && this.unitScope != null) { + if ((proposeType || proposeConstructor) && this.unitScope != null) { + ReferenceBinding outerInvocationType = scope.enclosingSourceType(); if(outerInvocationType != null) { ReferenceBinding temp = outerInvocationType.enclosingType(); @@ -5840,8 +5499,10 @@ public final class CompletionEngine if(isForbidden(sourceType)) continue next; - //@GINO: Anonymous UI Hide types - if( sourceType.isAnonymousType() )continue next; + //hide anonymous types + if( sourceType.isAnonymousType() ) { + continue next; + } if(proposeAllMemberTypes && sourceType != outerInvocationType) { @@ -5867,10 +5528,16 @@ public final class CompletionEngine char[] simpleName = CharOperation.subarray(sourceType.sourceName, index+1, sourceType.sourceName.length); if (!CharOperation.prefixEquals(token, simpleName, false) && !CharOperation.prefixEquals(token, sourceType.sourceName, false) - && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, simpleName))) continue ; + && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, simpleName))) { + + continue; + } } else if (!CharOperation.prefixEquals(token, sourceType.sourceName, false) - && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) continue ; + && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) { + + continue; + } for (int j = typesFound.size; --j >= 0;) { ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); @@ -5897,130 +5564,44 @@ public final class CompletionEngine relevance += computeRelevanceForException(sourceType.sourceName); } this.noProposal = false; - if(proposeType) { + if(proposeType && !this.assistNodeIsConstructor) { char[] typeName = sourceType.sourceName(); - createTypeProposal(sourceType, typeName, IAccessRule.K_ACCESSIBLE, typeName, relevance); + createTypeProposal( + sourceType, + typeName, + IAccessRule.K_ACCESSIBLE, + typeName, + relevance); + } + + if (proposeConstructor) { + findConstructors( + sourceType, + null, + scope, + FakeInvocationSite, + false); } } } if (isEmptyPrefix) { - if(proposeType && this.expectedTypesPtr > -1) { - next : for (int i = 0; i <= this.expectedTypesPtr; i++) { - if(this.expectedTypes[i] instanceof ReferenceBinding) { - ReferenceBinding refBinding = (ReferenceBinding)this.expectedTypes[i]; - - if (this.options.checkDeprecation && - refBinding.isViewedAsDeprecated() && - !scope.isDefinedInSameUnit(refBinding)) - continue next; - - int accessibility = IAccessRule.K_ACCESSIBLE; - if(refBinding.hasRestrictedAccess()) { - AccessRestriction accessRestriction = lookupEnvironment.getAccessRestriction(refBinding); - if(accessRestriction != null) { - switch (accessRestriction.getProblemId()) { - case IProblem.ForbiddenReference: - if (this.options.checkForbiddenReference) { - continue next; - } - accessibility = IAccessRule.K_NON_ACCESSIBLE; - break; - case IProblem.DiscouragedReference: - if (this.options.checkDiscouragedReference) { - continue next; - } - accessibility = IAccessRule.K_DISCOURAGED; - break; - } - } - } - - for (int j = 0; j < typesFound.size(); j++) { - ReferenceBinding typeFound = (ReferenceBinding)typesFound.elementAt(j); - if (typeFound == refBinding) { - continue next; - } - } - - boolean inSameUnit = this.unitScope.isDefinedInSameUnit(refBinding); - - // top level types of the current unit are already proposed. - if(skip || !inSameUnit || (inSameUnit && refBinding.isMemberType())) { - char[] packageName = refBinding.qualifiedPackageName(); - char[] typeName = refBinding.sourceName(); - char[] completionName = typeName; - - boolean isQualified = false; - if (!this.insideQualifiedReference && !refBinding.isMemberType()) { - if (mustQualifyType(packageName, typeName, null, refBinding.modifiers)) { - if (packageName == null || packageName.length == 0) - if (this.unitScope != null && this.unitScope.getDefaultPackage().compoundName != CharOperation.NO_CHAR_CHAR) - continue next; // ignore types from the default package from outside it - completionName = CharOperation.concat(packageName, typeName, '.'); - isQualified = true; - } - } - - if(this.assistNodeIsClass) { - if(!refBinding.isClass()) continue next; - } - - int relevance = computeBaseRelevance(); - relevance += computeRelevanceForResolution(); - relevance += computeRelevanceForInterestingProposal(); - relevance += computeRelevanceForCaseMatching(token, typeName); - relevance += computeRelevanceForExpectingType(refBinding); - relevance += computeRelevanceForQualification(isQualified); - relevance += computeRelevanceForRestrictions(accessibility); - - if(refBinding.isClass()) { - relevance += computeRelevanceForClass(); - relevance += computeRelevanceForException(typeName); - } - - this.noProposal = false; - if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { - CompletionProposal proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition); - proposal.setDeclarationSignature(packageName); - proposal.setSignature(getSignature(refBinding)); - proposal.setPackageName(packageName); - proposal.setTypeName(typeName); - proposal.setCompletion(completionName); - proposal.setFlags(refBinding.modifiers); - proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); - proposal.setRelevance(relevance); - proposal.setAccessibility(accessibility); - this.requestor.accept(proposal); - if(DEBUG) { - this.printDebug(proposal); - } - } - } - } - } - } - } else { - if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.KEYWORD)) { - if (this.assistNodeInJavadoc == 0 || (this.assistNodeInJavadoc & CompletionOnJavadoc.BASE_TYPES) != 0) { - findKeywords(token, BASE_TYPE_NAMES, false, false); - } + if (!proposeConstructor) { + findTypesFromExpectedTypes(token, scope, typesFound, proposeType, proposeConstructor); } - if(proposeType) { - int l = typesFound.size(); - for (int i = 0; i < l; i++) { - ReferenceBinding typeFound = (ReferenceBinding) typesFound.elementAt(i); - char[] fullyQualifiedTypeName = - CharOperation.concat( - typeFound.qualifiedPackageName(), - typeFound.qualifiedSourceName(), - '.'); - this.knownTypes.put(fullyQualifiedTypeName, this); - } + } else { + if (proposeConstructor) { + //search index for constructors that match + this.nameEnvironment.findConstructorDeclarations( + token, + this); + acceptConstructors(); + } else if (proposeType) { int searchFor = IJavaScriptSearchConstants.TYPE; if(this.assistNodeIsClass) { searchFor = IJavaScriptSearchConstants.CLASS; } + this.nameEnvironment.findTypes( token, proposeAllMemberTypes, @@ -6029,9 +5610,9 @@ public final class CompletionEngine this); acceptTypes(scope); } -// if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { -// this.nameEnvironment.findPackages(token, this); -// } + if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { + this.nameEnvironment.findPackages(token, this); + } } } @@ -6138,9 +5719,6 @@ public final class CompletionEngine this); acceptTypes(scope); } -// if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { -// this.nameEnvironment.findPackages(qualifiedName, this); -// } } private void findVariablesAndMethods( @@ -6371,6 +5949,8 @@ public final class CompletionEngine fieldsFound, methodsFound); } + + //propose methods from environment if token length is not 0 if (proposeMethod && token.length > 0) { this.nameEnvironment.findBindings( @@ -6380,6 +5960,8 @@ public final class CompletionEngine this); acceptBindings(token,false,false); } + + //propose fields from environment if token length is not 0 if (proposeField && token.length > 0) { this.nameEnvironment.findBindings( @@ -7349,7 +6931,7 @@ public final class CompletionEngine return true; } - public static char[] createNonGenericTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) { + public static char[] createNonGenericTypeSignature(char[] qualifiedTypeName) { return Signature.createCharArrayTypeSignature(qualifiedTypeName, true); } public static char[] createTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) { @@ -7427,7 +7009,7 @@ public final class CompletionEngine proposal.nameLookup = this.nameEnvironment.nameLookup; proposal.completionEngine = this; proposal.setDeclarationSignature(packageName); - proposal.setSignature(createNonGenericTypeSignature(packageName, typeName)); + proposal.setSignature(createNonGenericTypeSignature(typeName)); proposal.setPackageName(packageName); proposal.setTypeName(typeName); proposal.setCompletion(completionName); @@ -7448,7 +7030,7 @@ public final class CompletionEngine proposal.nameLookup = this.nameEnvironment.nameLookup; proposal.completionEngine = this; proposal.setDeclarationSignature(packageName); - proposal.setSignature(createNonGenericTypeSignature(packageName, typeName)); + proposal.setSignature(createNonGenericTypeSignature(typeName)); proposal.setPackageName(packageName); proposal.setTypeName(typeName); proposal.setCompletion(javadocCompletion); @@ -7728,4 +7310,273 @@ public final class CompletionEngine return currentToken; } + + private void findTypesFromExpectedTypes(char[] token, Scope scope, ObjectVector typesFound, boolean proposeType, boolean proposeConstructor) { + if(this.expectedTypesPtr > -1) { + int typeLength = token == null ? 0 : token.length; + + next : for (int i = 0; i <= this.expectedTypesPtr; i++) { + + if(this.expectedTypes[i] instanceof ReferenceBinding) { + ReferenceBinding refBinding = (ReferenceBinding)this.expectedTypes[i]; + + if (typeLength > 0) { + if (typeLength > refBinding.sourceName.length) continue next; + + if (!CharOperation.prefixEquals(token, refBinding.sourceName, false) + && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, refBinding.sourceName))) continue next; + } + + if (this.options.checkDeprecation && + refBinding.isViewedAsDeprecated() && + !scope.isDefinedInSameUnit(refBinding)) + continue next; + + int accessibility = IAccessRule.K_ACCESSIBLE; + if(refBinding.hasRestrictedAccess()) { + AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(refBinding); + if(accessRestriction != null) { + switch (accessRestriction.getProblemId()) { + case IProblem.ForbiddenReference: + if (this.options.checkForbiddenReference) { + continue next; + } + accessibility = IAccessRule.K_NON_ACCESSIBLE; + break; + case IProblem.DiscouragedReference: + if (this.options.checkDiscouragedReference) { + continue next; + } + accessibility = IAccessRule.K_DISCOURAGED; + break; + } + } + } + + for (int j = 0; j < typesFound.size(); j++) { + ReferenceBinding typeFound = (ReferenceBinding)typesFound.elementAt(j); + if (typeFound == refBinding) { + continue next; + } + } + + typesFound.add(refBinding); + + boolean inSameUnit = this.unitScope.isDefinedInSameUnit(refBinding); + + // top level types of the current unit are already proposed. + if(!inSameUnit || (inSameUnit && refBinding.isMemberType())) { + char[] packageName = refBinding.qualifiedPackageName(); + char[] typeName = refBinding.sourceName(); + char[] completionName = typeName; + + boolean isQualified = false; + if (!this.insideQualifiedReference && !refBinding.isMemberType()) { + if (mustQualifyType(packageName, typeName, null, refBinding.modifiers)) { + if (packageName == null || packageName.length == 0) + if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) + continue next; // ignore types from the default package from outside it + completionName = CharOperation.concat(packageName, typeName, '.'); + isQualified = true; + } + } + + if(this.assistNodeIsClass) { + if(!refBinding.isClass()) continue next; + } + + int relevance = computeBaseRelevance(); + relevance += computeRelevanceForResolution(); + relevance += computeRelevanceForInterestingProposal(); + relevance += computeRelevanceForCaseMatching(token, typeName); + relevance += computeRelevanceForExpectingType(refBinding); + relevance += computeRelevanceForQualification(isQualified); + relevance += computeRelevanceForRestrictions(accessibility); + + if(refBinding.isClass()) { + relevance += computeRelevanceForClass(); + relevance += computeRelevanceForException(typeName); + } + + if (proposeType && !this.assistNodeIsConstructor) { + this.noProposal = false; + if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { + CompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition); + proposal.setDeclarationSignature(packageName); + proposal.setSignature(getSignature(refBinding)); + proposal.setPackageName(packageName); + proposal.setTypeName(typeName); + proposal.setCompletion(completionName); + proposal.setFlags(refBinding.modifiers); + proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); + proposal.setRelevance(relevance); + proposal.setAccessibility(accessibility); + this.requestor.accept(proposal); + if(DEBUG) { + this.printDebug(proposal); + } + } + } + + if (proposeConstructor) { + findConstructors( + refBinding, + null, + scope, + FakeInvocationSite, + isQualified); + } + } + } + } + } + } + + private char[] getResolvedSignature(char[][] parameterTypes, char[] fullyQualifiedTypeName, int parameterCount, Scope scope) { + char[][] cn = CharOperation.splitOn('.', fullyQualifiedTypeName); + + TypeReference ref; + if (cn.length == 1) { + ref = new SingleTypeReference(cn[0], 0); + } else { + ref = new QualifiedTypeReference(cn,new long[cn.length]); + } + + TypeBinding guessedType = null; + switch (scope.kind) { + case Scope.COMPILATION_UNIT_SCOPE: + case Scope.METHOD_SCOPE : + case Scope.BLOCK_SCOPE : + guessedType = ref.resolveType((BlockScope)scope); + break; + case Scope.CLASS_SCOPE : + guessedType = ref.resolveType((ClassScope)scope); + break; + } + + + if (guessedType != null && guessedType.isValidBinding()) { + if (guessedType instanceof SourceTypeBinding) { + SourceTypeBinding refBinding = (SourceTypeBinding) guessedType; + + if (refBinding.scope == null || refBinding.classScope.referenceContext == null) return null; + + TypeDeclaration typeDeclaration = refBinding.classScope.referenceContext; + AbstractMethodDeclaration[] methods = typeDeclaration.methods; + + next : for (int i = 0; i < methods.length; i++) { + AbstractMethodDeclaration method = methods[i]; + + if (!method.isConstructor()) continue next; + + Argument[] arguments = method.arguments; + int argumentsLength = arguments == null ? 0 : arguments.length; + + if (parameterCount != argumentsLength) continue next; + + for (int j = 0; j < argumentsLength; j++) { + char[] argumentTypeName = getTypeName(arguments[j].type); + + if (!CharOperation.equals(argumentTypeName, parameterTypes[j])) { + continue next; + } + } + + refBinding.resolveTypesFor(method.binding); // force resolution + if (method.binding == null) continue next; + return getSignature(method.binding); + } + } + } + + return null; + } + + private static char[] getTypeName(TypeReference typeReference) { + char[] typeName = CharOperation.concatWith(typeReference.getTypeName(), '.'); + int dims = typeReference.dimensions(); + if (dims > 0) { + int length = typeName.length; + int newLength = length + (dims*2); + System.arraycopy(typeName, 0, typeName = new char[newLength], 0, length); + for (int k = length; k < newLength; k += 2) { + typeName[k] = '['; + typeName[k+1] = ']'; + } + } + + return typeName; + } + + /** + * <p>Represents a constructor accepted from the index.</p> + */ + private static class AcceptedConstructor { + /** + * <p>Modifiers to the constructor such as public/private</p> + * + * @see Flags + */ + public int modifiers; + + /** <p>Name of the type the constructor is for</p> */ + public char[] typeName; + + /** <p>Number of parameters for the constructor, or -1 for a default constructor</p> */ + public int parameterCount; + + /** <p>Type names of the parameters, should be same length as <code>parameterCount</code></p> */ + public char[][] parameterTypes; + + /** <p>Names of the parameters, should be same length as <code>parameterCount</code></p> */ + public char[][] parameterNames; + + /** + * <p>Accessibility of the constructor</p> + * + * @see IAccessRule + */ + public int accessibility; + + /** + * <p>Constructor</p> + * + * @param modifiers Modifiers to the constructor such as public/private + * @param typeName Name of the type the constructor is for + * @param parameterCount Number of parameters for the constructor, or -1 for a default constructor + * @param parameterTypes Type names of the parameters, should be same length as <code>parameterCount</code> + * @param parameterNames Names of the parameters, should be same length as <code>parameterCount</code> + * @param accessibility Accessibility of the constructor + * + * @see Flags + * @see IAccessRule + */ + private AcceptedConstructor( + int modifiers, + char[] typeName, + int parameterCount, + char[][] parameterTypes, + char[][] parameterNames, + int accessibility) { + + this.modifiers = modifiers; + this.typeName = typeName; + this.parameterCount = parameterCount; + this.parameterTypes = parameterTypes; + this.parameterNames = parameterNames; + this.accessibility = accessibility; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append('{'); + buffer.append(','); + buffer.append(this.typeName); + buffer.append('}'); + return buffer.toString(); + } + } } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISearchRequestor.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISearchRequestor.java index 32e1993d..d9a0c987 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISearchRequestor.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISearchRequestor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,6 +10,8 @@ *******************************************************************************/ package org.eclipse.wst.jsdt.internal.codeassist; +import org.eclipse.wst.jsdt.core.Flags; +import org.eclipse.wst.jsdt.core.IAccessRule; import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction; /** @@ -31,16 +33,6 @@ public interface ISearchRequestor { public void acceptType(char[] packageName, char [] fileName, char[] typeName, char[][] enclosingTypeNames, int modifiers, AccessRestriction accessRestriction); public void acceptBinding(char[] packageName, char [] fileName, char[] bindingName, int bindingType, int modifiers, AccessRestriction accessRestriction); -// /** -// * One result of the search consists of a new class. -// * -// * NOTE - All package and type names are presented in their readable form: -// * Package names are in the form "a.b.c". -// * Nested type names are in the qualified form "A.M". -// * The default package is represented by an empty array. -// */ -// public void acceptClass(char[] packageName, char[] typeName, int modifiers, AccessRestriction accessRestriction); - /** * One result of the search consists of a new package. * @@ -49,4 +41,27 @@ public interface ISearchRequestor { * The default package is represented by an empty array. */ public void acceptPackage(char[] packageName); + + /** + * <p>Accepts a constructor found during an index search.</p> + * + * @param modifiers Modifiers to the constructor such as public/private + * @param typeName Name of the type the constructor is for + * @param parameterCount Number of parameters for the constructor, or -1 for a default constructor + * @param parameterTypes Type names of the parameters, should be same length as <code>parameterCount</code> + * @param parameterNames Names of the parameters, should be same length as <code>parameterCount</code> + * @param path to the document containing the constructor match + * @param access Accessibility of the constructor + * + * @see Flags + * @see IAccessRule + */ + public void acceptConstructor( + int modifiers, + char[] typeName, + int parameterCount, + char[][] parameterTypes, + char[][] parameterNames, + String path, + AccessRestriction access); } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/MissingTypesGuesser.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/MissingTypesGuesser.java index c3b20c62..b38679cd 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/MissingTypesGuesser.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/MissingTypesGuesser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2009 IBM Corporation and others. + * Copyright (c) 2007, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -320,8 +320,18 @@ public class MissingTypesGuesser extends ASTVisitor { results.add(compoundName); } public void acceptBinding(char[] packageName, char[] fileName, char[] bindingName, int bindingType, int modifiers, AccessRestriction accessRestriction) { - // TODO Auto-generated method stub - + //do nothing + } + + /** + * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptConstructor( + * int, char[], int, char[][], char[][], java.lang.String, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction) + */ + public void acceptConstructor(int modifiers, char[] typeName, + int parameterCount, char[][] parameterTypes, char[][] parameterNames, + String path, AccessRestriction access) { + + //do nothing } }; diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/SelectionEngine.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/SelectionEngine.java index a31a9c95..69577239 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/SelectionEngine.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/SelectionEngine.java @@ -291,6 +291,18 @@ public final class SelectionEngine extends Engine implements ISearchRequestor { public void acceptPackage(char[] packageName) { // implementation of interface method } + + /** + * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptConstructor( + * int, char[], int, char[][], char[][], java.lang.String, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction) + */ + public void acceptConstructor(int modifiers, char[] typeName, + int parameterCount, char[][] parameterTypes, + char[][] parameterNames, String path, + AccessRestriction access) { + + // do nothing + } private void acceptQualifiedTypes() { if(this.acceptedClasses != null){ diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMemberAccess.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMemberAccess.java index fdf5fad5..17cf18ce 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMemberAccess.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMemberAccess.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -105,4 +105,14 @@ public class CompletionOnMemberAccess extends FieldReference { public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) { throw new CompletionNodeFound(this, scope); } + + /** + * + * @return <code>true</code> because this node is special because it is a completion node + * + * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#isSpecialNode() + */ + public boolean isSpecialNode() { + return true; + } } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java index 4d12a159..e8d7eb5e 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -24,6 +24,7 @@ package org.eclipse.wst.jsdt.internal.codeassist.complete; * which should be replaced by the completion. */ +import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode; import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference; import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope; @@ -32,81 +33,108 @@ import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope; import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding; public class CompletionOnSingleTypeReference extends SingleTypeReference { -public static final int K_TYPE = 0; -public static final int K_CLASS = 1; -public static final int K_INTERFACE = 2; -public static final int K_EXCEPTION = 3; - -private int kind = K_TYPE; -public boolean isCompletionNode; -public boolean isConstructorType; -public CompletionOnFieldType fieldTypeCompletionNode; - -public CompletionOnSingleTypeReference(char[] source, long pos) { - this(source, pos, K_TYPE); -} -public CompletionOnSingleTypeReference(char[] source, long pos, int kind) { - super(source, pos); - isCompletionNode = true; - this.kind = kind; -} -public void aboutToResolve(Scope scope) { - getTypeBinding(scope); -} -/* - * No expansion of the completion reference into an array one - */ -public TypeReference copyDims(int dim){ - return this; -} -protected TypeBinding getTypeBinding(Scope scope) { - if (this.fieldTypeCompletionNode != null) { - throw new CompletionNodeFound(this.fieldTypeCompletionNode, scope); - } - if(isCompletionNode) { + public static final int K_TYPE = 0; + public static final int K_CLASS = 1; + public static final int K_INTERFACE = 2; + public static final int K_EXCEPTION = 3; + + private int kind = K_TYPE; + public boolean isCompletionNode; + public boolean isConstructorType; + public CompletionOnFieldType fieldTypeCompletionNode; + + public CompletionOnSingleTypeReference(char[] source, long pos) { + this(source, pos, K_TYPE); + } + public CompletionOnSingleTypeReference(char[] source, long pos, int kind) { + super(source, pos); + isCompletionNode = true; + this.kind = kind; + } + public void aboutToResolve(Scope scope) { + getTypeBinding(scope); + } + /* + * No expansion of the completion reference into an array one + */ + public TypeReference copyDims(int dim){ + return this; + } + protected TypeBinding getTypeBinding(Scope scope) { + if (this.fieldTypeCompletionNode != null) { + throw new CompletionNodeFound(this.fieldTypeCompletionNode, scope); + } + if(isCompletionNode) { + throw new CompletionNodeFound(this, scope); + } else { + return super.getTypeBinding(scope); + } + } + public boolean isClass(){ + return this.kind == K_CLASS; + } + public boolean isInterface(){ + return this.kind == K_INTERFACE; + } + public boolean isException(){ + return this.kind == K_EXCEPTION; + } + public boolean isSuperType(){ + return this.kind == K_CLASS || this.kind == K_INTERFACE; + } + + public StringBuffer printExpression(int indent, StringBuffer output){ + switch (this.kind) { + case K_CLASS : + output.append("<CompleteOnClass:");//$NON-NLS-1$ + break; + case K_INTERFACE : + output.append("<CompleteOnInterface:");//$NON-NLS-1$ + break; + case K_EXCEPTION : + output.append("<CompleteOnException:");//$NON-NLS-1$ + break; + default : + output.append("<CompleteOnType:");//$NON-NLS-1$ + break; + } + return output.append(token).append('>'); + } + + public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) { + if (this.fieldTypeCompletionNode != null) { + throw new CompletionNodeFound(this.fieldTypeCompletionNode, scope); + } + if(isCompletionNode) { + throw new CompletionNodeFound(this, enclosingType, scope); + } else { + return super.resolveTypeEnclosing(scope, enclosingType); + } + } + + /** + * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#resolve(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope) + */ + public void resolve(BlockScope scope) { + super.resolve(scope); + throw new CompletionNodeFound(this, scope); - } else { - return super.getTypeBinding(scope); } -} -public boolean isClass(){ - return this.kind == K_CLASS; -} -public boolean isInterface(){ - return this.kind == K_INTERFACE; -} -public boolean isException(){ - return this.kind == K_EXCEPTION; -} -public boolean isSuperType(){ - return this.kind == K_CLASS || this.kind == K_INTERFACE; -} - -public StringBuffer printExpression(int indent, StringBuffer output){ - switch (this.kind) { - case K_CLASS : - output.append("<CompleteOnClass:");//$NON-NLS-1$ - break; - case K_INTERFACE : - output.append("<CompleteOnInterface:");//$NON-NLS-1$ - break; - case K_EXCEPTION : - output.append("<CompleteOnException:");//$NON-NLS-1$ - break; - default : - output.append("<CompleteOnType:");//$NON-NLS-1$ - break; + + /** + * @see org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference#resolveType(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope, boolean) + */ + public TypeBinding resolveType(BlockScope scope, boolean checkBounds) { + super.resolveType(scope, checkBounds); + + throw new CompletionNodeFound(this, scope); } - return output.append(token).append('>'); -} -public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) { - if (this.fieldTypeCompletionNode != null) { - throw new CompletionNodeFound(this.fieldTypeCompletionNode, scope); - } - if(isCompletionNode) { - throw new CompletionNodeFound(this, enclosingType, scope); - } else { - return super.resolveTypeEnclosing(scope, enclosingType); + + /** + * + * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#resolveForAllocation(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) + */ + public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) { + return this.resolveType(scope); } } -} diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionParser.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionParser.java index cfb795f8..ad21bd1a 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionParser.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionParser.java @@ -20,6 +20,9 @@ package org.eclipse.wst.jsdt.internal.codeassist.complete; * n means completion behind the n-th character */ +import org.eclipse.wst.jsdt.core.ast.IExpression; +import org.eclipse.wst.jsdt.core.ast.IFieldReference; +import org.eclipse.wst.jsdt.core.ast.ISingleNameReference; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser; import org.eclipse.wst.jsdt.internal.codeassist.impl.Keywords; @@ -3283,18 +3286,46 @@ protected JavadocParser createJavadocParser() { return new CompletionJavadocParser(this); } -public void createAssistTypeForAllocation(AllocationExpression expression) { - Expression member = expression.member; - if (member instanceof SingleNameReference) { - SingleNameReference snr = (SingleNameReference) member; - long position = (((long)snr.sourceStart)<<32)+snr.sourceEnd; - expression.member= new CompletionOnSingleTypeName(snr.token,position); - } - else - if (member instanceof CompletionOnQualifiedNameReference) { - CompletionOnQualifiedNameReference qnr = (CompletionOnQualifiedNameReference) member; - expression.member=new CompletionOnQualifiedType(qnr.tokens,qnr.completionIdentifier, qnr.sourcePositions); + /** + * @see org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser#createAssistTypeForAllocation(org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression) + */ + public void createAssistTypeForAllocation(AllocationExpression expression) { + Expression member = expression.member; + + /* create a CompletionOnSingleTypeReference from the existing + * member expression for the given allocation expression + */ + if (member instanceof SingleNameReference) { + SingleNameReference snr = (SingleNameReference) member; + long position = (((long)snr.sourceStart)<<32)+snr.sourceEnd; + expression.member= new CompletionOnSingleTypeReference(snr.token,position); + ((CompletionOnSingleTypeReference)expression.member).isConstructorType = true; } -} + else if(member instanceof CompletionOnMemberAccess) { + CompletionOnMemberAccess memberAccess = (CompletionOnMemberAccess) member; + + //iterate over the receivers to build the token and find the start of the expression + IExpression receiver = memberAccess.getReceiver(); + String token = new String(memberAccess.getToken()); + int start = memberAccess.sourceStart(); + while(receiver != null) { + start = receiver.sourceStart(); + if(receiver instanceof IFieldReference) { + IFieldReference ref = (IFieldReference)receiver; + token = new String(ref.getToken()) + "." + token; + receiver = ref.getReceiver(); + } else if(receiver instanceof ISingleNameReference) { + ISingleNameReference ref = (ISingleNameReference)receiver; + token = new String(ref.getToken()) + "." + token; + receiver = null; + } + } + + //create and set the CompletionOnSingleTypeReference + long position = (((long)start)<<32)+memberAccess.sourceEnd; + expression.member = new CompletionOnSingleTypeReference(token.toCharArray(), position); + ((CompletionOnSingleTypeReference)expression.member).isConstructorType = true; + } + } } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceElementParser.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceElementParser.java index a9399e40..ea51584f 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceElementParser.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceElementParser.java @@ -15,6 +15,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import org.eclipse.wst.jsdt.core.ast.IExpression; +import org.eclipse.wst.jsdt.core.ast.IFunctionExpression; import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.core.infer.InferredAttribute; @@ -177,6 +179,27 @@ public class LocalDeclarationVisitor extends ASTVisitor { return false; } + /** + * <p>Visit assignments so that if the right hand side is a function it can be indexed + * with the right hand side used as the selector.</p> + * + * @see org.eclipse.wst.jsdt.internal.compiler.ASTVisitor#visit(org.eclipse.wst.jsdt.internal.compiler.ast.Assignment, org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope) + */ + public boolean visit(Assignment assignment, BlockScope scope) { + boolean keepVisiting = true; + IExpression righHandSide = assignment.getExpression(); + if(righHandSide instanceof IFunctionExpression) { + IExpression leftHandSide = assignment.getLeftHandSide(); + + char[] selector = Util.getTypeName(leftHandSide); + if(selector != null) { + notifySourceElementRequestor(((IFunctionExpression) righHandSide).getMethodDeclaration(), + selector); + } + + } + return keepVisiting; + } public void endVisit(MethodDeclaration methodDeclaration, Scope scope) { nestedMethodIndex--; @@ -653,44 +676,10 @@ public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) && scanner.eofPosition >= parsedUnit.sourceEnd; // collect the top level ast nodes -// int length = 0; -// ASTNode[] nodes = null; if (sourceType == null){ if (isInRange) { requestor.enterCompilationUnit(); } - -// ImportReference currentPackage = parsedUnit.currentPackage; -// ImportReference[] imports = parsedUnit.imports; -// TypeDeclaration[] types = parsedUnit.types; -// length = -// (currentPackage == null ? 0 : 1) -// + (imports == null ? 0 : imports.length) -// + (types == null ? 0 : types.length); -// nodes = new ASTNode[length]; -// int index = 0; -// if (currentPackage != null) { -// nodes[index++] = currentPackage; -// } -// if (imports != null) { -// for (int i = 0, max = imports.length; i < max; i++) { -// nodes[index++] = imports[i]; -// } -// } -// if (types != null) { -// for (int i = 0, max = types.length; i < max; i++) { -// nodes[index++] = types[i]; -// } -// } - } else { -// TypeDeclaration[] types = parsedUnit.types; -// if (types != null) { -// length = types.length; -// nodes = new ASTNode[length]; -// for (int i = 0, max = types.length; i < max; i++) { -// nodes[i] = types[i]; -// } -// } } //visit each statement to notify context declarations @@ -698,46 +687,10 @@ public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) for( int i=0; i<parsedUnit.statements.length; i++ ){ parsedUnit.statements[i].traverse( contextDeclarationNotifier, parsedUnit.scope ); - } } -// length=(parsedUnit.statements!=null)? parsedUnit.statements.length : 0; -// nodes = new ASTNode[length]; -// -// // notify the nodes in the syntactical order -// if (nodes != null && length > 0) { -// System.arraycopy(parsedUnit.statements, 0, nodes, 0, length); -// quickSort(nodes, 0, length-1); -// for (int i=0;i<length;i++) { -// ASTNode node = nodes[i]; -// if (node instanceof LocalDeclaration) { -// LocalDeclaration var = (LocalDeclaration) node; -// notifySourceElementRequestor(var, null); -// -// } -// else if (node instanceof AbstractMethodDeclaration) { -// AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node; -// notifySourceElementRequestor(methodDeclaration); -// } -// else -// { -// notifySourceStatment(node); -// } -//// if (node instanceof ImportReference) { -//// ImportReference importRef = (ImportReference)node; -//// if (node == parsedUnit.currentPackage) { -//// notifySourceElementRequestor(importRef, true); -//// } else { -//// notifySourceElementRequestor(importRef, false); -//// } -//// } else { // instanceof TypeDeclaration -//// notifySourceElementRequestor((TypeDeclaration)node, sourceType == null, null); -//// } -// } -// } - for (int inx=0;inx<parsedUnit.numberInferredTypes;inx++) { InferredType type = parsedUnit.inferredTypes[inx]; @@ -796,9 +749,6 @@ public void notifySourceElementRequestor( InferredType type ) { fieldInfo.nameSourceEnd = field.nameStart+field.name.length-1; fieldInfo.type = field.type!=null ? field.type.getName():null; - -// fieldInfo.annotationPositions = collectAnnotationPositions(fieldDeclaration.annotations); -// fieldInfo.categories = (char[][]) this.nodesToCategories.get(fieldDeclaration); requestor.enterField(fieldInfo); //If this field is of an anonymous type, need to notify so that it shows as a child @@ -826,13 +776,14 @@ public void notifySourceElementRequestor( InferredType type ) { argumentTypes = new char[argumentLength][]; argumentNames = new char[argumentLength][]; for (int i = 0; i < argumentLength; i++) { - if (arguments[i].type!=null) + if (arguments[i].type!=null) { argumentTypes[i] = CharOperation.concatWith(arguments[i].type.getTypeName(), '.'); + } else if(arguments[i].inferredType != null) { + argumentTypes[i] = arguments[i].inferredType.getName(); + } argumentNames[i] = arguments[i].name; } } -// int selectorSourceEnd = this.sourceEnds.get(methodDeclaration); - methodInfo.declarationStart = methodDeclaration.declarationSourceStart; methodInfo.modifiers = methodDeclaration.modifiers; if (method.isStatic) { @@ -846,8 +797,14 @@ public void notifySourceElementRequestor( InferredType type ) { methodInfo.parameterTypes = argumentTypes; methodInfo.parameterNames = argumentNames; methodInfo.categories = (char[][]) this.nodesToCategories.get(methodDeclaration); - requestor.enterMethod(methodInfo); - + + //enter either constructor or method where appropriate + if(methodInfo.isConstructor) { + requestor.enterConstructor(methodInfo); + } else { + requestor.enterMethod(methodInfo); + } + visitIfNeeded( (MethodDeclaration)method.getFunctionDeclaration() ); requestor.exitMethod(methodDeclaration.declarationSourceEnd, -1, -1); @@ -859,15 +816,28 @@ public void notifySourceElementRequestor( InferredType type ) { } -//private void notifySourceStatment(ASTNode node) { -// // TODO Auto-generated method stub -// -//} - -/* - * Update the bodyStart of the corresponding parse node +/** + * <p>Notifies the requester of a method declaration using the {@link AbstractMethodDeclaration#selector} as the + * selector to notify with.</p> + * + * @param methodDeclaration to notify the requester of + * + * @see #notifySourceElementRequestor(AbstractMethodDeclaration, char[]) */ public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) { + this.notifySourceElementRequestor(methodDeclaration, methodDeclaration.selector); +} + +/** + * <p>Notifies the requester of a method declaration using the given selector rather then the selector set + * on the declaration itself.</p> + * + * <p>This is useful when the selector on the declaration is not set but it can be pre-determined some other way.</p> + * + * @param methodDeclaration to notify the requester of + * @param selector to use when notifying the requester of the given <code>methodDeclaration</code> + */ +public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration, char[] selector) { this.nestedMethodIndex++; // range check @@ -914,8 +884,11 @@ public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclara argumentTypes = new char[argumentLength][]; argumentNames = new char[argumentLength][]; for (int i = 0; i < argumentLength; i++) { - if (arguments[i].type!=null) + if (arguments[i].type!=null) { argumentTypes[i] = CharOperation.concatWith(arguments[i].type.getTypeName(), '.'); + } else if(arguments[i].inferredType != null) { + argumentTypes[i] = arguments[i].inferredType.getName(); + } argumentNames[i] = arguments[i].name; } isVarArgs = arguments[argumentLength-1].isVarArgs(); @@ -936,7 +909,7 @@ public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclara methodInfo.isConstructor = true; methodInfo.declarationStart = methodDeclaration.declarationSourceStart; methodInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag; - methodInfo.name = methodDeclaration.selector; + methodInfo.name = selector; methodInfo.nameSourceStart = methodDeclaration.sourceStart; methodInfo.nameSourceEnd = selectorSourceEnd; methodInfo.parameterTypes = argumentTypes; @@ -944,7 +917,10 @@ public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclara methodInfo.categories = (char[][]) this.nodesToCategories.get(methodDeclaration); requestor.enterConstructor(methodInfo); } - if (reportReferenceInfo) { + /* need this check because a constructor could have been made a constructor after the + * method declaration was created, and thus it is not a ConstructorDeclaration + */ + if (reportReferenceInfo && methodDeclaration instanceof ConstructorDeclaration) { ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration; ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall; if (constructorCall != null) { @@ -987,7 +963,7 @@ public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclara methodInfo.declarationStart = methodDeclaration.declarationSourceStart; methodInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag; methodInfo.returnType = returnType == null ? null : returnType.getName(); - methodInfo.name = methodDeclaration.selector; + methodInfo.name = selector; methodInfo.nameSourceStart = methodDeclaration.sourceStart; methodInfo.nameSourceEnd = selectorSourceEnd; methodInfo.parameterTypes = argumentTypes; @@ -1029,53 +1005,22 @@ public void notifySourceElementRequestor(AbstractVariableDeclaration fieldDeclar // remember deprecation so as to not lose it below boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0; - if (fieldDeclaration.initialization instanceof FunctionExpression) + if (fieldDeclaration.initialization instanceof FunctionExpression) { methodDeclaration=((FunctionExpression)fieldDeclaration.initialization).methodDeclaration; - else if (fieldDeclaration.initialization instanceof Assignment && - ((Assignment)fieldDeclaration.initialization).getExpression() instanceof FunctionExpression) + } else if (fieldDeclaration.initialization instanceof Assignment && + ((Assignment)fieldDeclaration.initialization).getExpression() instanceof FunctionExpression) { + methodDeclaration=((FunctionExpression)((Assignment)fieldDeclaration.initialization).getExpression()).methodDeclaration; + } + /* if the variable declaration has a method declaration on the right hand side notify of the declaration using the variable name as the method selector + * else notify of a field declaration + */ if (methodDeclaration!=null) { - - - char[][] argumentTypes = null; - char[][] argumentNames = null; -// boolean isVarArgs = false; - Argument[] arguments = methodDeclaration.arguments; - if (arguments != null) { - int argumentLength = arguments.length; - argumentTypes = new char[argumentLength][]; - argumentNames = new char[argumentLength][]; - for (int i = 0; i < argumentLength; i++) { - if (arguments[i].type!=null) - argumentTypes[i] = CharOperation.concatWith(arguments[i].type.getTypeName(), '.'); - argumentNames[i] = arguments[i].name; - } -// isVarArgs = arguments[argumentLength-1].isVarArgs(); - } - - ISourceElementRequestor.MethodInfo methodInfo = new ISourceElementRequestor.MethodInfo(); - methodInfo.declarationStart = fieldDeclaration.declarationSourceStart; - methodInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag; - methodInfo.returnType = methodDeclaration.returnType == null ? null : CharOperation.concatWith(methodDeclaration.returnType.getTypeName(), '.'); - methodInfo.name = fieldDeclaration.name; - methodInfo.nameSourceStart = fieldDeclaration.sourceStart; - methodInfo.nameSourceEnd = fieldDeclaration.sourceEnd; - methodInfo.parameterTypes = argumentTypes; - methodInfo.parameterNames = argumentNames; - methodInfo.categories = (char[][]) this.nodesToCategories.get(fieldDeclaration); - requestor.enterMethod(methodInfo); + this.notifySourceElementRequestor(methodDeclaration, fieldDeclaration.getName()); } else { - // if (fieldDeclaration.type == null) { - // // enum constant - // typeName = declaringType.name; - // currentModifiers |= ClassFileConstants.AccEnum; - // } else { - // // regular field - // typeName = CharOperation.concatWith(fieldDeclaration.type.getParameterizedTypeName(), '.'); - // } ISourceElementRequestor.FieldInfo fieldInfo = new ISourceElementRequestor.FieldInfo(); fieldInfo.declarationStart = fieldDeclaration.declarationSourceStart; fieldInfo.name = fieldDeclaration.name; @@ -1096,16 +1041,10 @@ public void notifySourceElementRequestor(AbstractVariableDeclaration fieldDeclar notifySourceElementRequestor(fieldDeclaration.inferredType); } } - } this.visitIfNeeded(fieldDeclaration, declaringType); if (isInRange){ - if (methodDeclaration!=null) - { - requestor.exitMethod(fieldDeclaration.declarationSourceEnd, -1, -1); - } - else - { + if (methodDeclaration == null) { requestor.exitField( // filter out initializations that are not a constant (simple check) (fieldDeclaration.initialization == null diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractMethodDeclaration.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractMethodDeclaration.java index 73ca5572..0af6e515 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractMethodDeclaration.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractMethodDeclaration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -29,7 +29,6 @@ import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo; import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext; import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding; import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope; -import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitBinding; import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding; import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope; @@ -48,6 +47,7 @@ public abstract class AbstractMethodDeclaration extends Statement implements IAbstractFunctionDeclaration, ProblemSeverities, ReferenceContext { public MethodScope scope; + private MethodScope prevScope; //it is not relevent for constructor but it helps to have the name of the constructor here //which is always the name of the class.....parsing do extra work to fill it up while it do not have to.... public char[] selector; @@ -77,6 +77,7 @@ public abstract class AbstractMethodDeclaration extends Statement AbstractMethodDeclaration(CompilationResult compilationResult){ this.compilationResult = compilationResult; + this.prevScope = null; } public void setArguments( IArgument[] args) { @@ -115,7 +116,10 @@ public abstract class AbstractMethodDeclaration extends Statement * Bind and add argument's binding into the scope of the method */ public void bindArguments() { - if (this.arguments != null) { + //only bind arguments if the current scope does not equal the scope last used to bind args + if (this.arguments != null && (this.prevScope == null || this.prevScope != this.scope)) { + this.prevScope = this.scope; + // by default arguments in abstract/native methods are considered to be used (no complaint is expected) if (this.binding == null) { for (int i = 0, length = this.arguments.length; i < length; i++) { @@ -126,9 +130,9 @@ public abstract class AbstractMethodDeclaration extends Statement if (this.arguments.length>0 && this.binding.parameters.length==0) // types not set yet { ReferenceBinding declaringClass = this.binding.declaringClass; - if (declaringClass instanceof CompilationUnitBinding) { - CompilationUnitBinding compilationUnitBinding = (CompilationUnitBinding) declaringClass; - compilationUnitBinding.resolveTypesFor(this.binding,this); + if (declaringClass instanceof SourceTypeBinding) { + SourceTypeBinding binding = (SourceTypeBinding) declaringClass; + binding.resolveTypesFor(this.binding,this); } } boolean used = this.binding.isAbstract(); @@ -160,9 +164,17 @@ public abstract class AbstractMethodDeclaration extends Statement return false; } - public boolean isConstructor() { - return false; + /** + * @return If the {@link #inferredMethod} is set then use that to determine if + * this declaration is a constructor, else <code>false</code> + */ + public boolean isConstructor() { + boolean isConstructor = false; + if(this.inferredMethod != null) { + isConstructor = this.inferredMethod.isConstructor; + } + return isConstructor; } public boolean isDefaultConstructor() { diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AllocationExpression.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AllocationExpression.java index 0e753643..07aba58e 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AllocationExpression.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AllocationExpression.java @@ -39,186 +39,183 @@ public class AllocationExpression extends Expression implements InvocationSite, public boolean isShort; -public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { - if (this.member!=null) - flowInfo = - this.member - .analyseCode(currentScope, flowContext, flowInfo) - .unconditionalInits(); - // process arguments - if (arguments != null) { - for (int i = 0, count = arguments.length; i < count; i++) { + public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { + if (this.member!=null) flowInfo = - arguments[i] + this.member .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); + // process arguments + if (arguments != null) { + for (int i = 0, count = arguments.length; i < count; i++) { + flowInfo = + arguments[i] + .analyseCode(currentScope, flowContext, flowInfo) + .unconditionalInits(); + } } + + return flowInfo; } - return flowInfo; -} - -public Expression enclosingInstance() { - return null; -} - -public boolean isSuperAccess() { - return false; -} - -public boolean isTypeAccess() { - return true; -} - -/* Inner emulation consists in either recording a dependency - * link only, or performing one level of propagation. - * - * Dependency mechanism is used whenever dealing with source target - * types, since by the time we reach them, we might not yet know their - * exact need. - */ -public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { - if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; - ReferenceBinding allocatedTypeErasure = binding.declaringClass; - - // perform some emulation work in case there is some and we are inside a local type only - if (allocatedTypeErasure.isNestedType() - && currentScope.enclosingSourceType().isLocalType()) { - - if (allocatedTypeErasure.isLocalType()) { - ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, false); - // request cascade of accesses + public Expression enclosingInstance() { + return null; + } + + public boolean isSuperAccess() { + return false; + } + + public boolean isTypeAccess() { + return true; + } + + /* Inner emulation consists in either recording a dependency + * link only, or performing one level of propagation. + * + * Dependency mechanism is used whenever dealing with source target + * types, since by the time we reach them, we might not yet know their + * exact need. + */ + public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { + if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; + ReferenceBinding allocatedTypeErasure = binding.declaringClass; + + // perform some emulation work in case there is some and we are inside a local type only + if (allocatedTypeErasure.isNestedType() + && currentScope.enclosingSourceType().isLocalType()) { + + if (allocatedTypeErasure.isLocalType()) { + ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, false); + // request cascade of accesses + } } } -} - -public StringBuffer printExpression(int indent, StringBuffer output) { - output.append("new "); //$NON-NLS-1$ - member.print(indent, output); - if (type != null) { // type null for enum constant initializations - type.printExpression(0, output); + public StringBuffer printExpression(int indent, StringBuffer output) { + output.append("new "); //$NON-NLS-1$ + member.print(indent, output); + + if (type != null) { // type null for enum constant initializations + type.printExpression(0, output); + } + if (!isShort) + { + output.append('('); + if (arguments != null) { + for (int i = 0; i < arguments.length; i++) { + if (i > 0) output.append(", "); //$NON-NLS-1$ + arguments[i].printExpression(0, output); + } + } + output.append(')'); + } + return output; } - if (!isShort) - { - output.append('('); + + public TypeBinding resolveType(BlockScope scope) { + // Propagate the type checking to the arguments, and check if the constructor is defined. + constant = Constant.NotAConstant; + if (this.member!=null) { + this.resolvedType=this.member.resolveForAllocation(scope, this); + if (this.resolvedType!=null && !this.resolvedType.isValidBinding()) { + scope.problemReporter().invalidType(this, this.resolvedType); + } + } + else if (this.type == null) { + // initialization of an enum constant + this.resolvedType = scope.enclosingReceiverType(); + } + else { + this.resolvedType = this.type.resolveType(scope, true /* check bounds*/); + } + // will check for null after args are resolved + // buffering the arguments' types + boolean argsContainCast = false; + TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; if (arguments != null) { - for (int i = 0; i < arguments.length; i++) { - if (i > 0) output.append(", "); //$NON-NLS-1$ - arguments[i].printExpression(0, output); + boolean argHasError = false; + int length = arguments.length; + argumentTypes = new TypeBinding[length]; + for (int i = 0; i < length; i++) { + Expression argument = this.arguments[i]; + if ((argumentTypes[i] = argument.resolveType(scope)) == null) { + argHasError = true; + argumentTypes[i]=TypeBinding.UNKNOWN; + } } } - output.append(')'); - } - return output; -} - -public TypeBinding resolveType(BlockScope scope) { - // Propagate the type checking to the arguments, and check if the constructor is defined. - constant = Constant.NotAConstant; - if (this.member!=null) { - this.resolvedType=this.member.resolveForAllocation(scope, this); - if (this.resolvedType!=null && !this.resolvedType.isValidBinding()) { - scope.problemReporter().invalidType(this, this.resolvedType); + if (this.resolvedType == null || this.resolvedType.isAnyType()|| this.resolvedType instanceof ProblemReferenceBinding) + { + this.binding= new ProblemMethodBinding( + TypeConstants.INIT, + Binding.NO_PARAMETERS, + ProblemReasons.NotFound); + this.resolvedType=TypeBinding.UNKNOWN; + return this.resolvedType; + } + + if (!this.resolvedType.isValidBinding()) + return null; + if (this.resolvedType instanceof ReferenceBinding ) + { + ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType; + if (!(binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) { + if (binding.declaringClass == null) + binding.declaringClass = allocationType; + scope.problemReporter().invalidConstructor(this, binding); + return this.resolvedType; + } + if (argumentTypes.length!=binding.parameters.length) + scope.problemReporter().wrongNumberOfArguments(this, binding); + if (isMethodUseDeprecated(binding, scope, true)) + scope.problemReporter().deprecatedMethod(binding, this); + checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this); + } + + return this.resolvedType; } - else if (this.type == null) { - // initialization of an enum constant - this.resolvedType = scope.enclosingReceiverType(); + + public void setActualReceiverType(ReferenceBinding receiverType) { + // ignored } - else { - this.resolvedType = this.type.resolveType(scope, true /* check bounds*/); + + public void setDepth(int i) { + // ignored } - // will check for null after args are resolved - // buffering the arguments' types - boolean argsContainCast = false; - TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; - if (arguments != null) { - boolean argHasError = false; - int length = arguments.length; - argumentTypes = new TypeBinding[length]; - for (int i = 0; i < length; i++) { - Expression argument = this.arguments[i]; - if ((argumentTypes[i] = argument.resolveType(scope)) == null) { - argHasError = true; - argumentTypes[i]=TypeBinding.UNKNOWN; + + public void setFieldIndex(int i) { + // ignored + } + + public void traverse(ASTVisitor visitor, BlockScope scope) { + if (visitor.visit(this, scope)) { + if (this.member!=null) + this.member.traverse(visitor, scope); + else if (this.type != null) { // enum constant scenario + this.type.traverse(visitor, scope); + } + if (this.arguments != null) { + for (int i = 0, argumentsLength = this.arguments.length; i < argumentsLength; i++) + this.arguments[i].traverse(visitor, scope); } } - if (argHasError) { -// if (this.resolvedType instanceof ReferenceBinding) { -// // record a best guess, for clients who need hint about possible contructor match -// TypeBinding[] pseudoArgs = new TypeBinding[length]; -// for (int i = length; --i >= 0;) -// pseudoArgs[i] = argumentTypes[i] == null ? this.resolvedType : argumentTypes[i]; // replace args with errors with receiver -// this.binding = scope.findMethod((ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this); -// } -// return this.resolvedType; - } + visitor.endVisit(this, scope); } - if (this.resolvedType == null || this.resolvedType.isAnyType()|| this.resolvedType instanceof ProblemReferenceBinding) - { - this.binding= new ProblemMethodBinding( - TypeConstants.INIT, - Binding.NO_PARAMETERS, - ProblemReasons.NotFound); - this.resolvedType=TypeBinding.UNKNOWN; - return this.resolvedType; - + public int getASTType() { + return IASTNode.ALLOCATION_EXPRESSION; + } - - if (!this.resolvedType.isValidBinding()) - return null; - if (this.resolvedType instanceof ReferenceBinding ) - { - ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType; - if (!(binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) { - if (binding.declaringClass == null) - binding.declaringClass = allocationType; - scope.problemReporter().invalidConstructor(this, binding); - return this.resolvedType; - } - if (argumentTypes.length!=binding.parameters.length) - scope.problemReporter().wrongNumberOfArguments(this, binding); - if (isMethodUseDeprecated(binding, scope, true)) - scope.problemReporter().deprecatedMethod(binding, this); - checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this); + + public IExpression getMember() { + return this.member; } - - return this.resolvedType; -} - -public void setActualReceiverType(ReferenceBinding receiverType) { - // ignored -} - -public void setDepth(int i) { - // ignored -} - -public void setFieldIndex(int i) { - // ignored -} - -public void traverse(ASTVisitor visitor, BlockScope scope) { - if (visitor.visit(this, scope)) { - if (this.member!=null) - this.member.traverse(visitor, scope); - else if (this.type != null) { // enum constant scenario - this.type.traverse(visitor, scope); - } - if (this.arguments != null) { - for (int i = 0, argumentsLength = this.arguments.length; i < argumentsLength; i++) - this.arguments[i].traverse(visitor, scope); - } + + /** + * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#resolveForAllocation(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) + */ + public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) { + return this.resolveType(scope); } - visitor.endVisit(this, scope); -} -public int getASTType() { - return IASTNode.ALLOCATION_EXPRESSION; - -} - -public IExpression getMember() { - return this.member; -} } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/FunctionExpression.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/FunctionExpression.java index 1006517a..66ddc9bc 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/FunctionExpression.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/FunctionExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -53,6 +53,7 @@ public class FunctionExpression extends Expression implements IFunctionExpressio constant = Constant.NotAConstant; this.methodDeclaration.scope=new MethodScope(scope,this.methodDeclaration,false); this.methodDeclaration.binding=this.methodDeclaration.scope.createMethod(this.methodDeclaration, null, scope.enclosingCompilationUnit(), false, false); + methodDeclaration.bindArguments(); this.methodDeclaration.binding.createFunctionTypeBinding(scope); this.methodDeclaration.resolve(scope); return this.methodDeclaration.binding.functionTypeBinding; diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/CompilationUnitBinding.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/CompilationUnitBinding.java index 4163287d..48fdbab7 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/CompilationUnitBinding.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/CompilationUnitBinding.java @@ -79,469 +79,6 @@ public class CompilationUnitBinding extends SourceTypeBinding { return this.signature = CharOperation.concat(Signature.C_COMPILATION_UNIT, constantPoolName(), ';'); } -// public char[] readableName() { -// return sourceName; -// } -// -//// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed -//// searches up the hierarchy as long as no potential (but not exact) match was found. -// public FunctionBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) { -// // sender from refScope calls recordTypeReference(this) -// int argCount = argumentTypes.length; -// boolean foundNothing = true; -// -// if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods -// long range; -// if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { -// nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) { -// FunctionBinding method = this.methods[imethod]; -// foundNothing = false; // inner type lookups must know that a method with this name exists -// if (method.parameters.length == argCount) { -// TypeBinding[] toMatch = method.parameters; -// for (int iarg = 0; iarg < argCount; iarg++) -// if (toMatch[iarg] != argumentTypes[iarg]) -// continue nextMethod; -// return method; -// } -// } -// } -// } else { -// // lazily sort methods -// if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { -// int length = this.methods.length; -// if (length > 1) -// ReferenceBinding.sortMethods(this.methods, 0, length); -// this.tagBits |= TagBits.AreMethodsSorted; -// } -// -// long range; -// if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) { -// // check unresolved method -// int start = (int) range, end = (int) (range >> 32); -// for (int imethod = start; imethod <= end; imethod++) { -// FunctionBinding method = this.methods[imethod]; -// if (resolveTypesFor(method) == null || method.returnType == null) { -// methods(); -// return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed -// } -// } -// // check dup collisions -//// boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; -// for (int i = start; i <= end; i++) { -// FunctionBinding method1 = this.methods[i]; -// for (int j = end; j > i; j--) { -// FunctionBinding method2 = this.methods[j]; -// boolean paramsMatch = -//// isSource15 -//// ? method1.areParameterErasuresEqual(method2) -//// : -// method1.areParametersEqual(method2); -// if (paramsMatch) { -// methods(); -// return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed -// } -// } -// } -// nextMethod: for (int imethod = start; imethod <= end; imethod++) { -// FunctionBinding method = this.methods[imethod]; -// TypeBinding[] toMatch = method.parameters; -// if (toMatch.length == argCount) { -// for (int iarg = 0; iarg < argCount; iarg++) -// if (toMatch[iarg] != argumentTypes[iarg]) -// continue nextMethod; -// return method; -// } -// } -// } -// } -// -// if (foundNothing) { -//// if (isInterface()) { -//// if (this.superInterfaces.length == 1) { -//// if (refScope != null) -//// refScope.recordTypeReference(this.superInterfaces[0]); -//// return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope); -//// } -//// } else if (this.superclass != null) { -//// if (refScope != null) -//// refScope.recordTypeReference(this.superclass); -//// return this.superclass.getExactMethod(selector, argumentTypes, refScope); -//// } -// } -// return null; -// } -// -//// NOTE: the type of a field of a source type is resolved when needed -// public FieldBinding getField(char[] fieldName, boolean needResolve) { -// -// if ((this.tagBits & TagBits.AreFieldsComplete) != 0) -// return ReferenceBinding.binarySearch(fieldName, this.fields); -// -// // lazily sort fields -// if ((this.tagBits & TagBits.AreFieldsSorted) == 0) { -// int length = this.fields.length; -// if (length > 1) -// ReferenceBinding.sortFields(this.fields, 0, length); -// this.tagBits |= TagBits.AreFieldsSorted; -// } -// // always resolve anyway on source types -// FieldBinding field = ReferenceBinding.binarySearch(fieldName, this.fields); -// if (field != null) { -// FieldBinding result = null; -// try { -// result = resolveTypeFor(field); -// return result; -// } finally { -// if (result == null) { -// // ensure fields are consistent reqardless of the error -// int newSize = this.fields.length - 1; -// if (newSize == 0) { -// this.fields = Binding.NO_FIELDS; -// } else { -// FieldBinding[] newFields = new FieldBinding[newSize]; -// int index = 0; -// for (int i = 0, length = this.fields.length; i < length; i++) { -// FieldBinding f = this.fields[i]; -// if (f == field) continue; -// newFields[index++] = f; -// } -// this.fields = newFields; -// } -// } -// } -// } -// return null; -// } -// -// -//// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed -// public FunctionBinding[] methods() { -// if ((this.tagBits & TagBits.AreMethodsComplete) != 0) -// return this.methods; -// -// // lazily sort methods -// if ((this.tagBits & TagBits.AreMethodsSorted) == 0) { -// int length = this.methods.length; -// if (length > 1) -// ReferenceBinding.sortMethods(this.methods, 0, length); -// this.tagBits |= TagBits.AreMethodsSorted; -// } -// -// int failed = 0; -// try { -// for (int i = 0, length = this.methods.length; i < length; i++) { -// if (resolveTypesFor(this.methods[i]) == null) { -// this.methods[i] = null; // unable to resolve parameters -// failed++; -// } -// } -// -// // find & report collision cases -// boolean complyTo15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; -// for (int i = 0, length = this.methods.length; i < length; i++) { -// FunctionBinding method = this.methods[i]; -// if (method == null) -// continue; -// char[] selector = method.selector; -// AbstractMethodDeclaration methodDecl = null; -// nextSibling: for (int j = i + 1; j < length; j++) { -// FunctionBinding method2 = this.methods[j]; -// if (method2 == null) -// continue nextSibling; -// if (!CharOperation.equals(selector, method2.selector)) -// break nextSibling; // methods with same selector are contiguous -// -// if (complyTo15 && method.returnType != null && method2.returnType != null) { -// // 8.4.2, for collision to be detected between m1 and m2: -// // signature(m1) == signature(m2) i.e. same arity, same type parameter count, can be substituted -// // signature(m1) == erasure(signature(m2)) or erasure(signature(m1)) == signature(m2) -// TypeBinding[] params1 = method.parameters; -// TypeBinding[] params2 = method2.parameters; -// int pLength = params1.length; -// if (pLength != params2.length) -// continue nextSibling; -// -// TypeVariableBinding[] vars = method.typeVariables; -// TypeVariableBinding[] vars2 = method2.typeVariables; -// boolean equalTypeVars = vars == vars2; -// FunctionBinding subMethod = method2; -// if (!equalTypeVars) { -// FunctionBinding temp = method.computeSubstitutedMethod(method2, this.scope.environment()); -// if (temp != null) { -// equalTypeVars = true; -// subMethod = temp; -// } -// } -// boolean equalParams = method.areParametersEqual(subMethod); -// if (equalParams && equalTypeVars) { -// // duplicates regardless of return types -// } else if (method.returnType.erasure() == subMethod.returnType.erasure() && (equalParams || method.areParameterErasuresEqual(method2))) { -// // name clash for sure if not duplicates, report as duplicates -// } else if (!equalTypeVars && vars != Binding.NO_TYPE_VARIABLES && vars2 != Binding.NO_TYPE_VARIABLES) { -// // type variables are different so we can distinguish between methods -// continue nextSibling; -// } else if (pLength > 0) { -// // check to see if the erasure of either method is equal to the other -// int index = pLength; -// for (; --index >= 0;) { -// if (params1[index] != params2[index].erasure()) -// break; -// if (params1[index] == params2[index]) { -// TypeBinding type = params1[index].leafComponentType(); -// if (type instanceof SourceTypeBinding && type.typeVariables() != Binding.NO_TYPE_VARIABLES) { -// index = pLength; // handle comparing identical source types like X<T>... its erasure is itself BUT we need to answer false -// break; -// } -// } -// } -// if (index >= 0 && index < pLength) { -// for (index = pLength; --index >= 0;) -// if (params1[index].erasure() != params2[index]) -// break; -// } -// if (index >= 0) -// continue nextSibling; -// } -// } else if (!method.areParametersEqual(method2)) { // prior to 1.5, parameter identity meant a collision case -// continue nextSibling; -// } -//// boolean isEnumSpecialMethod = isEnum() && (CharOperation.equals(selector,TypeConstants.VALUEOF) || CharOperation.equals(selector,TypeConstants.VALUES)); -// // report duplicate -// if (methodDecl == null) { -// methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost & may still be null if method is special -// if (methodDecl != null && methodDecl.binding != null) { // ensure its a valid user defined method -//// if (isEnumSpecialMethod) { -//// this.scope.problemReporter().duplicateEnumSpecialMethod(this, methodDecl); -//// } else { -// this.scope.problemReporter().duplicateMethodInType(this, methodDecl); -//// } -// methodDecl.binding = null; -// this.methods[i] = null; -// failed++; -// } -// } -// AbstractMethodDeclaration method2Decl = method2.sourceMethod(); -// if (method2Decl != null && method2Decl.binding != null) { // ensure its a valid user defined method -//// if (isEnumSpecialMethod) { -//// this.scope.problemReporter().duplicateEnumSpecialMethod(this, method2Decl); -//// } else { -// this.scope.problemReporter().duplicateMethodInType(this, method2Decl); -//// } -// method2Decl.binding = null; -// this.methods[j] = null; -// failed++; -// } -// } -//// if (/*method.returnType == null && */ methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions -//// method.sourceMethod().binding = null; -//// this.methods[i] = null; -//// failed++; -//// } -// } -// } finally { -// if (failed > 0) { -// int newSize = this.methods.length - failed; -// if (newSize == 0) { -// this.methods = Binding.NO_METHODS; -// } else { -// FunctionBinding[] newMethods = new FunctionBinding[newSize]; -// for (int i = 0, j = 0, length = this.methods.length; i < length; i++) -// if (this.methods[i] != null) -// newMethods[j++] = this.methods[i]; -// this.methods = newMethods; -// } -// } -// -// // handle forward references to potential default abstract methods -//// addDefaultAbstractMethods(); -// this.tagBits |= TagBits.AreMethodsComplete; -// } -// return this.methods; -// } -// -// private FieldBinding resolveTypeFor(FieldBinding field) { -// if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) -// return field; -// -//// if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { -//// if ((field.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0) -//// field.modifiers |= ClassFileConstants.AccDeprecated; -//// } -//// if (isViewedAsDeprecated() && !field.isDeprecated()) -//// field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; -//// if (hasRestrictedAccess()) -//// field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; -// FieldDeclaration[] fieldDecls = this.scope.referenceContext.fields; -// for (int f = 0, length = fieldDecls.length; f < length; f++) { -// if (fieldDecls[f].binding != field) -// continue; -// -// MethodScope initializationScope = field.isStatic() -// ? this.scope.referenceContext.staticInitializerScope -// : this.scope.referenceContext.initializerScope; -// FieldBinding previousField = initializationScope.initializedField; -// try { -// initializationScope.initializedField = field; -// FieldDeclaration fieldDecl = fieldDecls[f]; -// TypeBinding fieldType = -// fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT -// ? initializationScope.environment().convertToRawType(this) // enum constant is implicitly of declaring enum type -// : fieldDecl.type.resolveType(initializationScope, true /* check bounds*/); -// field.type = fieldType; -// field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; -// if (fieldType == null) { -// fieldDecls[f].binding = null; -// return null; -// } -// if (fieldType == TypeBinding.VOID) { -// this.scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]); -// fieldDecls[f].binding = null; -// return null; -// } -// if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == TypeBinding.VOID) { -// this.scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]); -// fieldDecls[f].binding = null; -// return null; -// } -// TypeBinding leafType = fieldType.leafComponentType(); -// if (leafType instanceof ReferenceBinding && (((ReferenceBinding)leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) { -// field.modifiers |= ExtraCompilerModifiers.AccGenericSignature; -// } -// } finally { -// initializationScope.initializedField = previousField; -// } -// return field; -// } -// return null; // should never reach this point -// } -// private FunctionBinding resolveTypesFor(FunctionBinding method) { -// if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) -// return method; -// -//// if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { -//// if ((method.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0) -//// method.modifiers |= ClassFileConstants.AccDeprecated; -//// } -//// if (isViewedAsDeprecated() && !method.isDeprecated()) -//// method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly; -//// if (hasRestrictedAccess()) -//// method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess; -// -// AbstractMethodDeclaration methodDecl = method.sourceMethod(); -// if (methodDecl == null) return null; // method could not be resolved in previous iteration -// -//// TypeParameter[] typeParameters = methodDecl.typeParameters(); -//// if (typeParameters != null) { -//// methodDecl.scope.connectTypeVariables(typeParameters, true); -//// // Perform deferred bound checks for type variables (only done after type variable hierarchy is connected) -//// for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) -//// typeParameters[i].checkBounds(methodDecl.scope); -//// } -//// TypeReference[] exceptionTypes = methodDecl.thrownExceptions; -//// if (exceptionTypes != null) { -//// int size = exceptionTypes.length; -//// method.thrownExceptions = new ReferenceBinding[size]; -//// int count = 0; -//// ReferenceBinding resolvedExceptionType; -//// for (int i = 0; i < size; i++) { -//// resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].resolveType(methodDecl.scope, true /* check bounds*/); -//// if (resolvedExceptionType == null) -//// continue; -//// if (resolvedExceptionType.isBoundParameterizedType()) { -//// methodDecl.scope.problemReporter().invalidParameterizedExceptionType(resolvedExceptionType, exceptionTypes[i]); -//// continue; -//// } -//// if (resolvedExceptionType.findSuperTypeErasingTo(TypeIds.T_JavaLangThrowable, true) == null) { -//// methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType); -//// continue; -//// } -//// if ((resolvedExceptionType.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) -//// method.modifiers |= ExtraCompilerModifiers.AccGenericSignature; -//// method.thrownExceptions[count++] = resolvedExceptionType; -//// } -//// if (count < size) -//// System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count); -//// } -//// -// boolean foundArgProblem = false; -// Argument[] arguments = methodDecl.arguments; -// if (arguments != null) { -// int size = arguments.length; -// method.parameters = new TypeBinding[size]; -// for (int i = 0; i < size; i++) { -// Argument arg = arguments[i]; -// if (arg.type==null) -// continue; -// TypeBinding parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/); -// if (parameterType == null) { -// foundArgProblem = true; -//// } -//// else if (parameterType == TypeBinding.VOID) { -//// methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg); -//// foundArgProblem = true; -//// } else if (parameterType.isArrayType() && ((ArrayBinding) parameterType).leafComponentType == TypeBinding.VOID) { -//// methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg); -//// foundArgProblem = true; -// } else { -// TypeBinding leafType = parameterType.leafComponentType(); -// if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) -// method.modifiers |= ExtraCompilerModifiers.AccGenericSignature; -// method.parameters[i] = parameterType; -// } -// } -// } -// -// boolean foundReturnTypeProblem = false; -// if (!method.isConstructor()) { -// TypeReference returnType = methodDecl instanceof FunctionDeclaration -// ? ((FunctionDeclaration) methodDecl).returnType -// : null; -// if (returnType != null) { -//// methodDecl.scope.problemReporter().missingReturnType(methodDecl); -//// method.returnType = null; -//// foundReturnTypeProblem = true; -//// } else { -// TypeBinding methodType = returnType.resolveType(methodDecl.scope, true /* check bounds*/); -// if (methodType == null) { -// foundReturnTypeProblem = true; -// } -//// else if (methodType.isArrayType() && ((ArrayBinding) methodType).leafComponentType == TypeBinding.VOID) { -//// methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (FunctionDeclaration) methodDecl); -//// foundReturnTypeProblem = true; -//// } -// else { -// method.returnType = methodType; -// TypeBinding leafType = methodType.leafComponentType(); -// if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) -// method.modifiers |= ExtraCompilerModifiers.AccGenericSignature; -// } -// } -// } -// if (foundArgProblem) { -// methodDecl.binding = null; -// method.parameters = Binding.NO_PARAMETERS; // see 107004 -// // nullify type parameter bindings as well as they have a backpointer to the method binding -// // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134) -//// if (typeParameters != null) -//// for (int i = 0, length = typeParameters.length; i < length; i++) -//// typeParameters[i].binding = null; -// return null; -// } -// if (foundReturnTypeProblem) -// return method; // but its still unresolved with a null return type & is still connected to its method declaration -// -// method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; -// return method; -// } -// -// -// public void setFields(FieldBinding[] fields) { -// this.fields = fields; -// } -// public void setMethods(FunctionBinding[] methods) { -// this.methods = methods; -// } - public AbstractMethodDeclaration sourceMethod(MethodBinding binding) { ProgramElement[] statements = compilationUnitScope.referenceContext.statements; for (int i = 0; i < statements.length; i++) { diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/CompilationUnitScope.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/CompilationUnitScope.java index b0250c10..9a3864dc 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/CompilationUnitScope.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/CompilationUnitScope.java @@ -23,6 +23,7 @@ import org.eclipse.wst.jsdt.core.infer.InferrenceProvider; import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor; import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode; import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression; import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference; import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration; @@ -76,18 +77,32 @@ class DeclarationVisitor extends ASTVisitor { ArrayList methods=new ArrayList(); public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { - TypeBinding type=localDeclaration.resolveVarType(scope); - LocalVariableBinding binding = new LocalVariableBinding(localDeclaration, type, 0, false); - localDeclaration.binding=binding; - addLocalVariable(binding); + if(localDeclaration.initialization instanceof FunctionExpression) { + this.visit(((FunctionExpression)localDeclaration.initialization).getMethodDeclaration(), scope); + } else { + TypeBinding type=localDeclaration.resolveVarType(scope); + LocalVariableBinding binding = new LocalVariableBinding(localDeclaration, type, 0, false); + localDeclaration.binding=binding; + addLocalVariable(binding); + } return false; } public boolean visit(MethodDeclaration methodDeclaration, Scope parentScope) { - if (methodDeclaration.selector!=null) + + char[] selector = null; + + if(methodDeclaration.selector != null) { + selector = methodDeclaration.selector; + } else if(methodDeclaration.inferredMethod != null && methodDeclaration.inferredMethod.isConstructor) { + //this is that inferred constructors get added to the methods list + selector = methodDeclaration.inferredMethod.name; + } + + if (selector!=null) { MethodScope scope = new MethodScope(parentScope,methodDeclaration, false); - MethodBinding methodBinding = scope.createMethod(methodDeclaration,methodDeclaration.selector,referenceContext.compilationUnitBinding,false,false); + MethodBinding methodBinding = scope.createMethod(methodDeclaration,selector,referenceContext.compilationUnitBinding,false,false); if (methodBinding != null && methodBinding.selector!=null) // is null if binding could not be created methods.add(methodBinding); if (methodBinding.selector!=null) @@ -96,10 +111,10 @@ class DeclarationVisitor extends ASTVisitor fPackage.addBinding(methodBinding, methodBinding.selector,Binding.METHOD); } methodDeclaration.binding=methodBinding; + methodDeclaration.bindArguments(); } return false; } - } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/MethodScope.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/MethodScope.java index af6308f3..57874e80 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/MethodScope.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/MethodScope.java @@ -181,47 +181,49 @@ public class MethodScope extends BlockScope { if (method.inferredMethod!=null && method.inferredMethod.isStatic) modifiers|= ClassFileConstants.AccStatic; if (method.isConstructor() || isConstructor) { - if (method.isDefaultConstructor() || isConstructor) + if (method.isDefaultConstructor() || isConstructor) { modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor; + } methodBinding = new MethodBinding(modifiers, name, TypeBinding.UNKNOWN, null, declaringClass); methodBinding.tagBits|=TagBits.IsConstructor; checkAndSetModifiersForConstructor(methodBinding); } else { -// if (declaringClass.isInterface()) // interface or annotation type -// modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract; TypeBinding returnType = (method.inferredType!=null)?method.inferredType.resolveType(this,method):TypeBinding.UNKNOWN; -// TypeBinding returnType = -// (method instanceof FunctionDeclaration && ((FunctionDeclaration)method).returnType!=null && method.inferredMethod!=null)?method.inferredType.resolveType(this,((FunctionDeclaration)method).returnType):TypeBinding.ANY; if (method.inferredType==null && method.inferredMethod!=null && method.inferredMethod.isConstructor - && method.inferredMethod.inType!=null) - { + && method.inferredMethod.inType!=null) { returnType=method.inferredMethod.inType.resolveType(this,method); } - if (returnType==null) + + //return type still null, return type is unknown + if (returnType==null) { returnType=TypeBinding.UNKNOWN; + } - if (isLocal && method.selector!=null) - { + if (isLocal && method.selector!=null) { methodBinding = new LocalFunctionBinding(modifiers, name,returnType, null, declaringClass); - } - else // not local method + } else{// not local method methodBinding = new MethodBinding(modifiers, name,returnType, null, declaringClass); - if (method.inferredMethod!=null) - { + } + + if (method.inferredMethod!=null) { methodBinding.tagBits |= TagBits.IsInferredType; - if ((method.bits&ASTNode.IsInferredJsDocType)!=0) + if ((method.bits&ASTNode.IsInferredJsDocType)!=0) { methodBinding.tagBits |= TagBits.IsInferredJsDocType; + + } } methodBinding.createFunctionTypeBinding(this); - if (method.inferredMethod!=null && method.inferredMethod.isConstructor) + if (method.inferredMethod!=null && method.inferredMethod.isConstructor) { methodBinding.tagBits|=TagBits.IsConstructor; + } checkAndSetModifiersForMethod(methodBinding); } this.isStatic =methodBinding.isStatic(); + //set arguments Argument[] argTypes = method.arguments; int argLength = argTypes == null ? 0 : argTypes.length; if (argLength > 0 && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { @@ -232,16 +234,6 @@ public class MethodScope extends BlockScope { return methodBinding; } - /* Overridden to detect the error case inside an explicit constructor call: - - class X { - int i; - X myX; - X(X x) { - this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors - } - } - */ public FieldBinding findField( TypeBinding receiverType, char[] fieldName, diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/Scope.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/Scope.java index 7a8ccafe..d9879f5a 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/Scope.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/Scope.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 IBM Corporation and others. + * Copyright (c) 2007, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -30,6 +30,7 @@ import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter; import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject; import org.eclipse.wst.jsdt.internal.compiler.util.ObjectVector; import org.eclipse.wst.jsdt.internal.compiler.util.SimpleSet; +import org.eclipse.wst.jsdt.internal.core.Logger; public abstract class Scope implements TypeConstants, TypeIds { @@ -1331,6 +1332,16 @@ public abstract class Scope implements TypeConstants, TypeIds { } } + /** + * <p><b>NOTE:</b> This function does not validate the given argument types because any number of arguments + * can be passed to any JavaScript function or constructor.</p> + * + * @param receiverType + * @param argumentTypes + * @param invocationSite + * @return The constructor for the given receiver type or a {@link ProblemMethodBinding} if the + * constructor is not visible. + */ public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) { CompilationUnitScope unitScope = compilationUnitScope(); LookupEnvironment env = unitScope.environment; @@ -1342,47 +1353,34 @@ public abstract class Scope implements TypeConstants, TypeIds { if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) { return methodBinding; } - MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT); - if (methods == Binding.NO_METHODS) - { - return new MethodBinding(0, TypeConstants.INIT, TypeBinding.UNKNOWN, null,receiverType); - - } - MethodBinding[] compatible = new MethodBinding[methods.length]; - int compatibleIndex = 0; - MethodBinding problemMethod = null; - for (int i = 0, length = methods.length; i < length; i++) { - MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite); - if (compatibleMethod != null) { - if (compatibleMethod.isValidBinding()) - compatible[compatibleIndex++] = compatibleMethod; - else if (problemMethod == null) - problemMethod = compatibleMethod; + + //get the methods + MethodBinding[] methods = receiverType.getMethods(receiverType.sourceName); + MethodBinding constructor = null; + if (methods == null || methods == Binding.NO_METHODS || methods.length == 0){ + constructor = new MethodBinding(0, receiverType.sourceName, receiverType, null,receiverType); + } else { + + if(methods.length > 1) { + Logger.log(Logger.WARNING, "There should only ever be one match for a constructor search" + + " but found " + methods.length + " when looking for " + + new String(receiverType.sourceName) + ". Using the first match."); } + + //should only ever be one constructor so use the first one in the list + constructor = methods[0]; } - if (compatibleIndex == 0) { - if (problemMethod == null) - return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound); - return problemMethod; - } - // need a more descriptive error... cannot convert from X to Y - - MethodBinding[] visible = new MethodBinding[compatibleIndex]; - int visibleIndex = 0; - for (int i = 0; i < compatibleIndex; i++) { - MethodBinding method = compatible[i]; - if (method.canBeSeenBy(invocationSite, this)) - visible[visibleIndex++] = method; + + //if can't be seen return problem binding + if(!constructor.canBeSeenBy(invocationSite, this)) { + constructor = new ProblemMethodBinding( + methods[0], + methods[0].selector, + methods[0].parameters, + ProblemReasons.NotVisible); } - if (visibleIndex == 1) return visible[0]; - if (visibleIndex == 0) - return new ProblemMethodBinding( - compatible[0], - TypeConstants.INIT, - compatible[0].parameters, - ProblemReasons.NotVisible); - // all of visible are from the same declaringClass, even before 1.4 we can call this method instead of mostSpecificClassMethodBinding - return mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, invocationSite, receiverType); + + return constructor; } catch (AbortCompilation e) { e.updateContext(invocationSite, referenceCompilationUnit().compilationResult); throw e; @@ -2004,8 +2002,6 @@ public abstract class Scope implements TypeConstants, TypeIds { case BLOCK_SCOPE : ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only if (localType != null) { - if (foundType != null && foundType != localType) - return new ProblemReferenceBinding(name, (ReferenceBinding)foundType, ProblemReasons.InheritedNameHidesEnclosingName); return localType; } break; @@ -2023,8 +2019,6 @@ public abstract class Scope implements TypeConstants, TypeIds { } scope = scope.parent; } - if (foundType != null && foundType.problemId() != ProblemReasons.NotVisible) - return foundType; } // at this point the scope is a compilation unit scope @@ -2043,8 +2037,6 @@ public abstract class Scope implements TypeConstants, TypeIds { typeOrPackageCache.put(name, binding = ((ImportBinding) binding).resolvedImport); // already know its visible } if ((mask & Binding.TYPE) != 0) { - if (foundType != null && foundType.problemId() != ProblemReasons.NotVisible && binding.problemId() != ProblemReasons.Ambiguous) - return foundType; // problem type from above supercedes NotFound type but not Ambiguous import case if (binding instanceof ReferenceBinding) return binding; // cached type found in previous walk below } @@ -2081,8 +2073,6 @@ public abstract class Scope implements TypeConstants, TypeIds { // check on file imports if (imports != null) { - boolean foundInImport = false; - Binding type = null; for (int i = 0, length = imports.length; i < length; i++) { ImportBinding someImport = imports[i]; if (someImport.reference!=null && someImport.reference.isFileImport()) diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/SourceTypeBinding.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/SourceTypeBinding.java index 532a9758..03ed1dd3 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/SourceTypeBinding.java @@ -192,15 +192,32 @@ public class SourceTypeBinding extends ReferenceBinding { MethodBinding[] methodBindings = new MethodBinding[size]; // create bindings for source methods for (int i = 0; i < size; i++) { - InferredMethod method = (InferredMethod) inferredType.methods - .get(i); - MethodScope scope = new MethodScope(this.scope, - (MethodDeclaration) method.getFunctionDeclaration(), false); + InferredMethod method = (InferredMethod) inferredType.methods.get(i); + + //determine if the method already has a resolved scope or not + boolean doesNotHaveResolvedScope = method.getFunctionDeclaration() instanceof AbstractMethodDeclaration && + ((AbstractMethodDeclaration)method.getFunctionDeclaration()).scope == null; + + //build method scope + MethodDeclaration methDec = (MethodDeclaration) method.getFunctionDeclaration(); + MethodScope scope = new MethodScope(this.scope, methDec, false); MethodBinding methodBinding = scope.createMethod(method, this); + + //bind arguments method.methodBinding = methodBinding; + methDec.binding = methodBinding; + methDec.bindArguments(); + if (methodBinding != null) // is null if binding could not be // created methodBindings[count++] = methodBinding; + + // if method did not already have a resolved scope, then add it to the environment + if(doesNotHaveResolvedScope) { + this.scope.environment().defaultPackage.addBinding( + methodBinding, methodBinding.selector, + Binding.METHOD); + } } if (count != methodBindings.length) System.arraycopy(methodBindings, 0, @@ -211,83 +228,6 @@ public class SourceTypeBinding extends ReferenceBinding { setMethods(methodBindings); } - // private void addDefaultAbstractMethods() { - // if ((this.tagBits & TagBits.KnowsDefaultAbstractMethods) != 0) return; - // - // this.tagBits |= TagBits.KnowsDefaultAbstractMethods; - // if (isClass() && isAbstract()) { - // if (this.scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_2) - // return; // no longer added for post 1.2 targets - // - // ReferenceBinding[] itsInterfaces = superInterfaces(); - // if (itsInterfaces != Binding.NO_SUPERINTERFACES) { - // FunctionBinding[] defaultAbstracts = null; - // int defaultAbstractsCount = 0; - // ReferenceBinding[] interfacesToVisit = itsInterfaces; - // int nextPosition = interfacesToVisit.length; - // for (int i = 0; i < nextPosition; i++) { - // ReferenceBinding superType = interfacesToVisit[i]; - // if (superType.isValidBinding()) { - // FunctionBinding[] superMethods = superType.methods(); - // nextAbstractMethod: for (int m = superMethods.length; --m >= 0;) { - // FunctionBinding method = superMethods[m]; - // // explicitly implemented ? - // if (implementsMethod(method)) - // continue nextAbstractMethod; - // if (defaultAbstractsCount == 0) { - // defaultAbstracts = new FunctionBinding[5]; - // } else { - // // already added as default abstract ? - // for (int k = 0; k < defaultAbstractsCount; k++) { - // FunctionBinding alreadyAdded = defaultAbstracts[k]; - // if (CharOperation.equals(alreadyAdded.selector, method.selector) && - // alreadyAdded.areParametersEqual(method)) - // continue nextAbstractMethod; - // } - // } - // FunctionBinding defaultAbstract = new FunctionBinding( - // method.modifiers | ExtraCompilerModifiers.AccDefaultAbstract, - // method.selector, - // method.returnType, - // method.parameters, - // method.thrownExceptions, - // this); - // if (defaultAbstractsCount == defaultAbstracts.length) - // System.arraycopy(defaultAbstracts, 0, defaultAbstracts = new - // FunctionBinding[2 * defaultAbstractsCount], 0, defaultAbstractsCount); - // defaultAbstracts[defaultAbstractsCount++] = defaultAbstract; - // } - // - // if ((itsInterfaces = superType.superInterfaces()) != - // Binding.NO_SUPERINTERFACES) { - // int itsLength = itsInterfaces.length; - // if (nextPosition + itsLength >= interfacesToVisit.length) - // System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new - // ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); - // nextInterface : for (int a = 0; a < itsLength; a++) { - // ReferenceBinding next = itsInterfaces[a]; - // for (int b = 0; b < nextPosition; b++) - // if (next == interfacesToVisit[b]) continue nextInterface; - // interfacesToVisit[nextPosition++] = next; - // } - // } - // } - // } - // if (defaultAbstractsCount > 0) { - // int length = this.methods.length; - // System.arraycopy(this.methods, 0, this.methods = new - // FunctionBinding[length + defaultAbstractsCount], 0, length); - // System.arraycopy(defaultAbstracts, 0, this.methods, length, - // defaultAbstractsCount); - // // re-sort methods - // length = length + defaultAbstractsCount; - // if (length > 1) - // ReferenceBinding.sortMethods(this.methods, 0, length); - // // this.tagBits |= TagBits.AreMethodsSorted; -- already set in #methods() - // } - // } - // } - // } public int kind() { return Binding.TYPE; } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/util/Util.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/util/Util.java index 3a288354..c02abbc4 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/util/Util.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/util/Util.java @@ -29,10 +29,6 @@ import org.eclipse.wst.jsdt.core.ast.IThisReference; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference; -/** - * No classes outside of this package and the JRE should be used to ensure - * that the parser update mechanisms are runnable. - */ public class Util implements SuffixConstants { public interface Displayable { @@ -504,14 +500,14 @@ public class Util implements SuffixConstants { return buffer.toString(); } - /* - * For SNR it returns the name - * For FR it construct a Qualified name separated by '.' - * - * If at any point it hits a portion of the Field reference that is - * not supported (such as a function call, a prototype, or this ) + /** + * <p>Builds a type name from an expression by iterating over all parts of the expression.<p> + * + * @param expression to iterate over and build a type name from + * @return type name built from iterating over the given <code>expression</code>, or + * <code>null</code> if a type name can not be built from the given expression */ - public final static char [] getTypeName( IExpression expression ){ + public final static char[] getTypeName(IExpression expression) { IExpression currExpr = expression; @@ -572,6 +568,4 @@ public class Util implements SuffixConstants { return selector; } - - } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/Logger.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/Logger.java new file mode 100644 index 00000000..c236141a --- /dev/null +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/Logger.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.internal.core; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.wst.jsdt.core.JavaScriptCore; +import org.osgi.framework.Bundle; + +/** +* +* Provisional API: This class/interface is part of an interim API that is still under development and expected to +* change significantly before reaching stability. It is being made available at this early stage to solicit feedback +* from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken +* (repeatedly) as the API evolves. +* +* @see org.eclipse.wst.jsdt.web.core.internal.Logger +*/ +public class Logger { + public static final int ERROR = IStatus.ERROR; // 4 + public static final int ERROR_DEBUG = 200 + Logger.ERROR; + public static final int INFO = IStatus.INFO; // 1 + public static final int INFO_DEBUG = 200 + Logger.INFO; + public static final int OK = IStatus.OK; // 0 + public static final int OK_DEBUG = 200 + Logger.OK; + private static final String PLUGIN_ID = JavaScriptCore.PLUGIN_ID; + public static final int WARNING = IStatus.WARNING; // 2 + public static final int WARNING_DEBUG = 200 + Logger.WARNING; + + /** + * Adds message to log. + * + * @param level + * severity level of the message (OK, INFO, WARNING, ERROR, + * OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG) + * @param message + * text to add to the log + * @param exception + * exception thrown + */ + protected static void _log(int level, String message, Throwable exception) { + if (level == Logger.OK_DEBUG || level == Logger.INFO_DEBUG || level == Logger.WARNING_DEBUG || level == Logger.ERROR_DEBUG) { + if (!Logger.isDebugging()) { + return; + } + } + int severity = IStatus.OK; + switch (level) { + case INFO_DEBUG: + case INFO: + severity = IStatus.INFO; + break; + case WARNING_DEBUG: + case WARNING: + severity = IStatus.WARNING; + break; + case ERROR_DEBUG: + case ERROR: + severity = IStatus.ERROR; + } + message = (message != null) ? message : "null"; //$NON-NLS-1$ + Status statusObj = new Status(severity, Logger.PLUGIN_ID, severity, message, exception); + Bundle bundle = Platform.getBundle(Logger.PLUGIN_ID); + if (bundle != null) { + Platform.getLog(bundle).log(statusObj); + } + } + + /** + * @return true if the platform is debugging + */ + public static boolean isDebugging() { + return Platform.inDebugMode(); + } + + public static void log(int level, String message) { + Logger._log(level, message, null); + } + + public static void log(int level, String message, Throwable exception) { + Logger._log(level, message, exception); + } + + public static void logException(String message, Throwable exception) { + Logger._log(Logger.ERROR, message, exception); + } + + public static void logException(Throwable exception) { + Logger._log(Logger.ERROR, exception.getMessage(), exception); + } +} diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/NameLookup.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/NameLookup.java index 440c05f2..aaf43abf 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/NameLookup.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/NameLookup.java @@ -307,10 +307,6 @@ public class NameLookup implements SuffixConstants { String path, AccessRestriction access) { if (excludePath!=null && path.equals(excludePath)) return false; - for (int i = 0; workingCopies!=null && i < workingCopies.length; i++) { - if (workingCopies[i].getPath().toString().equals(path)) - return false; - } foundPaths.add(path); return true; } @@ -2149,9 +2145,6 @@ public class NameLookup implements SuffixConstants { Path excludePath= (exclude!=null)? new Path(exclude) : null; MyRequestor requestor=new MyRequestor(); -// JavaElementRequestor elementRequestor = new JavaElementRequestor(); -// seekPackageFragments(packageName, false, elementRequestor); -// IPackageFragment[] packages= elementRequestor.getPackageFragments(); seekBindingsInWorkingCopies(bindingName, bindingType, -1, partialMatch, bindingName, acceptFlags, requestor); if (requestor.element != null) { diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/SearchableEnvironment.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/SearchableEnvironment.java index 24abd61a..3dd28835 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/SearchableEnvironment.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/SearchableEnvironment.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -36,6 +36,7 @@ import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType; import org.eclipse.wst.jsdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.wst.jsdt.internal.compiler.impl.ITypeRequestor; import org.eclipse.wst.jsdt.internal.core.search.BasicSearchEngine; +import org.eclipse.wst.jsdt.internal.core.search.IConstructorRequestor; import org.eclipse.wst.jsdt.internal.core.search.IRestrictedAccessBindingRequestor; import org.eclipse.wst.jsdt.internal.core.search.IRestrictedAccessTypeRequestor; @@ -674,6 +675,108 @@ public class SearchableEnvironment implements INameEnvironment, } } + /** + * <p>The progress monitor is used to be able to cancel completion operations</p> + * + * <p>Find constructor declarations that are defined + * in the current environment and whose name starts with the + * given prefix. The prefix is a qualified name separated by periods + * or a simple name (ex. foo.bar.V or V).</p> + * + * <p>The constructors found are passed to + * {@link ISearchRequestor#acceptConstructor(int, char[], int, char[][], char[][], String, AccessRestriction)}</p> + * + * @param prefix to use in the search + * @param storage to report constructor declarations matching the given prefix to + */ + public void findConstructorDeclarations(char[] prefix, final ISearchRequestor storage) { + final String excludePath; + if (this.unitToSkip != null && this.unitToSkip instanceof IJavaScriptElement) { + excludePath = ((IJavaScriptElement) this.unitToSkip).getPath().toString(); + } else { + excludePath = null; + } + + IProgressMonitor progressMonitor = new IProgressMonitor() { + boolean isCanceled = false; + public void beginTask(String name, int totalWork) { + // implements interface method + } + public void done() { + // implements interface method + } + public void internalWorked(double work) { + // implements interface method + } + public boolean isCanceled() { + return this.isCanceled; + } + public void setCanceled(boolean value) { + this.isCanceled = value; + } + public void setTaskName(String name) { + // implements interface method + } + public void subTask(String name) { + // implements interface method + } + public void worked(int work) { + // implements interface method + } + }; + + IConstructorRequestor constructorRequestor = new IConstructorRequestor() { + /** + * @see org.eclipse.wst.jsdt.internal.core.search.IConstructorRequestor#acceptConstructor( + * int, char[], int, char[][], char[][], java.lang.String, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction) + */ + public void acceptConstructor( + int modifiers, + char[] typeName, + int parameterCount, + char[][] parameterTypes, + char[][] parameterNames, + String path, + AccessRestriction access) { + + if (excludePath != null && excludePath.equals(path)) + return; + + storage.acceptConstructor( + modifiers, + typeName, + parameterCount, + parameterTypes, + parameterNames, + path, + access); + } + }; + + /* when matching on "Test|" will match on + * Test + * TestBar + * foo.Test + * foo.TestBar + * test.foo.Bar + */ + int matchRule = SearchPattern.R_REGEXP_MATCH; + String escapedPrefix = new String(prefix); + escapedPrefix.replaceAll("\\.", "\\."); //replace all "." with "\." + String regex = "(.*\\." + escapedPrefix + "[^\\.]*)|(" + escapedPrefix + ".*)"; + + try { + new BasicSearchEngine(this.workingCopies).searchAllConstructorDeclarations( + regex.toCharArray(), + matchRule, + this.searchScope, + constructorRequestor, + CANCEL_IF_NOT_READY_TO_SEARCH, + progressMonitor); + } catch (OperationCanceledException e) { + Logger.logException("Constructor search operation canceled.", e); + } + } /** * Returns all types whose name starts with the given (qualified) diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/index/Index.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/index/Index.java index e0122d0d..868f4831 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/index/Index.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/index/Index.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,6 +12,7 @@ package org.eclipse.wst.jsdt.internal.core.index; import java.io.File; import java.io.IOException; +import java.util.regex.Pattern; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; @@ -83,6 +84,12 @@ public static boolean isMatch(char[] pattern, char[] word, int matchRule) { return pattern[0] == word[0] && patternLength <= wordLength && CharOperation.prefixEquals(pattern, word); case SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE : return CharOperation.match(pattern, word, true); + case SearchPattern.R_REGEXP_MATCH: { + return Pattern.compile(new String(pattern), Pattern.CASE_INSENSITIVE).matcher(new String(word)).matches(); + } + case SearchPattern.R_REGEXP_MATCH | SearchPattern.R_CASE_SENSITIVE: { + return Pattern.matches(new String(pattern), new String(word)); + } } return false; } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java index d0af14a2..baa3bc4b 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -67,6 +67,7 @@ import org.eclipse.wst.jsdt.internal.core.JavaModelManager; import org.eclipse.wst.jsdt.internal.core.JavaProject; import org.eclipse.wst.jsdt.internal.core.search.indexing.IIndexConstants; import org.eclipse.wst.jsdt.internal.core.search.indexing.IndexManager; +import org.eclipse.wst.jsdt.internal.core.search.matching.ConstructorDeclarationPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.DeclarationOfAccessedFieldsPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.DeclarationOfReferencedMethodsPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.DeclarationOfReferencedTypesPattern; @@ -85,7 +86,7 @@ import org.eclipse.wst.jsdt.internal.core.util.Util; /** * Search basic engine. Public search engine (see {@link org.eclipse.wst.jsdt.core.search.SearchEngine} * for detailed comment), now uses basic engine functionalities. - * Note that serch basic engine does not implement deprecated functionalities... + * Note that search basic engine does not implement depreciated functionalities... */ public class BasicSearchEngine { @@ -518,7 +519,6 @@ public class BasicSearchEngine { final char[] bindingName, final int bindingType, final int matchRule, -// int searchFor, IJavaScriptSearchScope scope, final IRestrictedAccessBindingRequestor nameRequestor, int waitingPolicy, @@ -534,16 +534,6 @@ public class BasicSearchEngine { Util.verbose(" - scope: "+scope); //$NON-NLS-1$ } - // Return on invalid combination of package and type names -// if (packageName == null || packageName.length == 0) { -// if (bindingName != null && bindingName.length == 0) { -// if (VERBOSE) { -// Util.verbose(" => return no result due to invalid empty values for package and type names!"); //$NON-NLS-1$ -// } -// return; -// } -// } - IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); SearchPattern searchPattern=null; char suffix=0; @@ -642,47 +632,9 @@ public class BasicSearchEngine { public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) { // Filter unexpected types JavaSearchPattern record = (JavaSearchPattern)indexRecord; -// if (record.enclosingTypeNames == IIndexConstants.ONE_ZERO_CHAR) { -// return true; // filter out local and anonymous classes -// } - switch (copiesLength) { - case 0: - break; - case 1: - if (singleWkcpPath.equals(documentPath)) { - return true; // fliter out *the* working copy - } - break; - default: - if (workingCopyPaths.contains(documentPath)) { - return true; // filter out working copies - } - break; - } // Accept document path AccessRestriction accessRestriction = null; -// if (access != null) { -// // Compute document relative path -// int pkgLength = (record.pkg==null || record.pkg.length==0) ? 0 : record.pkg.length+1; -// int nameLength = record.simpleName==null ? 0 : record.simpleName.length; -// char[] path = new char[pkgLength+nameLength]; -// int pos = 0; -// if (pkgLength > 0) { -// System.arraycopy(record.pkg, 0, path, pos, pkgLength-1); -// CharOperation.replace(path, '.', '/'); -// path[pkgLength-1] = '/'; -// pos += pkgLength; -// } -// if (nameLength > 0) { -// System.arraycopy(record.simpleName, 0, path, pos, nameLength); -// pos += nameLength; -// } -// // Update access restriction if path is not empty -// if (pos > 0) { -// accessRestriction = access.getViolatedRestriction(path); -// } -// } int modifiers=ClassFileConstants.AccPublic; char[] packageName=null; char[] simpleBindingName=null; @@ -1583,4 +1535,106 @@ public class BasicSearchEngine { SearchPattern pattern = new DeclarationOfReferencedMethodsPattern(enclosingElement); searchDeclarations(enclosingElement, requestor, pattern, monitor); } + + /** + * <p>Used to search all constructor declarations for ones that match the given type name using the given role, + * in the given scope, reporting to the given requester.</p> + * + * @param typeNamePattern type name pattern to search for + * @param typeMatchRule Search pattern matching rule to use with the given <code>typeNamePattern</code> + * @param scope scope of the search + * @param nameRequester requester to report findings to + * @param waitingPolicy Policy to use when waiting for the index + * @param progressMonitor monitor to report index search progress to + * + * @see SearchPattern#R_CAMELCASE_MATCH + * @see SearchPattern#R_CASE_SENSITIVE + * @see SearchPattern#R_EQUIVALENT_MATCH + * @see SearchPattern#R_EXACT_MATCH + * @see SearchPattern#R_FULL_MATCH + * @see SearchPattern#R_PATTERN_MATCH + * @see SearchPattern#R_PREFIX_MATCH + * @see SearchPattern#R_REGEXP_MATCH + * + * @see IJavaScriptSearchConstants#FORCE_IMMEDIATE_SEARCH + * @see IJavaScriptSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH + * @see IJavaScriptSearchConstants#WAIT_UNTIL_READY_TO_SEARCH + */ + public void searchAllConstructorDeclarations( + final char[] typeNamePattern, + final int typeMatchRule, + IJavaScriptSearchScope scope, + final IConstructorRequestor nameRequester, + int waitingPolicy, + IProgressMonitor progressMonitor) { + + // Debug + if (VERBOSE) { + Util.verbose("BasicSearchEngine.searchAllConstructorDeclarations(char[], char[], int, IJavaSearchScope, IRestrictedAccessConstructorRequestor, int, IProgressMonitor)"); //$NON-NLS-1$ + Util.verbose(" - type name: "+(typeNamePattern==null?"null":new String(typeNamePattern))); //$NON-NLS-1$ //$NON-NLS-2$ + Util.verbose(" - type match rule: "+getMatchRuleString(typeMatchRule)); //$NON-NLS-1$ + Util.verbose(" - scope: "+scope); //$NON-NLS-1$ + } + + // Create pattern + IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); + final ConstructorDeclarationPattern pattern = new ConstructorDeclarationPattern( + typeNamePattern, + typeMatchRule); + + // Index requester + IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){ + public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) { + // Filter unexpected types + ConstructorDeclarationPattern record = (ConstructorDeclarationPattern)indexRecord; + + + // Accept document path + AccessRestriction accessRestriction = null; + if (access != null) { + // Compute document relative path + int nameLength = record.declaringSimpleName==null ? 0 : record.declaringSimpleName.length; + char[] path = new char[nameLength]; + int pos = 0; + + if (nameLength > 0) { + System.arraycopy(record.declaringSimpleName, 0, path, pos, nameLength); + pos += nameLength; + } + // Update access restriction if path is not empty + if (pos > 0) { + accessRestriction = access.getViolatedRestriction(path); + } + } + nameRequester.acceptConstructor( + record.modifiers, + record.declaringSimpleName, + record.parameterCount, + record.parameterTypes, + record.parameterNames, + documentPath, + accessRestriction); + return true; + } + }; + + try { + if (progressMonitor != null) { + progressMonitor.beginTask(Messages.engine_searching, 1000); + } + // Find constructor declarations from index + indexManager.performConcurrentJob( + new PatternSearchJob( + pattern, + getDefaultSearchParticipant(), // JavaScript search only + scope, + searchRequestor), + waitingPolicy, + progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 1000)); + } finally { + if (progressMonitor != null) { + progressMonitor.done(); + } + } + } } diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/IConstructorRequestor.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/IConstructorRequestor.java new file mode 100644 index 00000000..e8cccebc --- /dev/null +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/IConstructorRequestor.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.internal.core.search; + +import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction; + +/** + * A <code>IConstructorRequestor</code> collects search results from a <code>searchAllConstructorDeclarations</code> + * query to a <code>SearchBasicEngine</code> providing restricted access information of declaring type when a constructor is accepted. + */ +public interface IConstructorRequestor { + + /** + * <p>Accepts a constructor found during an index search.</p> + * + * @param modifiers Modifiers to the constructor such as public/private + * @param typeName Name of the type the constructor is for + * @param parameterCount Number of parameters for the constructor, or -1 for a default constructor + * @param parameterTypes Type names of the parameters, should be same length as <code>parameterCount</code> + * @param parameterNames Names of the parameters, should be same length as <code>parameterCount</code> + * @param path to the document containing the constructor match + * @param access Accessibility of the constructor + */ + public void acceptConstructor( + int modifiers, + char[] typeName, + int parameterCount, + char[][] parameterTypes, + char[][] parameterNames, + String path, + AccessRestriction access); +} diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/AbstractIndexer.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/AbstractIndexer.java index 7650b84f..9330e63b 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/AbstractIndexer.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/AbstractIndexer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,6 +13,7 @@ package org.eclipse.wst.jsdt.internal.core.search.indexing; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.core.search.SearchDocument; import org.eclipse.wst.jsdt.internal.core.JavaModelManager; +import org.eclipse.wst.jsdt.internal.core.search.matching.ConstructorDeclarationPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.ConstructorPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.FieldPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.MethodPattern; @@ -44,9 +45,9 @@ public abstract class AbstractIndexer implements IIndexConstants { SuperTypeReferencePattern.createIndexKey( modifiers, packageName, name, enclosingTypeNames, superclass)); } - public void addConstructorDeclaration(char[] typeName, char[][] parameterTypes) { + public void addConstructorDeclaration(char[] typeName, char[][] parameterTypes, char[][] parameterNames, int modifiers) { int argCount = parameterTypes == null ? 0 : parameterTypes.length; - addIndexEntry(CONSTRUCTOR_DECL, ConstructorPattern.createIndexKey(CharOperation.lastSegment(typeName,'.'), argCount)); + addIndexEntry(CONSTRUCTOR_DECL, ConstructorDeclarationPattern.createDeclarationIndexKey(typeName, argCount, parameterTypes, parameterNames, modifiers)); if (parameterTypes != null) { for (int i = 0; i < argCount; i++) diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/IIndexConstants.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/IIndexConstants.java index ecdb80e6..5d6366cf 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/IIndexConstants.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/IIndexConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -32,6 +32,7 @@ public interface IIndexConstants { char CLASS_SUFFIX = 'C'; char TYPE_SUFFIX = 0; char SEPARATOR= '/'; + char PARAMETER_SEPARATOR= ','; char SECONDARY_SUFFIX = 'S'; char[] ONE_STAR = new char[] {'*'}; diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/SourceIndexerRequestor.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/SourceIndexerRequestor.java index f7fc2991..5fadb995 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/SourceIndexerRequestor.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/indexing/SourceIndexerRequestor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -165,7 +165,7 @@ public void enterCompilationUnit() { * @see ISourceElementRequestor#enterConstructor(MethodInfo) */ public void enterConstructor(MethodInfo methodInfo) { - this.indexer.addConstructorDeclaration(methodInfo.name, methodInfo.parameterTypes); + this.indexer.addConstructorDeclaration(methodInfo.name, methodInfo.parameterTypes, methodInfo.parameterNames, methodInfo.modifiers); this.methodDepth++; } /** diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/matching/ConstructorDeclarationPattern.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/matching/ConstructorDeclarationPattern.java new file mode 100644 index 00000000..8cd2aa2c --- /dev/null +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/matching/ConstructorDeclarationPattern.java @@ -0,0 +1,250 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.internal.core.search.matching; + +import org.eclipse.wst.jsdt.core.compiler.CharOperation; +import org.eclipse.wst.jsdt.core.search.SearchPattern; +import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants; + +/** + * <p>Pattern used to find and store constructor declarations.</p> + */ +public class ConstructorDeclarationPattern extends ConstructorPattern { + public int modifiers; + public char[][] parameterTypes; + public char[][] parameterNames; + + public ConstructorDeclarationPattern(char[] declaringSimpleName, int matchRule) { + this(matchRule); + this.declaringSimpleName = (this.isCaseSensitive || this.isCamelCase) ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName); + this.findDeclarations = true; + this.findReferences = false; + this.parameterCount = -1; + } + + ConstructorDeclarationPattern(int matchRule) { + super(matchRule); + } + + public SearchPattern getBlankPattern() { + return new ConstructorDeclarationPattern(R_EXACT_MATCH | R_CASE_SENSITIVE); + } + public char[][] getIndexCategories() { + return DECL_CATEGORIES; + } + public boolean matchesDecodedKey(SearchPattern decodedPattern) { + ConstructorDeclarationPattern pattern = (ConstructorDeclarationPattern) decodedPattern; + + return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1 || this.varargs) + && matchesName(this.declaringSimpleName, pattern.declaringSimpleName); + } + + /** + * <p>Decodes an index key made with {@link #createDeclarationIndexKey(char[], int, char[][], char[][], int)} into the + * parameters of this pattern.</p> + * + * @see org.eclipse.wst.jsdt.internal.core.search.matching.ConstructorPattern#decodeIndexKey(char[]) + * + * @see #createDeclarationIndexKey(char[], int, char[][], char[][], int) + */ + public void decodeIndexKey(char[] key) { + //decode type name + int last = key.length - 1; + int slash = CharOperation.indexOf(SEPARATOR, key, 0); + this.declaringSimpleName = CharOperation.subarray(key, 0, slash); + + int start = slash + 1; + slash = CharOperation.indexOf(SEPARATOR, key, start); + last = slash - 1; + + //decode parameter count + this.parameterCount = 0; + int power = 1; + for (int i = last; i >= start; i--) { + if (i == last) { + this.parameterCount = key[i] - '0'; + } else { + power *= 10; + this.parameterCount += power * (key[i] - '0'); + } + } + + // initialize optional fields + this.modifiers = 0; + this.parameterTypes = null; + this.parameterNames = null; + + /* if no parameters just decode modifiers + * else decode parameters and modifiers + */ + start = slash + 1; + if (this.parameterCount == 0) { + slash = slash + 3; + last = slash - 1; + + this.modifiers = key[last-1] + (key[last]<<16); + } else if (this.parameterCount > 0){ + slash = CharOperation.indexOf(SEPARATOR, key, start); + last = slash - 1; + + + this.parameterTypes = CharOperation.splitOn(PARAMETER_SEPARATOR, key, start, slash); + + start = slash + 1; + slash = CharOperation.indexOf(SEPARATOR, key, start); + last = slash - 1; + + if (slash != start) { + this.parameterNames = CharOperation.splitOn(PARAMETER_SEPARATOR, key, start, slash); + } + + slash = slash + 3; + last = slash - 1; + + this.modifiers = key[last-1] + (key[last]<<16); + } else { + this.modifiers = ClassFileConstants.AccPublic; + } + } + + /** + * <p>Creates a constructor index key based on the given information to be placed in the index.</p> + * + * @param typeName Name of the type the constructor is for + * @param parameterCount Number of parameters for the constructor, or -1 for a default constructor + * @param parameterTypes Type names of the parameters, should be same length as <code>parameterCount</code> + * @param parameterNames Names of the parameters, should be same length as <code>parameterCount</code> + * @param modifiers Modifiers to the constructor such as public/private + * + * @return Constructor index key based on the given information to be used in an index + */ + public static char[] createDeclarationIndexKey( + char[] typeName, + int parameterCount, + char[][] parameterTypes, + char[][] parameterNames, + int modifiers) { + + char[] countChars; + char[] parameterTypesChars = null; + char[] parameterNamesChars = null; + + //use pre-made char array for arg counts less then 10, else build a new one + countChars = parameterCount < 10 ? COUNTS[parameterCount] : ("/" + String.valueOf(parameterCount)).toCharArray(); //$NON-NLS-1$ + + if (parameterCount > 0) { + //get param types + if (parameterTypes != null && parameterTypes.length == parameterCount) { + char[][] parameterTypeErasures = new char[parameterCount][]; + for (int i = 0; i < parameterTypes.length; i++) { + parameterTypeErasures[i] = getTypeErasure(parameterTypes[i]); + } + parameterTypesChars = CharOperation.concatWith(parameterTypeErasures, PARAMETER_SEPARATOR, false); + } + + //get param names + if (parameterNames != null && parameterNames.length == parameterCount) { + parameterNamesChars = CharOperation.concatWith(parameterNames, PARAMETER_SEPARATOR); + } + } + + //get lengths + int typeNameLength = typeName == null ? 0 : typeName.length; + int countCharsLength = countChars.length; + int parameterTypesLength = parameterTypesChars == null ? 0 : parameterTypesChars.length; + int parameterNamesLength = parameterNamesChars == null ? 0 : parameterNamesChars.length; + + int resultLength = typeNameLength + countCharsLength; + + //add length for parameters and separators + if (parameterCount > 0) { + resultLength += parameterTypesLength + parameterNamesLength + 2; //SEPARATOR=1 + SEPARATOR=1 + } + + //add length for modifiers and separator + resultLength += 3; + + //create result char array + char[] result = new char[resultLength]; + + //add type name to result + int pos = 0; + if (typeNameLength > 0) { + System.arraycopy(typeName, 0, result, pos, typeNameLength); + pos += typeNameLength; + } + + //add param count to result + if (countCharsLength > 0) { + System.arraycopy(countChars, 0, result, pos, countCharsLength); + pos += countCharsLength; + } + + // if params add to result + if (parameterCount > 0) { + //add param types + result[pos++] = SEPARATOR; + if (parameterTypesLength > 0) { + System.arraycopy(parameterTypesChars, 0, result, pos, parameterTypesLength); + + pos += parameterTypesLength; + } + + //add param names + result[pos++] = SEPARATOR; + if (parameterNamesLength > 0) { + System.arraycopy(parameterNamesChars, 0, result, pos, parameterNamesLength); + pos += parameterNamesLength; + } + + } + + //add modifiers + result[pos++] = SEPARATOR; + result[pos++] = (char) modifiers; + result[pos++] = (char) (modifiers>>16); + + return result; + } + + private static char[] getTypeErasure(char[] typeName) { + char[] typeErasurename = new char[0]; + if(typeName != null) { + int index; + if ((index = CharOperation.indexOf('<', typeName)) == -1) return typeName; + + int length = typeName.length; + typeErasurename = new char[length - 2]; + + System.arraycopy(typeName, 0, typeErasurename, 0, index); + + int depth = 1; + for (int i = index + 1; i < length; i++) { + switch (typeName[i]) { + case '<': + depth++; + break; + case '>': + depth--; + break; + default: + if (depth == 0) { + typeErasurename[index++] = typeName[i]; + } + break; + } + } + + System.arraycopy(typeErasurename, 0, typeErasurename = new char[index], 0, index); + } + return typeErasurename; + } +} diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/matching/MethodPattern.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/matching/MethodPattern.java index 63c0b483..703bb57d 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/matching/MethodPattern.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/matching/MethodPattern.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -55,8 +55,8 @@ char[][] methodArguments; protected static char[][] REF_CATEGORIES = { METHOD_REF }; protected static char[][] REF_AND_DECL_CATEGORIES = { METHOD_REF, METHOD_DECL }; protected static char[][] DECL_CATEGORIES = { METHOD_DECL }; -protected static char[][] FUNCTION_REF_AND_DECL_CATEGORIES = { METHOD_REF, FUNCTION_DECL }; -protected static char[][] FUNCTION_DECL_CATEGORIES = { FUNCTION_DECL }; +protected static char[][] FUNCTION_REF_AND_DECL_CATEGORIES = { METHOD_REF, FUNCTION_DECL, METHOD_DECL }; +protected static char[][] FUNCTION_DECL_CATEGORIES = { FUNCTION_DECL, METHOD_DECL }; /** * Method entries are encoded as selector '/' Arity: diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavaCompletionProposalComputer.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavaCompletionProposalComputer.java index 86d0fb8b..250d414c 100644 --- a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavaCompletionProposalComputer.java +++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavaCompletionProposalComputer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -163,6 +163,8 @@ public class JavaCompletionProposalComputer implements IJavaCompletionProposalCo collector.setAllowsRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_IMPORT, true); collector.setAllowsRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.METHOD_IMPORT, true); + collector.setAllowsRequiredProposals(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF, true); + // Set the favorite list to propose static members - since 3.3 collector.setFavoriteReferences(getFavoriteStaticMembers()); diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavaMethodCompletionProposal.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavaMethodCompletionProposal.java index 7f45bb6b..791022cb 100644 --- a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavaMethodCompletionProposal.java +++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavaMethodCompletionProposal.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,6 +16,7 @@ import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.wst.jsdt.core.CompletionProposal; import org.eclipse.wst.jsdt.core.IJavaScriptProject; import org.eclipse.wst.jsdt.core.Signature; +import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin; import org.eclipse.wst.jsdt.ui.PreferenceConstants; import org.eclipse.wst.jsdt.ui.text.java.JavaContentAssistInvocationContext; @@ -76,7 +77,9 @@ public class JavaMethodCompletionProposal extends LazyJavaCompletionProposal { } protected char[] computeTriggerCharacters() { - if (fProposal.getKind() == CompletionProposal.METHOD_NAME_REFERENCE) + if (fProposal.getKind() == CompletionProposal.METHOD_NAME_REFERENCE || + fProposal.getKind() == CompletionProposal.METHOD_REF || + fProposal.getKind() == CompletionProposal.CONSTRUCTOR_INVOCATION) return METHOD_NAME_TRIGGERS; if (hasParameters()) return METHOD_WITH_ARGUMENTS_TRIGGERS; @@ -101,7 +104,7 @@ public class JavaMethodCompletionProposal extends LazyJavaCompletionProposal { } private boolean computeHasParameters() throws IllegalArgumentException { - return Signature.getParameterCount(fProposal.getSignature()) > 0; + return fProposal.hasParameters() || Signature.getParameterCount(fProposal.getSignature()) > 0; } /** @@ -187,8 +190,18 @@ public class JavaMethodCompletionProposal extends LazyJavaCompletionProposal { * 4) by parameter type names */ char[] name= fProposal.getName(); - char[] parameterList= Signature.toCharArray(fProposal.getSignature(), null, null, false, false); - int parameterCount= Signature.getParameterCount(fProposal.getSignature()) % 10; // we don't care about insane methods with >9 parameters + char[] signature = fProposal.getSignature(); + char[] parameterList; + int parameterCount; + if(signature != null) { + parameterList= Signature.toCharArray(fProposal.getSignature(), null, null, false, false); + parameterCount= Signature.getParameterCount(fProposal.getSignature()) % 10; // we don't care about insane methods with >9 parameters + } else { + char[][] params = this.fProposal.getParamaterNames(); + parameterList = CharOperation.concatWith(params, ','); + parameterCount = params.length % 10; // we don't care about insane methods with >9 parameters + } + StringBuffer buf= new StringBuffer(name.length + 2 + parameterList.length); buf.append(name); @@ -205,6 +218,17 @@ public class JavaMethodCompletionProposal extends LazyJavaCompletionProposal { if (super.isValidPrefix(prefix)) return true; + // match on last part of the proposal + String name = new String(fProposal.getName()); + int lastSeperatorIndex = name.lastIndexOf('.'); + if(lastSeperatorIndex != -1) { + name = name.substring(lastSeperatorIndex+1); + name = name.toLowerCase(); + if(name.indexOf(prefix.toLowerCase()) == 0) { + return true; + } + } + String word= getDisplayString(); if (isInJavadoc()) { int idx = word.indexOf("{@link "); //$NON-NLS-1$ diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/MethodProposalInfo.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/MethodProposalInfo.java index db544dc2..43721906 100644 --- a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/MethodProposalInfo.java +++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/MethodProposalInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -62,8 +62,20 @@ public final class MethodProposalInfo extends MemberProposalInfo { String typeName = SignatureUtil.stripSignatureToFQN(String .valueOf(declarationSignature)); String name = String.valueOf(fProposal.getName()); - String[] parameters = Signature.getParameterTypes(String - .valueOf(fProposal.getSignature())); + + //get the parameter type names + String[] paramTypeNameStrings; + char[] signature = fProposal.getSignature(); + if(signature != null && signature.length > 0) { + paramTypeNameStrings = Signature.getParameterTypes(String.valueOf(fProposal.getSignature())); + } else { + char[][] paramTypeNameChars = this.fProposal.getParameterTypeNames(); + paramTypeNameStrings = new String[paramTypeNameChars.length]; + for(int i = 0; i < paramTypeNameChars.length; ++i) { + paramTypeNameStrings[i] = String.valueOf(paramTypeNameChars[i]); + } + } + //search all the possible types until a match is found IType[] types = fJavaProject.findTypes(typeName); if(types != null && types.length >0) { @@ -72,7 +84,7 @@ public final class MethodProposalInfo extends MemberProposalInfo { if (type != null) { boolean isConstructor = fProposal.isConstructor(); try { - func = findMethod(name, parameters, isConstructor, type); + func = findMethod(name, paramTypeNameStrings, isConstructor, type); } catch(JavaScriptModelException e) { //ignore, could not find method } @@ -81,7 +93,7 @@ public final class MethodProposalInfo extends MemberProposalInfo { } else { ITypeRoot typeRoot=fJavaProject.findTypeRoot(typeName); if(typeRoot != null) { - func = typeRoot.getFunction(name, parameters); + func = typeRoot.getFunction(name, paramTypeNameStrings); } } } @@ -205,13 +217,17 @@ public final class MethodProposalInfo extends MemberProposalInfo { * @return the simple erased name for signature */ private String computeSimpleTypeName(String signature, Map typeVariables) { - // method equality uses erased types - String erasure=signature; - erasure= erasure.replaceAll("/", "."); //$NON-NLS-1$//$NON-NLS-2$ - String simpleName= Signature.getSimpleName(Signature.toString(erasure)); - char[] typeVar= (char[]) typeVariables.get(simpleName); - if (typeVar != null) - simpleName= String.valueOf(Signature.getSignatureSimpleName(typeVar)); + String simpleName = ""; //$NON-NLS-1$ + if(signature != null && signature.length() > 0) { + // method equality uses erased types + String erasure=signature; + erasure= erasure.replaceAll("/", "."); //$NON-NLS-1$//$NON-NLS-2$ + simpleName= Signature.getSimpleName(Signature.toString(erasure)); + char[] typeVar= (char[]) typeVariables.get(simpleName); + if (typeVar != null) { + simpleName= String.valueOf(Signature.getSignatureSimpleName(typeVar)); + } + } return simpleName; } } diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/ui/text/java/CompletionProposalCollector.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/ui/text/java/CompletionProposalCollector.java index 531dc612..d5ce9df5 100644 --- a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/ui/text/java/CompletionProposalCollector.java +++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/ui/text/java/CompletionProposalCollector.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -395,6 +395,7 @@ public class CompletionProposalCollector extends CompletionRequestor { case CompletionProposal.FIELD_REF: case CompletionProposal.JSDOC_FIELD_REF: return createFieldProposal(proposal); + case CompletionProposal.CONSTRUCTOR_INVOCATION: case CompletionProposal.METHOD_REF: case CompletionProposal.METHOD_NAME_REFERENCE: case CompletionProposal.JSDOC_METHOD_REF: @@ -544,6 +545,7 @@ public class CompletionProposalCollector extends CompletionRequestor { */ protected final char[] getDeclaringType(CompletionProposal proposal) { switch (proposal.getKind()) { + case CompletionProposal.CONSTRUCTOR_INVOCATION: case CompletionProposal.METHOD_DECLARATION: case CompletionProposal.METHOD_NAME_REFERENCE: case CompletionProposal.JSDOC_METHOD_REF: @@ -721,7 +723,7 @@ public class CompletionProposalCollector extends CompletionRequestor { if(preferenceStore.getBoolean(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES)) { String completion= String.valueOf(methodProposal.getCompletion()); // normal behavior if this is not a normal completion or has no parameters - if ((completion.length() == 0) || ((completion.length() == 1) && completion.charAt(0) == ')') || Signature.getParameterCount(methodProposal.getSignature()) == 0 || getContext().isInJsdoc()) { + if ((completion.length() == 0) || ((completion.length() == 1) && completion.charAt(0) == ')') || getContext().isInJsdoc()) { proposal= new JavaMethodCompletionProposal(methodProposal, getInvocationContext()); } else { if (preferenceStore.getBoolean(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS)) diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/ui/text/java/CompletionProposalLabelProvider.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/ui/text/java/CompletionProposalLabelProvider.java index 044208e1..66c9505d 100644 --- a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/ui/text/java/CompletionProposalLabelProvider.java +++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/ui/text/java/CompletionProposalLabelProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 IBM Corporation and others. + * Copyright (c) 2005, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -95,11 +95,18 @@ public class CompletionProposalLabelProvider { // TODO remove once https://bugs.eclipse.org/bugs/show_bug.cgi?id=85293 // gets fixed. char[] signature= methodProposal.getSignature(); - char[][] parameterNames= methodProposal.findParameterNames(null); - char[][] parameterTypes= Signature.getParameterTypes(signature); - - for (int i= 0; i < parameterTypes.length; i++) - parameterTypes[i]= createTypeDisplayName(parameterTypes[i]); + char[][] parameterNames= methodProposal.getParamaterNames(); + char[][] parameterTypes; + + //if there is a signature use that, else get type names from proposal + if(signature != null && signature.length > 0) { + parameterTypes = Signature.getParameterTypes(signature); + for (int i= 0; i < parameterTypes.length; i++) { + parameterTypes[i]= createTypeDisplayName(parameterTypes[i]); + } + } else { + parameterTypes = methodProposal.getParameterTypeNames(); + } if (Flags.isVarargs(methodProposal.getFlags())) { int index= parameterTypes.length - 1; @@ -196,7 +203,7 @@ public class CompletionProposalLabelProvider { buffer.append(','); buffer.append(' '); } - if (!Arrays.equals(Signature.ANY, parameterTypes[i])) { + if (parameterTypes[i].length > 0 & !Arrays.equals(Signature.ANY, parameterTypes[i])) { buffer.append(parameterTypes[i]); buffer.append(' '); } @@ -249,14 +256,12 @@ public class CompletionProposalLabelProvider { nameBuffer.append(" "); //$NON-NLS-1$ //@GINO: Anonymous UI Label org.eclipse.wst.jsdt.internal.core.util.Util.insertTypeLabel( returnType, nameBuffer ); - //nameBuffer.append(returnType); } } // declaring type nameBuffer.append(" - "); //$NON-NLS-1$ String declaringType= extractDeclaringTypeFQN(methodProposal); -// declaringType= Signature.getSimpleName(declaringType); //@GINO: Anonymous UI Label org.eclipse.wst.jsdt.internal.core.util.Util.insertTypeLabel( declaringType, nameBuffer ); @@ -521,6 +526,7 @@ public class CompletionProposalLabelProvider { */ public String createLabel(CompletionProposal proposal) { switch (proposal.getKind()) { + case CompletionProposal.CONSTRUCTOR_INVOCATION: case CompletionProposal.METHOD_NAME_REFERENCE: case CompletionProposal.METHOD_REF: case CompletionProposal.POTENTIAL_METHOD_DECLARATION: @@ -565,25 +571,11 @@ public class CompletionProposalLabelProvider { * @return the created image descriptor, or <code>null</code> if no image is available */ public ImageDescriptor createImageDescriptor(CompletionProposal proposal) { -// char[] compUnit = proposal.getDeclarationTypeName(); -// char[] propType = proposal.getName(); -// IJavaScriptProject project = proposal.getJavaProject(); -// -// IJsGlobalScopeContainerInitializerExtension init = null; -// IType type = proposal.getNameLookup().findType(new String(compUnit), true, NameLookup.ACCEPT_ALL); -// IPackageFragment frag = type.getPackageFragment(); -// -// if(compUnit!=null && propType!=null) -// init = JSDScopeUiUtil.findLibraryUiInitializer(new Path(new String(compUnit)),project); -// if(init!=null) { -// ImageDescriptor description = init.getImage(new Path(new String(compUnit)),new String(propType), project); -// if( description!=null) return description; -// } - final int flags= proposal.getFlags(); ImageDescriptor descriptor; switch (proposal.getKind()) { + case CompletionProposal.CONSTRUCTOR_INVOCATION: case CompletionProposal.METHOD_DECLARATION: case CompletionProposal.METHOD_NAME_REFERENCE: case CompletionProposal.METHOD_REF: |