package org.eclipse.emf.test.tools.merger; import java.util.Hashtable; import junit.framework.TestCase; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.EnumConstantDeclaration; import org.eclipse.jdt.core.dom.EnumDeclaration; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.dom.rewrite.ListRewrite; import org.eclipse.jface.text.Document; import org.eclipse.text.edits.TextEdit; /** * Test that shows the difference in assigning line comments in enum and * class declarations. */ public class ASTEnumProblem extends TestCase { protected String enumSource = "enum E\n" + "{" + "\tENUM_CONST_1(\"String const 1\") //$NON-NLS-1$\n" + "\t, ENUM_CONST_2(\"String const 2\") //$NON-NLS-2$\n" + "\t;\n" + "\tString a; //$NON-NLS-1$\n" + "\tString b; //$NON-NLS-2$\n" + "}\n"; protected String classSource = "class X\n" + "{" + "\tString a; //$NON-NLS-1$\n" + "\tString b; //$NON-NLS-2$\n" + "}\n"; protected String expectedEnumSourceAfterAddingField = "enum E\n" + "{" + "\tENUM_CONST_1(\"String const 1\") //$NON-NLS-1$\n" + "\t, ENUM_CONST_2(\"String const 2\") //$NON-NLS-2$\n" + "\t;\n" + "\tString a; //$NON-NLS-1$\n" + "\tString b; //$NON-NLS-2$\n" + "\tint MISSING;\n" + "}\n"; protected String expectedEnumSourceAfterAddingEnumConst = "enum E\n" + "{" + "\tENUM_CONST_1(\"String const 1\") //$NON-NLS-1$\n" + "\t, MISSING, ENUM_CONST_2(\"String const 2\") //$NON-NLS-2$\n" + "\t, MISSING;\n" + "\tString a; //$NON-NLS-1$\n" + "\tString b; //$NON-NLS-2$\n" + "}\n"; protected String expectedClassSource = "class X\n" + "{" + "\tString a; //$NON-NLS-1$\n" + "\tString b; //$NON-NLS-2$\n" + "\tint MISSING;\n" + "}\n"; protected CompilationUnit enumCompilationUnit; protected CompilationUnit classCompilationUnit; @Override protected void setUp() throws Exception { adjustCompilerOptions(); enumCompilationUnit = parse(enumSource); classCompilationUnit = parse(classSource); } public void testReadEnumFieldDeclarations() { testReadFields(enumCompilationUnit, enumSource); } public void testReadClassFieldDeclarations() { testReadFields(classCompilationUnit, classSource); } public void testEnumConstants() { testReadEnumConsts(enumCompilationUnit, enumSource); } public void testAddEnumConst() throws Exception { assertEquals(expectedEnumSourceAfterAddingEnumConst, testAddConst(enumCompilationUnit, enumSource)); } public void testAddEnumField() throws Exception { assertEquals(expectedEnumSourceAfterAddingField, testAddField(enumCompilationUnit, enumSource)); } public void testAddClassField() throws Exception { assertEquals(expectedClassSource, testAddField(classCompilationUnit, classSource)); } protected void testReadFields(CompilationUnit cu, String source) { AbstractTypeDeclaration td = (AbstractTypeDeclaration) cu.types().get(0); FieldDeclaration field1 = (FieldDeclaration) td.bodyDeclarations().get(0); FieldDeclaration field2 = (FieldDeclaration) td.bodyDeclarations().get(1); String field1Source = source.substring(cu.getExtendedStartPosition(field1), cu.getExtendedStartPosition(field1) + cu.getExtendedLength(field1)); String field2Source = source.substring(cu.getExtendedStartPosition(field2), cu.getExtendedStartPosition(field2) + cu.getExtendedLength(field2)); assertEquals("String a; //$NON-NLS-1$", field1Source); // this fails for enum since line comment is not a part of the last field assertEquals("String b; //$NON-NLS-2$", field2Source); } protected void testReadEnumConsts(CompilationUnit cu, String source) { EnumDeclaration ed = (EnumDeclaration) cu.types().get(0); EnumConstantDeclaration constantDeclaration1 = (EnumConstantDeclaration)ed.enumConstants().get(0); EnumConstantDeclaration constantDeclaration2 = (EnumConstantDeclaration)ed.enumConstants().get(1); String const1Source = source.substring(cu.getExtendedStartPosition(constantDeclaration1), cu.getExtendedStartPosition(constantDeclaration1) + cu.getExtendedLength(constantDeclaration1)); String const2Source = source.substring(cu.getExtendedStartPosition(constantDeclaration2), cu.getExtendedStartPosition(constantDeclaration2) + cu.getExtendedLength(constantDeclaration2)); assertEquals("ENUM_CONST_1(\"String const 1\") //$NON-NLS-1$", const1Source); assertEquals("ENUM_CONST_2(\"String const 2\") //$NON-NLS-2$", const2Source); } protected String testAddField(CompilationUnit cu, String source) throws Exception { ASTRewrite rewriter = ASTRewrite.create(cu.getAST()); AbstractTypeDeclaration td = (AbstractTypeDeclaration) cu.types().get(0); ListRewrite lrw = rewriter.getListRewrite(td, td.getBodyDeclarationsProperty()); VariableDeclarationFragment newFragment = cu.getAST().newVariableDeclarationFragment(); FieldDeclaration newField = cu.getAST().newFieldDeclaration(newFragment); // for enum, new field is inserted before the line comment of the last field lrw.insertLast(newField, null); Document doc = new Document(source); TextEdit edit = rewriter.rewriteAST(doc, null); edit.apply(doc); return doc.get(); } protected String testAddConst(CompilationUnit cu, String source) throws Exception { ASTRewrite rewriter = ASTRewrite.create(cu.getAST()); EnumDeclaration ed = (EnumDeclaration) cu.types().get(0); ListRewrite lrw = rewriter.getListRewrite(ed, EnumDeclaration.ENUM_CONSTANTS_PROPERTY); EnumConstantDeclaration newEnumConstantDeclaration = cu.getAST().newEnumConstantDeclaration(); lrw.insertAt(newEnumConstantDeclaration, 1, null); newEnumConstantDeclaration = cu.getAST().newEnumConstantDeclaration(); lrw.insertLast(newEnumConstantDeclaration, null); Document doc = new Document(source); TextEdit edit = rewriter.rewriteAST(doc, null); edit.apply(doc); return doc.get(); } protected CompilationUnit parse(String source) { ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setSource(source.toCharArray()); return (CompilationUnit) parser.createAST(null); } protected void adjustCompilerOptions() { Hashtable options = JavaCore.getOptions(); options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5); JavaCore.setOptions(options); } }