support for constructor functions that return itself
if the constructor function is not called with "new"
diff --git a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/validation/FlowValidation.java b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/validation/FlowValidation.java
index 0a14be7..ac2b361 100644
--- a/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/validation/FlowValidation.java
+++ b/plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/validation/FlowValidation.java
@@ -18,6 +18,7 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dltk.core.builder.IBuildContext;
import org.eclipse.dltk.core.builder.IBuildParticipant;
+import org.eclipse.dltk.internal.javascript.ti.JSDocSupport;
import org.eclipse.dltk.javascript.ast.AbstractNavigationVisitor;
import org.eclipse.dltk.javascript.ast.BreakStatement;
import org.eclipse.dltk.javascript.ast.CaseClause;
@@ -44,6 +45,8 @@
import org.eclipse.dltk.javascript.ast.WhileStatement;
import org.eclipse.dltk.javascript.core.JavaScriptProblems;
import org.eclipse.dltk.javascript.parser.Reporter;
+import org.eclipse.dltk.javascript.parser.jsdoc.JSDocTag;
+import org.eclipse.dltk.javascript.parser.jsdoc.JSDocTags;
import org.eclipse.osgi.util.NLS;
public class FlowValidation extends AbstractNavigationVisitor<FlowStatus>
@@ -204,6 +207,17 @@
final FlowStatus result = super.visitFunctionStatement(node);
if (scope.contains(FlowEndKind.RETURNS_VALUE)
&& (scope.contains(FlowEndKind.RETURNS) || result.noReturn)) {
+ if (result.noReturn && result.returnValue
+ && node.getDocumentation() != null) {
+ JSDocTags parse = JSDocSupport.parse(node
+ .getDocumentation());
+ // if it does return a value and it has a no return and it
+ // is a constructor function then don't report it. Very
+ // likely a construct to support a constructor function
+ // without the new keyword.
+ if (parse.count(JSDocTag.CONSTRUCTOR) == 1)
+ return result;
+ }
reportInconsistentReturn(node);
}
return result;
diff --git a/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/validation/FlowValidationTests.java b/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/validation/FlowValidationTests.java
index f5c66d1..c8bfa1a 100644
--- a/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/validation/FlowValidationTests.java
+++ b/tests/org.eclipse.dltk.javascript.core.tests/src/org/eclipse/dltk/javascript/core/tests/validation/FlowValidationTests.java
@@ -454,5 +454,30 @@
final List<IProblem> problems = validate(sCode);
assertEquals(problems.toString(), 0, problems.size());
}
+
+
+ public void testConstructorFunctionReturningItself() {
+ final StringList code = new StringList();
+ code.add("/**");
+ code.add(" * @constructor");
+ code.add(" */");
+ code.add("function MyConstructor(){");
+ code.add(" if (!(this instanceof MyConstructor))");
+ code.add(" { return new MyConstructor() }");
+ code.add("}");
+ final String sCode = code.toString();
+ final List<IProblem> problems = validate(sCode);
+ assertEquals(problems.toString(), 0, problems.size());
+ }
+ public void testFunctionReturningItself() {
+ final StringList code = new StringList();
+ code.add("function MyConstructor(){");
+ code.add(" if (!(this instanceof MyConstructor))");
+ code.add(" { return new MyConstructor() }");
+ code.add("}");
+ final String sCode = code.toString();
+ final List<IProblem> problems = validate(sCode);
+ assertEquals(problems.toString(), 1, problems.size());
+ }
}