Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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.java208
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

Back to the top