blob: 184e265e1cdc6f70403d606e759938cc98803dba [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 xored software, Inc.
*
* 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:
* xored software, Inc. - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.javascript.core.tests.validation;
import static java.util.Collections.singleton;
import static org.eclipse.dltk.core.tests.TestSupport.notYetImplemented;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.dltk.compiler.problem.IProblem;
import org.eclipse.dltk.core.builder.IBuildParticipant;
import org.eclipse.dltk.core.tests.util.StringList;
import org.eclipse.dltk.internal.javascript.validation.ValidationMessages;
import org.eclipse.dltk.javascript.core.JavaScriptProblems;
import org.eclipse.dltk.javascript.core.tests.AbstractValidationTest;
@SuppressWarnings({ "nls", "restriction" })
public class TypeInfoValidationTests extends AbstractValidationTest {
@Override
protected IBuildParticipant createValidator() {
return new TestTypeInfoValidator();
}
public void testKnownType() {
final List<IProblem> problems = validate("/** @type String */ var x");
assertTrue(problems.isEmpty());
}
public void testUnknownType() {
final List<IProblem> problems = validate("/** @type LongString */ var x");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNKNOWN_TYPE, problems.get(0).getID());
}
public void testUnknownJavaScriptFunctionType() {
final List<IProblem> problems = validate("var x = new LongString()");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(0)
.getID());
}
public void testUnknownJavaScriptFunctionCall() {
final List<IProblem> problems = validate("var x = longString()");
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_FUNCTION, problems.get(0)
.getID());
}
public void testUnknownJavaScriptFunctionCallOnObject() {
StringList code = new StringList();
code.add("var x = new Object();");
code.add("x.longString();");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_METHOD, problems.get(0)
.getID());
}
public void testDeprecatedType() {
final List<IProblem> problems = validate("/** @type ExampleService2 */ var x");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_TYPE, problems.get(0)
.getID());
}
public void testDeprecatedTypeInNew() {
final List<IProblem> problems = validate("var x = new ExampleService2();");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_TYPE, problems.get(0)
.getID());
}
public void testDeprecatedTypeInInstanceOf() {
final StringList code = new StringList();
code.add("var x = null;");
code.add("var valid = x instanceof ExampleService2;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_TYPE, problems.get(0)
.getID());
}
public void testValidMethodCall() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("x.execute()");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.isEmpty());
}
public void testUndefinedMethodCall() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("x.runUndefindMethod()");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_JAVA_METHOD, problems.get(0)
.getID());
}
public void testMethodOverload1() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("x.run()");
code.add("x.run('Hello')");
code.add("x.run('Hello','World')");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testMethodOverload2() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("x.run('Hello','World','!')");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_JAVA_PARAMETERS, problems.get(0)
.getID());
}
public void testMethodCallWrongParamCount() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("x.execute(1)");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_JAVA_PARAMETERS, problems.get(0)
.getID());
}
public void testDeprecatedMethodCall() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("x.executeCompatible()");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_METHOD, problems.get(0)
.getID());
}
public void testDeprecatedMethodCall_TypeInference() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("var q = x.execute().service");
code.add("q.executeCompatible()");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_METHOD, problems.get(0)
.getID());
}
public void testPropertyAccess() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("var name = x.name");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.isEmpty());
}
public void testDeprecatedPropertyAccess() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("var name = x.nameCompatible");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_PROPERTY, problems.get(0)
.getID());
}
public void testDeprecatedUntypedPropertyAccess() {
StringList code = new StringList();
code.add("/** @type {WithUntypedProperty} */");
code.add("var x");
code.add("var name = x.untyped");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_PROPERTY, problems.get(0)
.getID());
}
public void testDeprecatedTopLevelProperty() {
StringList code = new StringList();
code.add("myExampleForms.service");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_PROPERTY, problems.get(0)
.getID());
assertTrue(problems.get(0).getMessage().contains("myExampleForms"));
}
public void testFunctionHidesPoperty() {
StringList code = new StringList();
code.add("function exampleForms(){}");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.FUNCTION_HIDES_VARIABLE, problems
.get(0).getID());
assertTrue(problems.get(0).getMessage().contains("exampleForms"));
}
public void testFunctionDoesntHidesAllowHidePoperty() {
StringList code = new StringList();
code.add("function exampleFormsHide(){}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testVarHidesXMLType() {
StringList code = new StringList();
code.add("var XML = 1");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.VAR_HIDES_PREDEFINED, problems.get(0)
.getID());
}
public void testVarHidesStringType() {
StringList code = new StringList();
code.add("var String = 1");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.VAR_HIDES_PREDEFINED, problems.get(0)
.getID());
}
public void testFunctionHidesStringType() {
StringList code = new StringList();
code.add("function String() {}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.FUNCTION_HIDES_PREDEFINED, problems
.get(0).getID());
}
public void testUndefinedPropertyAccess() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("var name = x.noname");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_JAVA_PROPERTY, problems
.get(0).getID());
}
public void testUndefinedTypePropertyAccess() {
StringList code = new StringList();
code.add("/** @type PersonClassIsNotDefined */");
code.add("var person");
code.add("var name = person.name");
code.add("var address = person.address");
final List<IProblem> problems = new ArrayList<IProblem>(
validate(code.toString()));
Collections.sort(problems, new Comparator<IProblem>() {
public int compare(IProblem o1, IProblem o2) {
return o1.getSourceStart() - o2.getSourceStart();
}
});
assertEquals(problems.toString(), 3, problems.size());
assertEquals(JavaScriptProblems.UNKNOWN_TYPE, problems.get(0).getID());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(1)
.getID());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(2)
.getID());
}
public void testUndefinedJavaPropertyAssignment() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("x.noname = true");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_JAVA_PROPERTY, problems
.get(0).getID());
}
public void testUndefinedJavaScriptObjectPropertyAssignment() {
StringList code = new StringList();
code.add("/** @type {Object} */");
code.add("var x");
code.add("x.noname = true");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUndefinedJavaScriptRecordTypePropertyAssignment() {
StringList code = new StringList();
code.add("/** @type {{}} */");
code.add("var x");
code.add("x.noname = true");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUndefinedJavaScriptCustomTypePropertyAssignment() {
StringList code = new StringList();
code.add("function MyObject(){}");
code.add("/** @type {MyObject} */");
code.add("var x");
code.add("x.noname = true");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUndefinedPropertyOnJavaPropert() {
final StringList code = new StringList();
code.add("function caller() {");
code.add(" exampleForms.test = 10;");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(validate.toString(), 1, validate.size());
}
public void testUndefinedPropertyAssignment_Object() {
StringList code = new StringList();
code.add("/** @type Object */");
code.add("var x");
code.add("x.noname = true");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUndefinedJavaPropertyOnTopLevelProperty() {
List<IProblem> problems = validate("exampleForms.test = 10;");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_JAVA_PROPERTY, problems
.get(0).getID());
}
public void testDeprecatedJavaPropertyOnTopLevelProperty() {
List<IProblem> problems = validate("exampleForms.deprecatedName = 'DLTK';");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_PROPERTY, problems.get(0)
.getID());
}
public void testUndefinedVariableAssignment() {
StringList code = new StringList();
code.add("x.noname = true");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(0)
.getID());
}
public void testPropertyAssignment() {
StringList code = new StringList();
code.add("var x = { }");
code.add("x.noname = true");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPropertyNullAssignment() {
StringList code = new StringList();
code.add("var x = { }");
code.add("x.noname = null");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPropertyAssignmentInIfBranch() {
StringList code = new StringList();
code.add("var condition = false;");
code.add("if (condition) {");
code.add("var x = { }");
code.add("x.noname = true");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPropertyNullAssignmentInIfBranch() {
StringList code = new StringList();
code.add("var condition = false;");
code.add("if (condition) {");
code.add("var x = { }");
code.add("x.noname = null");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testMethodAsPropertyAccess() {
StringList code = new StringList();
code.add("/** @type ExampleService */");
code.add("var x");
code.add("var name = x.execute");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testElementResolver() {
StringList code = new StringList();
code.add("exampleForms.service.name");
code.add("exampleForms.service.nameCompatible");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_PROPERTY, problems.get(0)
.getID());
}
public void testFunctionCallWithCorrectFunctionObjectArgument() {
StringList code = new StringList();
code.add("function Node1() {");
code.add("this.a=10;");
code.add("}");
code.add("function Node2() {");
code.add("this.a=10;");
code.add("}");
code.add("/** @param {Node1} arg */");
code.add("function call(arg){");
code.add("}");
code.add("function test(){");
code.add("call(new Node1());");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionCallWithInCorrectFunctionObjectArgument() {
StringList code = new StringList();
code.add("function Node1() {");
code.add("this.a=10;");
code.add("}");
code.add("function Node2() {");
code.add("this.a=10;");
code.add("}");
code.add("/** @param {Node1} arg */");
code.add("function call(arg){");
code.add("}");
code.add("function test(){");
code.add("call(new Node2());");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testFunctionCallWithCorrectFunctionObjectArgumentJSDOC() {
StringList code = new StringList();
code.add("function Node1() {");
code.add("this.a=10;");
code.add("}");
code.add("function Node2() {");
code.add("this.a=10;");
code.add("}");
code.add("/**");
code.add(" * @param {Node1} arg");
code.add(" */");
code.add("function call(arg){");
code.add("}");
code.add("function test(){");
code.add("call(new Node1());");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionCallWithInCorrectFunctionObjectArgumentJSDOC() {
StringList code = new StringList();
code.add("function Node1() {");
code.add("this.a=10;");
code.add("}");
code.add("function Node2() {");
code.add("this.a=10;");
code.add("}");
code.add("/**");
code.add(" * @param {Node1} arg");
code.add(" */");
code.add("function call(arg){");
code.add("}");
code.add("function test(){");
code.add("call(new Node2());");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testLazyVariableWithAssignment() {
StringList code = new StringList();
code.add("function Node1() {");
code.add("myVar = 10;");
code.add("}");
code.add("var myVar = 10;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testLazyVariableWithAssignmentAndAddition() {
StringList code = new StringList();
code.add("function Node1() {");
code.add("myVar += 10;");
code.add("}");
code.add("var myVar = 10;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testLazyJSObject() {
StringList code = new StringList();
code.add("var x = new function x(){");
code.add("this.newNode = function newNode(){");
code.add("return new Node()");
code.add("}");
code.add("function Node() {");
code.add("this.a=10;");
code.add("}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnType() {
StringList code = new StringList();
code.add("/**");
code.add(" * @return {String}");
code.add(" */");
code.add("function test() {");
code.add(" return '';");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnType2() {
StringList code = new StringList();
code.add("/**");
code.add(" * @param {ExampleService} srv");
code.add(" * @return {ExampleService}");
code.add(" */");
code.add("function test(srv) {");
code.add(" return srv;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnWrongType() {
StringList code = new StringList();
code.add("/**");
code.add(" * @return {String}");
code.add(" */");
code.add("function test() {");
code.add(" return 1;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testReturnNull() {
StringList code = new StringList();
code.add("/**");
code.add(" * @return {String}");
code.add(" */");
code.add("function test() {");
code.add(" return null;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnTypeDeclaredAndThrow() {
StringList code = new StringList();
code.add("/**");
code.add(" * @return {String}");
code.add(" */");
code.add("function test() {");
code.add(" throw 1;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testLazyReturnTypeWithJSDocParam() {
StringList code = new StringList();
code.add("/**");
code.add(" * @param {Node} node");
code.add(" */");
code.add("function addChild(node) {");
code.add(" return node;");
code.add("}");
code.add("function TestObject() {");
code.add(" var x = addChild(new Node());");
code.add(" x.a;");
code.add("}");
code.add("function Node() {");
code.add(" this.a = 10;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testLazyReturnTypeWithTypeInfo() {
StringList code = new StringList();
code.add("/**");
code.add(" * @param {Node} node");
code.add(" */");
code.add("function addChild(node) {");
code.add(" return node;");
code.add("}");
code.add("function TestObject() {");
code.add(" var x = addChild(new Node());");
code.add(" x.a;");
code.add("}");
code.add("function Node() {");
code.add(" this.a = 10;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testLazyReturnTypeWithNoTypeParamInfo() {
StringList code = new StringList();
code.add("/**");
code.add(" * @param node");
code.add(" */");
code.add("function addChild(node) {");
code.add(" return node;");
code.add("}");
code.add("function TestObject() {");
code.add(" var x = addChild(new Node());");
code.add(" var y = x.a;");
code.add("}");
code.add("function Node() {");
code.add(" this.a = 10;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testReturnFunction() {
StringList code = new StringList();
code.add("/**");
code.add(" * @return {function(String)}");
code.add(" */");
code.add("function test() {");
code.add(" return function(s) { return s;}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnFunctionWrong() {
StringList code = new StringList();
code.add("/**");
code.add(" * @return {function(String)}");
code.add(" */");
code.add("function test() {");
code.add(" return 1;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testLazyTypeWithAssignment() {
StringList code = new StringList();
code.add("function Node() {");
code.add(" this.nummer = 10;");
code.add("}");
code.add("function testNode() {");
code.add(" returnNode().nummer = 11;");
code.add("}");
code.add("function returnNode() {");
code.add(" return new Node();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testLazyInnerReference() {
StringList code = new StringList();
code.add("var NUM = function() {");
code.add(" /** @return {Number} */");
code.add(" var q = function() {");
code.add(" return new NUM();");
code.add(" }");
code.add(" return Number;");
code.add("}()");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testLazyInnerReference1() {
StringList code = new StringList();
code.add("var NUM");
code.add("NUM = function() {");
code.add(" /** @return {Number} */");
code.add(" var q = function() {");
code.add(" return new NUM();");
code.add(" }");
code.add(" return Number;");
code.add("}()");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testGenericParamWtihNoneGenericCall() {
List<String> code = new StringList();
code.add("/**");
code.add(" * @param {Array<String>} array the value of the node");
code.add(" */");
code.add("function testArray(array) {");
code.add("}");
code.add("function test() {");
code.add("testArray(new Array());");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
// assertEquals(JavaScriptProblems.WRONG_PARAMETERS_PARAMETERIZATION,
// problems.get(0).getID());
}
public void testGenericAnyWtihNoneGenericCall() {
List<String> code = new StringList();
code.add("/**");
code.add(" * @param {Array<*>} array the value of the node");
code.add(" */");
code.add("function testArray(array) {");
code.add("}");
code.add("function test() {");
code.add("testArray(new Array());");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testGenericParamWtihGenericCall() {
List<String> code = new StringList();
code.add("/**");
code.add(" * @param {Array<String>} array the value of the node");
code.add(" */");
code.add("function testArray(array) {");
code.add("}");
code.add("function test() {");
code.add("testArray(['test','test2']);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testNoneGenericParamWtihGenericCall() {
List<String> code = new StringList();
code.add("/**");
code.add(" * @param {Array} array the value of the node");
code.add(" */");
code.add("function testArray(array) {");
code.add("}");
code.add("function test() {");
code.add("testArray(['test','test2']);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionWithOptionalParams() {
List<String> code = new StringList();
code.add("/**");
code.add(" * @param {String} a");
code.add(" * @param {String} [b]");
code.add(" */");
code.add("function tester(a,b) {");
code.add("}");
code.add("function test() {");
code.add("tester('test');");
code.add("tester('test','test2');");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionCallWithUndefinedArgumments() {
List<String> code = new StringList();
code.add("/**");
code.add(" * @param {String} a");
code.add(" * @param {String} b");
code.add(" */");
code.add("function tester(a,b) {");
code.add("}");
code.add("function test() {");
code.add("tester(a,b);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(2, problems.size());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(0)
.getID());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(1)
.getID());
}
public void testUndefinedVariables() {
List<String> code = new StringList();
code.add("function test() {");
code.add("a=10");
code.add("b['test']='1'");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(2, problems.size());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(0)
.getID());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(1)
.getID());
}
public void testArrayLookupWithoutAssign() {
List<String> code = new StringList();
code.add("function test() {");
code.add(" var object = new Array();");
code.add(" var x = object['test'].length;");
code.add(" var y = object.test;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(0)
.getID());
}
public void testArrayLookupWithAssign() {
List<String> code = new StringList();
code.add("function test() {");
code.add("var object = new Array();");
code.add("object['test'] = '';");
code.add("var x = object['test'].length;");
code.add("object.test;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(0, problems.size());
}
public void testObjectInitalizerWithPropertyAndFunction() {
List<String> code = new StringList();
code.add("var initializer = {x:10,y:function(z){}};");
code.add("function testInitializer() {");
code.add("var a = initializer.x;");
code.add("var b = initializer.y(a);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDifferentReturnTypeThenDeclared() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {Number} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("return '';");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testDifferentReturnTypesThenDeclared() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {String} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("var result_1 = 1;");
code.add("var condition_1 = false;");
code.add("if(condition_1) {");
code.add("return result_1;");
code.add("}");
code.add("return '';");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testDifferentReturnTypesThenDeclaredWithUndefined() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {String} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("var result_1 = 1;");
code.add("var condition_1 = false;");
code.add("if(condition_1) {");
code.add("return undefined;");
code.add("}");
code.add("return '';");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDeclaredtArrayTypeWithUndefineReturn() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {Array<String>} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("return undefined;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDeclaredtArrayTypeWithNullReturn() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {Array<String>} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("return null;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDeclaredtArrayTypeWithEmptyReturn() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {Array<String>} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("return;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testDeclaredtArrayTypeWithEmptyReturnUndefined() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {Array<String>|undefined} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("return;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDeclaredtArrayTypeWithNoReturn() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {Array<String>} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testDeclaredtArrayTypeWithNoReturnUndefined() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {Array<String>|undefined} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDifferentReturnTypesThenDeclaredWithNull() {
List<String> code = new StringList();
code.add("/**");
code.add("* @return {String} some result info");
code.add("*/");
code.add("function someFunction() {");
code.add("var result_1 = 1;");
code.add("var condition_1 = false;");
code.add("if(condition_1) {");
code.add("return null;");
code.add("}");
code.add("return '';");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDifferentReturnTypes() {
List<String> code = new StringList();
code.add("function someFunction() {");
code.add("var condition_1 = false;");
code.add("if(condition_1) {");
code.add("return 1;");
code.add("}");
code.add("return '';");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.RETURN_INCONSISTENT, problems.get(0)
.getID());
}
public void testDifferentReturnTypesFirstNull() {
List<String> code = new StringList();
code.add("function test(a) {");
code.add(" if (a > 0) {");
code.add(" return null;");
code.add(" }");
code.add(" return [{}];");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testStringTypeAsFunctionCall() {
StringList code = new StringList();
code.add("var b = true");
code.add("var s = String(b)");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testNumberTypeAsFunctionCall() {
StringList code = new StringList();
code.add("var b = true");
code.add("var n = Number(b)");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testCallExternalFunctionViaReferenceCopy() {
StringList code = new StringList();
code.add("var p = parseInt");
code.add("var n = p('1')");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testVariableAssignedFunctionCallingItself() {
if (notYetImplemented(this))
return;
StringList code = new StringList();
code.add("var b = function a() {");
code.add("application.output(a);}");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testVariableAssignedObjectInitializerFunctionCallingItSelf() {
if (notYetImplemented(this))
return;
StringList code = new StringList();
code.add("var object = {");
code.add(" a: function c() {");
code.add(" c(); } }");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testVariableAssignedObjectInitializerFunctionWithThis() {
// if (notYetImplemented())
// return;
// doesn't report problem now, as this is untyped, so no checks
StringList code = new StringList();
code.add("var object = {");
code.add("a: function c() {this.b();},");
code.add("b: function() {}}");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testVariableAssignedObjectInitializerFunctionWithoutThis() {
StringList code = new StringList();
code.add("var object = {");
code.add("a: function c() {b();},");
code.add("b: function() {}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_FUNCTION, problems.get(0)
.getID());
}
public void testJSDocWithPropertiesNoArgumentProperties() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param anchor");
code.add("* @param {String} anchor.display");
code.add("* @param {String} anchor.page");
code.add("*/");
code.add("function test(anchor) {");
code.add("}");
code.add("function tester() {");
code.add("var obj = new Object();");
code.add("test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testJSDocWithPropertiesCorrectArgumentProperties() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param anchor");
code.add("* @param {String} anchor.display");
code.add("* @param {String} anchor.page");
code.add("*/");
code.add("function test(anchor) {");
code.add("}");
code.add("function tester() {");
code.add("var obj = new Object();");
code.add("obj.display ='display'");
code.add("obj.page ='page'");
code.add("test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testJSDocTypedObjectWithPropertiesCorrectArgumentProperties() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("* @param {String} anchor.display");
code.add("* @param {String} anchor.page");
code.add("*/");
code.add("function test(anchor) {");
code.add("}");
code.add("function tester() {");
code.add("var obj = new Object();");
code.add("obj.display ='display'");
code.add("obj.page ='page'");
code.add("test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testJSDocWithPropertiesWrongTypedArgumentProperties() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param anchor");
code.add("* @param {String} anchor.display");
code.add("* @param {String} anchor.page");
code.add("*/");
code.add("function test(anchor) {");
code.add("}");
code.add("function tester() {");
code.add("var obj = new Object();");
code.add("obj.display =10");
code.add("obj.page ='page'");
code.add("test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testJSDocWithOptionalPropertiesWithOnlyMandatoryArgumentProperties() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param anchor");
code.add("* @param {String} anchor.display");
code.add("* @param {String} anchor.page");
code.add("* @param {String} [anchor.space]");
code.add("* @param {String} [anchor.anchor]");
code.add("*/");
code.add("function test(anchor) {");
code.add("}");
code.add("function tester() {");
code.add("var obj = new Object();");
code.add("obj.display ='display'");
code.add("obj.page ='page'");
code.add("test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testJSDocWithOptionalPropertiesWithSomeOptionalArgumentProperties() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param anchor");
code.add("* @param {String} anchor.display");
code.add("* @param {String} anchor.page");
code.add("* @param {String} [anchor.space]");
code.add("* @param {String} [anchor.anchor]");
code.add("*/");
code.add("function test(anchor) {");
code.add("}");
code.add("function tester() {");
code.add("var obj = new Object();");
code.add("obj.display ='display'");
code.add("obj.page ='page'");
code.add("obj.space ='display'");
code.add("test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testJSDocWithOptionalPropertiesWithAllArgumentProperties() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param anchor");
code.add("* @param {String} anchor.display");
code.add("* @param {String} anchor.page");
code.add("* @param {String} [anchor.space]");
code.add("* @param {String} [anchor.anchor]");
code.add("*/");
code.add("function test(anchor) {");
code.add("}");
code.add("function tester() {");
code.add("var obj = new Object();");
code.add("obj.display ='display'");
code.add("obj.page ='page'");
code.add("obj.space ='display'");
code.add("obj.anchor ='page'");
code.add("test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertTrue(problems.toString(), problems.isEmpty());
}
public void testJSDocWithOptionalPropertiesWithAllArgumentPropertiesWrongType() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("* @param {String} anchor.display");
code.add("* @param {String} anchor.page");
code.add("* @param {String} [anchor.space]");
code.add("* @param {String} [anchor.anchor]");
code.add("*/");
code.add("function test(anchor) {");
code.add("}");
code.add("function tester() {");
code.add("var obj = new Object();");
code.add("obj.display ='display'");
code.add("obj.page ='page'");
code.add("obj.space ='display'");
code.add("obj.anchor =10");
code.add("test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testVariableDeclartionWithUnknowPropertyAssignment() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("*/");
code.add("function test(anchor) {");
code.add("var x = anchor.y");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(0)
.getID());
}
public void testVariableWithUnknowPropertyAssignment() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("*/");
code.add("function test(anchor) {");
code.add("var x = null;");
code.add("x = anchor.y");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(0)
.getID());
}
public void testFunctionCallWithUnknowProperty() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("*/");
code.add("function test(anchor) {");
code.add("test(anchor.xxx);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(0)
.getID());
}
public void testUnknowPropertyIfTest() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("*/");
code.add("function test(anchor) {");
code.add("if(anchor.xxx){}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnknowPropertyOfUnknownVariableIfTest() {
List<String> code = new StringList();
code.add("function test() {");
code.add(" if(unknown.xxx){}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(0)
.getID());
}
public void testDoubleUnknowPropertyIfTest() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("*/");
code.add("function test(anchor) {");
code.add(" if(anchor.xxx && anchor.yyyy){}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnknowVariableIfTest() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("*/");
code.add("function test(anchor) {");
code.add(" var x = anchorr.xxx");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(0)
.getID());
}
public void testUnknowPropertyOfPropertyIfTest() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {Object} anchor");
code.add("*/");
code.add("function test(anchor) {");
code.add(" var x = anchor.xxx.yyy");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(0)
.getID());
}
public void testStringArrayxInitializerWithNullElement() {
List<String> code = new StringList();
code.add("/**");
code.add("* @param {String[]} args");
code.add("*/");
code.add("function test2(args) {");
code.add(" test2(['hello',null]);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testNestedAnonymousReturnType() {
List<String> code = new StringList();
code.add("function Test() {");
code.add(" function Node() {");
code.add(" this.fun = function() {");
code.add(" return new Node();");
code.add(" }");
code.add(" }");
code.add(" this.getNode = function() {");
code.add(" return new Node();");
code.add(" }");
code.add("}");
code.add("function caller(){");
code.add(" var x = new Test();");
code.add(" var node = x.getNode();");
code.add(" var node2 = node.fun();");
code.add(" var node3 = node2.fun();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testMoreDeeplyNestedCallsToAnonymousReturnType() {
List<String> code = new StringList();
code.add("function Test() {");
code.add(" function Node() {");
code.add(" this.fun = function() {");
code.add(" return new Node();");
code.add(" }");
code.add(" }");
code.add(" this.getNode = function() {");
code.add(" return new Node();");
code.add(" }");
code.add("}");
code.add("function caller(){");
code.add(" var x = new Test();");
code.add(" var node = x.getNode();");
code.add(" var node2 = node.fun();");
code.add(" var node3 = node2.fun();");
code.add(" var node4 = node3.fun();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testNestedTypeToReturnType() {
if (notYetImplemented(this))
return;
List<String> code = new StringList();
code.add("function Test() {");
code.add(" function Node() {");
code.add(" this.fun = function() {");
code.add(" return new Node();");
code.add(" }");
code.add(" }");
code.add(" this.getNode = function() {");
code.add(" return new Node();");
code.add(" }");
code.add(" this.Node = Node;");
code.add("}");
code.add("/** @return {Test.Node} */");
code.add("function caller(){");
code.add(" var x = new Test();");
code.add(" return x.getNode();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testNestedFunctionTypeNewConstruct() {
List<String> code = new StringList();
code.add("function Test() {");
code.add(" function Node() {");
code.add(" this.fun = function() {");
code.add(" return new Node();");
code.add(" }");
code.add(" }");
code.add(" this.getNode = function() {");
code.add(" return new Node();");
code.add(" }");
code.add(" this.Node = Node;");
code.add("}");
code.add("function caller() {");
code.add(" var x = new Test();");
code.add(" var node = new x.Node();");
code.add(" node.fun();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testNestedObjectInitializerType() {
StringList code = new StringList();
code.add("var init = {Node: function(){} }");
code.add("/**");
code.add(" * @return {init.Node} */");
code.add("function caller2() {");
code.add(" return new init.Node();}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testNestedObjectInitializerTypeWithFunctionCall() {
StringList code = new StringList();
code.add("var init = {Node: function(){}, ");
code.add("fun: function() {return new init.Node();} }");
code.add("/**");
code.add(" * @return {init.Node} */");
code.add("function caller2() {");
code.add(" return init.fun();}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testNestedObjectInitializerWithThisTypeWithFunctionCall() {
if (true || notYetImplemented(this))
return;
final StringList code = new StringList();
code.add("var init = {");
code.add(" Node: function(){}, ");
code.add(" fun: function() {return new this.Node();}");
code.add("}");
code.add("/** @return {init.Node} */");
code.add("function caller2() {");
code.add(" return init.fun();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testOuterVariableInInnerFunction() {
StringList code = new StringList();
code.add("function Outer() {");
code.add("function inner() {");
code.add("variable = 10;");
code.add("}");
code.add("var variable;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testAssignmentOfVariableToUndefined() {
StringList code = new StringList();
code.add("function test() {");
code.add(" var str = '';");
code.add(" str.toLocaleString();");
code.add(" str = undefined;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testAssignmentOfArgumentToUndefined() {
StringList code = new StringList();
code.add("/** @param {String} str */");
code.add("function test(str) {");
code.add(" str.toLocaleString();");
code.add(" str = undefined;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testCompareOperatorsReturningBoolean() {
StringList code = new StringList();
code.add("/** @return {Boolean} */");
code.add("function test() {");
code.add(" var x = 1; var y = 2;");
code.add(" if(x > 1)");
code.add(" return (y == 2);");
code.add(" if(x > 1)");
code.add(" return (y != 2);");
code.add(" if(x > 1)");
code.add(" return (y < 2);");
code.add(" if(x > 1)");
code.add(" return (y > 2);");
code.add(" if(x > 1)");
code.add(" return (y >= 2);");
code.add(" if(x > 1)");
code.add(" return (y <= 2);");
code.add(" if(x > 1)");
code.add(" return (y === 2);");
code.add(" if(x > 1)");
code.add(" return (y !== 2);");
code.add(" return false;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnFromNestedCollections() {
StringList code = new StringList();
code.add("/** @return {Number} */");
code.add("function test() {");
code.add(" if (1 > 0) {");
code.add(" return 1");
code.add(" }");
code.add(" else {");
code.add(" return 2");
code.add(" }");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testObjectProperyReturnTypeWithDirectInitializer() {
StringList code = new StringList();
code.add("/** @return {{astring:String,anumber:Number}} */");
code.add("function test() {");
code.add("return {astring:'test',anumber:1}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testObjectProperyReturnNull() {
StringList code = new StringList();
code.add("/** @return {{astring:String,anumber:Number}} */");
code.add("function test() {");
code.add("return null");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testObjectProperyReturnTypeWithInvalidDirectInitializer() {
StringList code = new StringList();
code.add("/** @return {{astring:String,anumber:Number}} */");
code.add("function test() {");
code.add("return {aastring:'test',anumber:1}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testObjectProperyReturnTypeWithObjectInitializer() {
StringList code = new StringList();
code.add("/** @return {{astring:String,anumber:Number}} */");
code.add("function test() {");
code.add(" var obj = {astring:'test',anumber:1}");
code.add(" return obj;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testObjectProperyReturnTypeWithInvalidObjectInitializer() {
StringList code = new StringList();
code.add("/** @return {{astring:String,anumber:Number}} */");
code.add("function test() {");
code.add(" var obj = {aastring:'test',anumber:1}");
code.add(" return obj;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testObjectProperyReturnTypeWithObject() {
StringList code = new StringList();
code.add("/** @return {{astring:String,anumber:Number}} */");
code.add("function test() {");
code.add(" var obj = new Object();");
code.add(" obj.astring = ''");
code.add(" obj.anumber = 1");
code.add(" return obj;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testObjectProperyReturnTypeWithObjectWithDifferentType() {
StringList code = new StringList();
code.add("/** @return {{astring:String,anumber:Number}} */");
code.add("function test() {");
code.add(" var obj = new Object();");
code.add(" obj.astring = ''");
code.add(" obj.anumber = '1'");
code.add(" return obj;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testObjectProperyReturnTypeWithInvalidObject() {
StringList code = new StringList();
code.add("/** @return {{astring:String,anumber:Number}} */");
code.add("function test() {");
code.add(" var obj = new Object();");
code.add(" obj.aastring = ''");
code.add(" obj.anumber = 1");
code.add(" return obj;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE,
problems.get(0).getID());
}
public void testParamWithObjectDeclaration() {
StringList code = new StringList();
code.add("/** @param {{astring:String,anumber:Number}} myparam */");
code.add("function test(myparam) {");
code.add(" var x = myparam.astring");
code.add(" var y = myparam.anumber");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testParamWithObjectDeclarationInvalidProperty() {
StringList code = new StringList();
code.add("/** @param {{astring:String,anumber:Number}} myparam */");
code.add("function test(myparam) {");
code.add(" var x = myparam.aastring");
code.add(" var y = myparam.anumber");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(0)
.getID());
}
public void testParamWithObjectDeclarationCall() {
StringList code = new StringList();
code.add("/** @param {{astring:String,anumber:Number}} myparam */");
code.add("function test(myparam) {");
code.add("}");
code.add("function test2(myparam) {");
code.add(" test({astring:'',anumber:1});");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testParamWithOptinalObjectDeclarationCall() {
StringList code = new StringList();
code.add("/** @param {{astring:String, [anumber]:Number}} myparam */");
code.add("function test(myparam) {");
code.add("}");
code.add("function test2(myparam) {");
code.add(" test({astring:'',anumber:1});");
code.add(" test({astring:''});");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testParamWithObjectDeclarationCallWithDifferentType() {
StringList code = new StringList();
code.add("/** @param {{astring:String,anumber:Number}} myparam */");
code.add("function test(myparam) {");
code.add("}");
code.add("function test2(myparam) {");
code.add(" test({astring:'',anumber:'1'});");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testParamWithObjectDeclarationInvalidCall() {
StringList code = new StringList();
code.add("/** @param {{astring:String,anumber:Number}} myparam */");
code.add("function test(myparam) {");
code.add("}");
code.add("function test2(myparam) {");
code.add(" test({aastring:'',anumber:1});");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testReturnStringAdd() {
StringList code = new StringList();
code.add("/** @return {String} */");
code.add("function test() {");
code.add(" return 1 + ''");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testMapWithValueDeclaration() {
StringList code = new StringList();
code.add("/** @param {Object<String>} param */");
code.add("function test(param) {");
code.add(" var x = param['test'];");
code.add(" var p = x.toLocaleLowerCase();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testMapWithKeyValueDeclaration() {
StringList code = new StringList();
code.add("/** @param {Object<Number,String>} param */");
code.add("function test(param) {");
code.add(" var x = param['test'];");
code.add(" var p = x.toLocaleLowerCase();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testMapWithValueWithWrongTypeDeclaration() {
StringList code = new StringList();
code.add("/** @param {Object<Stringg>} param */");
code.add("function test(param) {");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNKNOWN_TYPE, problems.get(0).getID());
}
public void testMapWithKeyValueWithWrongTypeDeclaration() {
StringList code = new StringList();
code.add("/** @param {Object<Stringg,Numberr>} param */");
code.add("function test(param) {");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 2, problems.size());
assertEquals(JavaScriptProblems.UNKNOWN_TYPE, problems.get(0).getID());
assertEquals(JavaScriptProblems.UNKNOWN_TYPE, problems.get(1).getID());
}
public void testArrayWithWrongTypeDeclaration() {
StringList code = new StringList();
code.add("/** @param {Array<Stringg>} param */");
code.add("function test(param) {");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNKNOWN_TYPE, problems.get(0).getID());
}
public void testUnionWithWrongTypeDeclaration() {
StringList code = new StringList();
code.add("/** @param {Stringg|Number} param */");
code.add("function test(param) {");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNKNOWN_TYPE, problems.get(0).getID());
}
public void testJavaObjectAndUndefineReturn() {
StringList code = new StringList();
code.add("function test1(param) {");
code.add(" if (param) return new ExampleService();");
code.add(" else return undefined;");
code.add("}");
code.add("function test2(param) {");
code.add(" test1(true).name = 10;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testXMLWithParentheseExpression() {
StringList code = new StringList();
code.add("function test() {");
code.add(" var tmp = 10;");
code.add(" var xml = <></>;");
code.add(" var node = xml..*.object.(@qualifiedName == tmp);");
code.add(" if (node.length() == 0) {}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testXMLWithParentheseExpressionWithUnknownVariableReference() {
StringList code = new StringList();
code.add("function test() {");
code.add(" var xml = <></>;");
code.add(" var node = xml..*.object.(@qualifiedName == tmp);");
code.add(" if (node.length() == 0) {}");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(0)
.getID());
}
public void testReassignOfAVariableWithDifferentDataAccessingItRightBefore() {
StringList code = new StringList();
code.add("function getParamXML() {");
code.add(" var xml = <xml><data></data></xml>;");
code.add(" xml.data.ignoreComments;");
code.add(" xml = <xml><data1></data1></xml>;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testRecordTypeWithSpacesAndOwnCurlyBrackets() {
StringList code = new StringList();
code.add("/**");
code.add(" * @type {{height:Number, widgetName:String, widgetTitle: String,originalColumn: Number, originalPosition:Number,currentColumn:Number,currentPosition:Number,columns:{} }}");
code.add("*/");
code.add("var eventDataType;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnionTypeTest() throws Exception {
StringList code = new StringList();
code.add("/** @param {String|Number} param */");
code.add("function test(param) {");
code.add(" param.toFixed(1)");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnionUnknownTypeTest() throws Exception {
StringList code = new StringList();
code.add("/** @param {String|Numberr} param */");
code.add("function test(param) {");
code.add(" param.toFixed(1)");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 2, problems.size());
}
public void testVarArgs() throws Exception {
StringList code = new StringList();
code.add("var x = []");
code.add("x.splice(0,1)");
code.add("x.splice(0,1,2)");
code.add("x.splice(0,1,2,3)");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testVarArgsJS() throws Exception {
StringList code = new StringList();
code.add("/**");
code.add(" * @param {Number} x");
code.add(" * @param {Number} y");
code.add(" * @param {...Number} z");
code.add(" */");
code.add("function test(x, y, z) {}");
code.add("test(0,1)");
code.add("test(0,1,2)");
code.add("test(0,1,2,3)");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPossibleRecursionInNew() {
validate("var a = new a.toString()");
// just check there was stack overflow
}
public void testRecordTypeWithNumbersInPropertyName() throws Exception {
StringList code = new StringList();
code.add("/** @type {{prop1: String, prop2:Number}} */");
code.add("var x = null;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testMixedRecordTypes() throws Exception {
StringList code = new StringList();
code.add("/**");
code.add("* @param {Object} _someArg");
code.add("* @param {String} _someArg.strProp");
code.add("*/");
code.add("function firstFunc(_someArg){");
code.add("secondFunc(_someArg);");
code.add("}");
code.add("/**");
code.add("* @param {Object} _someArg - ");
code.add("* @param {String} _someArg.strProp");
code.add("*/");
code.add("function secondFunc(_someArg){");
code.add("secondFunc1(_someArg);");
code.add("}");
code.add("/**");
code.add("* @param {{strProp:String}} _someArg");
code.add("*/");
code.add("function firstFunc1(_someArg){");
code.add("secondFunc1(_someArg);");
code.add("}");
code.add("/**");
code.add("* @param {{strProp:String}} _someArg -");
code.add("*/");
code.add("function secondFunc1(_someArg){");
code.add("secondFunc(_someArg);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPrototypeFunctionCallApplyCalling() throws Exception {
StringList code = new StringList();
code.add("Number.prototype.toString.call(null,null);");
code.add("String.prototype.toString.apply(null,null);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testRecordTypeReturn() throws Exception {
StringList code = new StringList();
code.add("/**");
code.add("* @return {{propertyName: String, dataType: Number,defaultValue: Object, minValue: Object,maxValue: Object, allowBlank: Boolean,allowCustomValues: Boolean, valueListName: String}}");
code.add("*/");
code.add("function getRegisteredPropertyInfos()");
code.add("{");
code.add("/** @type {{propertyName: String, dataType: Number,defaultValue: Object, minValue: Object,maxValue: Object, allowBlank: Boolean,allowCustomValues: Boolean, valueListName: String}} */");
code.add("var _propInfos = [];");
code.add("return _propInfos;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testRightReturnArrayWithRecordTypeObjects() throws Exception {
StringList code = new StringList();
code.add("/**");
code.add("* @return {Array<{propertyName: String, dataType: Number,defaultValue: Object, minValue: Object,maxValue: Object, allowBlank: Boolean,allowCustomValues: Boolean, valueListName: String}>}");
code.add("*/");
code.add("function getRegisteredPropertyInfos()");
code.add("{");
code.add("/** @type {Array<{propertyName: String, dataType: Number,defaultValue: Object, minValue: Object,maxValue: Object, allowBlank: Boolean,allowCustomValues: Boolean, valueListName: String}>} */");
code.add("var _propInfos = [];");
code.add("return _propInfos;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testWrong1ReturnArrayWithRecordTypeObjects() throws Exception {
StringList code = new StringList();
code.add("/**");
code.add("* @return {Array<{propertyName: String, dataType: Number,defaultValue: Object, minValue: Object,maxValue: Object, allowBlank: Boolean,allowCustomValues: Boolean, valueListName: String}>}");
code.add("*/");
code.add("function getRegisteredPropertyInfos()");
code.add("{");
code.add("/** @type {Array<{propertyName: Number, dataType: Number,defaultValue: Object, minValue: Object,maxValue: Object, allowBlank: Boolean,allowCustomValues: Boolean, valueListName: String}>} */");
code.add("var _propInfos = [];");
code.add("return _propInfos;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE_PARAMETERIZATION,
problems.get(0).getID());
}
public void testWrong2ReturnArrayWithRecordTypeObjects() throws Exception {
StringList code = new StringList();
code.add("/**");
code.add("* @return {Array<{propertyName: String, dataType: Number,defaultValue: Object, minValue: Object,maxValue: Object, allowBlank: Boolean,allowCustomValues: Boolean, valueListName: String}>}");
code.add("*/");
code.add("function getRegisteredPropertyInfos()");
code.add("{");
code.add("/** @type {Array<{dataType: Number,defaultValue: Object, minValue: Object,maxValue: Object, allowBlank: Boolean,allowCustomValues: Boolean, valueListName: String}>} */");
code.add("var _propInfos = [];");
code.add("return _propInfos;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(
JavaScriptProblems.DECLARATION_MISMATCH_ACTUAL_RETURN_TYPE_PARAMETERIZATION,
problems.get(0).getID());
}
public void testPhantomPropertyUntyped() {
final StringList code = new StringList();
code.add("function test() {");
code.add(" var x");
code.add(" if (x.y) {"); // line #2
code.add(" return x.y;");
code.add(" }");
code.add(" return undefined;");
code.add("}");
final List<IProblem> noproblems = validate(code.toString());
assertEquals(noproblems.toString(), 0, noproblems.size());
// change the condition and make sure problems are reported
code.set(2, "if (x.y > 10) {");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testPhantomPropertyJava() {
final StringList code = new StringList();
code.add("/** @param {ExampleService} x */");
code.add("function test(x) {");
code.add(" if (x.y) {");
code.add(" return x.y;");
code.add(" }");
code.add(" else return undefined;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(),
singleton(JavaScriptProblems.UNDEFINED_JAVA_PROPERTY),
extractIds(problems));
}
public void testPhantomPropertyRecord() {
final StringList code = new StringList();
code.add("/** @param {{name:String,address:String}} x */");
code.add("function test(x) {");
code.add(" if (x.y) {");
code.add(" return x.y;");
code.add(" }");
code.add(" else return undefined;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(),
singleton(JavaScriptProblems.UNDEFINED_PROPERTY),
extractIds(problems));
}
public void testVarReferencedFromArrayLiteral() {
final StringList code = new StringList();
code.add("function test() {");
code.add(" var a = 10;");
code.add(" var point = {");
code.add(" x: 1,");
code.add(" y: [a]");
code.add(" };");
code.add(" return point;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testArrayPushValid() {
final StringList code = new StringList();
code.add("/** @type {Array<String>} */");
code.add("var a = []");
code.add("a.push('AAA')");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testArrayPushInvalid() {
final StringList code = new StringList();
code.add("/** @type {Array<String>} */");
code.add("var a = []");
code.add("a.push(1)");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testRecordTypeParamCalledWithAnNullButDeclaredArgumentValue() {
final StringList code = new StringList();
code.add("/** @type {Object<{icon:String,color:String}>} */");
code.add("var statusCodes = { ok: {icon: 'media:///check.png', color: null}, fail: {icon: 'media:///16forbidden.png', color: 'red'}, maybe: {icon: 'media:///check_orange.png', color: 'orange'}}");
code.add("/** @param {{code: {icon:String,color:String}=, text: String|XML=, toolTip: String=}} object */");
code.add("function onLoad(object) {");
code.add("onLoad({code:statusCodes.ok});");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testRecordTypeParamWithCompletelyDifferentArgumentRecordType() {
final StringList code = new StringList();
code.add("/** @type {Object<{icon:String,color:String}>} */");
code.add("var statusCodes = { ok: {icon: 'media:///check.png', color: null}, fail: {icon: 'media:///16forbidden.png', color: 'red'}, maybe: {icon: 'media:///check_orange.png', color: 'orange'}}");
code.add("/** @param {{code: {icon:String,color:String}=, text: String|XML=, toolTip: String=}} object */");
code.add("function onLoad(object) {");
code.add("onLoad(statusCodes.ok);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testRecordTypeParamWithPartiallyDifferentArgumentRecordType() {
final StringList code = new StringList();
code.add("/** @type {Object<{icon:String,color:String}>} */");
code.add("var statusCodes = { ok: {icon: 'media:///check.png', color: null}, fail: {icon: 'media:///16forbidden.png', color: 'red'}, maybe: {icon: 'media:///check_orange.png', color: 'orange'}}");
code.add("/** @param {{code: {icon:String,color:String}=, text: String|XML=, toolTip: String=}} object */");
code.add("function onLoad(object) {");
code.add("onLoad({code:statusCodes.ok,notinparamtype:1});");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionFromParamType() {
final StringList code = new StringList();
code.add("/** @param {function(String)} obj */");
code.add("function y(obj) {");
code.add(" obj('');");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionCallFromUnion() {
final StringList code = new StringList();
code.add("/** @param {function(String)|String} obj */");
code.add("function y(obj) {");
code.add(" obj('');");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnionParamTypeCompatibility1() {
final StringList code = new StringList();
code.add("/** @param {{name:String}} person */");
code.add("function test(person) {}");
code.add("");
code.add("/** @param {function(String)|String} obj */");
code.add("function y(obj) {");
code.add(" test({ name: obj });");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testUnionParamTypeCompatibility2() {
final StringList code = new StringList();
code.add("/** @param {String|Number} person */");
code.add("function test(person) {}");
code.add("");
code.add("/** @param {String|Number} obj */");
code.add("function y(obj) {");
code.add(" test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnionParamTypeCompatibility3() {
final StringList code = new StringList();
code.add("/** @param {String|Number} person */");
code.add("function test(person) {}");
code.add("");
code.add("/** @param {String|Number|Date} obj */");
code.add("function y(obj) {");
code.add(" test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testUnionParamTypeCompatibility4() {
final StringList code = new StringList();
code.add("/** @param {String|Number|Date} person */");
code.add("function test(person) {}");
code.add("");
code.add("/** @param {String|Number} obj */");
code.add("function y(obj) {");
code.add(" test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnionParamTypeCompatibility5() {
final StringList code = new StringList();
code.add("/** @param {String|Number|Date} person */");
code.add("function test(person) {}");
code.add("");
code.add("/** @param {Number} obj */");
code.add("function y(obj) {");
code.add(" test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnionParamTypeCompatibility6() {
final StringList code = new StringList();
code.add("/** @param {Number} person */");
code.add("function test(person) {}");
code.add("");
code.add("/** @param {String|Number|Date} obj */");
code.add("function y(obj) {");
code.add(" test(obj);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testArrayLookupWithUnknowVariables() {
final StringList code = new StringList();
code.add("var vAvailableLicenses = exampleForms.nothere[exampleForms.nothere2].nothere3.nothere4;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 2, problems.size());
}
public void testContinationAsFunctionCall() {
final StringList code = new StringList();
code.add("var c = new Continuation();");
code.add("c();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testObjectAsFunctionCall() {
final StringList code = new StringList();
code.add("var c = new Object();");
code.add("c();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_FUNCTION, problems.get(0).getID());
}
public void testPropertyAsFunctionCall() {
final StringList code = new StringList();
code.add("var s = '';");
code.add("s.length();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_FUNCTION, problems.get(0).getID());
}
public void testArrayWithJavaScriptType() {
final StringList code = new StringList();
code.add("function CustomType() {");
code.add(" this.myvar = 10;");
code.add("}");
code.add("function test(){");
code.add(" /** @type {Array<CustomType>} */");
code.add(" var myarray = [];");
code.add(" var x = myarray[0].myvar;");
code.add(" var item = myarray[0];");
code.add(" item.myvar;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPropertyWithDirectJavascriptChildrenNoType() {
List<String> lines = new StringList();
lines.add("var array = GLOBALS.test();");
lines.add("array.push('string');");
final List<IProblem> problems = validate(lines.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testConstructorWrongArgCount() {
final List<IProblem> problems = validate("var s = new String(1,2,3)");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testConstructorMismatchedOverload() {
final List<IProblem> problems = validate("var d = new Date(true)");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testConstructorMismatchedArgs() {
final List<IProblem> problems = validate("var d = new Date('','','')");
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testConstructorOverrides() {
List<IProblem> problems;
problems = validate("var d = new Date()");
assertEquals(problems.toString(), 0, problems.size());
problems = validate("var d = new Date('')");
assertEquals(problems.toString(), 0, problems.size());
problems = validate("var d = new Date(123456789)");
assertEquals(problems.toString(), 0, problems.size());
problems = validate("var d = new Date(2012,1,1)");
assertEquals(problems.toString(), 0, problems.size());
problems = validate("var d = new Date(1,2,3,4,5,6,7)");
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeCall() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @type {function(String)}");
code.add("*/");
code.add("var func;");
code.add("func('A')");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeCallError() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @type {function(String)}");
code.add("*/");
code.add("var func;");
code.add("func(1)");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testFunctionTypeCallParam() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String)} func");
code.add("*/");
code.add("function test(func) {");
code.add(" func('A')");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeCallParamError() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String)} func");
code.add("*/");
code.add("function test(func) {");
code.add(" func(1)");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testTypedArrayReturnValue() {
List<String> lines = new StringList();
lines.add("function SomeCustomType() {");
lines.add(" this.someExistingMethod = function() {}");
lines.add("}");
lines.add("/** ");
lines.add("* @return {Array<SomeCustomType>}");
lines.add("*/");
lines.add("function getTypedArray() {");
lines.add(" /** @type {Array<SomeCustomType>} */");
lines.add(" var array = new Array();");
lines.add(" array[0] = new SomeCustomType();");
lines.add(" array[0].someExistingMethod();");
lines.add(" return array;");
lines.add("}");
lines.add("function test() {");
lines.add(" /** @type {Array<SomeCustomType>} */");
lines.add(" var typedArray = getTypedArray(); ");
lines.add(" for each(var item in typedArray) {");
lines.add(" item.someExistingMethod(); ");
lines.add(" }");
lines.add("}");
final List<IProblem> problems = validate(lines.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testTypedArrayReturnValueWithoutTypeDeclare() {
List<String> lines = new StringList();
lines.add("function SomeCustomType() {");
lines.add(" this.someExistingMethod = function() {}");
lines.add("}");
lines.add("/** ");
lines.add("* @return {Array<SomeCustomType>}");
lines.add("*/");
lines.add("function getTypedArray() {");
lines.add(" /** @type {Array<SomeCustomType>} */");
lines.add(" var array = new Array();");
lines.add(" array[0] = new SomeCustomType();");
lines.add(" array[0].someExistingMethod();");
lines.add(" return array;");
lines.add("}");
lines.add("function test() {");
lines.add(" var typedArray = getTypedArray(); ");
lines.add(" for each(var item in typedArray) {");
lines.add(" item.someExistingMethod(); ");
lines.add(" }");
lines.add("}");
final List<IProblem> problems = validate(lines.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDeclaredClassAsFunction() {
final StringList code = new StringList();
code.add("/** @type {Class<String>} */");
code.add("var STRING;");
code.add("function testStr() {");
code.add(" return STRING('');");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDeclaredClassAsFunctionError() {
final StringList code = new StringList();
code.add("/** @type {Class<String>} */");
code.add("var STRING;");
code.add("function testStr() {");
code.add(" return STRING(1,2,3);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testAnyTypePhantomValue() {
final StringList code = new StringList();
code.add("function test() {");
code.add(" /** @type {*} */");
code.add(" var x;");
code.add(" return x.a() + x.b() + x.c;");
code.add("}");
{
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
code.remove(1);
{
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 3, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_METHOD, problems.get(0)
.getID());
assertEquals(JavaScriptProblems.UNDEFINED_METHOD, problems.get(1)
.getID());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(2)
.getID());
}
}
public void testAssignmentWithBranch() {
final StringList code = new StringList();
code.add("function test() {");
code.add(" var service;");
code.add(" if (test) {");
code.add(" service = exampleForms.service");
code.add(" var name = service.name;");
code.add(" }");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPrototype() {
final StringList code = new StringList();
code.add("String.prototype.foo = function() {}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testAssignToClass() {
final StringList code = new StringList();
code.add("String = 1");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNASSIGNABLE_ELEMENT, problems.get(0)
.getID());
assertEquals(ValidationMessages.UnassignableClass, problems.get(0)
.getMessage());
}
public void testAssignToGlobalFunction() {
final StringList code = new StringList();
code.add("parseInt = 1");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNASSIGNABLE_ELEMENT, problems.get(0)
.getID());
assertEquals(ValidationMessages.UnassignableMethod, problems.get(0)
.getMessage());
}
public void testAssignToFunction() {
final StringList code = new StringList();
code.add("function a() {}");
code.add("a = 1");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNASSIGNABLE_ELEMENT, problems.get(0)
.getID());
assertEquals(ValidationMessages.UnassignableFunction, problems.get(0)
.getMessage());
}
public void testAssignToFunctionInAFunction() {
final StringList code = new StringList();
code.add("function a() {}");
code.add("function b() {");
code.add(" a = 1");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNASSIGNABLE_ELEMENT, problems.get(0)
.getID());
assertEquals(ValidationMessages.UnassignableFunction, problems.get(0)
.getMessage());
}
public void testAssignToFunctionOfAParentClass() {
final StringList code = new StringList();
code.add("function baseObject() {");
code.add(" this.myPublicMethod = function() { }");
code.add("}");
code.add("/**");
code.add(" * @constructor");
code.add(" * @extends {baseObject}");
code.add(" */");
code.add("function childObject() {");
code.add(" this.myPublicMethod = function() { }");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
// This test will not always fail!, this is because sometimes it can map on
// String other times it maps on Number (ImmutableValue.getChild())
public void testDoubleReferences() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @return {Array<Number>}");
code.add(" */");
code.add("function test2() {");
code.add(" /** @type {Array<Number>} */");
code.add(" var array = new Array();");
code.add(" return array");
code.add("}");
code.add("function test() {");
code.add(" var z = 1;");
code.add(" if (x) {");
code.add(" /** @type {Array<String>} */");
code.add(" var x = test2();");
code.add(" var y = x[0];");
code.add(" y.bold();");
code.add(" }");
code.add(" else {");
code.add(" z = z + 2;");
code.add(" }");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testArrayAccess1() {
final StringList code = new StringList();
code.add("var strings = ['A','B','C'];");
code.add("strings[0].aaa();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_METHOD, problems.get(0)
.getID());
}
public void testArrayAccess1property() {
final StringList code = new StringList();
code.add("var strings = ['A','B','C'];");
code.add("strings[0].aaa;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(0)
.getID());
}
public void testArrayAccess2() {
final StringList code = new StringList();
code.add("/** @type {Array<String>} */");
code.add("var strings;");
code.add("strings[0].aaa();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_METHOD, problems.get(0)
.getID());
}
public void testArrayAccess2property() {
final StringList code = new StringList();
code.add("/** @type {Array<String>} */");
code.add("var strings;");
code.add("strings[0].aaa;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(0)
.getID());
}
public void testEmptyArrayLiteralCompatibility() {
final StringList code = new StringList();
code.add("/** @param {Array<String>} ss */");
code.add("function test(ss) {}");
code.add("test([]);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeMethods() {
final StringList code = new StringList();
code.add("/** @type {function(String, Number):Date} **/");
code.add("var f;");
code.add("f.apply({}, []).getFullYear();");
code.add("f.apply({}, [\"aaa\", 222]).getFullYear();");
code.add("f.call([], \"bbb\", 333).getFullYear();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeMethodsErrors() {
final StringList code = new StringList();
code.add("/** @type {function(Number):Date} **/");
code.add("var f;");
code.add("f.call({}, 111, 222);");
code.add("f.call({});");
code.add("f.call({}, 111).iDoNotExist();");
code.add("f.apply({}, {});");
code.add("f.apply({}, []).iAmUndefined;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 5, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(1)
.getID());
assertEquals(JavaScriptProblems.UNDEFINED_METHOD, problems.get(2)
.getID());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(3)
.getID());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(4)
.getID());
}
public void testMultiDimRecordType() {
final StringList code = new StringList();
code.add("/**");
code.add("* @param {Object} data");
code.add("* @param {Object} options");
code.add("* @param {Object} options.backgroundColor");
code.add("* @param {String} options.backgroundColor.fill");
code.add("* @param {String} options.backgroundColor.stroke");
code.add("* @param {Number} options.backgroundColor.strokeWidth");
code.add("*");
code.add("*/");
code.add("function draw(data, options) {");
code.add("var s = options.backgroundColor.fill;");
code.add("s.toUpperCase();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testThisAnnotationError() {
final StringList code = new StringList();
code.add("/** @this {String} */");
code.add("var g = function () {");
code.add("this.length; // OK");
code.add("this.fixed(); // OK");
code.add("this.getDay(); // warning - undefined member");
code.add("this.myMethod(); // warning - undefined member");
code.add("this.ble; // warning - undefined member");
code.add("}");
code.add("g.apply('');");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 3, problems.size());
assertEquals(JavaScriptProblems.UNDEFINED_METHOD, problems.get(0)
.getID());
assertEquals(JavaScriptProblems.UNDEFINED_METHOD, problems.get(1)
.getID());
assertEquals(JavaScriptProblems.UNDEFINED_PROPERTY, problems.get(2)
.getID());
}
public void testThisAnnotationValid() {
final StringList code = new StringList();
code.add("var g = function () {");
code.add("this.length;");
code.add("this.fixed();");
code.add("this.getDay();");
code.add("this.myMethod();");
code.add("this.ble;");
code.add("}");
code.add("g.apply('');");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testJavaScriptDynamicArrayAcces() {
final StringList code = new StringList();
code.add("var x = new Array();");
code.add("x['test']();");
code.add("var y = {}");
code.add("y['test']();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testJavaScriptDynamicArrayAccesProperty() {
final StringList code = new StringList();
code.add("var x = new Array();");
code.add("x['test'].aaa;");
code.add("var y = {}");
code.add("y['test'].aaa;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testJavaScriptNewArray() {
final StringList code = new StringList();
code.add("var x = new Array();");
code.add("x[0].aaa;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testJavaObjectDynamicArrayAcces() {
final StringList code = new StringList();
code.add("exampleForms['test']();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testJavaObjectDynamicArrayAccesProperty() {
final StringList code = new StringList();
code.add("exampleForms['test'].aaa;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testGenericCopyMethod() {
final StringList code = new StringList();
code.add("/** @param {String} value */");
code.add("function testStr(value) {}");
code.add("/** @param {Number} value */");
code.add("function testNum(value) {}");
code.add("var s = exampleCopy('str');");
code.add("testStr(s);");
code.add("var n = exampleCopy(1);");
code.add("testNum(n);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testMapRecordCompatibilityOK() {
final StringList code = new StringList();
code.add("/** @param {Object<Number>} m */");
code.add("function withMap(m) {}");
code.add("withMap({ a: 1, b: 2, c: 3 })");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testMapRecordCompatibilityError() {
final StringList code = new StringList();
code.add("/** @param {Object<Number>} m */");
code.add("function withMap(m) {}");
code.add("withMap({ a: 1, b: 2, c: '' })");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testReturnWith2NewInstances() throws Exception {
StringList code = new StringList();
code.add("function myObject() { this.me = 'myself'; }");
code.add("function createMyObject(myParam) {");
code.add(" if (!myParam) { return new myObject(); }");
code.add(" return new myObject();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnWith1NewInstanceAnd1CallInstance() throws Exception {
StringList code = new StringList();
code.add("function myObject() { this.me = 'myself'; }");
code.add("function getMyObject() {");
code.add(" return new myObject();");
code.add("}");
code.add("function createMyObject(myParam) {");
code.add(" if (!myParam) { return new myObject(); }");
code.add(" return getMyObject();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnWith2CallInstance() throws Exception {
StringList code = new StringList();
code.add("function myObject() { this.me = 'myself'; }");
code.add("function getMyObject() {");
code.add(" return new myObject();");
code.add("}");
code.add("function getMyObject2() {");
code.add(" return new myObject();");
code.add("}");
code.add("function createMyObject(myParam) {");
code.add(" if (!myParam) { return getMyObject2(); }");
code.add(" return getMyObject();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnWith1CallJSDocInstanceAnd1NewInstance()
throws Exception {
StringList code = new StringList();
code.add("function myObject() { this.me = 'myself'; }");
code.add("/**");
code.add(" * @return {myObject}");
code.add(" */");
code.add("function getMyObject() {");
code.add(" return null;");
code.add("}");
code.add("function createMyObject(myParam) {");
code.add(" if (!myParam) { return new myObject(); }");
code.add(" return getMyObject();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testReturnWith2CallJSDocInstance() throws Exception {
StringList code = new StringList();
code.add("function myObject() { this.me = 'myself'; }");
code.add("/**");
code.add(" * @return {myObject}");
code.add(" */");
code.add("function getMyObject() {");
code.add(" return null;");
code.add("}");
code.add("/**");
code.add(" * @return {myObject}");
code.add(" */");
code.add("function getMyObject2() {");
code.add(" return null;");
code.add("}");
code.add("function createMyObject(myParam) {");
code.add(" if (!myParam) { return getMyObject2(); }");
code.add(" return getMyObject();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testGenericReturnCallSort() {
StringList code = new StringList();
code.add("/**");
code.add(" * @return {Array<String>}");
code.add(" */");
code.add("function getJSFormHierarchy() {");
code.add(" /** @type {Array<String>} */");
code.add(" var retval = new Array();");
code.add(" return retval.sort(function(){});");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testGenericReturnCallReverse() {
StringList code = new StringList();
code.add("/**");
code.add(" * @return {Array<String>}");
code.add(" */");
code.add("function getJSFormHierarchy() {");
code.add(" /** @type {Array<String>} */");
code.add(" var retval = new Array();");
code.add(" return retval.reverse();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testRecordTypeObjectProperty() {
StringList code = new StringList();
code.add("/**");
code.add(" * @param {String} form");
code.add(" */");
code.add("function forEach(form) {");
code.add("var processed = { }");
code.add("processed.hasOwnProperty(form);");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testVariableTypedAsCustomTypeReferecingItselfArrayThroughDoc() {
// if (notYetImplemented(this))
// return;
// this works now because the Type Array<MyObject> is mapped to Array<Any> and then everything is allowed
// but it shouldn't it should be allowed because there is really a myfunc method with a number function..
final StringList code = new StringList();
code.add("function MyObject() {");
code.add(" this.num = 10;");
code.add(" /**");
code.add(" * @param {Number} x");
code.add(" * @return {MyObject}");
code.add(" */");
code.add(" this.myfunc = function(x) {");
code.add(" return null;");
code.add(" }");
code.add("}");
code.add("function test() {");
code.add(" /** @type {Array<MyObject>} */");
code.add(" this.scopeOneItems = new Array();");
code.add(" this.scopeOneItems[1].myfunc(1)");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testVariableTypedAsCustomTypeReferecingItselfArrayThroughDocWrongCall() {
final StringList code = new StringList();
code.add("function MyObject() {");
code.add(" this.num = 10;");
code.add(" /**");
code.add(" * @param {Number} x");
code.add(" * @return {MyObject}");
code.add(" */");
code.add(" this.myfunc = function(x) {");
code.add(" return null;");
code.add(" }");
code.add("}");
code.add("function test() {");
code.add(" /** @type {Array<MyObject>} */");
code.add(" this.scopeOneItems = new Array();");
code.add(" this.scopeOneItems[1].myfunc('1')");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(1, validate.size());
}
public void testLazyFunctionCallWithJSDocArrayReturnType() {
final StringList code = new StringList();
code.add("function test() {");
code.add(" var x = getChildFormsInEditMode();");
code.add(" x.length;");
code.add("}");
code.add("/**");
code.add(" * @return {Array<String>}");
code.add(" */");
code.add("function getChildFormsInEditMode() {");
code.add(" /** @type {Array<String>} */");
code.add(" var _formAr = [];");
code.add(" return _formAr;");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testNewWithoutCallExpression() {
final List<IProblem> problems = validate("var test = new Test");
assertEquals(problems.toString(), 1, problems.size());
}
public void testLazyFunctionTypeInFunctionAndVariableDoc() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @type {Array<RuntimeProperty>}");
code.add(" */");
code.add("var runtimeProperties = null;");
code.add("/**");
code.add("* @return {Array<RuntimeProperty>} properties");
code.add("*/");
code.add("function getRuntimeProperties() {");
code.add("/** @type {Array<RuntimeProperty>} */");
code.add("var result = null;");
code.add("return result;");
code.add("}");
code.add("function RuntimeProperty() {");
code.add("this.test = 10;");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testDefaultObjectMethodOnLocalType() {
final StringList code = new StringList();
code.add("function test() {");
code.add("var y = new MyObject();");
code.add("y.toString();");
code.add("}");
code.add("function MyObject() {");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testLocalTypeConstructorCallWithArgument() {
final StringList code = new StringList();
code.add("function test() {");
code.add("var y = new MyObject();");
code.add("y.toString();");
code.add("}");
code.add("/**");
code.add("* @param {String} x");
code.add("*/");
code.add("function MyObject(x) {");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(1, validate.size());
}
public void testRecordTypeWrappedInUnion() {
final StringList code = new StringList();
code.add("/**");
code.add("* @return {{test:String,test2:Number}}");
code.add("*/");
code.add("function test() {");
code.add(" /** @type {{test:String,test2:Number}} */");
code.add(" var x = new Object();");
code.add(" x.test = '';");
code.add(" x.test2 = 2;");
code.add(" return x;");
code.add("}");
code.add("function caller() {");
code.add(" var x = test();");
code.add(" reciever(x);");
code.add("}");
code.add("/**");
code.add("* @param {{test:String,test2:Number}} y");
code.add("*/");
code.add("function reciever(y) {");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testForInVariableDeclared() {
final StringList code = new StringList();
code.add("var obj = {a:1,b:2}");
code.add("for (k in obj) {");
code.add("}");
List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.UNDECLARED_VARIABLE, problems.get(0)
.getID());
}
public void testLocalTypesInArrayInitializer() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function someCustType() {}");
code.add("/**");
code.add("* @param {Array<someCustType>} arg");
code.add(" */");
code.add("function someFunc(arg) {}");
code.add("function caller() {");
code.add(" someFunc([new someCustType(), new someCustType()]);");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testMixedLocalTypesInArrayInitializer() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function someCustType2() {}");
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function someCustType() {}"); code.add("/**");
code.add("* @param {Array<someCustType>} arg");
code.add(" */");
code.add("function someFunc(arg) {}");
code.add("function caller() {");
code.add(" someFunc([new someCustType(), new someCustType2()]);");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(1, validate.size());
}
public void testRecordTypeParamWithNullArgument() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {{x:Number}} obj");
code.add(" */");
code.add("function showForm(obj){ }");
code.add("function caller() {");
code.add(" showForm(null);");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testConstructorFunctionReassignedToVariable() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function MyObject() {");
code.add("}");
code.add("var test = MyObject;");
code.add("function caller() {");
code.add(" var x = new test();");
code.add(" callee(x);");
code.add("}");
code.add("/**");
code.add("* @param {MyObject} x");
code.add("*/");
code.add("function callee(x) {");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testLocalTypeParamWithNullArgument() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function someCustType() {}");
code.add("/**");
code.add(" * @param {someCustType} obj");
code.add(" */");
code.add("function showForm(obj){ }");
code.add("function caller() {");
code.add(" showForm(null);");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testLocalTypeInRecordType() {
final StringList code = new StringList();
code.add("function MyObject() {");
code.add(" this.mytest = function() {}");
code.add("}");
code.add("/**");
code.add(" * @param {MyObject} param.options");
code.add(" */");
code.add("function test(param) {");
code.add(" param.options.mytest();");
code.add("}");
List<IProblem> validate = validate(code.toString());
assertEquals(0, validate.size());
}
public void testInlineBlock() {
final StringList code = new StringList();
code.add("(function(a) {");
code.add("})()");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS_UNTYPED,
problems.get(0).getID());
}
public void testInlineBlockWithUndefined() {
final StringList code = new StringList();
code.add("(function(undefined) {");
code.add("})()");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testExtends() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function BaseBase() {");
code.add(" this.basebase = function(a) {}");
code.add(" this.x = 10;");
code.add("}");
code.add("/**");
code.add(" * @constructor");
code.add(" * @extends {BaseBase}");
code.add(" */");
code.add("function Base() {");
code.add(" /** @this {Base} */");
code.add(" this.mytest = function(a) {");
code.add(" this.basebase(this.x);");
code.add(" }");
code.add("}");
code.add("/**");
code.add(" * @constructor");
code.add(" * @extends {Base}");
code.add(" */");
code.add("function Child () {");
code.add(" /** @this {Child} */");
code.add(" this.childsTest = function() {");
code.add(" this.mytest(1);");
code.add(" this.x = 11;");
code.add(" this.basebase(this.x);");
code.add(" }");
code.add("}");
code.add("function test() {");
code.add(" var x = new Child();");
code.add(" x.childsTest();");
code.add(" x.mytest(2);");
code.add(" x.x = 1;");
code.add(" x.basebase(x.x);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testExtendsSubAsArgumentForBaseParam() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function BaseBase() {}");
code.add("/**");
code.add(" * @constructor");
code.add(" * @extends {BaseBase}");
code.add(" */");
code.add("function Base(){}");
code.add("/**");
code.add(" * @constructor");
code.add(" * @extends {Base}");
code.add(" */");
code.add("function Sub() {}");
code.add("function test() {");
code.add(" amethod(new Sub());");
code.add(" amethod(new Base());");
code.add("}");
code.add("/**");
code.add(" * @param {BaseBase} a");
code.add(" */");
code.add("function amethod(a) {}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testExtendsBaseAsArgumentForSubParam() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function Base(){}");
code.add("/**");
code.add(" * @constructor");
code.add(" * @extends {Base}");
code.add(" */");
code.add("function Sub() {}");
code.add("function test() {");
code.add(" amethod(new Base());");
code.add("}");
code.add("/**");
code.add(" * @param {Sub} a");
code.add(" */");
code.add("function amethod(a) {}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
assertEquals(JavaScriptProblems.WRONG_PARAMETERS, problems.get(0)
.getID());
}
public void testRecordTypeCommonBaseTest() {
final StringList code = new StringList();
code.add("/**");
code.add("* @param {Array<Number>|Array<{data: Array<Array<Number>>,label: String=}>} options");
code.add("*/");
code.add("function test(options) {}");
code.add("function test1() {");
code.add(" test([");
code.add(" { data : [[0, 4]], label : 'Comedy' },");
code.add(" { data : [[0, 3]], label : 'Action' },");
code.add(" { data : [[0, 1.03]], label : 'Romance', pie : { explode : 50}},");
code.add(" { data : [[0, 3.5]], label : 'Drama' }");
code.add(" ])");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testRecordTypeCommonBaseTestWithDifferentType() {
final StringList code = new StringList();
code.add("/**");
code.add("* @param {Array<Number>|Array<{data: Array<Array<Number>>,label: String=}>} options");
code.add("*/");
code.add("function test(options) {}");
code.add("function test1() {");
code.add(" test([");
code.add(" { data : [[0, 4]], label : 'Comedy' },");
code.add(" { data : [[0, 3]], label : 'Action' },");
code.add(" { data : [[0, 1.03]], label : 'Romance', pie : { explode : 50}},");
code.add(" { data1 : [[0, 3.5]], label : 'Drama' }");
code.add(" ])");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testFluentTypeRecordType() {
final StringList code = new StringList();
code.add("/**");
code.add("* @typedef {{val:Number,add:function(Number):FluentType}}");
code.add("*/");
code.add("var FluentType = null;");
code.add("/**");
code.add("* @param {Number} myVal");
code.add("* @return {FluentType}");
code.add("*/");
code.add("function newFluent(myVal) {");
code.add("return {val:myVal,add:function(num) {}};");
code.add("}");
code.add("function testFluency() {");
code.add("var fl = newFluent(12);");
code.add("fl.add(4).add(5);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFluentTypeRecordTypeWithError() {
final StringList code = new StringList();
code.add("/**");
code.add("* @typedef {{val:FluentType,add:function(FluentType):FluentType}}");
code.add("*/");
code.add("var FluentType = null;");
code.add("/**");
code.add("* @param {Number} myVal");
code.add("* @return {FluentType}");
code.add("*/");
code.add("function newFluent(myVal) {");
code.add("return {val:myVal,add:function(num) {}};");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testThisCallInObjectFunction() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor");
code.add(" */");
code.add("function Myconstructor(){");
code.add(" this.getArray = function(){");
code.add(" return []");
code.add(" },");
code.add(" this.test = function() {");
code.add(" var shouldBeArray = this.getArray()");
code.add(" for (var i = 0, len = shouldBeArray.length; i < len; i++) {}");
code.add(" }");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testProtectedProperty() {
if (notYetImplemented(this)) {
return;
}
final StringList code = new StringList();
code.add("function tst() {");
code.add("/**");
code.add(" * @protected");
code.add(" */");
code.add("this.myproperty = null;");
code.add("}");
code.add("function test() {");
code.add(" var x = new tst();");
code.add(" x.myproperty;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testProtectedMemberInAssignedInSubtype() {
if (notYetImplemented(this)) {
return;
}
final StringList code = new StringList();
code.add("/** @constructor*/");
code.add("function proto() {");
code.add(" /** @protected */");
code.add(" this.map = null");
code.add("}");
code.add("/**");
code.add(" * @constructor");
code.add(" * @extends {proto}");
code.add(" */");
code.add("function ProtoExt() {");
code.add(" this.map = 1");
code.add("}");
code.add("function testProtoExt() {");
code.add(" var x = new ProtoExt()");
code.add(" x.map;");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testFunctionTypeExactParam() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number)} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number)} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeObjectParam() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number)} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(Object,Object)} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeObjectArgument() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(Object, Object)} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number)} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testFunctionTypeExactReturnType() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number):Boolean} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number):Boolean} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeObjectReturnType() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number):Object} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number):Boolean} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeObjectCallerReturnType() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number):Boolean} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number):Object} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testFunctionTypeObjectNoReturnType() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number)} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number):Object} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeObjectNoCallerReturnType() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number):Boolean} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number)} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testFunctionTypeOptionalParam() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number, String=):Boolean} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number):Boolean} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testFunctionTypeOptionalArgument() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {function(String, Number):Boolean} f");
code.add(" */");
code.add("function test(f) {}");
code.add("/** @type {function(String,Number,String=):Boolean} */");
code.add("var f = function(a,b){};");
code.add("test(f);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPrototypeFunction() {
final StringList code = new StringList();
code.add("function A() {}");
code.add("A.prototype.testDirectAssignment = function(){ }");
code.add("var x = new A();");
code.add("x.testDirectAssignment();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPrototypeFunctionWithExtends() {
final StringList code = new StringList();
code.add("function A() {}");
code.add("/**");
code.add(" * @extends {A}");
code.add(" */");
code.add("function B() {}");
code.add("B.prototype = new A();");
code.add("B.prototype.testDirectAssignment = function(){ }");
code.add("var x = new B();");
code.add("x.testDirectAssignment();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPrototypeFunctionWith2Extends() {
final StringList code = new StringList();
code.add("function A() {}");
code.add("A.prototype.afunction = function(){ }");
code.add("/**");
code.add(" * @extends {A}");
code.add(" */");
code.add("function B() {}");
code.add("B.prototype = new A();");
code.add("B.prototype.bfunction = function(){ }");
code.add("/**");
code.add(" * @extends {B}");
code.add(" */");
code.add("function C() {}");
code.add("C.prototype = new B();");
code.add("C.prototype.testDirectAssignment = function(){ }");
code.add("var x = new C();");
code.add("x.testDirectAssignment();");
code.add("x.bfunction();");
code.add("x.afunction();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPrototypeWithRecordTypeConstruction() {
final StringList code = new StringList();
code.add("function D1() {}");
code.add("D1.prototype = {test: function(a){}}");
code.add("D1.prototype.testDirectAssignment = function(b){}");
code.add("var x = new D1()");
code.add("x.test(1)");
code.add("x.testDirectAssignment(2)");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPrototypeThroughObjectCreate() {
final StringList code = new StringList();
code.add("function Base(name) {");
code.add(" this.name = name");
code.add("}");
code.add("Base.prototype = {");
code.add(" baseMethod: function(a,b,c) {");
code.add(" return 'baseMethod called'");
code.add(" }");
code.add("}");
code.add("/**");
code.add(" * @extends {Base}");
code.add(" */");
code.add("function Sub(name, age) {");
code.add(" Base.call(this, name)");
code.add(" this.age = age");
code.add("}");
code.add("Sub.prototype = Object.create(Base.prototype, {");
code.add(" subMethod: {");
code.add(" value: function(a,b) {");
code.add(" return 'subMethod called'");
code.add(" },");
code.add(" enumerable: true");
code.add(" }");
code.add(" })");
code.add("Sub.prototype.subMethod2 = function(a,b,c) {");
code.add(" return 'subMethod2 called'");
code.add("}");
code.add("function test2() {");
code.add(" var x = new Sub('DLTK', 11)");
code.add(" var name = x.name;");
code.add(" var age = x.age;");
code.add(" x.baseMethod(name,age,age);");
code.add(" x.subMethod(name,age)");
code.add(" x.subMethod2(name,age,age);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testPrototypeOverrideFunctions() {
final StringList code = new StringList();
code.add("function Base(name) {");
code.add(" this.name = name");
code.add("}");
code.add("Base.prototype = {");
code.add(" method: function(a,b,c) {");
code.add(" return 'method1 in base called'");
code.add(" }");
code.add("}");
code.add("Base.prototype.method2 = function(a,b,c) {");
code.add(" return 'method2 in base called'");
code.add("}");
code.add("/**");
code.add(" * @extends {Base}");
code.add(" */");
code.add("function Sub(name, age) {");
code.add(" Base.call(this, name)");
code.add(" this.age = age");
code.add("}");
code.add("Sub.prototype = Object.create(Base.prototype, {");
code.add(" method: {");
code.add(" value: function(a,b) {");
code.add(" return 'method1 in sub called'");
code.add(" },");
code.add(" enumerable: true");
code.add(" }");
code.add(" })");
code.add("Sub.prototype.method2 = function(a,b,c) {");
code.add(" return 'method2 in sub called'");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testApplyCall() {
final StringList code = new StringList();
code.add("function test() {var args = Array.prototype.slice.apply(arguments, [1]);");
code.add("args.slice(1);}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testCallCall() {
final StringList code = new StringList();
code.add("function test() {");
code.add("var args = Array.prototype.slice.call(arguments, 1);");
code.add("args.slice(1);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testBindCall() {
final StringList code = new StringList();
code.add("function A(nr) {");
code.add(" this.nr = nr;");
code.add(" /**");
code.add(" * @return {Number}");
code.add(" */");
code.add(" this.getNr = function()");
code.add(" {");
code.add(" return this.nr;");
code.add(" }");
code.add("}");
code.add("var a1 = new A(1);");
code.add("var a2 = new A(2);");
code.add("var a = a1.getNr();");
code.add("a.toExponential();");
code.add("var b = a1.getNr.bind(a2)();");
code.add("b.toExponential();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testDeprecatedPrototypeFunctions() {
final StringList code = new StringList();
code.add("function Sub(name, age) {");
code.add(" this.age = age");
code.add("}");
code.add("Sub.prototype = {");
code.add(" /** @deprecated */");
code.add(" baseMethod: function() {");
code.add(" return 'baseMethod called'");
code.add(" }");
code.add("}");
code.add("/** @deprecated */");
code.add("Sub.prototype.subMethod2 = function(a,b,c) {");
code.add(" return 'subMethod2 called'");
code.add("}");
code.add("function test2() {");
code.add(" var y = new Sub('test2',2);");
code.add(" y.subMethod2(1,2,3);");
code.add(" y.baseMethod();");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 2, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_FUNCTION, problems.get(0)
.getID());
assertEquals(JavaScriptProblems.DEPRECATED_FUNCTION, problems.get(1)
.getID());
}
public void testDeprecatedValidation() {
final StringList code = new StringList();
code.add("var y = {");
code.add(" /**");
code.add(" * @deprecated");
code.add(" */");
code.add(" func1: function() {}");
code.add("}");
code.add("/**");
code.add(" * @deprecated");
code.add(" */");
code.add("y.func = function() {}");
code.add("/**");
code.add(" * @deprecated");
code.add(" */");
code.add("function test() {}");
code.add("y.test = test;");
code.add("y.func();");
code.add("y.func1();");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 3, problems.size());
assertEquals(JavaScriptProblems.DEPRECATED_FUNCTION, problems.get(0)
.getID());
assertEquals(JavaScriptProblems.DEPRECATED_FUNCTION, problems.get(1)
.getID());
assertEquals(JavaScriptProblems.DEPRECATED_FUNCTION, problems.get(2)
.getID());
}
public void testObjectCreateWith2SubclassesUsingtheBase() {
final StringList code = new StringList();
code.add("function AbstractMessage(format, parameters, throwable) {");
code.add(" this.throwable = throwable");
code.add("}");
code.add("/**");
code.add(" * @return {Error}");
code.add(" */");
code.add(" AbstractMessage.prototype.getThrowable = function() {");
code.add(" return null;");
code.add("}");
code.add("function ObjectMessage(object) {}");
code.add("ObjectMessage.prototype = Object.create(AbstractMessage.prototype)");
code.add("ObjectMessage.prototype.constructor = ObjectMessage");
code.add("ObjectMessage.prototype.getThrowable = function() {");
code.add(" return (this.format instanceof Error) ? this.format : null");
code.add("}");
code.add("function LogEvent(message) {");
code.add(" /**");
code.add(" * @type {AbstractMessage}");
code.add(" */");
code.add(" this.message = message");
code.add("}");
code.add("function OutputAppender() {}");
code.add("/**");
code.add(" * @param {LogEvent} logEvent");
code.add(" */");
code.add("OutputAppender.prototype.append = function(logEvent){");
code.add(" var ex2 = logEvent.message.getThrowable()");
code.add(" ex2.stack");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testUnionTypeAsArgument() {
final StringList code = new StringList();
code.add("var s = '== {{DATE}} ==';");
code.add("var x = 10;");
code.add("if (s)");
code.add(" x = ''");
code.add("s = s.replace('',x);");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testThisAssignedToVariable() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @constructor ");
code.add(" */");
code.add("function cust() {");
code.add(" var self = this;");
code.add(" this.boo = 42;");
code.add(" this.func = function(){");
code.add(" self.boo.toFixed()");
code.add(" }");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testOptionalRecordTypePropertiesParam() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {Function} f");
code.add(" * @param {Boolean} [options.one]");
code.add(" * @param {Boolean} [options.two]");
code.add(" */");
code.add("function api(f, options) {}");
code.add("function test() {");
code.add(" api(function(){})");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void testNoneOptionalRecordTypePropertiesParam() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {Function} f");
code.add(" * @param {Boolean} options.one");
code.add(" * @param {Boolean} [options.two]");
code.add(" */");
code.add("function api(f, options) {}");
code.add("function test() {");
code.add(" api(function(){})");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 1, problems.size());
}
public void testUnionTypeWithArray() {
final StringList code = new StringList();
code.add("/**");
code.add(" * @param {Array<Array<*>|Number>} a");
code.add(" */");
code.add("function call(a) {}");
code.add("function test() {");
code.add(" var array1 = [1,2];");
code.add(" call(array1);");
code.add(" var array2 = [[1,2]];");
code.add(" call(array2);");
code.add(" var array3 = [[1,2],1];");
code.add(" call(array3);");
code.add(" var array4 = [['1','2'],1];");
code.add(" call(array4);");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void test2ApplyMethodOnPrototypeMethod() {
final StringList code = new StringList();
code.add("function MyConstuctor() {}");
code.add("/**");
code.add(" * @return {String}");
code.add(" */");
code.add(" MyConstuctor.prototype.newMessage = function(message, params) {");
code.add(" return ''");
code.add(" }");
code.add("/**");
code.add(" * @param {String} text");
code.add(" */");
code.add("function meth2(text) {}");
code.add("function testMeth() {");
code.add(" var o = new MyConstuctor()");
code.add(" meth2(o.newMessage.apply(null,[1,2]))");
code.add("}");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
public void test2PrototypeWithGetSetProperty() {
final StringList code = new StringList();
code.add("function x(){}");
code.add("x.prototype = Object.create(Object.prototype, {");
code.add(" bar: {");
code.add(" configurable: false,");
code.add(" get: function() { return 10 },");
code.add(" set: function(value) { }");
code.add("}});");
code.add("var p = new x();");
code.add("var o = p.bar;");
final List<IProblem> problems = validate(code.toString());
assertEquals(problems.toString(), 0, problems.size());
}
}