Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvrubezhny2014-01-17 16:16:16 +0000
committervrubezhny2014-01-20 17:31:19 +0000
commit3273bc6228fe672ff69169ffbc0d6d1d86286db4 (patch)
treed9c0f95200faec3a5e78f76ce1ad66649acc2295
parent4f73ccf2e33dd85457081780d4acb34f01377f5b (diff)
downloadwebtools.maps-3273bc6228fe672ff69169ffbc0d6d1d86286db4.tar.gz
webtools.maps-3273bc6228fe672ff69169ffbc0d6d1d86286db4.tar.xz
webtools.maps-3273bc6228fe672ff69169ffbc0d6d1d86286db4.zip
[411589] Invalid this detectionv201401221723
The infer engine is made to calculate the correct types for local declarations initialized by this reference value JUnit Test Case is added due to verify the issue. Change-Id: Id0204f7e22c0c3b14a1c6bfb535fe3cfa9524061 Signed-off-by: vrubezhny <vrubezhny@exadel.com>
-rw-r--r--bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferEngine.java125
-rw-r--r--tests/org.eclipse.wst.jsdt.core.tests.compiler/src/org/eclipse/wst/jsdt/core/tests/compiler/regression/InferTypesTests.java26
2 files changed, 151 insertions, 0 deletions
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 57d1fbd90..aa6c309b4 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
@@ -44,6 +44,7 @@ import org.eclipse.wst.jsdt.core.ast.ITrueLiteral;
import org.eclipse.wst.jsdt.core.compiler.CharOperation;
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.AbstractVariableDeclaration;
import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference;
@@ -434,6 +435,7 @@ public class InferEngine extends ASTVisitor implements IInferEngine {
} else {
if (this.isExpressionAType(localDeclaration.getInitialization())) {
localDeclaration.setIsType(true);
+ handleLocalDeclarationExpressionType(localDeclaration);
}
InferredType type = this.getTypeForVariableInitialization(localDeclaration.getName(), localDeclaration.getInitialization());
if (localDeclaration.getInferredType() == null || (type != null && type.isAnonymous))
@@ -1171,6 +1173,129 @@ public class InferEngine extends ASTVisitor implements IInferEngine {
/**
* @param assignment
* @return whether a type was not created for this assignment
+ * @since 1.3
+ */
+ protected boolean handleLocalDeclarationExpressionType(ILocalDeclaration localDeclaration) {
+ IExpression expr = localDeclaration.getInitialization();
+ InferredType type = null;
+
+ if(expr instanceof IAssignment) {
+ type = ((IAssignment) expr).getInferredType();
+ } else if(expr instanceof IAbstractVariableDeclaration) {
+ type = ((IAbstractVariableDeclaration) expr).getInferredType();
+ } else if(expr instanceof IFieldReference) {
+ IExpression receiver = ((IFieldReference) expr).getReceiver();
+ InferredType receiverType = this.getTypeOf(receiver);
+ if(receiverType != null) {
+ InferredAttribute attr = receiverType.findAttribute(((IFieldReference) expr).getToken());
+ if (attr != null)
+ type = attr.inType;
+ }
+ } else if(expr instanceof ISingleNameReference) {
+ IAbstractVariableDeclaration varDecl = this.getVariable(expr);
+ if(varDecl != null) {
+ type = varDecl.getInferredType();
+ }
+
+ if(type == null) {
+ IAssignment assign = this.getAssignment(expr);
+ if(assign != null) {
+ type = assign.getInferredType();
+ }
+ }
+
+ if(type == null) {
+ IAbstractFunctionDeclaration funcDecl = this.getFunction(expr);
+ if(funcDecl != null && funcDecl.getName() != null) {
+ type = this.findDefinedType(funcDecl.getName());
+ }
+ }
+
+ if(type == null) {
+ type =this.compUnit.findInferredType(((ISingleNameReference) expr).getToken());
+ }
+ } else if(expr instanceof IThisReference) {
+ InferredType newType = null;
+
+ IFunctionDeclaration parentMethod = this.currentContext.currentMethod;
+ IAssignment parentAssignment = this.currentContext.parent.currentAssignment;
+ ILocalDeclaration parentLocalDeclaration = this.currentContext.parent.currentLocalDeclaration;
+ char[] newTypeName = null;
+ int typeStart = 0;
+ int typeEnd = 0;
+ /* if there is a current assignment and LHS is a function and that function
+ * is the current method then use the RHS as the type name
+ *
+ * else if there is a current local declaration and the LHS is a function and
+ * that function is the current method then use the RHS as the type name
+ *
+ * else if the parent method is not in a type and has a name use that as the type
+ * name */
+ if(this.currentContext.parent != null
+ && parentAssignment != null
+ && parentAssignment.getExpression() instanceof IFunctionExpression
+ && ((IFunctionExpression) parentAssignment.getExpression()).getMethodDeclaration() == parentMethod) {
+ // see if we're adding a field through the prototype
+ if (parentAssignment.getLeftHandSide().getASTType() == IASTNode.FIELD_REFERENCE
+ && ((Expression) ((IFieldReference) parentAssignment.getLeftHandSide()).getReceiver()).isPrototype()) {
+ newTypeName = Util.getTypeName(((IFieldReference) ((IFieldReference) parentAssignment.getLeftHandSide()).getReceiver()).getReceiver());
+ }
+ else {
+ newTypeName = Util.getTypeName(parentAssignment.getLeftHandSide());
+ }
+ typeStart = parentAssignment.sourceStart();
+ typeEnd = parentAssignment.sourceEnd();
+ } else if(this.currentContext.parent != null
+ && parentLocalDeclaration != null
+ && parentLocalDeclaration.getInitialization() instanceof IFunctionExpression
+ && ((IFunctionExpression) parentLocalDeclaration.getInitialization()).getMethodDeclaration() == parentMethod) {
+
+ newTypeName = parentLocalDeclaration.getName();
+ typeStart = parentLocalDeclaration.sourceStart();
+ typeEnd = parentLocalDeclaration.sourceEnd();
+ } else if(parentMethod != null
+ && parentMethod.getName() != null
+ && (parentMethod.getInferredMethod() == null || parentMethod.getInferredMethod().inType == null)) {
+
+ newTypeName = parentMethod.getName();
+ typeStart = parentMethod.sourceStart();
+ typeEnd = parentMethod.sourceEnd();
+ }
+
+ // if calculated new type name, use it to create a new type
+ if(newTypeName != null) {
+ newType = compUnit.findInferredType(newTypeName);
+ // create the new type if not found
+ if(newType == null) {
+ newType = addType(newTypeName);
+ }
+ } else {
+ return false; // no type to create
+ }
+
+ newType.setIsDefinition(true);
+ newType.updatePositions(typeStart, typeEnd);
+ type = newType;
+ }
+ // prevent Object literal based anonymous types from being created more than once
+ if(passNumber == 1 && expr instanceof IObjectLiteral) {
+ return false;
+ }
+
+ if (type != null) {
+ this.setTypeOf(expr, type);
+ if (localDeclaration instanceof AbstractVariableDeclaration) {
+ ((AbstractVariableDeclaration)localDeclaration).setInferredType(type);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param assignment
+ * @return whether a type was not created for this assignment
*/
protected boolean handlePotentialType(IAssignment assignment) {
diff --git a/tests/org.eclipse.wst.jsdt.core.tests.compiler/src/org/eclipse/wst/jsdt/core/tests/compiler/regression/InferTypesTests.java b/tests/org.eclipse.wst.jsdt.core.tests.compiler/src/org/eclipse/wst/jsdt/core/tests/compiler/regression/InferTypesTests.java
index c0e85fb3b..ffd37727b 100644
--- a/tests/org.eclipse.wst.jsdt.core.tests.compiler/src/org/eclipse/wst/jsdt/core/tests/compiler/regression/InferTypesTests.java
+++ b/tests/org.eclipse.wst.jsdt.core.tests.compiler/src/org/eclipse/wst/jsdt/core/tests/compiler/regression/InferTypesTests.java
@@ -2606,4 +2606,30 @@ public class InferTypesTests extends AbstractRegressionTest {
);
assertNull("There should not be a global function def()", declaration.findInferredType("@G".toCharArray()).findMethod("def".toCharArray(), null));
}
+
+ /*
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=411589 - Invalid this detection
+ */
+ public void testInitializationWithThisReference() {
+ CompilationUnitDeclaration declaration = this.runInferTest(
+ "(function() {\n" +
+ " var clazz = function() {\n" +
+ " var me = this;\n" +
+ " var you = me;\n" +
+ " me.funcMe = function() {return this;};\n" +
+ " you.funcYou = function() {return this;};\n" +
+ " this.funcWe = function() {return this;};\n" +
+ " }\n" +
+ "})();",
+ "X.js",
+ null,
+ getDefaultOptions()
+ );
+ assertNull("There should not be a global function funcMe()", declaration.findInferredType("@G".toCharArray()).findMethod("funcMe".toCharArray(), null));
+ assertNull("There should not be a global function funcYou()", declaration.findInferredType("@G".toCharArray()).findMethod("funcYou".toCharArray(), null));
+
+ assertNotNull("There should be a local method funcMe() in class clazz", declaration.findInferredType("clazz".toCharArray()).findMethod("funcMe".toCharArray(), null));
+ assertNotNull("There should be a local method funcYou() in class clazz", declaration.findInferredType("clazz".toCharArray()).findMethod("funcYou".toCharArray(), null));
+ assertNotNull("There should be a local method funcWe() in class clazz", declaration.findInferredType("clazz".toCharArray()).findMethod("funcWe".toCharArray(), null));
+ }
}

Back to the top