| /******************************************************************************* |
| * 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()); |
| |
| } |
| } |