From 2cdc69c5f37b8df754ffadef03fb964ebafb6cc4 Mon Sep 17 00:00:00 2001 From: danglotb Date: Mon, 12 Jun 2017 14:07:29 +0200 Subject: [PATCH] fix checkstyle --- .../visitor/DefaultJavaPrettyPrinter.java | 3464 ++++++++--------- .../java/spoon/test/literal/LiteralTest.java | 259 +- 2 files changed, 1862 insertions(+), 1861 deletions(-) diff --git a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java index 6de53e3bb95..2abcde4667f 100644 --- a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java +++ b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java @@ -1,16 +1,16 @@ /** * Copyright (C) 2006-2017 INRIA and contributors * Spoon - http://spoon.gforge.inria.fr/ - * + *

* This software is governed by the CeCILL-C License under French law and * abiding by the rules of distribution of free software. You can use, modify * and/or redistribute the software under the terms of the CeCILL-C license as * circulated by CEA, CNRS and INRIA at http://www.cecill.info. - * + *

* This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. - * + *

* The fact that you are presently reading this means that you have had * knowledge of the CeCILL-C license and that you accept its terms. */ @@ -125,1737 +125,1737 @@ */ public class DefaultJavaPrettyPrinter implements CtVisitor, PrettyPrinter { - /** - * Java file extension (.java). - */ - public static final String JAVA_FILE_EXTENSION = ".java"; - - /** - * Package declaration file name. - */ - public static final String JAVA_PACKAGE_DECLARATION = "package-info" + JAVA_FILE_EXTENSION; - - /** - * Line separator which is used by the system - */ - public static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - /** - * The star at the beginning of a block/JavaDoc comment line - */ - public static final String COMMENT_STAR = " * "; - - /** - * The end of a block/JavaDoc comment - */ - public static final String BLOCK_COMMENT_END = " */"; - - /** - * The beginning of a JavaDoc comment - */ - public static final String JAVADOC_START = "/**"; - - /** - * The beginning of a inline comment - */ - public static final String INLINE_COMMENT_START = "// "; - - /** - * The beginning of a block comment - */ - public static final String BLOCK_COMMENT_START = "/* "; - - /** - * The printing context. - */ - public PrintingContext context = new PrintingContext(); - - /** - * Handle imports of classes. - */ - private ImportScanner importsContext; - - /** - * Environment which Spoon is executed. - */ - private Environment env; - - /** - * Printer helper. - */ - private PrinterHelper printer; - - /** - * Element printer helper. - */ - private ElementPrinterHelper elementPrinterHelper; - - /** - * Compilation unit we are printing. - */ - private CompilationUnit sourceCompilationUnit; - - /** - * Creates a new code generator visitor. - */ - public DefaultJavaPrettyPrinter(Environment env) { - this.env = env; - printer = new PrinterHelper(env); - elementPrinterHelper = new ElementPrinterHelper(printer, this, env); - if (env.isAutoImports()) { - this.importsContext = new ImportScannerImpl(); - } else { - this.importsContext = new MinimalImportScanner(); - } - } - - /** - * Enters an expression. - */ - protected void enterCtExpression(CtExpression e) { - if (!(e instanceof CtStatement)) { - elementPrinterHelper.writeComment(e, CommentOffset.BEFORE); - } - printer.mapLine(e, sourceCompilationUnit); - if (shouldSetBracket(e)) { - context.parenthesedExpression.push(e); - printer.write("("); - } - if (!e.getTypeCasts().isEmpty()) { - for (CtTypeReference r : e.getTypeCasts()) { - printer.write("("); - DefaultJavaPrettyPrinter.this.scan(r); - printer.write(") "); - printer.write("("); - context.parenthesedExpression.push(e); - } - } - } - - /** - * Enters a statement. - */ - protected void enterCtStatement(CtStatement s) { - elementPrinterHelper.writeComment(s, CommentOffset.BEFORE); - printer.mapLine(s, sourceCompilationUnit); - elementPrinterHelper.writeAnnotations(s); - if (s.getLabel() != null) { - printer.write(s.getLabel()).write(" : "); - } - } - - /** - * Exits an expression. - */ - protected void exitCtExpression(CtExpression e) { - while ((context.parenthesedExpression.size() > 0) && e == context.parenthesedExpression.peek()) { - context.parenthesedExpression.pop(); - printer.write(")"); - } - if (!(e instanceof CtStatement)) { - elementPrinterHelper.writeComment(e, CommentOffset.AFTER); - } - } - - /** - * Make the imports for a given type. - */ - public Collection computeImports(CtType type) { - context.currentTopLevel = type; - importsContext.computeImports(context.currentTopLevel); - return importsContext.getAllImports(); - } - - /** - * Make the imports for all elements. - */ - public void computeImports(CtElement element) { - if (env.isAutoImports()) { - importsContext.computeImports(element); - } - } - - /** - * The generic scan method for an element. - */ - public DefaultJavaPrettyPrinter scan(CtElement e) { - if (e != null) { - context.elementStack.push(e); - if (env.isPreserveLineNumbers()) { - if (!(e instanceof CtNamedElement)) { - printer.adjustStartPosition(e); - } - } - e.accept(this); - context.elementStack.pop(); - } - return this; - } - - /** - * The generic scan method for a reference. - */ - public DefaultJavaPrettyPrinter scan(CtReference ref) { - if (ref != null) { - ref.accept(this); - } - return this; - } - - private boolean shouldSetBracket(CtExpression e) { - if (e.getTypeCasts().size() != 0) { - return true; - } - try { - if ((e.getParent() instanceof CtBinaryOperator) || (e.getParent() instanceof CtUnaryOperator)) { - return (e instanceof CtTargetedExpression) || (e instanceof CtAssignment) || (e instanceof CtConditional) || (e instanceof CtUnaryOperator) || e instanceof CtBinaryOperator; - } - if (e.getParent() instanceof CtTargetedExpression) { - return (e instanceof CtBinaryOperator) || (e instanceof CtAssignment) || (e instanceof CtConditional) || (e instanceof CtUnaryOperator); - } - } catch (ParentNotInitializedException ex) { - // nothing we accept not to have a parent - } - return false; - } - - /** - * Gets the currently pretty-printed string. - */ - @Override - public String toString() { - return printer.toString(); - } - - @Override - public void visitCtAnnotation(CtAnnotation annotation) { - elementPrinterHelper.writeAnnotations(annotation); - printer.write("@"); - scan(annotation.getAnnotationType()); - if (annotation.getValues().size() > 0) { - printer.write("("); - for (Entry e : annotation.getValues().entrySet()) { - printer.write(e.getKey() + " = "); - elementPrinterHelper.writeAnnotationElement(annotation.getFactory(), e.getValue()); - printer.write(", "); - } - printer.removeLastChar(); - printer.write(")"); - } - printer.writeln().writeTabs(); - } - - @Override - public void visitCtAnnotationType(CtAnnotationType annotationType) { - visitCtType(annotationType); - printer.write("@interface " + annotationType.getSimpleName() + " {").incTab(); - - elementPrinterHelper.writeElementList(annotationType.getTypeMembers()); - printer.decTab().writeTabs().write("}"); - } - - @Override - public void visitCtAnonymousExecutable(CtAnonymousExecutable impl) { - elementPrinterHelper.writeComment(impl); - elementPrinterHelper.writeAnnotations(impl); - elementPrinterHelper.writeModifiers(impl); - scan(impl.getBody()); - } - - @Override - public void visitCtArrayRead(CtArrayRead arrayRead) { - printCtArrayAccess(arrayRead); - } - - @Override - public void visitCtArrayWrite(CtArrayWrite arrayWrite) { - printCtArrayAccess(arrayWrite); - } - - private > void printCtArrayAccess(CtArrayAccess arrayAccess) { - enterCtExpression(arrayAccess); - scan(arrayAccess.getTarget()); - printer.write("["); - scan(arrayAccess.getIndexExpression()); - printer.write("]"); - exitCtExpression(arrayAccess); - } - - @Override - public void visitCtArrayTypeReference(CtArrayTypeReference reference) { - if (reference.isImplicit()) { - return; - } - scan(reference.getComponentType()); - if (!context.skipArray()) { - printer.write("[]"); - } - } - - @Override - public void visitCtAssert(CtAssert asserted) { - enterCtStatement(asserted); - printer.write("assert "); - scan(asserted.getAssertExpression()); - if (asserted.getExpression() != null) { - printer.write(" : "); - scan(asserted.getExpression()); - } - - } - - @Override - public void visitCtAssignment(CtAssignment assignement) { - enterCtStatement(assignement); - enterCtExpression(assignement); - scan(assignement.getAssigned()); - printer.write(" = "); - scan(assignement.getAssignment()); - exitCtExpression(assignement); - } - - @Override - public void visitCtBinaryOperator(CtBinaryOperator operator) { - enterCtExpression(operator); - scan(operator.getLeftHandOperand()); - printer.write(" ").writeOperator(operator.getKind()).write(" "); - scan(operator.getRightHandOperand()); - exitCtExpression(operator); - } - - @Override - public void visitCtBlock(CtBlock block) { - enterCtStatement(block); - if (!block.isImplicit()) { - printer.write("{"); - } - printer.incTab(); - for (CtStatement statement : block.getStatements()) { - if (!statement.isImplicit()) { - printer.writeln().writeTabs(); - elementPrinterHelper.writeStatement(statement); - } - } - printer.decTab(); - printer.adjustEndPosition(block); - if (env.isPreserveLineNumbers()) { - if (!block.isImplicit()) { - printer.writeTabs().write("}"); - } - } else { - printer.writeln().writeTabs(); - if (!block.isImplicit()) { - printer.write("}"); - } - } - } - - @Override - public void visitCtBreak(CtBreak breakStatement) { - enterCtStatement(breakStatement); - printer.write("break"); - if (breakStatement.getTargetLabel() != null) { - printer.write(" " + breakStatement.getTargetLabel()); - } - } - - @Override - @SuppressWarnings("rawtypes") - public void visitCtCase(CtCase caseStatement) { - enterCtStatement(caseStatement); - if (caseStatement.getCaseExpression() != null) { - printer.write("case "); - // writing enum case expression - if (caseStatement.getCaseExpression() instanceof CtFieldAccess) { - final CtFieldReference variable = ((CtFieldAccess) caseStatement.getCaseExpression()).getVariable(); - // In noclasspath mode, we don't have always the type of the declaring type. - if (variable.getType() != null - && variable.getDeclaringType() != null - && variable.getType().getQualifiedName().equals(variable.getDeclaringType().getQualifiedName())) { - printer.write(variable.getSimpleName()); - } else { - scan(caseStatement.getCaseExpression()); - } - } else { - scan(caseStatement.getCaseExpression()); - } - } else { - printer.write("default"); - } - printer.write(" :").incTab(); - - for (CtStatement statement : caseStatement.getStatements()) { - printer.writeln().writeTabs(); - elementPrinterHelper.writeStatement(statement); - } - printer.decTab(); - } - - @Override - public void visitCtCatch(CtCatch catchBlock) { - elementPrinterHelper.writeComment(catchBlock, CommentOffset.BEFORE); - printer.write(" catch ("); - CtCatchVariable parameter = catchBlock.getParameter(); - if (parameter.getMultiTypes().size() > 0) { - for (int i = 0; i < parameter.getMultiTypes().size(); i++) { - CtTypeReference type = parameter.getMultiTypes().get(i); - scan(type); - if (i < parameter.getMultiTypes().size() - 1) { - printer.write(" | "); - } - } - printer.write(" " + parameter.getSimpleName()); - } else { - scan(parameter); - } - printer.write(") "); - scan(catchBlock.getBody()); - } - - @Override - public void visitCtClass(CtClass ctClass) { - context.pushCurrentThis(ctClass); - if (ctClass.getSimpleName() != null && !CtType.NAME_UNKNOWN.equals(ctClass.getSimpleName()) && !ctClass.isAnonymous()) { - visitCtType(ctClass); - if (ctClass.isLocalType()) { - printer.write("class " + ctClass.getSimpleName().replaceAll("^[0-9]*", "")); - } else { - printer.write("class " + ctClass.getSimpleName()); - } - - elementPrinterHelper.writeFormalTypeParameters(ctClass); - elementPrinterHelper.writeExtendsClause(ctClass); - elementPrinterHelper.writeImplementsClause(ctClass); - } - // lst.addAll(elementPrinterHelper.getComments(ctClass, CommentOffset.INSIDE)); - printer.write(" {").incTab(); - elementPrinterHelper.writeElementList(ctClass.getTypeMembers()); - printer.adjustEndPosition(ctClass).decTab().writeTabs().write("}"); - context.popCurrentThis(); - } - - @Override - public void visitCtTypeParameter(CtTypeParameter typeParameter) { - CtTypeParameterReference ref = typeParameter.getReference(); - if (ref.isImplicit()) { - return; - } - elementPrinterHelper.writeAnnotations(ref); - if (printQualified(ref)) { - printer.write(ref.getQualifiedName()); - } else { - printer.write(ref.getSimpleName()); - } - if (ref.getBoundingType() != null) { - if (ref.isUpper()) { - printer.write(" extends "); - } else { - printer.write(" super "); - } - scan(ref.getBoundingType()); - } - } - - @Override - public void visitCtConditional(CtConditional conditional) { - enterCtExpression(conditional); - CtExpression condition = conditional.getCondition(); - boolean parent; - try { - parent = conditional.getParent() instanceof CtAssignment || conditional.getParent() instanceof CtVariable; - } catch (ParentNotInitializedException ex) { - // nothing if we have no parent - parent = false; - } - if (parent) { - printer.write("("); - } - scan(condition); - if (parent) { - printer.write(")"); - } - printer.write(" ? "); - CtExpression thenExpression = conditional.getThenExpression(); - scan(thenExpression); - printer.write(" : "); - - CtExpression elseExpression = conditional.getElseExpression(); - boolean isAssign = false; - if ((isAssign = elseExpression instanceof CtAssignment)) { - printer.write("("); - } - scan(elseExpression); - if (isAssign) { - printer.write(")"); - } - exitCtExpression(conditional); - } - - @Override - public void visitCtConstructor(CtConstructor constructor) { - elementPrinterHelper.writeComment(constructor); - elementPrinterHelper.visitCtNamedElement(constructor, sourceCompilationUnit); - elementPrinterHelper.writeModifiers(constructor); - elementPrinterHelper.writeFormalTypeParameters(constructor); - if (constructor.getFormalCtTypeParameters().size() > 0) { - printer.write(' '); - } - if (constructor.getDeclaringType() != null) { - if (constructor.getDeclaringType().isLocalType()) { - printer.write(constructor.getDeclaringType().getSimpleName().replaceAll("^[0-9]*", "")); - } else { - printer.write(constructor.getDeclaringType().getSimpleName()); - } - } - elementPrinterHelper.writeExecutableParameters(constructor); - elementPrinterHelper.writeThrowsClause(constructor); - printer.write(" "); - scan(constructor.getBody()); - } - - @Override - public void visitCtContinue(CtContinue continueStatement) { - enterCtStatement(continueStatement); - printer.write("continue"); - if (continueStatement.getTargetLabel() != null) { - printer.write(" " + continueStatement.getTargetLabel()); - } - } - - @Override - public void visitCtDo(CtDo doLoop) { - enterCtStatement(doLoop); - printer.write("do"); - elementPrinterHelper.writeIfOrLoopBlock(doLoop.getBody()); - printer.write("while ("); - scan(doLoop.getLoopingExpression()); - printer.write(" )"); - } - - @Override - public > void visitCtEnum(CtEnum ctEnum) { - visitCtType(ctEnum); - printer.write("enum " + ctEnum.getSimpleName()); - elementPrinterHelper.writeImplementsClause(ctEnum); - context.pushCurrentThis(ctEnum); - printer.write(" {").incTab().writeln(); - - if (ctEnum.getEnumValues().size() == 0) { - printer.writeTabs().write(";").writeln(); - } else { - for (CtEnumValue enumValue : ctEnum.getEnumValues()) { - scan(enumValue); - printer.write(", "); - } - printer.removeLastChar(); - printer.write(";"); - } - - elementPrinterHelper.writeElementList(ctEnum.getTypeMembers()); - printer.decTab().writeTabs().write("}"); - context.popCurrentThis(); - } - - @Override - public void visitCtExecutableReference(CtExecutableReference reference) { - printer.write(reference.getSignature()); - } - - @Override - public void visitCtField(CtField f) { - elementPrinterHelper.writeComment(f); - elementPrinterHelper.visitCtNamedElement(f, sourceCompilationUnit); - elementPrinterHelper.writeModifiers(f); - scan(f.getType()); - printer.write(" "); - printer.write(f.getSimpleName()); - - if (f.getDefaultExpression() != null) { - printer.write(" = "); - scan(f.getDefaultExpression()); - } - printer.write(";"); - } - - @Override - public void visitCtEnumValue(CtEnumValue enumValue) { - elementPrinterHelper.visitCtNamedElement(enumValue, sourceCompilationUnit); - printer.write(enumValue.getSimpleName()); - if (enumValue.getDefaultExpression() != null) { - CtConstructorCall constructorCall = (CtConstructorCall) enumValue.getDefaultExpression(); - if (constructorCall.getArguments().size() > 0) { - printer.write("("); - boolean first = true; - for (CtExpression ctexpr : constructorCall.getArguments()) { - if (first) { - first = false; - } else { - printer.write(","); - } - scan(ctexpr); - } - printer.write(")"); - } - if (constructorCall instanceof CtNewClass) { - scan(((CtNewClass) constructorCall).getAnonymousClass()); - } - } - } - - @Override - public void visitCtFieldRead(CtFieldRead fieldRead) { - printCtFieldAccess(fieldRead); - } - - @Override - public void visitCtFieldWrite(CtFieldWrite fieldWrite) { - printCtFieldAccess(fieldWrite); - } - - private void printCtFieldAccess(CtFieldAccess f) { - enterCtExpression(f); - try (Writable _context = context.modify()) { - if (f.getVariable().isStatic() && f.getTarget() instanceof CtTypeAccess) { - _context.ignoreGenerics(true); - } - CtExpression target = f.getTarget(); - if (target != null) { - boolean isInitializeStaticFinalField = isInitializeStaticFinalField(f.getTarget()); - boolean isStaticField = f.getVariable().isStatic(); - boolean isImportedField = importsContext.isImported(f.getVariable()); - - if (!isInitializeStaticFinalField && !(isStaticField && isImportedField)) { - if (target.isImplicit()) { - /* + /** + * Java file extension (.java). + */ + public static final String JAVA_FILE_EXTENSION = ".java"; + + /** + * Package declaration file name. + */ + public static final String JAVA_PACKAGE_DECLARATION = "package-info" + JAVA_FILE_EXTENSION; + + /** + * Line separator which is used by the system + */ + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + /** + * The star at the beginning of a block/JavaDoc comment line + */ + public static final String COMMENT_STAR = " * "; + + /** + * The end of a block/JavaDoc comment + */ + public static final String BLOCK_COMMENT_END = " */"; + + /** + * The beginning of a JavaDoc comment + */ + public static final String JAVADOC_START = "/**"; + + /** + * The beginning of a inline comment + */ + public static final String INLINE_COMMENT_START = "// "; + + /** + * The beginning of a block comment + */ + public static final String BLOCK_COMMENT_START = "/* "; + + /** + * The printing context. + */ + public PrintingContext context = new PrintingContext(); + + /** + * Handle imports of classes. + */ + private ImportScanner importsContext; + + /** + * Environment which Spoon is executed. + */ + private Environment env; + + /** + * Printer helper. + */ + private PrinterHelper printer; + + /** + * Element printer helper. + */ + private ElementPrinterHelper elementPrinterHelper; + + /** + * Compilation unit we are printing. + */ + private CompilationUnit sourceCompilationUnit; + + /** + * Creates a new code generator visitor. + */ + public DefaultJavaPrettyPrinter(Environment env) { + this.env = env; + printer = new PrinterHelper(env); + elementPrinterHelper = new ElementPrinterHelper(printer, this, env); + if (env.isAutoImports()) { + this.importsContext = new ImportScannerImpl(); + } else { + this.importsContext = new MinimalImportScanner(); + } + } + + /** + * Enters an expression. + */ + protected void enterCtExpression(CtExpression e) { + if (!(e instanceof CtStatement)) { + elementPrinterHelper.writeComment(e, CommentOffset.BEFORE); + } + printer.mapLine(e, sourceCompilationUnit); + if (shouldSetBracket(e)) { + context.parenthesedExpression.push(e); + printer.write("("); + } + if (!e.getTypeCasts().isEmpty()) { + for (CtTypeReference r : e.getTypeCasts()) { + printer.write("("); + DefaultJavaPrettyPrinter.this.scan(r); + printer.write(") "); + printer.write("("); + context.parenthesedExpression.push(e); + } + } + } + + /** + * Enters a statement. + */ + protected void enterCtStatement(CtStatement s) { + elementPrinterHelper.writeComment(s, CommentOffset.BEFORE); + printer.mapLine(s, sourceCompilationUnit); + elementPrinterHelper.writeAnnotations(s); + if (s.getLabel() != null) { + printer.write(s.getLabel()).write(" : "); + } + } + + /** + * Exits an expression. + */ + protected void exitCtExpression(CtExpression e) { + while ((context.parenthesedExpression.size() > 0) && e == context.parenthesedExpression.peek()) { + context.parenthesedExpression.pop(); + printer.write(")"); + } + if (!(e instanceof CtStatement)) { + elementPrinterHelper.writeComment(e, CommentOffset.AFTER); + } + } + + /** + * Make the imports for a given type. + */ + public Collection computeImports(CtType type) { + context.currentTopLevel = type; + importsContext.computeImports(context.currentTopLevel); + return importsContext.getAllImports(); + } + + /** + * Make the imports for all elements. + */ + public void computeImports(CtElement element) { + if (env.isAutoImports()) { + importsContext.computeImports(element); + } + } + + /** + * The generic scan method for an element. + */ + public DefaultJavaPrettyPrinter scan(CtElement e) { + if (e != null) { + context.elementStack.push(e); + if (env.isPreserveLineNumbers()) { + if (!(e instanceof CtNamedElement)) { + printer.adjustStartPosition(e); + } + } + e.accept(this); + context.elementStack.pop(); + } + return this; + } + + /** + * The generic scan method for a reference. + */ + public DefaultJavaPrettyPrinter scan(CtReference ref) { + if (ref != null) { + ref.accept(this); + } + return this; + } + + private boolean shouldSetBracket(CtExpression e) { + if (e.getTypeCasts().size() != 0) { + return true; + } + try { + if ((e.getParent() instanceof CtBinaryOperator) || (e.getParent() instanceof CtUnaryOperator)) { + return (e instanceof CtTargetedExpression) || (e instanceof CtAssignment) || (e instanceof CtConditional) || (e instanceof CtUnaryOperator) || e instanceof CtBinaryOperator; + } + if (e.getParent() instanceof CtTargetedExpression) { + return (e instanceof CtBinaryOperator) || (e instanceof CtAssignment) || (e instanceof CtConditional) || (e instanceof CtUnaryOperator); + } + } catch (ParentNotInitializedException ex) { + // nothing we accept not to have a parent + } + return false; + } + + /** + * Gets the currently pretty-printed string. + */ + @Override + public String toString() { + return printer.toString(); + } + + @Override + public void visitCtAnnotation(CtAnnotation annotation) { + elementPrinterHelper.writeAnnotations(annotation); + printer.write("@"); + scan(annotation.getAnnotationType()); + if (annotation.getValues().size() > 0) { + printer.write("("); + for (Entry e : annotation.getValues().entrySet()) { + printer.write(e.getKey() + " = "); + elementPrinterHelper.writeAnnotationElement(annotation.getFactory(), e.getValue()); + printer.write(", "); + } + printer.removeLastChar(); + printer.write(")"); + } + printer.writeln().writeTabs(); + } + + @Override + public void visitCtAnnotationType(CtAnnotationType annotationType) { + visitCtType(annotationType); + printer.write("@interface " + annotationType.getSimpleName() + " {").incTab(); + + elementPrinterHelper.writeElementList(annotationType.getTypeMembers()); + printer.decTab().writeTabs().write("}"); + } + + @Override + public void visitCtAnonymousExecutable(CtAnonymousExecutable impl) { + elementPrinterHelper.writeComment(impl); + elementPrinterHelper.writeAnnotations(impl); + elementPrinterHelper.writeModifiers(impl); + scan(impl.getBody()); + } + + @Override + public void visitCtArrayRead(CtArrayRead arrayRead) { + printCtArrayAccess(arrayRead); + } + + @Override + public void visitCtArrayWrite(CtArrayWrite arrayWrite) { + printCtArrayAccess(arrayWrite); + } + + private > void printCtArrayAccess(CtArrayAccess arrayAccess) { + enterCtExpression(arrayAccess); + scan(arrayAccess.getTarget()); + printer.write("["); + scan(arrayAccess.getIndexExpression()); + printer.write("]"); + exitCtExpression(arrayAccess); + } + + @Override + public void visitCtArrayTypeReference(CtArrayTypeReference reference) { + if (reference.isImplicit()) { + return; + } + scan(reference.getComponentType()); + if (!context.skipArray()) { + printer.write("[]"); + } + } + + @Override + public void visitCtAssert(CtAssert asserted) { + enterCtStatement(asserted); + printer.write("assert "); + scan(asserted.getAssertExpression()); + if (asserted.getExpression() != null) { + printer.write(" : "); + scan(asserted.getExpression()); + } + + } + + @Override + public void visitCtAssignment(CtAssignment assignement) { + enterCtStatement(assignement); + enterCtExpression(assignement); + scan(assignement.getAssigned()); + printer.write(" = "); + scan(assignement.getAssignment()); + exitCtExpression(assignement); + } + + @Override + public void visitCtBinaryOperator(CtBinaryOperator operator) { + enterCtExpression(operator); + scan(operator.getLeftHandOperand()); + printer.write(" ").writeOperator(operator.getKind()).write(" "); + scan(operator.getRightHandOperand()); + exitCtExpression(operator); + } + + @Override + public void visitCtBlock(CtBlock block) { + enterCtStatement(block); + if (!block.isImplicit()) { + printer.write("{"); + } + printer.incTab(); + for (CtStatement statement : block.getStatements()) { + if (!statement.isImplicit()) { + printer.writeln().writeTabs(); + elementPrinterHelper.writeStatement(statement); + } + } + printer.decTab(); + printer.adjustEndPosition(block); + if (env.isPreserveLineNumbers()) { + if (!block.isImplicit()) { + printer.writeTabs().write("}"); + } + } else { + printer.writeln().writeTabs(); + if (!block.isImplicit()) { + printer.write("}"); + } + } + } + + @Override + public void visitCtBreak(CtBreak breakStatement) { + enterCtStatement(breakStatement); + printer.write("break"); + if (breakStatement.getTargetLabel() != null) { + printer.write(" " + breakStatement.getTargetLabel()); + } + } + + @Override + @SuppressWarnings("rawtypes") + public void visitCtCase(CtCase caseStatement) { + enterCtStatement(caseStatement); + if (caseStatement.getCaseExpression() != null) { + printer.write("case "); + // writing enum case expression + if (caseStatement.getCaseExpression() instanceof CtFieldAccess) { + final CtFieldReference variable = ((CtFieldAccess) caseStatement.getCaseExpression()).getVariable(); + // In noclasspath mode, we don't have always the type of the declaring type. + if (variable.getType() != null + && variable.getDeclaringType() != null + && variable.getType().getQualifiedName().equals(variable.getDeclaringType().getQualifiedName())) { + printer.write(variable.getSimpleName()); + } else { + scan(caseStatement.getCaseExpression()); + } + } else { + scan(caseStatement.getCaseExpression()); + } + } else { + printer.write("default"); + } + printer.write(" :").incTab(); + + for (CtStatement statement : caseStatement.getStatements()) { + printer.writeln().writeTabs(); + elementPrinterHelper.writeStatement(statement); + } + printer.decTab(); + } + + @Override + public void visitCtCatch(CtCatch catchBlock) { + elementPrinterHelper.writeComment(catchBlock, CommentOffset.BEFORE); + printer.write(" catch ("); + CtCatchVariable parameter = catchBlock.getParameter(); + if (parameter.getMultiTypes().size() > 0) { + for (int i = 0; i < parameter.getMultiTypes().size(); i++) { + CtTypeReference type = parameter.getMultiTypes().get(i); + scan(type); + if (i < parameter.getMultiTypes().size() - 1) { + printer.write(" | "); + } + } + printer.write(" " + parameter.getSimpleName()); + } else { + scan(parameter); + } + printer.write(") "); + scan(catchBlock.getBody()); + } + + @Override + public void visitCtClass(CtClass ctClass) { + context.pushCurrentThis(ctClass); + if (ctClass.getSimpleName() != null && !CtType.NAME_UNKNOWN.equals(ctClass.getSimpleName()) && !ctClass.isAnonymous()) { + visitCtType(ctClass); + if (ctClass.isLocalType()) { + printer.write("class " + ctClass.getSimpleName().replaceAll("^[0-9]*", "")); + } else { + printer.write("class " + ctClass.getSimpleName()); + } + + elementPrinterHelper.writeFormalTypeParameters(ctClass); + elementPrinterHelper.writeExtendsClause(ctClass); + elementPrinterHelper.writeImplementsClause(ctClass); + } + // lst.addAll(elementPrinterHelper.getComments(ctClass, CommentOffset.INSIDE)); + printer.write(" {").incTab(); + elementPrinterHelper.writeElementList(ctClass.getTypeMembers()); + printer.adjustEndPosition(ctClass).decTab().writeTabs().write("}"); + context.popCurrentThis(); + } + + @Override + public void visitCtTypeParameter(CtTypeParameter typeParameter) { + CtTypeParameterReference ref = typeParameter.getReference(); + if (ref.isImplicit()) { + return; + } + elementPrinterHelper.writeAnnotations(ref); + if (printQualified(ref)) { + printer.write(ref.getQualifiedName()); + } else { + printer.write(ref.getSimpleName()); + } + if (ref.getBoundingType() != null) { + if (ref.isUpper()) { + printer.write(" extends "); + } else { + printer.write(" super "); + } + scan(ref.getBoundingType()); + } + } + + @Override + public void visitCtConditional(CtConditional conditional) { + enterCtExpression(conditional); + CtExpression condition = conditional.getCondition(); + boolean parent; + try { + parent = conditional.getParent() instanceof CtAssignment || conditional.getParent() instanceof CtVariable; + } catch (ParentNotInitializedException ex) { + // nothing if we have no parent + parent = false; + } + if (parent) { + printer.write("("); + } + scan(condition); + if (parent) { + printer.write(")"); + } + printer.write(" ? "); + CtExpression thenExpression = conditional.getThenExpression(); + scan(thenExpression); + printer.write(" : "); + + CtExpression elseExpression = conditional.getElseExpression(); + boolean isAssign = false; + if ((isAssign = elseExpression instanceof CtAssignment)) { + printer.write("("); + } + scan(elseExpression); + if (isAssign) { + printer.write(")"); + } + exitCtExpression(conditional); + } + + @Override + public void visitCtConstructor(CtConstructor constructor) { + elementPrinterHelper.writeComment(constructor); + elementPrinterHelper.visitCtNamedElement(constructor, sourceCompilationUnit); + elementPrinterHelper.writeModifiers(constructor); + elementPrinterHelper.writeFormalTypeParameters(constructor); + if (constructor.getFormalCtTypeParameters().size() > 0) { + printer.write(' '); + } + if (constructor.getDeclaringType() != null) { + if (constructor.getDeclaringType().isLocalType()) { + printer.write(constructor.getDeclaringType().getSimpleName().replaceAll("^[0-9]*", "")); + } else { + printer.write(constructor.getDeclaringType().getSimpleName()); + } + } + elementPrinterHelper.writeExecutableParameters(constructor); + elementPrinterHelper.writeThrowsClause(constructor); + printer.write(" "); + scan(constructor.getBody()); + } + + @Override + public void visitCtContinue(CtContinue continueStatement) { + enterCtStatement(continueStatement); + printer.write("continue"); + if (continueStatement.getTargetLabel() != null) { + printer.write(" " + continueStatement.getTargetLabel()); + } + } + + @Override + public void visitCtDo(CtDo doLoop) { + enterCtStatement(doLoop); + printer.write("do"); + elementPrinterHelper.writeIfOrLoopBlock(doLoop.getBody()); + printer.write("while ("); + scan(doLoop.getLoopingExpression()); + printer.write(" )"); + } + + @Override + public > void visitCtEnum(CtEnum ctEnum) { + visitCtType(ctEnum); + printer.write("enum " + ctEnum.getSimpleName()); + elementPrinterHelper.writeImplementsClause(ctEnum); + context.pushCurrentThis(ctEnum); + printer.write(" {").incTab().writeln(); + + if (ctEnum.getEnumValues().size() == 0) { + printer.writeTabs().write(";").writeln(); + } else { + for (CtEnumValue enumValue : ctEnum.getEnumValues()) { + scan(enumValue); + printer.write(", "); + } + printer.removeLastChar(); + printer.write(";"); + } + + elementPrinterHelper.writeElementList(ctEnum.getTypeMembers()); + printer.decTab().writeTabs().write("}"); + context.popCurrentThis(); + } + + @Override + public void visitCtExecutableReference(CtExecutableReference reference) { + printer.write(reference.getSignature()); + } + + @Override + public void visitCtField(CtField f) { + elementPrinterHelper.writeComment(f); + elementPrinterHelper.visitCtNamedElement(f, sourceCompilationUnit); + elementPrinterHelper.writeModifiers(f); + scan(f.getType()); + printer.write(" "); + printer.write(f.getSimpleName()); + + if (f.getDefaultExpression() != null) { + printer.write(" = "); + scan(f.getDefaultExpression()); + } + printer.write(";"); + } + + @Override + public void visitCtEnumValue(CtEnumValue enumValue) { + elementPrinterHelper.visitCtNamedElement(enumValue, sourceCompilationUnit); + printer.write(enumValue.getSimpleName()); + if (enumValue.getDefaultExpression() != null) { + CtConstructorCall constructorCall = (CtConstructorCall) enumValue.getDefaultExpression(); + if (constructorCall.getArguments().size() > 0) { + printer.write("("); + boolean first = true; + for (CtExpression ctexpr : constructorCall.getArguments()) { + if (first) { + first = false; + } else { + printer.write(","); + } + scan(ctexpr); + } + printer.write(")"); + } + if (constructorCall instanceof CtNewClass) { + scan(((CtNewClass) constructorCall).getAnonymousClass()); + } + } + } + + @Override + public void visitCtFieldRead(CtFieldRead fieldRead) { + printCtFieldAccess(fieldRead); + } + + @Override + public void visitCtFieldWrite(CtFieldWrite fieldWrite) { + printCtFieldAccess(fieldWrite); + } + + private void printCtFieldAccess(CtFieldAccess f) { + enterCtExpression(f); + try (Writable _context = context.modify()) { + if (f.getVariable().isStatic() && f.getTarget() instanceof CtTypeAccess) { + _context.ignoreGenerics(true); + } + CtExpression target = f.getTarget(); + if (target != null) { + boolean isInitializeStaticFinalField = isInitializeStaticFinalField(f.getTarget()); + boolean isStaticField = f.getVariable().isStatic(); + boolean isImportedField = importsContext.isImported(f.getVariable()); + + if (!isInitializeStaticFinalField && !(isStaticField && isImportedField)) { + if (target.isImplicit()) { + /* * target is implicit, check whether there is no conflict with an local variable, catch variable or parameter * in case of conflict make it explicit, otherwise the field access is shadowed by that variable. * Search for potential variable declaration until we found a class which declares or inherits this field */ - final CtField field = f.getVariable().getFieldDeclaration(); - final String fieldName = field.getSimpleName(); - CtVariable var = f.getVariable().map(new PotentialVariableDeclarationFunction(fieldName)).first(); - if (var != field) { - //another variable declaration was found which is hiding the field declaration for this field access. Make the field access expicit - target.setImplicit(false); - } - } - printer.snapshotLength(); - scan(target); - if (printer.hasNewContent()) { - printer.write("."); - } - } - _context.ignoreStaticAccess(true); - } - scan(f.getVariable()); - } - exitCtExpression(f); - } - - /** - * Check if the target expression is a static final field initialized in a static anonymous block. - */ - private boolean isInitializeStaticFinalField(CtExpression targetExp) { - final CtElement parent; - final CtAnonymousExecutable anonymousParent; - try { - parent = targetExp.getParent(); - anonymousParent = targetExp.getParent(CtAnonymousExecutable.class); - } catch (ParentNotInitializedException e) { - return false; - } - if (parent instanceof CtFieldWrite - && targetExp.equals(((CtFieldWrite) parent).getTarget()) - && anonymousParent != null - && ((CtFieldWrite) parent).getVariable() != null - && ((CtFieldWrite) parent).getVariable().getModifiers().contains(ModifierKind.STATIC) - && ((CtFieldWrite) parent).getVariable().getModifiers().contains(ModifierKind.FINAL)) { - return true; - } - return false; - } - - @Override - public void visitCtThisAccess(CtThisAccess thisAccess) { - try { - enterCtExpression(thisAccess); - - // we only write qualified this when this is required - // this is good both in fully-qualified mode and in readable (with-imports) mode - // the implicit information is used for analysis (eg are visibility caused by implicit bugs?) but - // not for pretty-printing - CtTypeAccess target = (CtTypeAccess) thisAccess.getTarget(); - CtTypeReference targetType = target.getAccessedType(); - - // readable mode as close as possible to the original code - if (thisAccess.isImplicit()) { - // write nothing, "this" is implicit and we unfortunately cannot always know - // what the good target is in JDTTreeBuilder - return; - } - - // the simplest case: we always print "this" if we're in the top-level class, - // this is shorter (no qualified this), explicit, and less fragile wrt transformation - if (targetType == null || (thisAccess.getParent(CtType.class) != null && thisAccess.getParent(CtType.class).isTopLevel())) { - printer.write("this"); - return; // still go through finally block below - } - - // we cannot have fully-qualified this in anonymous classes - // we simply print "this" and it always works - // this has to come after the implicit test just before - if (targetType.isAnonymous()) { - printer.write("this"); - return; - } - - // complex case of qualifed this - if (!context.currentThis.isEmpty()) { - - CtType lastType = context.currentThis.peekFirst().type; - String lastTypeQualifiedName = lastType.getQualifiedName(); - String targetTypeQualifiedName = targetType.getQualifiedName(); - - if (!lastTypeQualifiedName.equals(targetTypeQualifiedName)) { - printer.snapshotLength(); - visitCtTypeReferenceWithoutGenerics(targetType); - if (printer.hasNewContent()) { - printer.write("."); - } - printer.write("this"); - return; - } - } - - // the default super simple case only comes at the end - printer.write("this"); - } finally { - exitCtExpression(thisAccess); - } - } - - @Override - public void visitCtSuperAccess(CtSuperAccess f) { - enterCtExpression(f); - if (f.getTarget() != null) { - scan(f.getTarget()); - printer.write("."); - } - printer.write("super"); - - exitCtExpression(f); - } - - @Override - public void visitCtJavaDoc(CtJavaDoc comment) { - visitCtComment(comment); - } - - @Override - public void visitCtJavaDocTag(CtJavaDocTag docTag) { - printer.write(COMMENT_STAR); - printer.write(CtJavaDocTag.JAVADOC_TAG_PREFIX); - printer.write(docTag.getType().name().toLowerCase()); - printer.write(" "); - if (docTag.getType().hasParam()) { - printer.write(docTag.getParam()).writeln().writeTabs(); - } - - String[] tagLines = docTag.getContent().split(LINE_SEPARATOR); - for (int i = 0; i < tagLines.length; i++) { - String com = tagLines[i]; - if (i > 0 || docTag.getType().hasParam()) { - printer.write(COMMENT_STAR); - } - if (docTag.getType().hasParam()) { - printer.write("\t\t"); - } - printer.write(com.trim()).writeln().writeTabs(); - } - } - - @Override - public void visitCtComment(CtComment comment) { - if (!env.isCommentsEnabled() && context.elementStack.size() > 1) { - return; - } - switch (comment.getCommentType()) { - case FILE: - printer.write(JAVADOC_START).writeln(); - break; - case JAVADOC: - printer.write(JAVADOC_START).writeln().writeTabs(); - break; - case INLINE: - printer.write(INLINE_COMMENT_START); - break; - case BLOCK: - printer.write(BLOCK_COMMENT_START); - break; - } - String content = comment.getContent(); - switch (comment.getCommentType()) { - case INLINE: - printer.write(content); - break; - default: - String[] lines = content.split(LINE_SEPARATOR); - for (int i = 0; i < lines.length; i++) { - String com = lines[i]; - if (comment.getCommentType() == CtComment.CommentType.BLOCK) { - printer.write(com); - if (lines.length > 1) { - printer.writeln().writeTabs(); - } - } else { - if (com.length() > 0) { - printer.write(COMMENT_STAR + com).writeln().writeTabs(); - } else { - printer.write(" *" /* no trailing space */ + com).writeln().writeTabs(); - } - } - - } - if (comment instanceof CtJavaDoc) { - if (!((CtJavaDoc) comment).getTags().isEmpty()) { - printer.write(" *").writeln().writeTabs(); - } - for (CtJavaDocTag docTag : ((CtJavaDoc) comment).getTags()) { - scan(docTag); - } - } - break; - } - - switch (comment.getCommentType()) { - case BLOCK: - printer.write(BLOCK_COMMENT_END); - break; - case FILE: - printer.write(BLOCK_COMMENT_END); - break; - case JAVADOC: - printer.write(BLOCK_COMMENT_END); - break; - } - } - - @Override - public void visitCtAnnotationFieldAccess(CtAnnotationFieldAccess annotationFieldAccess) { - enterCtExpression(annotationFieldAccess); - try (Writable _context = context.modify()) { - if (annotationFieldAccess.getTarget() != null) { - scan(annotationFieldAccess.getTarget()); - printer.write("."); - _context.ignoreStaticAccess(true); - } - _context.ignoreGenerics(true); - scan(annotationFieldAccess.getVariable()); - printer.write("()"); - } - exitCtExpression(annotationFieldAccess); - } - - @Override - public void visitCtFieldReference(CtFieldReference reference) { - boolean isStatic = reference.getSimpleName().equals("class") || !reference.getSimpleName().equals("super") && reference.isStatic(); - - boolean printType = true; - - if (reference.isFinal() && reference.isStatic()) { - CtTypeReference declTypeRef = reference.getDeclaringType(); - if (declTypeRef.isAnonymous()) { - //never print anonymous class ref - printType = false; - } else { - if (context.isInCurrentScope(declTypeRef)) { - //do not printType if we are in scope of that type - printType = false; - } - } - } - - if (isStatic && printType && !context.ignoreStaticAccess()) { - try (Writable _context = context.modify().ignoreGenerics(true)) { - scan(reference.getDeclaringType()); - } - printer.write("."); - } - printer.write(reference.getSimpleName()); - } - - @Override - public void visitCtFor(CtFor forLoop) { - enterCtStatement(forLoop); - printer.write("for ("); - List st = forLoop.getForInit(); - if (st.size() > 0) { - scan(st.get(0)); - } - if (st.size() > 1) { - try (Writable _context = context.modify().noTypeDecl(true)) { - for (int i = 1; i < st.size(); i++) { - printer.write(", "); - scan(st.get(i)); - } - } - } - printer.write("; "); - scan(forLoop.getExpression()); - printer.write(";"); - if (!forLoop.getForUpdate().isEmpty()) { - printer.write(" "); - } - for (CtStatement s : forLoop.getForUpdate()) { - scan(s); - printer.write(" , "); - } - if (forLoop.getForUpdate().size() > 0) { - printer.removeLastChar(); - } - printer.write(")"); - elementPrinterHelper.writeIfOrLoopBlock(forLoop.getBody()); - } - - @Override - public void visitCtForEach(CtForEach foreach) { - enterCtStatement(foreach); - printer.write("for ("); - scan(foreach.getVariable()); - printer.write(" : "); - scan(foreach.getExpression()); - printer.write(")"); - elementPrinterHelper.writeIfOrLoopBlock(foreach.getBody()); - } - - @Override - public void visitCtIf(CtIf ifElement) { - enterCtStatement(ifElement); - printer.write("if ("); - scan(ifElement.getCondition()); - printer.write(")"); - elementPrinterHelper.writeIfOrLoopBlock(ifElement.getThenStatement()); - if (ifElement.getElseStatement() != null) { - List comments = elementPrinterHelper.getComments(ifElement, CommentOffset.INSIDE); - for (CtComment comment : comments) { - SourcePosition thenPosition = - ifElement.getThenStatement().getPosition() == null ? ((CtBlock) ifElement.getThenStatement()).getStatement(0).getPosition() : ifElement.getThenStatement().getPosition(); - if (comment.getPosition().getSourceStart() > thenPosition.getSourceEnd()) { - elementPrinterHelper.writeComment(comment); - } - } - printer.write("else"); - elementPrinterHelper.writeIfOrLoopBlock(ifElement.getElseStatement()); - } - } - - @Override - public void visitCtInterface(CtInterface intrface) { - visitCtType(intrface); - printer.write("interface " + intrface.getSimpleName()); - if (intrface.getFormalCtTypeParameters() != null) { - elementPrinterHelper.writeFormalTypeParameters(intrface); - } - - if (intrface.getSuperInterfaces().size() > 0) { - printer.write(" extends "); - for (CtTypeReference ref : intrface.getSuperInterfaces()) { - scan(ref); - printer.write(" , "); - } - printer.removeLastChar(); - } - context.pushCurrentThis(intrface); - printer.write(" {").incTab(); - // Content - elementPrinterHelper.writeElementList(intrface.getTypeMembers()); - printer.decTab().writeTabs().write("}"); - context.popCurrentThis(); - } - - @Override - public void visitCtInvocation(CtInvocation invocation) { - enterCtStatement(invocation); - enterCtExpression(invocation); - if (invocation.getExecutable().isConstructor()) { - // It's a constructor (super or this) - elementPrinterHelper.writeActualTypeArguments(invocation.getExecutable()); - CtType parentType; - try { - parentType = invocation.getParent(CtType.class); - } catch (ParentNotInitializedException e) { - parentType = null; - } - if (parentType != null && parentType.getQualifiedName() != null && parentType.getQualifiedName().equals(invocation.getExecutable().getDeclaringType().getQualifiedName())) { - printer.write("this"); - } else { - printer.snapshotLength(); - scan(invocation.getTarget()); - if (printer.hasNewContent()) { - printer.write("."); - } - printer.write("super"); - } - } else { - // It's a method invocation - printer.snapshotLength(); - try (Writable _context = context.modify()) { - if (invocation.getTarget() instanceof CtTypeAccess) { - _context.ignoreGenerics(true); - } - scan(invocation.getTarget()); - } - if (printer.hasNewContent()) { - printer.write("."); - } - - elementPrinterHelper.writeActualTypeArguments(invocation); - if (env.isPreserveLineNumbers()) { - printer.adjustStartPosition(invocation); - } - printer.write(invocation.getExecutable().getSimpleName()); - } - printer.write("("); - boolean remove = false; - for (CtExpression e : invocation.getArguments()) { - scan(e); - printer.write(", "); - remove = true; - } - if (remove) { - printer.removeLastChar(); - } - printer.write(")"); - exitCtExpression(invocation); - } - - @Override - public void visitCtLiteral(CtLiteral literal) { - enterCtExpression(literal); - if (literal.getValue() == null) { - printer.write("null"); - } else if (literal.getValue() instanceof Long) { - printer.write(literal.getValue() + "L"); - } else if (literal.getValue() instanceof Float) { - printer.write(literal.getValue() + "F"); - } else if (literal.getValue() instanceof Character) { - printer.write("'"); - - boolean mayContainsSpecialCharacter = true; - - SourcePosition position = literal.getPosition(); - if (position != null) { - // the size of the string in the source code, the -1 is the size of the ' or " in the source code - int stringLength = position.getSourceEnd() - position.getSourceStart() - 1; - // if the string in the source is not the same as the string in the literal, the string may contains special characters - mayContainsSpecialCharacter = stringLength != 1; - } - printer.writeCharLiteral((Character)literal.getValue(), mayContainsSpecialCharacter); - - printer.write("'"); - } else if (literal.getValue() instanceof String) { - printer.write('\"'); - - boolean mayContainsSpecialCharacters = true; - - SourcePosition position = literal.getPosition(); - if (position != null) { - // the size of the string in the source code, the -1 is the size of the ' or " in the source code - int stringLength = position.getSourceEnd() - position.getSourceStart() - 1; - // if the string in the source is not the same as the string in the literal, the string may contains special characters - mayContainsSpecialCharacters = ((String) literal.getValue()).length() != stringLength; - } - printer.writeStringLiteral((String) literal.getValue(), mayContainsSpecialCharacters); - - printer.write('\"'); - } else if (literal.getValue() instanceof Class) { - printer.write(((Class) literal.getValue()).getName()); - } else { - printer.write(literal.getValue().toString()); - } - exitCtExpression(literal); - } - - @Override - public void visitCtLocalVariable(CtLocalVariable localVariable) { - if (!context.noTypeDecl()) { - enterCtStatement(localVariable); - } - if (env.isPreserveLineNumbers()) { - printer.adjustStartPosition(localVariable); - } - if (!context.noTypeDecl()) { - elementPrinterHelper.writeModifiers(localVariable); - scan(localVariable.getType()); - printer.write(" "); - } - printer.write(localVariable.getSimpleName()); - if (localVariable.getDefaultExpression() != null) { - printer.write(" = "); - scan(localVariable.getDefaultExpression()); - } - } - - @Override - public void visitCtLocalVariableReference(CtLocalVariableReference reference) { - printer.write(reference.getSimpleName()); - } - - @Override - public void visitCtCatchVariable(CtCatchVariable catchVariable) { - if (env.isPreserveLineNumbers()) { - printer.adjustStartPosition(catchVariable); - } - elementPrinterHelper.writeModifiers(catchVariable); - scan(catchVariable.getType()); - printer.write(" "); - printer.write(catchVariable.getSimpleName()); - } - - @Override - public void visitCtCatchVariableReference(CtCatchVariableReference reference) { - printer.write(reference.getSimpleName()); - } - - @Override - public void visitCtMethod(CtMethod m) { - elementPrinterHelper.writeComment(m); - elementPrinterHelper.visitCtNamedElement(m, sourceCompilationUnit); - elementPrinterHelper.writeModifiers(m); - if (m.isDefaultMethod()) { - printer.write("default "); - } - elementPrinterHelper.writeFormalTypeParameters(m); - if (m.getFormalCtTypeParameters().size() > 0) { - printer.write(' '); - } - try (Writable _context = context.modify().ignoreGenerics(false)) { - scan(m.getType()); - } - printer.write(" "); - printer.write(m.getSimpleName()); - elementPrinterHelper.writeExecutableParameters(m); - elementPrinterHelper.writeThrowsClause(m); - if (m.getBody() != null) { - printer.write(" "); - scan(m.getBody()); - if (m.getBody().getPosition() != null) { - if (m.getBody().getPosition().getCompilationUnit() == sourceCompilationUnit) { - if (m.getBody().getStatements().isEmpty() || !(m.getBody().getStatements().get(m.getBody().getStatements().size() - 1) instanceof CtReturn)) { - printer.putLineNumberMapping(m.getBody().getPosition().getEndLine()); - } - } else { - printer.undefineLine(); - } - } else { - printer.undefineLine(); - } - } else { - printer.write(";"); - } - } - - @Override - public void visitCtAnnotationMethod(CtAnnotationMethod annotationMethod) { - elementPrinterHelper.writeComment(annotationMethod); - elementPrinterHelper.visitCtNamedElement(annotationMethod, sourceCompilationUnit); - elementPrinterHelper.writeModifiers(annotationMethod); - scan(annotationMethod.getType()); - printer.write(" "); - printer.write(annotationMethod.getSimpleName()); - - printer.write("()"); - if (annotationMethod.getDefaultExpression() != null) { - printer.write(" default "); - scan(annotationMethod.getDefaultExpression()); - } - printer.write(";"); - } - - @Override - @SuppressWarnings("rawtypes") - public void visitCtNewArray(CtNewArray newArray) { - enterCtExpression(newArray); - boolean isNotInAnnotation; - try { - isNotInAnnotation = (newArray.getParent(CtAnnotationType.class) == null) && (newArray.getParent(CtAnnotation.class) == null); - } catch (ParentNotInitializedException e) { - isNotInAnnotation = true; - } - - if (isNotInAnnotation) { - CtTypeReference ref = newArray.getType(); - - if (ref != null) { - printer.write("new "); - } - - try (Writable _context = context.modify().skipArray(true)) { - scan(ref); - } - for (int i = 0; ref instanceof CtArrayTypeReference; i++) { - printer.write("["); - if (newArray.getDimensionExpressions().size() > i) { - CtExpression e = newArray.getDimensionExpressions().get(i); - scan(e); - } - printer.write("]"); - ref = ((CtArrayTypeReference) ref).getComponentType(); - } - } - if (newArray.getDimensionExpressions().size() == 0) { - printer.write("{ "); - List> l_elements = newArray.getElements(); - for (int i = 0; i < l_elements.size(); i++) { - CtExpression e = l_elements.get(i); - scan(e); - printer.write(" , "); - if (i + 1 == l_elements.size()) { - printer.removeLastChar(); - // if the last element c - List comments = elementPrinterHelper.getComments(e, CommentOffset.AFTER); - // if the last element contains an inline comment, print a new line before closing the array - if (!comments.isEmpty() && comments.get(comments.size() - 1).getCommentType() == CtComment.CommentType.INLINE) { - printer.writeln(); - } - } - } - - elementPrinterHelper.writeComment(newArray, CommentOffset.INSIDE); - printer.write(" }"); - } - elementPrinterHelper.writeComment(newArray, CommentOffset.AFTER); - exitCtExpression(newArray); - } - - - @Override - public void visitCtConstructorCall(CtConstructorCall ctConstructorCall) { - enterCtStatement(ctConstructorCall); - enterCtExpression(ctConstructorCall); - - printConstructorCall(ctConstructorCall); - - exitCtExpression(ctConstructorCall); - } - - @Override - public void visitCtNewClass(CtNewClass newClass) { - enterCtStatement(newClass); - enterCtExpression(newClass); - - printConstructorCall(newClass); - - scan(newClass.getAnonymousClass()); - exitCtExpression(newClass); - } - - private void printConstructorCall(CtConstructorCall ctConstructorCall) { - try (Writable _context = context.modify()) { - if (ctConstructorCall.getTarget() != null) { - scan(ctConstructorCall.getTarget()); - printer.write("."); - _context.ignoreEnclosingClass(true); - } - - if (hasDeclaringTypeWithGenerics(ctConstructorCall.getType())) { - _context.ignoreEnclosingClass(true); - } - - printer.write("new "); - - if (ctConstructorCall.getActualTypeArguments().size() > 0) { - elementPrinterHelper.writeActualTypeArguments(ctConstructorCall); - } - - scan(ctConstructorCall.getType()); - } - - printer.write("("); - for (CtCodeElement exp : ctConstructorCall.getArguments()) { - scan(exp); - printer.write(", "); - } - if (ctConstructorCall.getArguments().size() > 0) { - printer.removeLastChar(); - } - printer.write(")"); - } - - /** - * JDT doesn't support new Foo.Bar(). To avoid reprint this kind of type reference, - * we check that the reference has a declaring type with generics. - * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=474593 - * - * @param reference - * Type reference concerned by the bug. - * @return true if a declaring type have generic types. - */ - private boolean hasDeclaringTypeWithGenerics(CtTypeReference reference) { - // We don't have a declaring type, it can't have generics. - if (reference == null) { - return false; - } - // If the declaring type isn't a type, we don't need this hack. - if (reference.getDeclaringType() == null) { - return false; - } - // If current reference is a class declared in a method, we don't need this hack. - if (reference.isLocalType()) { - return false; - } - // If declaring type have generics, we return true. - if (reference.getDeclaringType().getActualTypeArguments().size() != 0) { - return true; - } - // Checks if the declaring type has generic types. - return hasDeclaringTypeWithGenerics(reference.getDeclaringType()); - } - - @Override - public void visitCtLambda(CtLambda lambda) { - enterCtExpression(lambda); - - printer.write("("); - if (lambda.getParameters().size() > 0) { - for (CtParameter parameter : lambda.getParameters()) { - scan(parameter); - printer.write(","); - } - printer.removeLastChar(); - } - printer.write(") -> "); - - if (lambda.getBody() != null) { - scan(lambda.getBody()); - } else { - scan(lambda.getExpression()); - } - exitCtExpression(lambda); - } - - @Override - public > void visitCtExecutableReferenceExpression(CtExecutableReferenceExpression expression) { - enterCtExpression(expression); - scan(expression.getTarget()); - printer.write("::"); - if (expression.getExecutable().isConstructor()) { - printer.write("new"); - } else { - printer.write(expression.getExecutable().getSimpleName()); - } - exitCtExpression(expression); - } - - @Override - public void visitCtOperatorAssignment(CtOperatorAssignment assignment) { - enterCtStatement(assignment); - enterCtExpression(assignment); - scan(assignment.getAssigned()); - printer.write(" "); - printer.writeOperator(assignment.getKind()); - printer.write("= "); - scan(assignment.getAssignment()); - exitCtExpression(assignment); - } - - @Override - public void visitCtPackage(CtPackage ctPackage) { - if (!ctPackage.isUnnamedPackage()) { - printer.write("package " + ctPackage.getQualifiedName() + ";"); - } else { - printer.write("// default package (CtPackage.TOP_LEVEL_PACKAGE_NAME in Spoon= unnamed package)\n"); - } - } - - @Override - public void visitCtPackageReference(CtPackageReference reference) { - printer.write(reference.getSimpleName()); - } - - @Override - public void visitCtParameter(CtParameter parameter) { - elementPrinterHelper.writeComment(parameter); - elementPrinterHelper.writeAnnotations(parameter); - elementPrinterHelper.writeModifiers(parameter); - if (parameter.isVarArgs()) { - scan(((CtArrayTypeReference) parameter.getType()).getComponentType()); - printer.write("..."); - } else { - scan(parameter.getType()); - } - printer.write(" "); - printer.write(parameter.getSimpleName()); - } - - @Override - public void visitCtParameterReference(CtParameterReference reference) { - printer.write(reference.getSimpleName()); - } - - @Override - public void visitCtReturn(CtReturn returnStatement) { - enterCtStatement(returnStatement); - printer.write("return "); - scan(returnStatement.getReturnedExpression()); - } - - private void visitCtType(CtType type) { - elementPrinterHelper.writeComment(type, CommentOffset.BEFORE); - printer.mapLine(type, sourceCompilationUnit); - if (type.isTopLevel()) { - context.currentTopLevel = type; - } - elementPrinterHelper.visitCtNamedElement(type, sourceCompilationUnit); - elementPrinterHelper.writeModifiers(type); - } - - @Override - public void visitCtStatementList(CtStatementList statements) { - for (CtStatement s : statements.getStatements()) { - scan(s); - } - } - - @Override - public void visitCtSwitch(CtSwitch switchStatement) { - enterCtStatement(switchStatement); - printer.write("switch ("); - scan(switchStatement.getSelector()); - printer.write(") {").incTab(); - for (CtCase c : switchStatement.getCases()) { - printer.writeln().writeTabs(); - scan(c); - } - if (env.isPreserveLineNumbers()) { - printer.decTab().write("}"); - } else { - printer.decTab().writeln().writeTabs().write("}"); - } - } - - @Override - public void visitCtSynchronized(CtSynchronized synchro) { - enterCtStatement(synchro); - printer.write("synchronized"); - if (synchro.getExpression() != null) { - printer.write("("); - scan(synchro.getExpression()); - printer.write(") "); - } - scan(synchro.getBlock()); - } - - @Override - public void visitCtThrow(CtThrow throwStatement) { - enterCtStatement(throwStatement); - printer.write("throw "); - scan(throwStatement.getThrownExpression()); - } - - @Override - public void visitCtTry(CtTry tryBlock) { - enterCtStatement(tryBlock); - printer.write("try "); - scan(tryBlock.getBody()); - for (CtCatch c : tryBlock.getCatchers()) { - scan(c); - } - - if (tryBlock.getFinalizer() != null) { - printer.write(" finally "); - scan(tryBlock.getFinalizer()); - } - } - - @Override - public void visitCtTryWithResource(CtTryWithResource tryWithResource) { - enterCtStatement(tryWithResource); - printer.write("try "); - if (tryWithResource.getResources() != null && !tryWithResource.getResources().isEmpty()) { - printer.write("("); - for (CtLocalVariable r : tryWithResource.getResources()) { - scan(r); - printer.write(";"); - } - printer.removeLastChar(); - printer.write(") "); - } - scan(tryWithResource.getBody()); - for (CtCatch c : tryWithResource.getCatchers()) { - scan(c); - } - - if (tryWithResource.getFinalizer() != null) { - printer.write(" finally "); - scan(tryWithResource.getFinalizer()); - } - } - - @Override - public void visitCtTypeParameterReference(CtTypeParameterReference ref) { - if (ref.isImplicit()) { - return; - } - elementPrinterHelper.writeAnnotations(ref); - if (printQualified(ref)) { - printer.write(ref.getQualifiedName()); - } else { - printer.write(ref.getSimpleName()); - } - } - - @Override - public void visitCtWildcardReference(CtWildcardReference wildcardReference) { - if (wildcardReference.isImplicit()) { - return; - } - elementPrinterHelper.writeAnnotations(wildcardReference); - if (printQualified(wildcardReference)) { - printer.write(wildcardReference.getQualifiedName()); - } else { - printer.write(wildcardReference.getSimpleName()); - } - if (wildcardReference.getBoundingType() != null) { - if (wildcardReference.isUpper()) { - printer.write(" extends "); - } else { - printer.write(" super "); - } - scan(wildcardReference.getBoundingType()); - } - } - - private boolean printQualified(CtTypeReference ref) { - if (importsContext.isImported(ref) || (this.env.isAutoImports() && ref.getPackage() != null && ref.getPackage().getSimpleName().equals("java.lang"))) { - // If my.pkg.Something is imported, but - //A) we are in the context of a class which is also called "Something", - //B) we are in the context of a class which defines field which is also called "Something", - // we should still use qualified version my.pkg.Something - for (TypeContext typeContext : context.currentThis) { - if (typeContext.getSimpleName().equals(ref.getSimpleName()) - && !Objects.equals(typeContext.getPackage(), ref.getPackage())) { - return true; - } - if (typeContext.isNameConflict(ref.getSimpleName())) { - return true; - } - } - return false; - } else { - return true; - } - } - - - @Override - public void visitCtIntersectionTypeReference(CtIntersectionTypeReference reference) { - for (CtTypeReference bound : reference.getBounds()) { - scan(bound); - printer.write(" & "); - } - printer.removeLastChar(); - } - - @Override - public void visitCtTypeReference(CtTypeReference ref) { - visitCtTypeReference(ref, true); - } - - @Override - public void visitCtTypeAccess(CtTypeAccess typeAccess) { - if (typeAccess.isImplicit()) { - return; - } - enterCtExpression(typeAccess); - scan(typeAccess.getAccessedType()); - exitCtExpression(typeAccess); - } - - private void visitCtTypeReferenceWithoutGenerics(CtTypeReference ref) { - visitCtTypeReference(ref, false); - } - - private void visitCtTypeReference(CtTypeReference ref, boolean withGenerics) { - if (ref.isImplicit()) { - return; - } - if (ref.isPrimitive()) { - elementPrinterHelper.writeAnnotations(ref); - printer.write(ref.getSimpleName()); - return; - } - boolean isInner = ref.getDeclaringType() != null; - if (isInner) { - if (!context.ignoreEnclosingClass() && !ref.isLocalType()) { - //compute visible type which can be used to print access path to ref - CtTypeReference accessType = ref.getAccessType(); - if (!accessType.isAnonymous()) { - try (Writable _context = context.modify()) { - if (!withGenerics) { - _context.ignoreGenerics(true); - } - scan(accessType); - } - printer.write("."); - } - } - //?? are these annotations on correct place ?? - elementPrinterHelper.writeAnnotations(ref); - if (ref.isLocalType()) { - printer.write(ref.getSimpleName().replaceAll("^[0-9]*", "")); - } else { - printer.write(ref.getSimpleName()); - } - } else { - if (ref.getPackage() != null && printQualified(ref)) { - if (!ref.getPackage().isUnnamedPackage()) { - scan(ref.getPackage()); - printer.write(CtPackage.PACKAGE_SEPARATOR); - } - } - elementPrinterHelper.writeAnnotations(ref); - printer.write(ref.getSimpleName()); - } - if (withGenerics && !context.ignoreGenerics()) { - try (Writable _context = context.modify().ignoreEnclosingClass(false)) { - elementPrinterHelper.writeActualTypeArguments(ref); - } - } - } - - @Override - public void visitCtUnaryOperator(CtUnaryOperator operator) { - enterCtStatement(operator); - enterCtExpression(operator); - printer.preWriteUnaryOperator(operator.getKind()); - scan(operator.getOperand()); - printer.postWriteUnaryOperator(operator.getKind()); - exitCtExpression(operator); - } - - @Override - public void visitCtVariableRead(CtVariableRead variableRead) { - enterCtExpression(variableRead); - printer.write(variableRead.getVariable().getSimpleName()); - exitCtExpression(variableRead); - } - - @Override - public void visitCtVariableWrite(CtVariableWrite variableWrite) { - enterCtExpression(variableWrite); - printer.write(variableWrite.getVariable().getSimpleName()); - exitCtExpression(variableWrite); - } - - public void visitCtWhile(CtWhile whileLoop) { - enterCtStatement(whileLoop); - printer.write("while ("); - scan(whileLoop.getLoopingExpression()); - printer.write(")"); - - elementPrinterHelper.writeIfOrLoopBlock(whileLoop.getBody()); - } - - @Override - public void visitCtCodeSnippetExpression(CtCodeSnippetExpression expression) { - elementPrinterHelper.writeComment(expression); - printer.write(expression.getValue()); - } - - @Override - public void visitCtCodeSnippetStatement(CtCodeSnippetStatement statement) { - elementPrinterHelper.writeComment(statement); - printer.write(statement.getValue()); - } - - public ElementPrinterHelper getElementPrinterHelper() { - return elementPrinterHelper; - } - - public PrintingContext getContext() { - return context; - } - - @Override - public void visitCtUnboundVariableReference(CtUnboundVariableReference reference) { - printer.write(reference.getSimpleName()); - } - - @Override - public String getPackageDeclaration() { - return printPackageInfo(context.currentTopLevel.getPackage()); - } - - @Override - public String printPackageInfo(CtPackage pack) { - PrinterHelper bck = printer; - ElementPrinterHelper bck2 = elementPrinterHelper; - printer = new PrinterHelper(env); - elementPrinterHelper = new ElementPrinterHelper(printer, this, env); - - elementPrinterHelper.writeComment(pack); - - for (CtAnnotation a : pack.getAnnotations()) { - a.accept(this); - } - - if (!pack.isUnnamedPackage()) { - printer.write("package " + pack.getQualifiedName() + ";"); - } - String ret = printer.toString(); - elementPrinterHelper = bck2; - printer = bck; - - return ret; - } - - @Override - public String getResult() { - return printer.toString(); - } - - @Override - public void reset() { - printer = new PrinterHelper(env); - elementPrinterHelper.setPrinter(printer); - context = new PrintingContext(); - if (env.isAutoImports()) { - this.importsContext = new ImportScannerImpl(); - } else { - this.importsContext = new MinimalImportScanner(); - } - } - - @Override - public void calculate(CompilationUnit sourceCompilationUnit, List> types) { - this.sourceCompilationUnit = sourceCompilationUnit; - - // reset the importsContext to avoid errors with multiple CU - if (env.isAutoImports()) { - this.importsContext = new ImportScannerImpl(); - } else { - this.importsContext = new MinimalImportScanner(); - } - - Set imports = new HashSet<>(); - for (CtType t : types) { - imports.addAll(computeImports(t)); - } - elementPrinterHelper.writeHeader(types, imports); - for (CtType t : types) { - scan(t); - if (!env.isPreserveLineNumbers()) { - // saving lines and chars - printer.writeln().writeln().writeTabs(); - } else { - printer.adjustEndPosition(t); - } - } - } - - @Override - public Map getLineNumberMapping() { - return printer.getLineNumberMapping(); - } + final CtField field = f.getVariable().getFieldDeclaration(); + final String fieldName = field.getSimpleName(); + CtVariable var = f.getVariable().map(new PotentialVariableDeclarationFunction(fieldName)).first(); + if (var != field) { + //another variable declaration was found which is hiding the field declaration for this field access. Make the field access expicit + target.setImplicit(false); + } + } + printer.snapshotLength(); + scan(target); + if (printer.hasNewContent()) { + printer.write("."); + } + } + _context.ignoreStaticAccess(true); + } + scan(f.getVariable()); + } + exitCtExpression(f); + } + + /** + * Check if the target expression is a static final field initialized in a static anonymous block. + */ + private boolean isInitializeStaticFinalField(CtExpression targetExp) { + final CtElement parent; + final CtAnonymousExecutable anonymousParent; + try { + parent = targetExp.getParent(); + anonymousParent = targetExp.getParent(CtAnonymousExecutable.class); + } catch (ParentNotInitializedException e) { + return false; + } + if (parent instanceof CtFieldWrite + && targetExp.equals(((CtFieldWrite) parent).getTarget()) + && anonymousParent != null + && ((CtFieldWrite) parent).getVariable() != null + && ((CtFieldWrite) parent).getVariable().getModifiers().contains(ModifierKind.STATIC) + && ((CtFieldWrite) parent).getVariable().getModifiers().contains(ModifierKind.FINAL)) { + return true; + } + return false; + } + + @Override + public void visitCtThisAccess(CtThisAccess thisAccess) { + try { + enterCtExpression(thisAccess); + + // we only write qualified this when this is required + // this is good both in fully-qualified mode and in readable (with-imports) mode + // the implicit information is used for analysis (eg are visibility caused by implicit bugs?) but + // not for pretty-printing + CtTypeAccess target = (CtTypeAccess) thisAccess.getTarget(); + CtTypeReference targetType = target.getAccessedType(); + + // readable mode as close as possible to the original code + if (thisAccess.isImplicit()) { + // write nothing, "this" is implicit and we unfortunately cannot always know + // what the good target is in JDTTreeBuilder + return; + } + + // the simplest case: we always print "this" if we're in the top-level class, + // this is shorter (no qualified this), explicit, and less fragile wrt transformation + if (targetType == null || (thisAccess.getParent(CtType.class) != null && thisAccess.getParent(CtType.class).isTopLevel())) { + printer.write("this"); + return; // still go through finally block below + } + + // we cannot have fully-qualified this in anonymous classes + // we simply print "this" and it always works + // this has to come after the implicit test just before + if (targetType.isAnonymous()) { + printer.write("this"); + return; + } + + // complex case of qualifed this + if (!context.currentThis.isEmpty()) { + + CtType lastType = context.currentThis.peekFirst().type; + String lastTypeQualifiedName = lastType.getQualifiedName(); + String targetTypeQualifiedName = targetType.getQualifiedName(); + + if (!lastTypeQualifiedName.equals(targetTypeQualifiedName)) { + printer.snapshotLength(); + visitCtTypeReferenceWithoutGenerics(targetType); + if (printer.hasNewContent()) { + printer.write("."); + } + printer.write("this"); + return; + } + } + + // the default super simple case only comes at the end + printer.write("this"); + } finally { + exitCtExpression(thisAccess); + } + } + + @Override + public void visitCtSuperAccess(CtSuperAccess f) { + enterCtExpression(f); + if (f.getTarget() != null) { + scan(f.getTarget()); + printer.write("."); + } + printer.write("super"); + + exitCtExpression(f); + } + + @Override + public void visitCtJavaDoc(CtJavaDoc comment) { + visitCtComment(comment); + } + + @Override + public void visitCtJavaDocTag(CtJavaDocTag docTag) { + printer.write(COMMENT_STAR); + printer.write(CtJavaDocTag.JAVADOC_TAG_PREFIX); + printer.write(docTag.getType().name().toLowerCase()); + printer.write(" "); + if (docTag.getType().hasParam()) { + printer.write(docTag.getParam()).writeln().writeTabs(); + } + + String[] tagLines = docTag.getContent().split(LINE_SEPARATOR); + for (int i = 0; i < tagLines.length; i++) { + String com = tagLines[i]; + if (i > 0 || docTag.getType().hasParam()) { + printer.write(COMMENT_STAR); + } + if (docTag.getType().hasParam()) { + printer.write("\t\t"); + } + printer.write(com.trim()).writeln().writeTabs(); + } + } + + @Override + public void visitCtComment(CtComment comment) { + if (!env.isCommentsEnabled() && context.elementStack.size() > 1) { + return; + } + switch (comment.getCommentType()) { + case FILE: + printer.write(JAVADOC_START).writeln(); + break; + case JAVADOC: + printer.write(JAVADOC_START).writeln().writeTabs(); + break; + case INLINE: + printer.write(INLINE_COMMENT_START); + break; + case BLOCK: + printer.write(BLOCK_COMMENT_START); + break; + } + String content = comment.getContent(); + switch (comment.getCommentType()) { + case INLINE: + printer.write(content); + break; + default: + String[] lines = content.split(LINE_SEPARATOR); + for (int i = 0; i < lines.length; i++) { + String com = lines[i]; + if (comment.getCommentType() == CtComment.CommentType.BLOCK) { + printer.write(com); + if (lines.length > 1) { + printer.writeln().writeTabs(); + } + } else { + if (com.length() > 0) { + printer.write(COMMENT_STAR + com).writeln().writeTabs(); + } else { + printer.write(" *" /* no trailing space */ + com).writeln().writeTabs(); + } + } + + } + if (comment instanceof CtJavaDoc) { + if (!((CtJavaDoc) comment).getTags().isEmpty()) { + printer.write(" *").writeln().writeTabs(); + } + for (CtJavaDocTag docTag : ((CtJavaDoc) comment).getTags()) { + scan(docTag); + } + } + break; + } + + switch (comment.getCommentType()) { + case BLOCK: + printer.write(BLOCK_COMMENT_END); + break; + case FILE: + printer.write(BLOCK_COMMENT_END); + break; + case JAVADOC: + printer.write(BLOCK_COMMENT_END); + break; + } + } + + @Override + public void visitCtAnnotationFieldAccess(CtAnnotationFieldAccess annotationFieldAccess) { + enterCtExpression(annotationFieldAccess); + try (Writable _context = context.modify()) { + if (annotationFieldAccess.getTarget() != null) { + scan(annotationFieldAccess.getTarget()); + printer.write("."); + _context.ignoreStaticAccess(true); + } + _context.ignoreGenerics(true); + scan(annotationFieldAccess.getVariable()); + printer.write("()"); + } + exitCtExpression(annotationFieldAccess); + } + + @Override + public void visitCtFieldReference(CtFieldReference reference) { + boolean isStatic = reference.getSimpleName().equals("class") || !reference.getSimpleName().equals("super") && reference.isStatic(); + + boolean printType = true; + + if (reference.isFinal() && reference.isStatic()) { + CtTypeReference declTypeRef = reference.getDeclaringType(); + if (declTypeRef.isAnonymous()) { + //never print anonymous class ref + printType = false; + } else { + if (context.isInCurrentScope(declTypeRef)) { + //do not printType if we are in scope of that type + printType = false; + } + } + } + + if (isStatic && printType && !context.ignoreStaticAccess()) { + try (Writable _context = context.modify().ignoreGenerics(true)) { + scan(reference.getDeclaringType()); + } + printer.write("."); + } + printer.write(reference.getSimpleName()); + } + + @Override + public void visitCtFor(CtFor forLoop) { + enterCtStatement(forLoop); + printer.write("for ("); + List st = forLoop.getForInit(); + if (st.size() > 0) { + scan(st.get(0)); + } + if (st.size() > 1) { + try (Writable _context = context.modify().noTypeDecl(true)) { + for (int i = 1; i < st.size(); i++) { + printer.write(", "); + scan(st.get(i)); + } + } + } + printer.write("; "); + scan(forLoop.getExpression()); + printer.write(";"); + if (!forLoop.getForUpdate().isEmpty()) { + printer.write(" "); + } + for (CtStatement s : forLoop.getForUpdate()) { + scan(s); + printer.write(" , "); + } + if (forLoop.getForUpdate().size() > 0) { + printer.removeLastChar(); + } + printer.write(")"); + elementPrinterHelper.writeIfOrLoopBlock(forLoop.getBody()); + } + + @Override + public void visitCtForEach(CtForEach foreach) { + enterCtStatement(foreach); + printer.write("for ("); + scan(foreach.getVariable()); + printer.write(" : "); + scan(foreach.getExpression()); + printer.write(")"); + elementPrinterHelper.writeIfOrLoopBlock(foreach.getBody()); + } + + @Override + public void visitCtIf(CtIf ifElement) { + enterCtStatement(ifElement); + printer.write("if ("); + scan(ifElement.getCondition()); + printer.write(")"); + elementPrinterHelper.writeIfOrLoopBlock(ifElement.getThenStatement()); + if (ifElement.getElseStatement() != null) { + List comments = elementPrinterHelper.getComments(ifElement, CommentOffset.INSIDE); + for (CtComment comment : comments) { + SourcePosition thenPosition = + ifElement.getThenStatement().getPosition() == null ? ((CtBlock) ifElement.getThenStatement()).getStatement(0).getPosition() : ifElement.getThenStatement().getPosition(); + if (comment.getPosition().getSourceStart() > thenPosition.getSourceEnd()) { + elementPrinterHelper.writeComment(comment); + } + } + printer.write("else"); + elementPrinterHelper.writeIfOrLoopBlock(ifElement.getElseStatement()); + } + } + + @Override + public void visitCtInterface(CtInterface intrface) { + visitCtType(intrface); + printer.write("interface " + intrface.getSimpleName()); + if (intrface.getFormalCtTypeParameters() != null) { + elementPrinterHelper.writeFormalTypeParameters(intrface); + } + + if (intrface.getSuperInterfaces().size() > 0) { + printer.write(" extends "); + for (CtTypeReference ref : intrface.getSuperInterfaces()) { + scan(ref); + printer.write(" , "); + } + printer.removeLastChar(); + } + context.pushCurrentThis(intrface); + printer.write(" {").incTab(); + // Content + elementPrinterHelper.writeElementList(intrface.getTypeMembers()); + printer.decTab().writeTabs().write("}"); + context.popCurrentThis(); + } + + @Override + public void visitCtInvocation(CtInvocation invocation) { + enterCtStatement(invocation); + enterCtExpression(invocation); + if (invocation.getExecutable().isConstructor()) { + // It's a constructor (super or this) + elementPrinterHelper.writeActualTypeArguments(invocation.getExecutable()); + CtType parentType; + try { + parentType = invocation.getParent(CtType.class); + } catch (ParentNotInitializedException e) { + parentType = null; + } + if (parentType != null && parentType.getQualifiedName() != null && parentType.getQualifiedName().equals(invocation.getExecutable().getDeclaringType().getQualifiedName())) { + printer.write("this"); + } else { + printer.snapshotLength(); + scan(invocation.getTarget()); + if (printer.hasNewContent()) { + printer.write("."); + } + printer.write("super"); + } + } else { + // It's a method invocation + printer.snapshotLength(); + try (Writable _context = context.modify()) { + if (invocation.getTarget() instanceof CtTypeAccess) { + _context.ignoreGenerics(true); + } + scan(invocation.getTarget()); + } + if (printer.hasNewContent()) { + printer.write("."); + } + + elementPrinterHelper.writeActualTypeArguments(invocation); + if (env.isPreserveLineNumbers()) { + printer.adjustStartPosition(invocation); + } + printer.write(invocation.getExecutable().getSimpleName()); + } + printer.write("("); + boolean remove = false; + for (CtExpression e : invocation.getArguments()) { + scan(e); + printer.write(", "); + remove = true; + } + if (remove) { + printer.removeLastChar(); + } + printer.write(")"); + exitCtExpression(invocation); + } + + @Override + public void visitCtLiteral(CtLiteral literal) { + enterCtExpression(literal); + if (literal.getValue() == null) { + printer.write("null"); + } else if (literal.getValue() instanceof Long) { + printer.write(literal.getValue() + "L"); + } else if (literal.getValue() instanceof Float) { + printer.write(literal.getValue() + "F"); + } else if (literal.getValue() instanceof Character) { + printer.write("'"); + + boolean mayContainsSpecialCharacter = true; + + SourcePosition position = literal.getPosition(); + if (position != null) { + // the size of the string in the source code, the -1 is the size of the ' or " in the source code + int stringLength = position.getSourceEnd() - position.getSourceStart() - 1; + // if the string in the source is not the same as the string in the literal, the string may contains special characters + mayContainsSpecialCharacter = stringLength != 1; + } + printer.writeCharLiteral((Character) literal.getValue(), mayContainsSpecialCharacter); + + printer.write("'"); + } else if (literal.getValue() instanceof String) { + printer.write('\"'); + + boolean mayContainsSpecialCharacters = true; + + SourcePosition position = literal.getPosition(); + if (position != null) { + // the size of the string in the source code, the -1 is the size of the ' or " in the source code + int stringLength = position.getSourceEnd() - position.getSourceStart() - 1; + // if the string in the source is not the same as the string in the literal, the string may contains special characters + mayContainsSpecialCharacters = ((String) literal.getValue()).length() != stringLength; + } + printer.writeStringLiteral((String) literal.getValue(), mayContainsSpecialCharacters); + + printer.write('\"'); + } else if (literal.getValue() instanceof Class) { + printer.write(((Class) literal.getValue()).getName()); + } else { + printer.write(literal.getValue().toString()); + } + exitCtExpression(literal); + } + + @Override + public void visitCtLocalVariable(CtLocalVariable localVariable) { + if (!context.noTypeDecl()) { + enterCtStatement(localVariable); + } + if (env.isPreserveLineNumbers()) { + printer.adjustStartPosition(localVariable); + } + if (!context.noTypeDecl()) { + elementPrinterHelper.writeModifiers(localVariable); + scan(localVariable.getType()); + printer.write(" "); + } + printer.write(localVariable.getSimpleName()); + if (localVariable.getDefaultExpression() != null) { + printer.write(" = "); + scan(localVariable.getDefaultExpression()); + } + } + + @Override + public void visitCtLocalVariableReference(CtLocalVariableReference reference) { + printer.write(reference.getSimpleName()); + } + + @Override + public void visitCtCatchVariable(CtCatchVariable catchVariable) { + if (env.isPreserveLineNumbers()) { + printer.adjustStartPosition(catchVariable); + } + elementPrinterHelper.writeModifiers(catchVariable); + scan(catchVariable.getType()); + printer.write(" "); + printer.write(catchVariable.getSimpleName()); + } + + @Override + public void visitCtCatchVariableReference(CtCatchVariableReference reference) { + printer.write(reference.getSimpleName()); + } + + @Override + public void visitCtMethod(CtMethod m) { + elementPrinterHelper.writeComment(m); + elementPrinterHelper.visitCtNamedElement(m, sourceCompilationUnit); + elementPrinterHelper.writeModifiers(m); + if (m.isDefaultMethod()) { + printer.write("default "); + } + elementPrinterHelper.writeFormalTypeParameters(m); + if (m.getFormalCtTypeParameters().size() > 0) { + printer.write(' '); + } + try (Writable _context = context.modify().ignoreGenerics(false)) { + scan(m.getType()); + } + printer.write(" "); + printer.write(m.getSimpleName()); + elementPrinterHelper.writeExecutableParameters(m); + elementPrinterHelper.writeThrowsClause(m); + if (m.getBody() != null) { + printer.write(" "); + scan(m.getBody()); + if (m.getBody().getPosition() != null) { + if (m.getBody().getPosition().getCompilationUnit() == sourceCompilationUnit) { + if (m.getBody().getStatements().isEmpty() || !(m.getBody().getStatements().get(m.getBody().getStatements().size() - 1) instanceof CtReturn)) { + printer.putLineNumberMapping(m.getBody().getPosition().getEndLine()); + } + } else { + printer.undefineLine(); + } + } else { + printer.undefineLine(); + } + } else { + printer.write(";"); + } + } + + @Override + public void visitCtAnnotationMethod(CtAnnotationMethod annotationMethod) { + elementPrinterHelper.writeComment(annotationMethod); + elementPrinterHelper.visitCtNamedElement(annotationMethod, sourceCompilationUnit); + elementPrinterHelper.writeModifiers(annotationMethod); + scan(annotationMethod.getType()); + printer.write(" "); + printer.write(annotationMethod.getSimpleName()); + + printer.write("()"); + if (annotationMethod.getDefaultExpression() != null) { + printer.write(" default "); + scan(annotationMethod.getDefaultExpression()); + } + printer.write(";"); + } + + @Override + @SuppressWarnings("rawtypes") + public void visitCtNewArray(CtNewArray newArray) { + enterCtExpression(newArray); + boolean isNotInAnnotation; + try { + isNotInAnnotation = (newArray.getParent(CtAnnotationType.class) == null) && (newArray.getParent(CtAnnotation.class) == null); + } catch (ParentNotInitializedException e) { + isNotInAnnotation = true; + } + + if (isNotInAnnotation) { + CtTypeReference ref = newArray.getType(); + + if (ref != null) { + printer.write("new "); + } + + try (Writable _context = context.modify().skipArray(true)) { + scan(ref); + } + for (int i = 0; ref instanceof CtArrayTypeReference; i++) { + printer.write("["); + if (newArray.getDimensionExpressions().size() > i) { + CtExpression e = newArray.getDimensionExpressions().get(i); + scan(e); + } + printer.write("]"); + ref = ((CtArrayTypeReference) ref).getComponentType(); + } + } + if (newArray.getDimensionExpressions().size() == 0) { + printer.write("{ "); + List> l_elements = newArray.getElements(); + for (int i = 0; i < l_elements.size(); i++) { + CtExpression e = l_elements.get(i); + scan(e); + printer.write(" , "); + if (i + 1 == l_elements.size()) { + printer.removeLastChar(); + // if the last element c + List comments = elementPrinterHelper.getComments(e, CommentOffset.AFTER); + // if the last element contains an inline comment, print a new line before closing the array + if (!comments.isEmpty() && comments.get(comments.size() - 1).getCommentType() == CtComment.CommentType.INLINE) { + printer.writeln(); + } + } + } + + elementPrinterHelper.writeComment(newArray, CommentOffset.INSIDE); + printer.write(" }"); + } + elementPrinterHelper.writeComment(newArray, CommentOffset.AFTER); + exitCtExpression(newArray); + } + + + @Override + public void visitCtConstructorCall(CtConstructorCall ctConstructorCall) { + enterCtStatement(ctConstructorCall); + enterCtExpression(ctConstructorCall); + + printConstructorCall(ctConstructorCall); + + exitCtExpression(ctConstructorCall); + } + + @Override + public void visitCtNewClass(CtNewClass newClass) { + enterCtStatement(newClass); + enterCtExpression(newClass); + + printConstructorCall(newClass); + + scan(newClass.getAnonymousClass()); + exitCtExpression(newClass); + } + + private void printConstructorCall(CtConstructorCall ctConstructorCall) { + try (Writable _context = context.modify()) { + if (ctConstructorCall.getTarget() != null) { + scan(ctConstructorCall.getTarget()); + printer.write("."); + _context.ignoreEnclosingClass(true); + } + + if (hasDeclaringTypeWithGenerics(ctConstructorCall.getType())) { + _context.ignoreEnclosingClass(true); + } + + printer.write("new "); + + if (ctConstructorCall.getActualTypeArguments().size() > 0) { + elementPrinterHelper.writeActualTypeArguments(ctConstructorCall); + } + + scan(ctConstructorCall.getType()); + } + + printer.write("("); + for (CtCodeElement exp : ctConstructorCall.getArguments()) { + scan(exp); + printer.write(", "); + } + if (ctConstructorCall.getArguments().size() > 0) { + printer.removeLastChar(); + } + printer.write(")"); + } + + /** + * JDT doesn't support new Foo.Bar(). To avoid reprint this kind of type reference, + * we check that the reference has a declaring type with generics. + * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=474593 + * + * @param reference + * Type reference concerned by the bug. + * @return true if a declaring type have generic types. + */ + private boolean hasDeclaringTypeWithGenerics(CtTypeReference reference) { + // We don't have a declaring type, it can't have generics. + if (reference == null) { + return false; + } + // If the declaring type isn't a type, we don't need this hack. + if (reference.getDeclaringType() == null) { + return false; + } + // If current reference is a class declared in a method, we don't need this hack. + if (reference.isLocalType()) { + return false; + } + // If declaring type have generics, we return true. + if (reference.getDeclaringType().getActualTypeArguments().size() != 0) { + return true; + } + // Checks if the declaring type has generic types. + return hasDeclaringTypeWithGenerics(reference.getDeclaringType()); + } + + @Override + public void visitCtLambda(CtLambda lambda) { + enterCtExpression(lambda); + + printer.write("("); + if (lambda.getParameters().size() > 0) { + for (CtParameter parameter : lambda.getParameters()) { + scan(parameter); + printer.write(","); + } + printer.removeLastChar(); + } + printer.write(") -> "); + + if (lambda.getBody() != null) { + scan(lambda.getBody()); + } else { + scan(lambda.getExpression()); + } + exitCtExpression(lambda); + } + + @Override + public > void visitCtExecutableReferenceExpression(CtExecutableReferenceExpression expression) { + enterCtExpression(expression); + scan(expression.getTarget()); + printer.write("::"); + if (expression.getExecutable().isConstructor()) { + printer.write("new"); + } else { + printer.write(expression.getExecutable().getSimpleName()); + } + exitCtExpression(expression); + } + + @Override + public void visitCtOperatorAssignment(CtOperatorAssignment assignment) { + enterCtStatement(assignment); + enterCtExpression(assignment); + scan(assignment.getAssigned()); + printer.write(" "); + printer.writeOperator(assignment.getKind()); + printer.write("= "); + scan(assignment.getAssignment()); + exitCtExpression(assignment); + } + + @Override + public void visitCtPackage(CtPackage ctPackage) { + if (!ctPackage.isUnnamedPackage()) { + printer.write("package " + ctPackage.getQualifiedName() + ";"); + } else { + printer.write("// default package (CtPackage.TOP_LEVEL_PACKAGE_NAME in Spoon= unnamed package)\n"); + } + } + + @Override + public void visitCtPackageReference(CtPackageReference reference) { + printer.write(reference.getSimpleName()); + } + + @Override + public void visitCtParameter(CtParameter parameter) { + elementPrinterHelper.writeComment(parameter); + elementPrinterHelper.writeAnnotations(parameter); + elementPrinterHelper.writeModifiers(parameter); + if (parameter.isVarArgs()) { + scan(((CtArrayTypeReference) parameter.getType()).getComponentType()); + printer.write("..."); + } else { + scan(parameter.getType()); + } + printer.write(" "); + printer.write(parameter.getSimpleName()); + } + + @Override + public void visitCtParameterReference(CtParameterReference reference) { + printer.write(reference.getSimpleName()); + } + + @Override + public void visitCtReturn(CtReturn returnStatement) { + enterCtStatement(returnStatement); + printer.write("return "); + scan(returnStatement.getReturnedExpression()); + } + + private void visitCtType(CtType type) { + elementPrinterHelper.writeComment(type, CommentOffset.BEFORE); + printer.mapLine(type, sourceCompilationUnit); + if (type.isTopLevel()) { + context.currentTopLevel = type; + } + elementPrinterHelper.visitCtNamedElement(type, sourceCompilationUnit); + elementPrinterHelper.writeModifiers(type); + } + + @Override + public void visitCtStatementList(CtStatementList statements) { + for (CtStatement s : statements.getStatements()) { + scan(s); + } + } + + @Override + public void visitCtSwitch(CtSwitch switchStatement) { + enterCtStatement(switchStatement); + printer.write("switch ("); + scan(switchStatement.getSelector()); + printer.write(") {").incTab(); + for (CtCase c : switchStatement.getCases()) { + printer.writeln().writeTabs(); + scan(c); + } + if (env.isPreserveLineNumbers()) { + printer.decTab().write("}"); + } else { + printer.decTab().writeln().writeTabs().write("}"); + } + } + + @Override + public void visitCtSynchronized(CtSynchronized synchro) { + enterCtStatement(synchro); + printer.write("synchronized"); + if (synchro.getExpression() != null) { + printer.write("("); + scan(synchro.getExpression()); + printer.write(") "); + } + scan(synchro.getBlock()); + } + + @Override + public void visitCtThrow(CtThrow throwStatement) { + enterCtStatement(throwStatement); + printer.write("throw "); + scan(throwStatement.getThrownExpression()); + } + + @Override + public void visitCtTry(CtTry tryBlock) { + enterCtStatement(tryBlock); + printer.write("try "); + scan(tryBlock.getBody()); + for (CtCatch c : tryBlock.getCatchers()) { + scan(c); + } + + if (tryBlock.getFinalizer() != null) { + printer.write(" finally "); + scan(tryBlock.getFinalizer()); + } + } + + @Override + public void visitCtTryWithResource(CtTryWithResource tryWithResource) { + enterCtStatement(tryWithResource); + printer.write("try "); + if (tryWithResource.getResources() != null && !tryWithResource.getResources().isEmpty()) { + printer.write("("); + for (CtLocalVariable r : tryWithResource.getResources()) { + scan(r); + printer.write(";"); + } + printer.removeLastChar(); + printer.write(") "); + } + scan(tryWithResource.getBody()); + for (CtCatch c : tryWithResource.getCatchers()) { + scan(c); + } + + if (tryWithResource.getFinalizer() != null) { + printer.write(" finally "); + scan(tryWithResource.getFinalizer()); + } + } + + @Override + public void visitCtTypeParameterReference(CtTypeParameterReference ref) { + if (ref.isImplicit()) { + return; + } + elementPrinterHelper.writeAnnotations(ref); + if (printQualified(ref)) { + printer.write(ref.getQualifiedName()); + } else { + printer.write(ref.getSimpleName()); + } + } + + @Override + public void visitCtWildcardReference(CtWildcardReference wildcardReference) { + if (wildcardReference.isImplicit()) { + return; + } + elementPrinterHelper.writeAnnotations(wildcardReference); + if (printQualified(wildcardReference)) { + printer.write(wildcardReference.getQualifiedName()); + } else { + printer.write(wildcardReference.getSimpleName()); + } + if (wildcardReference.getBoundingType() != null) { + if (wildcardReference.isUpper()) { + printer.write(" extends "); + } else { + printer.write(" super "); + } + scan(wildcardReference.getBoundingType()); + } + } + + private boolean printQualified(CtTypeReference ref) { + if (importsContext.isImported(ref) || (this.env.isAutoImports() && ref.getPackage() != null && ref.getPackage().getSimpleName().equals("java.lang"))) { + // If my.pkg.Something is imported, but + //A) we are in the context of a class which is also called "Something", + //B) we are in the context of a class which defines field which is also called "Something", + // we should still use qualified version my.pkg.Something + for (TypeContext typeContext : context.currentThis) { + if (typeContext.getSimpleName().equals(ref.getSimpleName()) + && !Objects.equals(typeContext.getPackage(), ref.getPackage())) { + return true; + } + if (typeContext.isNameConflict(ref.getSimpleName())) { + return true; + } + } + return false; + } else { + return true; + } + } + + + @Override + public void visitCtIntersectionTypeReference(CtIntersectionTypeReference reference) { + for (CtTypeReference bound : reference.getBounds()) { + scan(bound); + printer.write(" & "); + } + printer.removeLastChar(); + } + + @Override + public void visitCtTypeReference(CtTypeReference ref) { + visitCtTypeReference(ref, true); + } + + @Override + public void visitCtTypeAccess(CtTypeAccess typeAccess) { + if (typeAccess.isImplicit()) { + return; + } + enterCtExpression(typeAccess); + scan(typeAccess.getAccessedType()); + exitCtExpression(typeAccess); + } + + private void visitCtTypeReferenceWithoutGenerics(CtTypeReference ref) { + visitCtTypeReference(ref, false); + } + + private void visitCtTypeReference(CtTypeReference ref, boolean withGenerics) { + if (ref.isImplicit()) { + return; + } + if (ref.isPrimitive()) { + elementPrinterHelper.writeAnnotations(ref); + printer.write(ref.getSimpleName()); + return; + } + boolean isInner = ref.getDeclaringType() != null; + if (isInner) { + if (!context.ignoreEnclosingClass() && !ref.isLocalType()) { + //compute visible type which can be used to print access path to ref + CtTypeReference accessType = ref.getAccessType(); + if (!accessType.isAnonymous()) { + try (Writable _context = context.modify()) { + if (!withGenerics) { + _context.ignoreGenerics(true); + } + scan(accessType); + } + printer.write("."); + } + } + //?? are these annotations on correct place ?? + elementPrinterHelper.writeAnnotations(ref); + if (ref.isLocalType()) { + printer.write(ref.getSimpleName().replaceAll("^[0-9]*", "")); + } else { + printer.write(ref.getSimpleName()); + } + } else { + if (ref.getPackage() != null && printQualified(ref)) { + if (!ref.getPackage().isUnnamedPackage()) { + scan(ref.getPackage()); + printer.write(CtPackage.PACKAGE_SEPARATOR); + } + } + elementPrinterHelper.writeAnnotations(ref); + printer.write(ref.getSimpleName()); + } + if (withGenerics && !context.ignoreGenerics()) { + try (Writable _context = context.modify().ignoreEnclosingClass(false)) { + elementPrinterHelper.writeActualTypeArguments(ref); + } + } + } + + @Override + public void visitCtUnaryOperator(CtUnaryOperator operator) { + enterCtStatement(operator); + enterCtExpression(operator); + printer.preWriteUnaryOperator(operator.getKind()); + scan(operator.getOperand()); + printer.postWriteUnaryOperator(operator.getKind()); + exitCtExpression(operator); + } + + @Override + public void visitCtVariableRead(CtVariableRead variableRead) { + enterCtExpression(variableRead); + printer.write(variableRead.getVariable().getSimpleName()); + exitCtExpression(variableRead); + } + + @Override + public void visitCtVariableWrite(CtVariableWrite variableWrite) { + enterCtExpression(variableWrite); + printer.write(variableWrite.getVariable().getSimpleName()); + exitCtExpression(variableWrite); + } + + public void visitCtWhile(CtWhile whileLoop) { + enterCtStatement(whileLoop); + printer.write("while ("); + scan(whileLoop.getLoopingExpression()); + printer.write(")"); + + elementPrinterHelper.writeIfOrLoopBlock(whileLoop.getBody()); + } + + @Override + public void visitCtCodeSnippetExpression(CtCodeSnippetExpression expression) { + elementPrinterHelper.writeComment(expression); + printer.write(expression.getValue()); + } + + @Override + public void visitCtCodeSnippetStatement(CtCodeSnippetStatement statement) { + elementPrinterHelper.writeComment(statement); + printer.write(statement.getValue()); + } + + public ElementPrinterHelper getElementPrinterHelper() { + return elementPrinterHelper; + } + + public PrintingContext getContext() { + return context; + } + + @Override + public void visitCtUnboundVariableReference(CtUnboundVariableReference reference) { + printer.write(reference.getSimpleName()); + } + + @Override + public String getPackageDeclaration() { + return printPackageInfo(context.currentTopLevel.getPackage()); + } + + @Override + public String printPackageInfo(CtPackage pack) { + PrinterHelper bck = printer; + ElementPrinterHelper bck2 = elementPrinterHelper; + printer = new PrinterHelper(env); + elementPrinterHelper = new ElementPrinterHelper(printer, this, env); + + elementPrinterHelper.writeComment(pack); + + for (CtAnnotation a : pack.getAnnotations()) { + a.accept(this); + } + + if (!pack.isUnnamedPackage()) { + printer.write("package " + pack.getQualifiedName() + ";"); + } + String ret = printer.toString(); + elementPrinterHelper = bck2; + printer = bck; + + return ret; + } + + @Override + public String getResult() { + return printer.toString(); + } + + @Override + public void reset() { + printer = new PrinterHelper(env); + elementPrinterHelper.setPrinter(printer); + context = new PrintingContext(); + if (env.isAutoImports()) { + this.importsContext = new ImportScannerImpl(); + } else { + this.importsContext = new MinimalImportScanner(); + } + } + + @Override + public void calculate(CompilationUnit sourceCompilationUnit, List> types) { + this.sourceCompilationUnit = sourceCompilationUnit; + + // reset the importsContext to avoid errors with multiple CU + if (env.isAutoImports()) { + this.importsContext = new ImportScannerImpl(); + } else { + this.importsContext = new MinimalImportScanner(); + } + + Set imports = new HashSet<>(); + for (CtType t : types) { + imports.addAll(computeImports(t)); + } + elementPrinterHelper.writeHeader(types, imports); + for (CtType t : types) { + scan(t); + if (!env.isPreserveLineNumbers()) { + // saving lines and chars + printer.writeln().writeln().writeTabs(); + } else { + printer.adjustEndPosition(t); + } + } + } + + @Override + public Map getLineNumberMapping() { + return printer.getLineNumberMapping(); + } } diff --git a/src/test/java/spoon/test/literal/LiteralTest.java b/src/test/java/spoon/test/literal/LiteralTest.java index 971651d64e0..375ea057537 100644 --- a/src/test/java/spoon/test/literal/LiteralTest.java +++ b/src/test/java/spoon/test/literal/LiteralTest.java @@ -22,144 +22,145 @@ import static spoon.testing.utils.ModelUtils.canBeBuilt; public class LiteralTest { - @Test - public void testCharLiteralInNoClasspath() throws Exception { - final Launcher launcher = new Launcher(); - launcher.addInputResource("./src/test/resources/noclasspath/SecondaryIndexManager.java"); - launcher.setSourceOutputDirectory("./target/literal"); - launcher.getEnvironment().setNoClasspath(true); - launcher.run(); - - final CtClass aClass = launcher.getFactory().Class().get("org.apache.cassandra.index.SecondaryIndexManager"); - TreeSet> ts = new TreeSet>(new DeepRepresentationComparator()); - - ts.addAll(aClass.getElements(new TypeFilter>(CtLiteral.class) { - @Override - public boolean matches(CtLiteral element) { - return element.getValue() instanceof Character && super.matches(element); - } - })); - - assertTrue(ts.last().getType().isPrimitive()); - assertEquals(':', ts.last().getValue()); - canBeBuilt("./target/literal", 8, true); - } - - @Test - public void testLiteralInForEachWithNoClasspath() { - Launcher runLaunch = new Launcher(); - runLaunch.getEnvironment().setNoClasspath(true); - runLaunch.addInputResource("./src/test/resources/noclasspath/LiteralInForEach.java"); - runLaunch.buildModel(); - } - @Test - public void testBuildLiternal() throws Exception { - CtType ctType = buildClass(Tacos.class); - TypeFactory typeFactory = ctType.getFactory().Type(); - - CtLiteral literal = (CtLiteral) ctType.getField("a").getDefaultExpression(); - assertEquals(0, literal.getValue()); - assertTrue(literal.getType().isPrimitive()); - assertEquals(typeFactory.INTEGER_PRIMITIVE, literal.getType()); - - - literal = (CtLiteral) ctType.getField("b").getDefaultExpression(); - assertEquals(0x0, literal.getValue()); - assertTrue(literal.getType().isPrimitive()); - assertEquals(typeFactory.INTEGER_PRIMITIVE, literal.getType()); - - - literal = (CtLiteral) ctType.getField("c").getDefaultExpression(); - assertEquals(0f, literal.getValue()); - assertTrue(literal.getType().isPrimitive()); - assertEquals(typeFactory.FLOAT_PRIMITIVE, literal.getType()); - - - literal = (CtLiteral) ctType.getField("d").getDefaultExpression(); - assertEquals(0l, literal.getValue()); - assertTrue(literal.getType().isPrimitive()); - assertEquals(typeFactory.LONG_PRIMITIVE, literal.getType()); - - - literal = (CtLiteral) ctType.getField("e").getDefaultExpression(); - assertEquals(0d, literal.getValue()); - assertTrue(literal.getType().isPrimitive()); - assertEquals(typeFactory.DOUBLE_PRIMITIVE, literal.getType()); - - - literal = (CtLiteral) ctType.getField("f").getDefaultExpression(); - assertEquals('0', literal.getValue()); - assertTrue(literal.getType().isPrimitive()); - assertEquals(typeFactory.CHARACTER_PRIMITIVE, literal.getType()); - - - literal = (CtLiteral) ctType.getField("g").getDefaultExpression(); - assertEquals("0", literal.getValue()); - assertFalse(literal.getType().isPrimitive()); - assertEquals(typeFactory.STRING, literal.getType()); - - literal = (CtLiteral) ctType.getField("h").getDefaultExpression(); - assertEquals(null, literal.getValue()); - assertFalse(literal.getType().isPrimitive()); - assertEquals(typeFactory.NULL_TYPE, literal.getType()); - - } - - @Test - public void testFactoryLiternal() { - Launcher runLaunch = new Launcher(); - Factory factory = runLaunch.getFactory(); - CodeFactory code = factory.Code(); - - CtLiteral literal = code.createLiteral(1); - assertEquals(1, literal.getValue()); - assertEquals(factory.Type().integerPrimitiveType(), literal.getType()); - - literal = code.createLiteral(new Integer(1)); - assertEquals(1, literal.getValue()); - assertEquals(factory.Type().integerPrimitiveType(), literal.getType()); - - literal = code.createLiteral(1.0); - assertEquals(1.0, literal.getValue()); - assertEquals(factory.Type().doublePrimitiveType(), literal.getType()); - - literal = code.createLiteral("literal"); - assertEquals("literal", literal.getValue()); - assertEquals(factory.Type().stringType(), literal.getType()); - } + @Test + public void testCharLiteralInNoClasspath() throws Exception { + final Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/resources/noclasspath/SecondaryIndexManager.java"); + launcher.setSourceOutputDirectory("./target/literal"); + launcher.getEnvironment().setNoClasspath(true); + launcher.run(); + + final CtClass aClass = launcher.getFactory().Class().get("org.apache.cassandra.index.SecondaryIndexManager"); + TreeSet> ts = new TreeSet>(new DeepRepresentationComparator()); - @Test - public void testEscapedString() throws Exception { + ts.addAll(aClass.getElements(new TypeFilter>(CtLiteral.class) { + @Override + public boolean matches(CtLiteral element) { + return element.getValue() instanceof Character && super.matches(element); + } + })); + + assertTrue(ts.last().getType().isPrimitive()); + assertEquals(':', ts.last().getValue()); + canBeBuilt("./target/literal", 8, true); + } + + @Test + public void testLiteralInForEachWithNoClasspath() { + Launcher runLaunch = new Launcher(); + runLaunch.getEnvironment().setNoClasspath(true); + runLaunch.addInputResource("./src/test/resources/noclasspath/LiteralInForEach.java"); + runLaunch.buildModel(); + } + + @Test + public void testBuildLiternal() throws Exception { + CtType ctType = buildClass(Tacos.class); + TypeFactory typeFactory = ctType.getFactory().Type(); + + CtLiteral literal = (CtLiteral) ctType.getField("a").getDefaultExpression(); + assertEquals(0, literal.getValue()); + assertTrue(literal.getType().isPrimitive()); + assertEquals(typeFactory.INTEGER_PRIMITIVE, literal.getType()); + + + literal = (CtLiteral) ctType.getField("b").getDefaultExpression(); + assertEquals(0x0, literal.getValue()); + assertTrue(literal.getType().isPrimitive()); + assertEquals(typeFactory.INTEGER_PRIMITIVE, literal.getType()); + + + literal = (CtLiteral) ctType.getField("c").getDefaultExpression(); + assertEquals(0f, literal.getValue()); + assertTrue(literal.getType().isPrimitive()); + assertEquals(typeFactory.FLOAT_PRIMITIVE, literal.getType()); + + + literal = (CtLiteral) ctType.getField("d").getDefaultExpression(); + assertEquals(0l, literal.getValue()); + assertTrue(literal.getType().isPrimitive()); + assertEquals(typeFactory.LONG_PRIMITIVE, literal.getType()); + + + literal = (CtLiteral) ctType.getField("e").getDefaultExpression(); + assertEquals(0d, literal.getValue()); + assertTrue(literal.getType().isPrimitive()); + assertEquals(typeFactory.DOUBLE_PRIMITIVE, literal.getType()); + + + literal = (CtLiteral) ctType.getField("f").getDefaultExpression(); + assertEquals('0', literal.getValue()); + assertTrue(literal.getType().isPrimitive()); + assertEquals(typeFactory.CHARACTER_PRIMITIVE, literal.getType()); + + + literal = (CtLiteral) ctType.getField("g").getDefaultExpression(); + assertEquals("0", literal.getValue()); + assertFalse(literal.getType().isPrimitive()); + assertEquals(typeFactory.STRING, literal.getType()); + + literal = (CtLiteral) ctType.getField("h").getDefaultExpression(); + assertEquals(null, literal.getValue()); + assertFalse(literal.getType().isPrimitive()); + assertEquals(typeFactory.NULL_TYPE, literal.getType()); + + } + + @Test + public void testFactoryLiternal() { + Launcher runLaunch = new Launcher(); + Factory factory = runLaunch.getFactory(); + CodeFactory code = factory.Code(); + + CtLiteral literal = code.createLiteral(1); + assertEquals(1, literal.getValue()); + assertEquals(factory.Type().integerPrimitiveType(), literal.getType()); + + literal = code.createLiteral(new Integer(1)); + assertEquals(1, literal.getValue()); + assertEquals(factory.Type().integerPrimitiveType(), literal.getType()); + + literal = code.createLiteral(1.0); + assertEquals(1.0, literal.getValue()); + assertEquals(factory.Type().doublePrimitiveType(), literal.getType()); + + literal = code.createLiteral("literal"); + assertEquals("literal", literal.getValue()); + assertEquals(factory.Type().stringType(), literal.getType()); + } + + @Test + public void testEscapedString() throws Exception { /* test escaped char: spoon change octal values by equivalent unicode values */ - Launcher launcher = new Launcher(); - launcher.addInputResource("./src/test/java/spoon/test/literal/testclasses/EscapedLiteral.java"); - launcher.getEnvironment().setCommentEnabled(true); - launcher.getEnvironment().setAutoImports(true); - launcher.buildModel(); - final CtClass ctClass = launcher.getFactory().Class().get("spoon.test.literal.testclasses.EscapedLiteral"); + Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/java/spoon/test/literal/testclasses/EscapedLiteral.java"); + launcher.getEnvironment().setCommentEnabled(true); + launcher.getEnvironment().setAutoImports(true); + launcher.buildModel(); + final CtClass ctClass = launcher.getFactory().Class().get("spoon.test.literal.testclasses.EscapedLiteral"); - assertTrue('\u0000' == (char)((CtLiteral)ctClass.getField("c1").getDefaultExpression()).getValue()); - assertTrue('\0' == (char)((CtLiteral)ctClass.getField("c1").getDefaultExpression()).getValue()); + assertTrue('\u0000' == (char) ((CtLiteral) ctClass.getField("c1").getDefaultExpression()).getValue()); + assertTrue('\0' == (char) ((CtLiteral) ctClass.getField("c1").getDefaultExpression()).getValue()); - assertTrue('\u0007' == (char)((CtLiteral)ctClass.getField("c2").getDefaultExpression()).getValue()); - assertTrue('\7' == (char)((CtLiteral)ctClass.getField("c2").getDefaultExpression()).getValue()); + assertTrue('\u0007' == (char) ((CtLiteral) ctClass.getField("c2").getDefaultExpression()).getValue()); + assertTrue('\7' == (char) ((CtLiteral) ctClass.getField("c2").getDefaultExpression()).getValue()); - assertTrue('\77' == (char)((CtLiteral)ctClass.getField("c3").getDefaultExpression()).getValue()); - assertTrue('?' == (char)((CtLiteral)ctClass.getField("c3").getDefaultExpression()).getValue()); + assertTrue('\77' == (char) ((CtLiteral) ctClass.getField("c3").getDefaultExpression()).getValue()); + assertTrue('?' == (char) ((CtLiteral) ctClass.getField("c3").getDefaultExpression()).getValue()); - assertTrue('\177' == (char)((CtLiteral)ctClass.getField("c4").getDefaultExpression()).getValue()); - assertTrue('\u007f' == (char)((CtLiteral)ctClass.getField("c4").getDefaultExpression()).getValue()); + assertTrue('\177' == (char) ((CtLiteral) ctClass.getField("c4").getDefaultExpression()).getValue()); + assertTrue('\u007f' == (char) ((CtLiteral) ctClass.getField("c4").getDefaultExpression()).getValue()); - assertTrue('\277' == (char)((CtLiteral)ctClass.getField("c5").getDefaultExpression()).getValue()); - assertTrue('\u00bf' == (char)((CtLiteral)ctClass.getField("c5").getDefaultExpression()).getValue()); + assertTrue('\277' == (char) ((CtLiteral) ctClass.getField("c5").getDefaultExpression()).getValue()); + assertTrue('\u00bf' == (char) ((CtLiteral) ctClass.getField("c5").getDefaultExpression()).getValue()); - assertTrue('\377' == (char)((CtLiteral)ctClass.getField("c6").getDefaultExpression()).getValue()); - assertTrue('\u00ff' == (char)((CtLiteral)ctClass.getField("c6").getDefaultExpression()).getValue()); + assertTrue('\377' == (char) ((CtLiteral) ctClass.getField("c6").getDefaultExpression()).getValue()); + assertTrue('\u00ff' == (char) ((CtLiteral) ctClass.getField("c6").getDefaultExpression()).getValue()); - assertTrue('\u0000' == (char)((CtLiteral)ctClass.getField("c7").getDefaultExpression()).getValue()); - assertTrue('\u0001' == (char)((CtLiteral)ctClass.getField("c8").getDefaultExpression()).getValue()); - assertTrue('\u0002' == (char)((CtLiteral)ctClass.getField("c9").getDefaultExpression()).getValue()); - } + assertTrue('\u0000' == (char) ((CtLiteral) ctClass.getField("c7").getDefaultExpression()).getValue()); + assertTrue('\u0001' == (char) ((CtLiteral) ctClass.getField("c8").getDefaultExpression()).getValue()); + assertTrue('\u0002' == (char) ((CtLiteral) ctClass.getField("c9").getDefaultExpression()).getValue()); + } }