/* * Copyright 2011 Google Inc. All Rights Reserved. * * Licensed 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 com.google.devtools.j2objc.gen; import com.google.devtools.j2objc.GenerationTest; import java.io.IOException; /** * Verifies Javadoc comments are generated in a format compatible * with Xcode Quick Help, HeaderDoc and Doxygen. * * @author Tom Ball */ public class JavadocGeneratorTest extends GenerationTest { @Override protected void setUp() throws IOException { super.setUp(); options.setDocCommentsEnabled(true); } public void testBasicDocComments() throws IOException { String translation = translateSourceFile( "/** Class javadoc for Test. */ class Test { \n" + "/** Field javadoc. */\n" + "int i;" + "/** Method javadoc.\n" + " * @param foo Unused.\n" + " * @return always false.\n" + " */\n" + "boolean test(int foo) { return false; } }", "Test", "Test.h"); assertTranslation(translation, "@brief Class javadoc for Test."); assertTranslation(translation, "@brief Field javadoc."); assertTranslatedLines(translation, "@brief Method javadoc.", "@param foo Unused.", "@return always false."); } public void testLinkTag() throws IOException { String translation = translateSourceFile( "/** Class javadoc for {@link Test}. */ class Test {" + " /** See {@link #bar}. */ void foo() {}" + " /** See {@linkplain #bar}. */ void foo2() {}" + " /** See {@link Test#bar()}. */ void foo3() {}" + " /** See {@link foo.bar.Mumble Mumble}.*/ void foo4() {}}", "Test", "Test.h"); assertTranslation(translation, "@brief Class javadoc for <code>Test</code>."); assertTranslation(translation, "@brief See <code>bar</code>."); assertTranslation(translation, "@brief See bar."); assertTranslation(translation, "@brief See <code>Test.bar()</code>."); assertTranslation(translation, "@brief See <code>Mumble</code>."); } public void testLiteralTag() throws IOException { String translation = translateSourceFile( "/** Class javadoc for {@literal <Test>}. */ class Test {}", "Test", "Test.h"); assertTranslation(translation, "@brief Class javadoc for <Test>."); } // Javadoc supports @param tags on classes, to document type parameters. Since there's // no equivalent in Objective C, these tags need to be removed. public void testTypeParamTagRemoval() throws IOException { String translation = translateSourceFile( "/** Class javadoc for Test.\n" + " * @param <T> the test name\n" + " */ class Test <T> {\n" + " /** Method javadoc.\n" + " * @param <T> the type to be returned.\n" + " */ T test() { return null; }}", "Test", "Test.h"); assertTranslation(translation, "@brief Class javadoc for Test."); assertTranslation(translation, "@brief Method javadoc."); assertNotInTranslation(translation, "@param"); assertNotInTranslation(translation, "<T>"); } public void testPreTags() throws IOException { String translation = translateSourceFile( // Include two <pre> tags to make sure the second isn't skipped. "/** Comment fragment from JSONObject.java.\n" + " * Encodes this object as a compact JSON string, such as:\n" + " * <pre>{\"query\":\"Pizza\",\"locations\":[94043,90210]}</pre>\n" + " * or maybe <pre>{\"query\":\"Fuel\",\"locations\":[96011]}</pre>\n" + " */ class Test {}", "Test", "Test.h"); assertTranslatedSegments(translation, "@brief Comment fragment from JSONObject.java.", "Encodes this object as a compact JSON string, such as:", "@code", "{\"query\":\"Pizza\",\"locations\":[94043,90210]}", "@endcode", "or maybe", "@code", "{\"query\":\"Fuel\",\"locations\":[96011]}", "@endcode", "*/"); } // Verify that code tags inside of a pre tag are erased. public void testPreAndCodeTags() throws IOException { String translation = translateSourceFile( "/** Comment fragment from DelayQueue.java.\n" + " * The following code can be used to dump a delay queue into a newly\n" + " * allocated array of {@code Delayed}:\n" + "* <pre> {@code Delayed[] a = q.toArray(new Delayed[0]);}</pre>\n" + "* Note that {@code toArray(new Object[0])} is identical in function to\n" + "* {@code toArray()}.\n" + "*/ class Test {}", "Test", "Test.h"); assertTranslatedLines(translation, "@brief Comment fragment from DelayQueue.java.", "The following code can be used to dump a delay queue into a newly", "allocated array of <code>Delayed</code>:", "@code", "Delayed[] a = q.toArray(new Delayed[0]);", "@endcode", "Note that <code>toArray(new Object[0])</code> is identical in function to", "<code>toArray()</code>.", "*/"); } // Verify that the @param name text is updated if NameTable renames a parameter. public void testReservedParamName() throws IOException { String translation = translateSourceFile( "class Test { \n" + "/** Method javadoc.\n" + " * @param out Unused.\n" + " * @param description Unused." + " */\n" + "void test(int out, String description) {}}", "Test", "Test.h"); assertTranslation(translation, "@param outArg Unused."); assertTranslation(translation, "@param description_ Unused."); } // Verify that tags without following text are skipped, such as "@param\n". public void testSkipEmptyTags() throws IOException { String translation = translateSourceFile( "/** Class javadoc for Test.\n" + " * @see\n" + " * @since\n" + " */ class Test { \n" + "/** Method javadoc.\n" + " * @param \n" + " * @return\n" + " * @throws\n" + " */\n" + "boolean test(int foo) { return false; } }", "Test", "Test.h"); assertTranslation(translation, "@brief Class javadoc for Test."); assertNotInTranslation(translation, "@see"); assertNotInTranslation(translation, "@since"); assertNotInTranslation(translation, "@param"); assertNotInTranslation(translation, "@return"); assertNotInTranslation(translation, "@throws"); } public void testBadPreTag() throws IOException { String translation = translateSourceFile( "/** Example:\n" + " * </pre>\n" // Closing tag before opening one below. + " * class Foo {\n" + " * Foo bar;\n" + " * }<pre>\n" + " */\n" + "class Test {}", "Test", "Test.h"); assertTranslation(translation, "@code"); } // Verify that the formatting inside <pre>...</pre> and @{code ...} isn't reformatted. public void testPreserveLiteralFormatting() throws IOException { String translation = translateSourceFile( "/** Example:\n" + " * <pre>\n" + " * class Foo {\n" + " * @Property(\"copy, nonatomic\")\n" + " * protected String bar;\n" + " * }</pre>\n" + " *\n" // Make sure "short" lines are handled correctly. + " */\n" + "class Test {}", "Test", "Test.h"); assertTranslation(translation, " @Property(\"copy, nonatomic\")\n"); assertTranslation(translation, " protected String bar;\n"); // Same test, but without leading '*' in comment lines. translation = translateSourceFile( "/** Example:\n" + "<pre>\n" + "class Foo {\n" + " @Property(\"copy, nonatomic\")\n" + " protected String bar;\n" + "}</pre>\n" + " */\n" + "class Test {}", "Test", "Test.h"); assertTranslation(translation, " @Property(\"copy, nonatomic\")\n"); assertTranslation(translation, " protected String bar;\n"); } // Verify style tags are skipped, since Quick Help displays them. public void testStyleTagsSkipped() throws IOException { String translation = translateSourceFile( "/** <h3>Regular expression syntax</h3>\n" + " * <span class=\"datatable\">\n" + " * <style type=\"text/css\">\n" + " * .datatable td { padding-right: 20px; }\n" + " * </style>\n" + " */\n" + "class Test {}", "Test", "Test.h"); assertNotInTranslation(translation, "<style"); assertTranslatedLines(translation, "/*!", "@brief <h3>Regular expression syntax</h3>", "<span class=\"datatable\">", "*/"); } public void testSeeTag() throws IOException { String translation = translateSourceFile( "/** Class javadoc for Test.\n" + " * @see <a href=\"http://developers.facebook.com/docs/reference/javascript/FB.init/\">" + "FB.init</a>\n" + " */ class Test {}", "Test", "Test.h"); assertTranslation(translation, "@brief Class javadoc for Test."); assertTranslation(translation, "- seealso: " + "<a href=\"http://developers.facebook.com/docs/reference/javascript/FB.init/\">"); } // Verify that unknown tags are not printed. public void testUnknownTag() throws IOException { String translation = translateSourceFile( "/** Class javadoc for Test.\n" + " * @jls 11.2 Some JLS reference.\n" + " */ class Test {}", "Test", "Test.h"); assertTranslation(translation, "@brief Class javadoc for Test."); assertNotInTranslation(translation, "11.2 Some JLS reference."); } }