Skip to content

Commit 5564c53

Browse files
gunnarmorlingagudian
authored andcommitted
mapstruct#1056 Making sure indentation level in formatting writer never goes below 0
1 parent 40fc561 commit 5564c53

7 files changed

Lines changed: 200 additions & 10 deletions

File tree

processor/src/main/java/org/mapstruct/ap/internal/writer/IndentationCorrectingWriter.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ State doHandleCharacter(char c, StateContext context) {
117117
switch ( c ) {
118118
case '{':
119119
case '(':
120-
context.indentationLevel++;
120+
context.incrementIndentationLevel();
121121
return IN_TEXT;
122122
case '}':
123123
case ')':
124-
context.indentationLevel--;
124+
context.decrementIndentationLevel();
125125
return IN_TEXT;
126126
case '\"':
127127
return IN_STRING;
@@ -139,10 +139,11 @@ State doHandleCharacter(char c, StateContext context) {
139139
*/
140140
@Override
141141
void doOnEntry(StateContext context) throws IOException {
142-
context.writer.write( getIndentation( context.indentationLevel ) );
142+
context.writer.write( getIndentation( context.getIndentationLevel() ) );
143143

144144
if ( DEBUG ) {
145-
System.out.print( new String( getIndentation( context.indentationLevel ) ).replace( " ", "_" ) );
145+
System.out.print( new String( getIndentation( context.getIndentationLevel() ) )
146+
.replace( " ", "_" ) );
146147
}
147148
}
148149

@@ -173,11 +174,11 @@ State doHandleCharacter(char c, StateContext context) {
173174
switch ( c ) {
174175
case '{':
175176
case '(':
176-
context.indentationLevel++;
177+
context.incrementIndentationLevel();
177178
return IN_TEXT;
178179
case '}':
179180
case ')':
180-
context.indentationLevel--;
181+
context.decrementIndentationLevel();
181182
return IN_TEXT;
182183
case '\"':
183184
return IN_STRING;
@@ -298,14 +299,14 @@ State doHandleCharacter(char c, StateContext context) {
298299
switch ( c ) {
299300
case '{':
300301
case '(':
301-
context.indentationLevel++;
302+
context.incrementIndentationLevel();
302303
return START_OF_LINE;
303304
case '}':
304305
if ( context.consecutiveLineBreaks > 0 ) {
305306
context.consecutiveLineBreaks = 0; // remove previous blank lines
306307
}
307308
case ')':
308-
context.indentationLevel--;
309+
context.decrementIndentationLevel();
309310
return START_OF_LINE;
310311
case '\r':
311312
return isWindows() ? IN_LINE_BREAK : AFTER_LINE_BREAK;
@@ -407,7 +408,7 @@ private static class StateContext {
407408
/**
408409
* Keeps track of the current indentation level, as implied by brace characters.
409410
*/
410-
int indentationLevel;
411+
private int indentationLevel;
411412

412413
/**
413414
* The number of consecutive line-breaks when within {@link State#AFTER_LINE_BREAK}.
@@ -423,5 +424,22 @@ void reset(char[] characters, int off) {
423424
this.lastStateChange = off;
424425
this.currentIndex = 0;
425426
}
427+
428+
void incrementIndentationLevel() {
429+
indentationLevel++;
430+
}
431+
432+
void decrementIndentationLevel() {
433+
// decrementing below 0 indicates misbalanced braces in the code, typically because too many closing braces
434+
// are given in an expression; we let that code pass through, the compiler will complain eventually about
435+
// the malformed source file
436+
if ( indentationLevel > 0 ) {
437+
indentationLevel--;
438+
}
439+
}
440+
441+
int getIndentationLevel() {
442+
return indentationLevel;
443+
}
426444
}
427445
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.test.erroneous.misbalancedbraces;
20+
21+
import org.mapstruct.Mapper;
22+
import org.mapstruct.Mapping;
23+
24+
@Mapper
25+
public interface MapperWithMalformedExpression {
26+
27+
@Mapping(target = "foo", expression = "java( Boolean.valueOf( source.foo > 0 ) ) )")
28+
Target sourceToTarget(Source source);
29+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.test.erroneous.misbalancedbraces;
20+
21+
import javax.tools.Diagnostic.Kind;
22+
23+
import org.junit.Test;
24+
import org.junit.runner.RunWith;
25+
import org.mapstruct.ap.testutil.IssueKey;
26+
import org.mapstruct.ap.testutil.WithClasses;
27+
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
28+
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
29+
import org.mapstruct.ap.testutil.compilation.annotation.DisableCheckstyle;
30+
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
31+
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
32+
33+
/**
34+
* Test for making sure that expressions with too many closing braces are passed through, letting the compiler raise an
35+
* error.
36+
*
37+
* @author Gunnar Morling
38+
*/
39+
@WithClasses({ MapperWithMalformedExpression.class, Source.class, Target.class })
40+
@DisableCheckstyle
41+
@RunWith(AnnotationProcessorTestRunner.class)
42+
public class MisbalancedBracesTest {
43+
44+
// the compiler messages due to the additional closing brace differ between JDK and Eclipse, hence we can only
45+
// assert on the line number but not the message
46+
@Test
47+
@IssueKey("1056")
48+
@ExpectedCompilationOutcome(
49+
value = CompilationResult.FAILED,
50+
diagnostics = { @Diagnostic(kind = Kind.ERROR, line = 20) }
51+
)
52+
public void expressionWithMisbalancedBracesIsPassedThrough() {
53+
}
54+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.test.erroneous.misbalancedbraces;
20+
21+
public class Source {
22+
23+
//CHECKSTYLE:OFF
24+
public int foo;
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.test.erroneous.misbalancedbraces;
20+
21+
public class Target {
22+
23+
//CHECKSTYLE:OFF
24+
public boolean foo;
25+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.ap.testutil.compilation.annotation;
20+
21+
import java.lang.annotation.ElementType;
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
24+
import java.lang.annotation.Target;
25+
26+
/**
27+
* Disables CheckStyle for the sources generated by this test.
28+
*
29+
* @author Gunnar Morling
30+
*/
31+
@Retention(RetentionPolicy.RUNTIME)
32+
@Target(ElementType.TYPE)
33+
public @interface DisableCheckstyle {
34+
}

processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.mapstruct.ap.testutil.WithServiceImplementation;
4444
import org.mapstruct.ap.testutil.WithServiceImplementations;
4545
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
46+
import org.mapstruct.ap.testutil.compilation.annotation.DisableCheckstyle;
4647
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
4748
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption;
4849
import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOptions;
@@ -78,6 +79,7 @@ abstract class CompilingStatement extends Statement {
7879

7980
private final FrameworkMethod method;
8081
private final CompilationCache compilationCache;
82+
private final boolean runCheckstyle;
8183
private Statement next;
8284

8385
private String classOutputDir;
@@ -88,6 +90,7 @@ abstract class CompilingStatement extends Statement {
8890
CompilingStatement(FrameworkMethod method, CompilationCache compilationCache) {
8991
this.method = method;
9092
this.compilationCache = compilationCache;
93+
this.runCheckstyle = !method.getMethod().getDeclaringClass().isAnnotationPresent( DisableCheckstyle.class );
9194

9295
this.compilationRequest = new CompilationRequest( getTestClasses(), getServices(), getProcessorOptions() );
9396
}
@@ -202,7 +205,9 @@ protected void generateMapperImplementation() throws Exception {
202205

203206
assertDiagnostics( actualResult.getDiagnostics(), expectedResult.getDiagnostics() );
204207

205-
assertCheckstyleRules();
208+
if ( runCheckstyle ) {
209+
assertCheckstyleRules();
210+
}
206211
}
207212

208213
private void assertCheckstyleRules() throws Exception {

0 commit comments

Comments
 (0)