package uk.co.badgersinfoil.metaas; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.Iterator; import uk.co.badgersinfoil.metaas.dom.ASArg; import uk.co.badgersinfoil.metaas.dom.ASClassType; import uk.co.badgersinfoil.metaas.dom.ASCompilationUnit; import uk.co.badgersinfoil.metaas.dom.ASType; import uk.co.badgersinfoil.metaas.dom.DocComment; import uk.co.badgersinfoil.metaas.dom.ASMethod; import uk.co.badgersinfoil.metaas.dom.DocTag; import uk.co.badgersinfoil.metaas.dom.Visibility; import junit.framework.TestCase; public class DocCommentTests extends TestCase { private ActionScriptFactory fact = new ActionScriptFactory(); private ASCompilationUnit unit; private ASClassType clazz; protected void setUp() { ActionScriptFactory fact = new ActionScriptFactory(); unit = fact.newClass("Test"); clazz = (ASClassType)unit.getType(); } protected void tearDown() throws IOException { CodeMirror.assertReflection(fact, unit); } public void testEndOfCommentMarker() { try { clazz.getDocumentation().setDescriptionString("*/"); fail("should not allow '*/' within a doc-comment"); } catch (SyntaxException e) { // expected } } public void testParaEndOfCommentMarker() { try { clazz.getDocumentation().addParaTag("foo", "*/"); fail("should not allow '*/' within a doc-comment"); } catch (SyntaxException e) { // expected } } public void testSetNewDescription() { clazz.setDescription("hello"); assertEquals("hello", clazz.getDescriptionString().trim()); } public void testSetBadDescription() { try { clazz.setDescription("hello\n@param foo great"); fail("should have rejected description with trailing tagged-paragraph"); } catch (SyntaxException e) { // expected } } public void testGetDescriptionNoDocs() { assertNull(clazz.getDescriptionString()); } public void testRemoveDescription() { clazz.setDescription(null); assertEquals(null, clazz.getDescriptionString()); } public void testGetExistingDescription() { clazz.getDocumentation().setDescriptionString("hello world"); clazz.getDocumentation().addParaTag("param", "foo bar"); assertEquals("hello world", clazz.getDescriptionString().trim()); } public void testNewArgNoDocs() { ASMethod meth = clazz.newMethod("test", Visibility.PUBLIC, "void"); ASArg test = meth.addParam("test", "String"); assertNull(test.getDescriptionString()); test.setDescription("a test!"); assertEquals("a test!", test.getDescriptionString().trim()); // insert a description before the @param meth.setDescription("foo\nbar"); assertEquals("foo\nbar", meth.getDescriptionString().trim()); String actualDesc = test.getDescriptionString(); assertNotNull(actualDesc); assertEquals("a test!", actualDesc.trim()); } public void testUpdateArgDocs() { ASMethod meth = clazz.newMethod("test", Visibility.PUBLIC, "void"); ASArg test = meth.addParam("test", "String"); assertNull(test.getDescriptionString()); test.setDescription("initial text!"); assertEquals("initial text!", test.getDescriptionString().trim()); test.setDescription("replacement text"); assertEquals("replacement text", test.getDescriptionString().trim()); } public void testParaTagUpdateNewline() throws IOException { DocComment doc = clazz.getDocumentation(); doc.addParaTag("test", "initial text"); DocTag tag = doc.findFirstTag("test"); tag.setBody("replacement\ncontent"); ActionScriptWriter writer = fact.newWriter(); StringWriter buff = new StringWriter(); writer.write(buff, unit); String[] lines = buff.toString().split("\n"); // check indentation, skipping first and last lines, for (int i=1; i<lines.length-1; i++) { assertIndent("\t", lines[i]); } } private static void assertIndent(String indent, String line) { if (line.length() == 0) { // blank lines allowed return; } assertTrue("expected indentation "+ActionScriptFactory.str(indent)+" but line started with "+ActionScriptFactory.str(line.substring(0, indent.length())), line.startsWith(indent)); } public void testReturnDocs() { ASMethod meth = clazz.newMethod("test", Visibility.PUBLIC, "void"); assertNull(meth.getReturnDescriptionString()); meth.setReturnDescription(null); // should not fail meth.setReturnDescription("blah blah"); assertEquals("blah blah", meth.getReturnDescriptionString().trim()); } public void testRemoveReturnDocs() { ASMethod meth = clazz.newMethod("test", Visibility.PUBLIC, "void"); meth.setReturnDescription("blah blah"); meth.setReturnDescription(null); assertNull(meth.getReturnDescriptionString()); } public void testDocumentation() { DocComment doc = clazz.getDocumentation(); assertNotNull(doc); assertNull(doc.getDescriptionString()); } public void testFindTags() { DocComment doc = clazz.getDocumentation(); doc.addParaTag("param", "arg0 blah"); doc.addParaTag("param", "arg1 blah blah"); doc.addParaTag("param", "arg2 blah blah blah"); Iterator i = doc.findTags("param"); assertTrue(i.hasNext()); assertTrue(((DocTag)i.next()).getBodyString().trim().startsWith("arg0")); assertTrue(i.hasNext()); assertTrue(((DocTag)i.next()).getBodyString().trim().startsWith("arg1")); assertTrue(i.hasNext()); assertTrue(((DocTag)i.next()).getBodyString().trim().startsWith("arg2")); } public void testDocTagName() { DocComment doc = clazz.getDocumentation(); doc.addParaTag("param", "arg0 blah"); DocTag tag = doc.findFirstTag("param"); assertEquals("param", tag.getName()); tag.setName("see"); assertEquals("see", tag.getName()); // TODO: assert that the comment is removed? } public void testDelete() { DocComment doc = clazz.getDocumentation(); doc.setDescriptionString("boo\nfoo"); doc.addParaTag("param", "arg0 blah"); doc.addParaTag("param", "arg1 blah blah"); doc.addParaTag("param", "arg2 blah blah blah"); DocTag arg1 = null; for (Iterator i=doc.findTags("param"); i.hasNext(); ) { DocTag tag = (DocTag)i.next(); if (tag.getBodyString().trim().startsWith("arg1")) { arg1 = tag; break; } } assertNotNull(arg1); doc.delete(arg1); // check it's gone, Iterator i = doc.findTags("param"); assertTrue(i.hasNext()); assertTrue(((DocTag)i.next()).getBodyString().trim().startsWith("arg0")); assertTrue(i.hasNext()); assertTrue(((DocTag)i.next()).getBodyString().trim().startsWith("arg2")); // doc.delete(doc.findFirstTag("param")); // doc.delete(doc.findFirstTag("param")); // i = doc.findTags(); // assertFalse(i.hasNext()); } public void testAddToParsedContent() throws IOException { ActionScriptParser p = fact.newParser(); StringReader in = new StringReader( "package {\n" + " public class Test {\n" + " public function foo() {\n" + " }\n" + " }\n" + "}\n" ); unit = p.parse(in); ASType type = unit.getType(); ASMethod foo = type.getMethod("foo"); foo.setDescription("woo!"); ActionScriptWriter writer = fact.newWriter(); StringWriter out = new StringWriter(); writer.write(out, unit); String result = out.toString(); // find the end of what would be the only comment block, int pos = result.indexOf("*/"); char firstCharAfterComment = result.charAt(pos+2); assertTrue("expected a newline to appear after newly inserted comment: 0x"+Integer.toHexString(firstCharAfterComment), firstCharAfterComment=='\n' || firstCharAfterComment=='\r'); } }