/******************************************************************************* * Copyright (c) 2011 NumberFour AG * * 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: * NumberFour AG - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.javascript.core.tests.typeinfo; import java.text.ParseException; import junit.framework.TestCase; import org.eclipse.dltk.internal.javascript.ti.JSDocProblem; import org.eclipse.dltk.javascript.core.Types; import org.eclipse.dltk.javascript.typeinfo.JSDocParseException; import org.eclipse.dltk.javascript.typeinfo.JSDocTypeParser; import org.eclipse.dltk.javascript.typeinfo.model.ArrayType; import org.eclipse.dltk.javascript.typeinfo.model.ClassType; import org.eclipse.dltk.javascript.typeinfo.model.FunctionType; import org.eclipse.dltk.javascript.typeinfo.model.JSType; import org.eclipse.dltk.javascript.typeinfo.model.ParameterKind; import org.eclipse.dltk.javascript.typeinfo.model.RecordMember; import org.eclipse.dltk.javascript.typeinfo.model.RecordType; import org.eclipse.dltk.javascript.typeinfo.model.SimpleType; import org.eclipse.dltk.javascript.typeinfo.model.UnionType; import org.eclipse.emf.common.util.EList; @SuppressWarnings("restriction") public class JSDocTypeParserTests extends TestCase { private JSType parse(String expression) { try { return new JSDocTypeParser().parse(expression); } catch (ParseException e) { System.out.println(expression); final StringBuilder sb = new StringBuilder(); for (int i = 0; i < e.getErrorOffset(); ++i) sb.append(' '); sb.append("^^^ ").append(e.getMessage()); System.out.println(sb.toString()); throw new RuntimeException(e); } } private ParseException parseError(String expression) { try { new JSDocTypeParser().parse(expression); fail("parse(" + expression + ") is expected to fail"); return null;// fail() never returns } catch (ParseException e) { return e; } } private static void assertRef(final String expected, JSType type) { assertEquals(expected, ((SimpleType) type).getTarget().getName()); } public void testSimple() { JSType type = parse("String"); assertRef("String", type); } public void testSimpleTranslated() { JSType type = parse("string"); assertRef("String", type); } public void testSimpleParentheses() { JSType type = parse("( string )"); assertRef("String", type); } public void testParenthesesError() { final String expression = "(string"; final ParseException exception = parseError(expression); assertEquals(") expected", exception.getMessage()); assertEquals(expression.length(), exception.getErrorOffset()); } public void testUnexpectedContentError() { final String expression = "string)))"; final ParseException exception = parseError(expression); assertEquals("Unexpected )))", exception.getMessage()); assertEquals(expression.length() - 3, exception.getErrorOffset()); } public void testClassOfNumber() { final String expression = "Class<Number>"; final ClassType type = (ClassType) parse(expression); assertSame(Types.NUMBER, type.getTarget()); } public void testClassOfSomething() { final String expression = "Class<Something>"; final ClassType type = (ClassType) parse(expression); assertEquals("Something", type.getTarget().getName()); } public void testWrongClassParameterization() { final String expression = "Class<Array<Number>>"; final JSDocParseException exception = (JSDocParseException) parseError(expression); assertEquals(JSDocProblem.WRONG_TYPE_PARAMETERIZATION, exception.problemId); assertEquals("Class cannot be parameterized with ArrayType", exception.getMessage()); } public void testArray() { JSType type = parse("Array.<String>"); assertRef("String", ((ArrayType) type).getItemType()); } public void testUnionType() { UnionType type = (UnionType) parse("String|Number"); assertEquals(2, type.getTargets().size()); assertRef("String", type.getTargets().get(0)); assertRef("Number", type.getTargets().get(1)); } public void testUnionParenthesesType() { UnionType type = (UnionType) parse("(String | Number)"); assertEquals(2, type.getTargets().size()); assertRef("String", type.getTargets().get(0)); assertRef("Number", type.getTargets().get(1)); } public void testRecordType() { final RecordType type = (RecordType) parse("{ astring : String , anumber : Number }"); assertEquals(2, type.getMembers().size()); assertEquals("astring", type.getMembers().get(0).getName()); assertRef("String", type.getMembers().get(0).getType()); assertEquals("anumber", type.getMembers().get(1).getName()); assertRef("Number", type.getMembers().get(1).getType()); } public void testRecordTypeWithOptionalBrackets() { final RecordType type = (RecordType) parse("{astring:String, [anumber]:Number}"); assertEquals(2, type.getMembers().size()); assertEquals("astring", type.getMembers().get(0).getName()); assertRef("String", type.getMembers().get(0).getType()); assertEquals("anumber", type.getMembers().get(1).getName()); assertRef("Number", type.getMembers().get(1).getType()); assertTrue(((RecordMember) type.getMembers().get(1)).isOptional()); } public void testRecordTypeWithOptionalClosureStyle() { final RecordType type = (RecordType) parse("{astring:String,anumber:Number=}"); assertEquals(2, type.getMembers().size()); assertEquals("astring", type.getMembers().get(0).getName()); assertRef("String", type.getMembers().get(0).getType()); assertEquals("anumber", type.getMembers().get(1).getName()); assertRef("Number", type.getMembers().get(1).getType()); assertTrue(((RecordMember) type.getMembers().get(1)).isOptional()); } public void testRecordTypeWithLiteralQuotedProperties() { final RecordType type = (RecordType) parse("{'a-string':String, anumber:Number=}"); assertEquals(1, type.getMembers().size()); assertEquals("anumber", type.getMembers().get(0).getName()); assertRef("Number", type.getMembers().get(0).getType()); assertTrue(((RecordMember) type.getMembers().get(0)).isOptional()); } public void testFunctionType1() { final FunctionType type = (FunctionType) parse("function():String"); assertEquals(0, type.getParameters().size()); assertRef("String", type.getReturnType()); } public void testFunctionType2() { final FunctionType type = (FunctionType) parse("function(String)"); assertEquals(1, type.getParameters().size()); assertRef("String", type.getParameters().get(0).getType()); assertNull(type.getReturnType()); } public void testFunctionType3() { final FunctionType type = (FunctionType) parse("function( String ) : Number"); assertEquals(1, type.getParameters().size()); assertRef("String", type.getParameters().get(0).getType()); assertRef("Number", type.getReturnType()); } public void testFunctionType4() { final FunctionType type = (FunctionType) parse("function ( String ) : Number"); assertEquals(1, type.getParameters().size()); assertRef("String", type.getParameters().get(0).getType()); assertRef("Number", type.getReturnType()); } public void testFunctionTypeVarArgs() { final FunctionType type = (FunctionType) parse("function(string, ...[number]): number"); assertEquals(2, type.getParameters().size()); assertRef("String", type.getParameters().get(0).getType()); assertRef("Number", type.getParameters().get(1).getType()); assertEquals(ParameterKind.VARARGS, type.getParameters().get(1) .getKind()); assertRef("Number", type.getReturnType()); } public void testUnitonWithFunction1() { final UnionType type = (UnionType) parse("String|function(Number):Number|String"); final EList<JSType> parts = type.getTargets(); assertEquals(3, parts.size()); final SimpleType part0 = (SimpleType) parts.get(0); assertEquals("String", part0.getName()); final FunctionType part1 = (FunctionType) parts.get(1); assertEquals("Number", part1.getReturnType().getName()); final SimpleType part2 = (SimpleType) parts.get(2); assertEquals("String", part2.getName()); } public void testUnitonWithFunction2() { final UnionType type = (UnionType) parse("String|function(Number):(Number|String)"); final EList<JSType> parts = type.getTargets(); assertEquals(2, parts.size()); final SimpleType part0 = (SimpleType) parts.get(0); assertEquals("String", part0.getName()); final FunctionType part1 = (FunctionType) parts.get(1); final UnionType resultType = (UnionType) part1.getReturnType(); assertEquals(2, resultType.getTargets().size()); assertEquals("Number", resultType.getTargets().get(0).getName()); assertEquals("String", resultType.getTargets().get(1).getName()); } }