| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.javascript2.jsdoc; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import org.netbeans.modules.javascript2.doc.JsDocumentationTestBase; |
| import org.netbeans.modules.javascript2.doc.spi.JsComment; |
| import org.netbeans.modules.javascript2.doc.spi.JsDocumentationHolder; |
| import org.netbeans.modules.javascript2.editor.parser.JsParserResult; |
| import org.netbeans.modules.javascript2.jsdoc.model.AssignElement; |
| import org.netbeans.modules.javascript2.jsdoc.model.DeclarationElement; |
| import org.netbeans.modules.javascript2.jsdoc.model.DescriptionElement; |
| import org.netbeans.modules.javascript2.jsdoc.model.JsDocElement; |
| import org.netbeans.modules.javascript2.jsdoc.model.JsDocElementType; |
| import org.netbeans.modules.javascript2.jsdoc.model.LinkElement; |
| import org.netbeans.modules.javascript2.jsdoc.model.NamedParameterElement; |
| import org.netbeans.modules.javascript2.jsdoc.model.ParameterElement; |
| import org.netbeans.modules.javascript2.jsdoc.model.SimpleElement; |
| import org.netbeans.modules.javascript2.jsdoc.model.UnnamedParameterElement; |
| import org.netbeans.modules.parsing.api.ParserManager; |
| import org.netbeans.modules.parsing.api.ResultIterator; |
| import org.netbeans.modules.parsing.api.Source; |
| import org.netbeans.modules.parsing.api.UserTask; |
| import org.netbeans.modules.parsing.spi.Parser; |
| |
| /** |
| * |
| * @author Martin Fousek <marfous@netbeans.org> |
| */ |
| public class JsDocModelTest extends JsDocumentationTestBase { |
| |
| private static JsDocElementComparator elementComparator = new JsDocElementComparator(); |
| |
| public JsDocModelTest(String testName) { |
| super(testName); |
| } |
| |
| /** |
| * The string should look like: <type>||<key1>=<value1>:<key2>=<value2>;<type> |
| */ |
| private static List<JsDocElement> parseExpected(String expected) { |
| List<JsDocElement> elements = new ArrayList<JsDocElement>(); |
| String[] tags = expected.split("[;]+"); |
| for (String tag : tags) { |
| String[] tmp = tag.split("[|][|]"); |
| FakeJsDocElement element = new FakeJsDocElement(JsDocElementType.fromString(tmp[0])); |
| if (tmp.length > 1) { |
| String[] keyValues = tmp[1].split("[:]+"); |
| for (String keyValue : keyValues) { |
| String[] items = keyValue.split("[=]+"); |
| if (items.length == 1) { |
| // in context sensitive cases |
| element.addProperty("desc", items[0]); |
| } else { |
| element.addProperty(items[0], items[1]); |
| } |
| } |
| } |
| elements.add(element); |
| } |
| return elements; |
| } |
| |
| private static void checkJsDocElements(String expected, List<? extends JsDocElement> elements) { |
| List<JsDocElement> expectedTags = parseExpected(expected); |
| assertElementsEquality(expectedTags, elements); |
| |
| } |
| |
| private void checkJsDocBlock(Source source, final int offset, final String expected) throws Exception { |
| ParserManager.parse(Collections.singleton(source), new UserTask() { |
| public @Override void run(ResultIterator resultIterator) throws Exception { |
| Parser.Result result = resultIterator.getParserResult(); |
| assertTrue(result instanceof JsParserResult); |
| JsParserResult parserResult = (JsParserResult) result; |
| |
| JsDocumentationHolder documentationHolder = getDocumentationHolder(parserResult, new JsDocDocumentationProvider()); |
| JsComment comment = documentationHolder.getCommentForOffset(offset, documentationHolder.getCommentBlocks()); |
| checkJsDocElements(expected, ((JsDocComment) comment).getTags()); |
| } |
| }); |
| } |
| |
| public void testContextSensitiveDescription() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line1;"); |
| checkJsDocBlock(source, caretOffset, "contextSensitive||This could be description"); |
| } |
| |
| public void testArgument() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line2;"); |
| checkJsDocBlock(source, caretOffset, "@argument||type=paramType:name=paramName:desc=paramDescription"); |
| } |
| |
| public void testAugments() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line3;"); |
| checkJsDocBlock(source, caretOffset, "@augments||type=otherClass"); |
| } |
| |
| public void testAuthor() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line4;"); |
| checkJsDocBlock(source, caretOffset, "@author||desc=Jackie Chan"); |
| } |
| |
| public void testBorrows() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line5;"); |
| checkJsDocBlock(source, caretOffset, "@borrows||param1=otherMemberName:param2=thisMemberName"); |
| } |
| |
| public void testClass() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line6;"); |
| checkJsDocBlock(source, caretOffset, "@class||desc=description"); |
| } |
| |
| public void testConstant() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line7;"); |
| checkJsDocBlock(source, caretOffset, "@constant"); |
| } |
| |
| public void testConstructor() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line8;"); |
| checkJsDocBlock(source, caretOffset, "@constructor"); |
| } |
| |
| public void testConstructs() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line9;"); |
| checkJsDocBlock(source, caretOffset, "@constructs"); |
| } |
| |
| public void testDefault() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line10;"); |
| checkJsDocBlock(source, caretOffset, "@default||desc=valueDescription"); |
| } |
| |
| public void testDeprecated() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line11;"); |
| checkJsDocBlock(source, caretOffset, "@deprecated||desc=deprecatedDescription"); |
| } |
| |
| public void testDescription() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line12;"); |
| checkJsDocBlock(source, caretOffset, "@description||desc=description"); |
| } |
| |
| public void testEvent() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line13;"); |
| checkJsDocBlock(source, caretOffset, "@event"); |
| } |
| |
| public void testExample() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line14;"); |
| checkJsDocBlock(source, caretOffset, "@example||desc=var bleeper"); |
| } |
| |
| public void testExtends() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line15;"); |
| checkJsDocBlock(source, caretOffset, "@extends||type=otherClass"); |
| } |
| |
| public void testField() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line16;"); |
| checkJsDocBlock(source, caretOffset, "@field"); |
| } |
| |
| public void testFileOverview() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line17;"); |
| checkJsDocBlock(source, caretOffset, "@fileOverview||desc=fileDescription"); |
| } |
| |
| public void testFunction() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line18;"); |
| checkJsDocBlock(source, caretOffset, "@function"); |
| } |
| |
| public void testIgnore() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line19;"); |
| checkJsDocBlock(source, caretOffset, "@ignore"); |
| } |
| |
| public void testInner() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line20;"); |
| checkJsDocBlock(source, caretOffset, "@inner"); |
| } |
| |
| public void testLends() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line21;"); |
| checkJsDocBlock(source, caretOffset, "@lends||namepath=symbolAlias"); |
| } |
| |
| public void testMemberOf() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line22;"); |
| checkJsDocBlock(source, caretOffset, "@memberOf||namepath=parentNamepath"); |
| } |
| |
| public void testName() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line23;"); |
| checkJsDocBlock(source, caretOffset, "@name||namepath=theNamepath"); |
| } |
| |
| public void testNamespace() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line24;"); |
| checkJsDocBlock(source, caretOffset, "@namespace||desc=description"); |
| } |
| |
| public void testParam() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line25;"); |
| checkJsDocBlock(source, caretOffset, "@param||type=paramType:name=paramName:desc=paramDescription"); |
| } |
| |
| public void testPrivate() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line26;"); |
| checkJsDocBlock(source, caretOffset, "@private"); |
| } |
| |
| public void testProperty() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line27;"); |
| checkJsDocBlock(source, caretOffset, "@property||type=propertyType:name=propertyName:desc=propertyDescription"); |
| } |
| |
| public void testPublic() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line28;"); |
| checkJsDocBlock(source, caretOffset, "@public"); |
| } |
| |
| public void testRequires() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line29;"); |
| checkJsDocBlock(source, caretOffset, "@requires||desc=requireDescription"); |
| } |
| |
| public void testReturn() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line30;"); |
| checkJsDocBlock(source, caretOffset, "@return||type=returnType:desc=returnDescription"); |
| } |
| |
| public void testReturns() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line31;"); |
| checkJsDocBlock(source, caretOffset, "@returns||type=returnType:desc=returnDescription"); |
| } |
| |
| public void testSee() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line32;"); |
| checkJsDocBlock(source, caretOffset, "@see||desc=seeDescription"); |
| } |
| |
| public void testSince() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line33;"); |
| checkJsDocBlock(source, caretOffset, "@since||desc=versionDescription"); |
| } |
| |
| public void testStatic() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line34;"); |
| checkJsDocBlock(source, caretOffset, "@static"); |
| } |
| |
| public void testThrows() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line35;"); |
| checkJsDocBlock(source, caretOffset, "@throws||type=exceptionType:desc=exceptionDescription"); |
| } |
| |
| public void testType() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line36;"); |
| checkJsDocBlock(source, caretOffset, "@type||type=typeName"); |
| } |
| |
| public void testVersion() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "var ^line37;"); |
| checkJsDocBlock(source, caretOffset, "@version||desc=versionDescription"); |
| } |
| |
| public void testParameterWithoutDesc() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/parameterTypes.js")); |
| final int caretOffset = getCaretOffset(source, "function ^line1(userName){}"); |
| checkJsDocBlock(source, caretOffset, "@param||type=String:name=userName"); |
| } |
| |
| public void testParameterWithMoreTypes() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/parameterTypes.js")); |
| final int caretOffset = getCaretOffset(source, "function ^line2(product){}"); |
| checkJsDocBlock(source, caretOffset, "@param||type=String|Number:name=product"); |
| } |
| |
| public void testParameterOptional() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/parameterTypes.js")); |
| final int caretOffset = getCaretOffset(source, "function ^line3(accessLevel){}"); |
| checkJsDocBlock(source, caretOffset, "@param||type=String:name=accessLevel:desc=accessLevel is optional"); |
| } |
| |
| public void testParameterOptionalWithDefault() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/parameterTypes.js")); |
| final int caretOffset = getCaretOffset(source, "function ^line4(accessLevel){}"); |
| checkJsDocBlock(source, caretOffset, "@param||type=String:name=accessLevel:desc=accessLevel is optional"); |
| } |
| |
| public void test217949() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/modelTestFile.js")); |
| final int caretOffset = getCaretOffset(source, "function test(p1, p2) ^{"); |
| checkJsDocBlock(source, caretOffset, "@param||type=NULL:name=p1:desc=textA;@param||type=Cislo:name=p2:desc=text2"); |
| } |
| |
| public void test233176() throws Exception { |
| Source source = getTestSource(getTestFile("testfiles/jsdoc/issue233176.js")); |
| final int caretOffset = getCaretOffset(source, "^this.buildingId;"); |
| checkJsDocBlock(source, caretOffset, "@type||type=Number"); |
| } |
| |
| /** |
| * Examples of expected values: |
| * @borrows <param1> as <param2> |
| * @type <type> |
| * @author <desc> |
| * @memberOf <namepath> |
| * @param <type> <name> <desc> |
| * @private |
| * @throws <type> <desc> |
| */ |
| private static void assertElementEquality(FakeJsDocElement expected, JsDocElement parsed) { |
| switch (parsed.getType().getCategory()) { |
| case ASSIGN: |
| assertTrue(parsed instanceof AssignElement); |
| AssignElement assignElement = (AssignElement) parsed; |
| assertEquals(expected.getProperty("param1"), assignElement.getOtherMemberName().toString()); |
| assertEquals(expected.getProperty("param2"), assignElement.getThisMemberName().toString()); |
| break; |
| case DECLARATION: |
| assertTrue(parsed instanceof DeclarationElement); |
| DeclarationElement declarationElement = (DeclarationElement) parsed; |
| assertEquals(expected.getProperty("type"), declarationElement.getDeclaredType().getType()); |
| break; |
| case DESCRIPTION: |
| assertTrue(parsed instanceof DescriptionElement); |
| DescriptionElement descElement = (DescriptionElement) parsed; |
| assertEquals(expected.getProperty("desc"), descElement.getDescription()); |
| break; |
| case LINK: |
| assertTrue(parsed instanceof LinkElement); |
| LinkElement linkElement = (LinkElement) parsed; |
| assertEquals(expected.getProperty("namepath"), linkElement.getLinkedPath().toString()); |
| break; |
| case NAMED_PARAMETER: |
| assertTrue(parsed instanceof NamedParameterElement); |
| NamedParameterElement namedParameterElement = (NamedParameterElement) parsed; |
| assertEquals(expected.getProperty("name"), namedParameterElement.getParamName().getName()); |
| assertEquals(expected.getProperty("desc"), namedParameterElement.getParamDescription().toString()); |
| assertTypesEquality(expected, namedParameterElement); |
| break; |
| case SIMPLE: |
| assertTrue(parsed instanceof SimpleElement); |
| break; |
| case UNNAMED_PARAMETER: |
| assertTrue(parsed instanceof UnnamedParameterElement); |
| UnnamedParameterElement unnamedParameterElement = (UnnamedParameterElement) parsed; |
| assertEquals(expected.getProperty("desc"), unnamedParameterElement.getParamDescription().toString()); |
| assertTypesEquality(expected, unnamedParameterElement); |
| break; |
| default: |
| throw new AssertionError(); |
| } |
| } |
| |
| private static void assertTypesEquality(FakeJsDocElement expected, ParameterElement element) { |
| if (expected.getProperty("type").indexOf("|") != -1) { |
| String[] splitedType = expected.getProperty("type").split("[|]"); |
| for (int i = 0; i < splitedType.length; i++) { |
| assertEquals(splitedType[i], element.getParamTypes().get(i).getType()); |
| } |
| } else { |
| if ("NULL".equals(expected.getProperty("type"))) { |
| assertTrue(element.getParamTypes().isEmpty()); |
| } else { |
| assertEquals(expected.getProperty("type"), element.getParamTypes().get(0).getType()); |
| } |
| } |
| } |
| |
| private static void assertElementsEquality(List<JsDocElement> expectedTags, List<? extends JsDocElement> elements) { |
| Collections.sort(expectedTags, elementComparator); |
| Collections.sort(elements, elementComparator); |
| |
| assertEquals(expectedTags.size(), elements.size()); |
| |
| for (int i = 0; i < expectedTags.size(); i++) { |
| JsDocElement expected = expectedTags.get(i); |
| JsDocElement parsed = elements.get(i); |
| assertElementEquality((FakeJsDocElement) expected, parsed); |
| } |
| } |
| |
| private static class JsDocElementComparator implements Comparator<JsDocElement> { |
| |
| @Override |
| public int compare(JsDocElement o1, JsDocElement o2) { |
| return o1.getType().toString().compareTo(o2.getType().toString()); |
| } |
| |
| } |
| |
| private static class FakeJsDocElement implements JsDocElement { |
| |
| private final JsDocElementType type; |
| private Map<String, String> properties = new HashMap<String, String>(); |
| |
| public FakeJsDocElement(JsDocElementType type) { |
| assertNotNull(type); |
| this.type = type; |
| } |
| |
| @Override |
| public JsDocElementType getType() { |
| return type; |
| } |
| |
| public void addProperty(String key, String value) { |
| assertNotNull(key); |
| assertNotNull(value); |
| properties.put(key, value); |
| } |
| |
| public String getProperty(String key) { |
| String property = properties.get(key); |
| return property == null ? "" : property; |
| } |
| } |
| } |