diff --git a/processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java b/processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java index c99b96af8..0ff950dc1 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java @@ -117,11 +117,11 @@ class IndentationCorrectingWriter extends Writer { switch ( c ) { case '{': case '(': - context.indentationLevel++; + context.incrementIndentationLevel(); return IN_TEXT; case '}': case ')': - context.indentationLevel--; + context.decrementIndentationLevel(); return IN_TEXT; case '\"': return IN_STRING; @@ -139,10 +139,11 @@ class IndentationCorrectingWriter extends Writer { */ @Override void doOnEntry(StateContext context) throws IOException { - context.writer.write( getIndentation( context.indentationLevel ) ); + context.writer.write( getIndentation( context.getIndentationLevel() ) ); if ( DEBUG ) { - System.out.print( new String( getIndentation( context.indentationLevel ) ).replace( " ", "_" ) ); + System.out.print( new String( getIndentation( context.getIndentationLevel() ) ) + .replace( " ", "_" ) ); } } @@ -173,11 +174,11 @@ class IndentationCorrectingWriter extends Writer { switch ( c ) { case '{': case '(': - context.indentationLevel++; + context.incrementIndentationLevel(); return IN_TEXT; case '}': case ')': - context.indentationLevel--; + context.decrementIndentationLevel(); return IN_TEXT; case '\"': return IN_STRING; @@ -298,14 +299,14 @@ class IndentationCorrectingWriter extends Writer { switch ( c ) { case '{': case '(': - context.indentationLevel++; + context.incrementIndentationLevel(); return START_OF_LINE; case '}': if ( context.consecutiveLineBreaks > 0 ) { context.consecutiveLineBreaks = 0; // remove previous blank lines } case ')': - context.indentationLevel--; + context.decrementIndentationLevel(); return START_OF_LINE; case '\r': return isWindows() ? IN_LINE_BREAK : AFTER_LINE_BREAK; @@ -407,7 +408,7 @@ class IndentationCorrectingWriter extends Writer { /** * Keeps track of the current indentation level, as implied by brace characters. */ - int indentationLevel; + private int indentationLevel; /** * The number of consecutive line-breaks when within {@link State#AFTER_LINE_BREAK}. @@ -423,5 +424,22 @@ class IndentationCorrectingWriter extends Writer { this.lastStateChange = off; this.currentIndex = 0; } + + void incrementIndentationLevel() { + indentationLevel++; + } + + void decrementIndentationLevel() { + // decrementing below 0 indicates misbalanced braces in the code, typically because too many closing braces + // are given in an expression; we let that code pass through, the compiler will complain eventually about + // the malformed source file + if ( indentationLevel > 0 ) { + indentationLevel--; + } + } + + int getIndentationLevel() { + return indentationLevel; + } } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/MapperWithMalformedExpression.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/MapperWithMalformedExpression.java new file mode 100644 index 000000000..7fb159871 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/MapperWithMalformedExpression.java @@ -0,0 +1,29 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.erroneous.misbalancedbraces; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +@Mapper +public interface MapperWithMalformedExpression { + + @Mapping(target = "foo", expression = "java( Boolean.valueOf( source.foo > 0 ) ) )") + Target sourceToTarget(Source source); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/MisbalancedBracesTest.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/MisbalancedBracesTest.java new file mode 100644 index 000000000..97353ad81 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/MisbalancedBracesTest.java @@ -0,0 +1,54 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.erroneous.misbalancedbraces; + +import javax.tools.Diagnostic.Kind; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; +import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic; +import org.mapstruct.ap.testutil.compilation.annotation.DisableCheckstyle; +import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +/** + * Test for making sure that expressions with too many closing braces are passed through, letting the compiler raise an + * error. + * + * @author Gunnar Morling + */ +@WithClasses({ MapperWithMalformedExpression.class, Source.class, Target.class }) +@DisableCheckstyle +@RunWith(AnnotationProcessorTestRunner.class) +public class MisbalancedBracesTest { + + // the compiler messages due to the additional closing brace differ between JDK and Eclipse, hence we can only + // assert on the line number but not the message + @Test + @IssueKey("1056") + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { @Diagnostic(kind = Kind.ERROR, line = 20) } + ) + public void expressionWithMisbalancedBracesIsPassedThrough() { + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/Source.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/Source.java new file mode 100644 index 000000000..be8bcbbac --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/Source.java @@ -0,0 +1,25 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.erroneous.misbalancedbraces; + +public class Source { + + //CHECKSTYLE:OFF + public int foo; +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/Target.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/Target.java new file mode 100644 index 000000000..d7fc73817 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/misbalancedbraces/Target.java @@ -0,0 +1,25 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.erroneous.misbalancedbraces; + +public class Target { + + //CHECKSTYLE:OFF + public boolean foo; +} diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/DisableCheckstyle.java b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/DisableCheckstyle.java new file mode 100644 index 000000000..ee21d4588 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/DisableCheckstyle.java @@ -0,0 +1,34 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.testutil.compilation.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Disables CheckStyle for the sources generated by this test. + * + * @author Gunnar Morling + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface DisableCheckstyle { +} diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java index fc536bf98..95b4a91e4 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java @@ -43,6 +43,7 @@ import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithServiceImplementation; import org.mapstruct.ap.testutil.WithServiceImplementations; import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; +import org.mapstruct.ap.testutil.compilation.annotation.DisableCheckstyle; import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption; import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOptions; @@ -78,6 +79,7 @@ abstract class CompilingStatement extends Statement { private final FrameworkMethod method; private final CompilationCache compilationCache; + private final boolean runCheckstyle; private Statement next; private String classOutputDir; @@ -88,6 +90,7 @@ abstract class CompilingStatement extends Statement { CompilingStatement(FrameworkMethod method, CompilationCache compilationCache) { this.method = method; this.compilationCache = compilationCache; + this.runCheckstyle = !method.getMethod().getDeclaringClass().isAnnotationPresent( DisableCheckstyle.class ); this.compilationRequest = new CompilationRequest( getTestClasses(), getServices(), getProcessorOptions() ); } @@ -202,7 +205,9 @@ abstract class CompilingStatement extends Statement { assertDiagnostics( actualResult.getDiagnostics(), expectedResult.getDiagnostics() ); - assertCheckstyleRules(); + if ( runCheckstyle ) { + assertCheckstyleRules(); + } } private void assertCheckstyleRules() throws Exception {