diff options
Diffstat (limited to 'bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/MethodScope.java')
-rw-r--r-- | bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/MethodScope.java | 208 |
1 files changed, 192 insertions, 16 deletions
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 57874e80..3a5930ba 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2013 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,20 +10,24 @@ *******************************************************************************/ package org.eclipse.wst.jsdt.internal.compiler.lookup; +import org.eclipse.wst.jsdt.core.ast.IAbstractVariableDeclaration; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.core.infer.InferredMethod; import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode; 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.ProgramElement; import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference; +import org.eclipse.wst.jsdt.internal.compiler.ast.Statement; import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo; import org.eclipse.wst.jsdt.internal.compiler.flow.UnconditionalFlowInfo; import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext; import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter; +import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject; /** * Particular block scope used for methods, constructors or clinits, representing @@ -43,7 +47,6 @@ public class MethodScope extends BlockScope { // flow analysis public int analysisIndex; // for setting flow-analysis id - public boolean isPropagatingInnerClassEmulation; // for local variables table attributes public int lastIndex = 0; @@ -53,8 +56,23 @@ public class MethodScope extends BlockScope { public static final char [] ARGUMENTS_NAME={'a','r','g','u','m','e','n','t','s'}; - public LocalVariableBinding argumentsBinding ; + public LocalVariableBinding argumentsBinding; + /** + * <p> + * Map of variable names to statements that have not been resolved that + * define those variables. + * </p> + */ + private HashtableOfObject fUnresolvedLocalVars; + + /** + * <p> + * Map of function names to statements that have not been resolved that + * define those variables. + * </p> + */ + private HashtableOfObject fUnresolvedLocalFuncs; public MethodScope(Scope parent, ReferenceContext context, boolean isStatic) { @@ -174,17 +192,25 @@ public class MethodScope extends BlockScope { MethodBinding methodBinding=null; // is necessary to ensure error reporting this.referenceContext = method; - method.scope = this; + method.setScope(this); int modifiers = method.modifiers | ExtraCompilerModifiers.AccUnresolved; if ((method.modifiers &(ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected))==0) modifiers|=ClassFileConstants.AccPublic; if (method.inferredMethod!=null && method.inferredMethod.isStatic) modifiers|= ClassFileConstants.AccStatic; - if (method.isConstructor() || isConstructor) { + if (isConstructor) { if (method.isDefaultConstructor() || isConstructor) { modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor; } - methodBinding = new MethodBinding(modifiers, name, TypeBinding.UNKNOWN, null, declaringClass); + TypeBinding constructorType = null; + if (method.inferredMethod!=null && method.inferredMethod.inType != null) { + constructorType=method.inferredMethod.inType.resolveType(this,method); + } + //return type still null, return type is unknown + if (constructorType==null) { + constructorType=TypeBinding.UNKNOWN; + } + methodBinding = new MethodBinding(modifiers, name, constructorType, null, constructorType instanceof ReferenceBinding ? (ReferenceBinding) constructorType : declaringClass); methodBinding.tagBits|=TagBits.IsConstructor; checkAndSetModifiersForConstructor(methodBinding); } else { @@ -200,7 +226,7 @@ public class MethodScope extends BlockScope { returnType=TypeBinding.UNKNOWN; } - if (isLocal && method.selector!=null) { + if (isLocal && method.getName()!=null) { methodBinding = new LocalFunctionBinding(modifiers, name,returnType, null, declaringClass); } else{// not local method @@ -215,12 +241,13 @@ public class MethodScope extends BlockScope { } } - methodBinding.createFunctionTypeBinding(this); - if (method.inferredMethod!=null && method.inferredMethod.isConstructor) { - methodBinding.tagBits|=TagBits.IsConstructor; - } + //methodBinding.createFunctionTypeBinding(this); +// if (method.inferredMethod!=null && method.inferredMethod.isConstructor) { +// methodBinding.tagBits|=TagBits.IsConstructor; +// } checkAndSetModifiersForMethod(methodBinding); } + methodBinding.createFunctionTypeBinding(this); this.isStatic =methodBinding.isStatic(); //set arguments @@ -399,12 +426,161 @@ public class MethodScope extends BlockScope { return s; } + /** + * <p> + * This implementation first calls super, if that returns no binding or a + * problem binding then the list of unresolved local variables is checked, + * and if there is a statement that defines a variable with the correct + * name it is resolved, and then the super implementation is called again. + * </p> + * + * <p> + * This allows {@link #addUnresolvedLocalVar(char[], Statement)} to be used in + * conjunction with this method to prevent having to resolve the entire + * {@link AbstractMethodDeclaration} associated with this scope. + * </p> + * + * @see org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope#findVariable(char[]) + */ public LocalVariableBinding findVariable(char[] variableName) { LocalVariableBinding binding = super.findVariable(variableName); - if (binding==null && CharOperation.equals(variableName,ARGUMENTS_NAME)) - binding=this.argumentsBinding; + if (binding == null && CharOperation.equals(variableName,ARGUMENTS_NAME)) { + binding = this.argumentsBinding; + } + + // if super could not find a good binding then check list of unresolved local variables + if(binding == null && this.fUnresolvedLocalVars != null) { + IAbstractVariableDeclaration statement = (IAbstractVariableDeclaration)this.fUnresolvedLocalVars.removeKey(variableName); + if(statement != null && statement instanceof ProgramElement) { + //resolve and then call super again + ((ProgramElement)statement).resolve(this); + binding = super.findVariable(variableName); + } + } + return binding; } - - -} + + /** + * <p> + * This implementation first calls super, if that returns no binding or a + * problem binding then the list of unresolved local functions is checked, + * and if there is a statement that defines a function with the correct + * name it is resolved, and then its binding is returned. + * </p> + * + * <p> + * This allows {@link #addUnresolvedLocalFunc(char[], AbstractMethodDeclaration)} to be used in + * conjunction with this method to prevent having to resolve the entire + * {@link AbstractMethodDeclaration} associated with this scope. + * </p> + * + * @see org.eclipse.wst.jsdt.internal.compiler.lookup.Scope#findMethod(org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding, char[], org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding[], org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite) + */ + public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { + MethodBinding binding = super.findMethod(receiverType, selector, argumentTypes, invocationSite); + + // if super could not find a good binding then check list of unresolved local functions + if((binding == null || !binding.isValidBinding()) && this.fUnresolvedLocalFuncs != null) { + AbstractMethodDeclaration statement = (AbstractMethodDeclaration)this.fUnresolvedLocalFuncs.removeKey(selector); + if(statement != null) { + //resolve and then return the statements binding + statement.resolve(this); + binding = statement.getBinding(); + } + } + + return binding; + } + + /** + * <p> + * This implementation first calls super, if that returns no binding or a + * problem binding then the list of unresolved local functions is checked, + * and if there is a statement that defines a function with the correct + * name it is resolved, and then its binding is returned. + * </p> + * + * <p> + * This allows {@link #addUnresolvedLocalFunc(char[], AbstractMethodDeclaration)} to be used in + * conjunction with this method to prevent having to resolve the entire + * {@link AbstractMethodDeclaration} associated with this scope. + * </p> + * + * @see org.eclipse.wst.jsdt.internal.compiler.lookup.Scope#findMethod(org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding, char[], org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding[], org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite) + */ + public MethodBinding findMethod(char[] methodName, TypeBinding[]argumentTypes, boolean checkVars) { + MethodBinding binding = super.findMethod(methodName, argumentTypes, checkVars); + + // if super could not find a good binding then check list of unresolved local functions + if((binding == null || !binding.isValidBinding()) && this.fUnresolvedLocalFuncs != null) { + AbstractMethodDeclaration methDecl = (AbstractMethodDeclaration)this.fUnresolvedLocalFuncs.removeKey(methodName); + if(methDecl != null) { + //resolve and then return the statements binding + binding = methDecl.getBinding(); + if(binding == null || !binding.isValidBinding()) { + + /* if it is anonymous, but has a name (has to to be here) then this is a + * function assignment to a variable not declared in this scope so + * build with compilation unit scope. + * + * else build with this scope */ + Scope scope = null; + if(methDecl.isAnonymous()) { + scope = this.compilationUnitScope(); + } else { + scope = this; + } + methDecl.resolve(scope); + } + binding = methDecl.getBinding(); + } + } + + return binding; + } + + /** + * <p> + * Adds an unresolved local variable defined in this scope to be resolved + * on an as needed basses. + * </p> + * + * @param name + * the name of the unresolved local variable + * @param expr + * {@link IAbstractVariableDeclaration} that defines the unresolved local variable + * that will be used to resolve it if needed + */ + public void addUnresolvedLocalVar(char[] name, IAbstractVariableDeclaration expr) { + if(name != null && name.length > 0 && expr != null) { + if(this.fUnresolvedLocalVars == null) { + this.fUnresolvedLocalVars = new HashtableOfObject(); + } + + this.fUnresolvedLocalVars.put(name, expr); + } + } + + /** + * <p> + * Adds an unresolved local function defined in this scope to be resolved + * on an as needed basses. + * </p> + * + * @param name + * the name of the unresolved local function + * @param expr + * {@link AbstractMethodDeclaration} that defines the unresolved local function + * that will be used to resolve it if needed + */ + public void addUnresolvedLocalFunc(char[] name, AbstractMethodDeclaration func) { + if(name != null && name.length > 0 && func != null) { + if(this.fUnresolvedLocalFuncs == null) { + this.fUnresolvedLocalFuncs = new HashtableOfObject(); + } + + this.fUnresolvedLocalFuncs.put(name, func); + } + } +}
\ No newline at end of file |