Skip to content

Commit 47ca32b

Browse files
committed
SONARJAVA-1586 Execute post statement check only once for SE checks
1 parent a680947 commit 47ca32b

2 files changed

Lines changed: 86 additions & 27 deletions

File tree

java-frontend/src/main/java/org/sonar/java/se/CheckerDispatcher.java

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class CheckerDispatcher implements CheckerContext {
3333
private final JavaFileScannerContext context;
3434
private final List<SECheck> checks;
3535
private Tree syntaxNode;
36-
private int currentCheckerIndex = 0;
36+
private int currentCheckerIndex = -1;
3737
private boolean transition = false;
3838

3939
public CheckerDispatcher(ExplodedGraphWalker explodedGraphWalker, JavaFileScannerContext context, List<SECheck> checks) {
@@ -58,32 +58,7 @@ public boolean executeCheckPreStatement(Tree syntaxNode) {
5858

5959
public void executeCheckPostStatement(Tree syntaxNode) {
6060
this.syntaxNode = syntaxNode;
61-
ProgramState ps;
62-
for (SECheck checker : checks) {
63-
ps = checker.checkPostStatement(this, syntaxNode);
64-
if (ps == null) {
65-
throw new IllegalStateException("Post statement processing is not allowed to generate a sink yet!");
66-
}
67-
explodedGraphWalker.programState = ps;
68-
}
69-
}
70-
71-
private void executePost() {
72-
this.transition = false;
73-
if (currentCheckerIndex < checks.size()) {
74-
explodedGraphWalker.programState = checks.get(currentCheckerIndex).checkPostStatement(this, syntaxNode);
75-
} else {
76-
if (explodedGraphWalker.programPosition.i< explodedGraphWalker.programPosition.block.elements().size()) {
77-
explodedGraphWalker.clearStack(explodedGraphWalker.programPosition.block.elements().get(explodedGraphWalker.programPosition.i));
78-
}
79-
explodedGraphWalker.enqueue(
80-
new ExplodedGraph.ProgramPoint(explodedGraphWalker.programPosition.block, explodedGraphWalker.programPosition.i + 1),
81-
explodedGraphWalker.programState, explodedGraphWalker.node.exitPath);
82-
return;
83-
}
84-
if (!transition) {
85-
addTransition(explodedGraphWalker.programState);
86-
}
61+
addTransition(explodedGraphWalker.programState);
8762
}
8863

8964
@Override
@@ -112,6 +87,24 @@ public void addTransition(ProgramState state) {
11287
this.transition = true;
11388
}
11489

90+
private void executePost() {
91+
this.transition = false;
92+
if (currentCheckerIndex < checks.size()) {
93+
explodedGraphWalker.programState = checks.get(currentCheckerIndex).checkPostStatement(this, syntaxNode);
94+
} else {
95+
if (explodedGraphWalker.programPosition.i< explodedGraphWalker.programPosition.block.elements().size()) {
96+
explodedGraphWalker.clearStack(explodedGraphWalker.programPosition.block.elements().get(explodedGraphWalker.programPosition.i));
97+
}
98+
explodedGraphWalker.enqueue(
99+
new ExplodedGraph.ProgramPoint(explodedGraphWalker.programPosition.block, explodedGraphWalker.programPosition.i + 1),
100+
explodedGraphWalker.programState, explodedGraphWalker.node.exitPath);
101+
return;
102+
}
103+
if (!transition) {
104+
addTransition(explodedGraphWalker.programState);
105+
}
106+
}
107+
115108
@Override
116109
public Object createSink() {
117110
transition = true;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* SonarQube Java
3+
* Copyright (C) 2012-2016 SonarSource SA
4+
* mailto:contact AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.java.se;
21+
22+
import com.google.common.collect.Lists;
23+
import org.junit.Test;
24+
import org.sonar.java.cfg.CFG;
25+
import org.sonar.java.se.checks.NullDereferenceCheck;
26+
import org.sonar.java.se.checks.SECheck;
27+
import org.sonar.plugins.java.api.JavaFileScannerContext;
28+
import org.sonar.plugins.java.api.tree.Tree;
29+
30+
import java.util.List;
31+
32+
import static org.fest.assertions.Assertions.assertThat;
33+
import static org.mockito.Mockito.mock;
34+
35+
public class CheckerDispatcherTest {
36+
37+
@Test
38+
public void test_only_one_execution_of_post_statement_by_check() {
39+
List<SECheck> checks = Lists.newArrayList(new NullDereferenceCheck(), new CheckTest(), new CheckTest(), new CheckTest());
40+
CheckerDispatcher checkerDispatcher = new CheckerDispatcher(mockExplodedGraphWalker(), mock(JavaFileScannerContext.class), checks);
41+
checkerDispatcher.executeCheckPostStatement(mock(Tree.class));
42+
for (SECheck check : checks) {
43+
if(check instanceof CheckTest) {
44+
assertThat(((CheckTest) check).postStatementExecution).isEqualTo(1);
45+
}
46+
}
47+
}
48+
49+
private static ExplodedGraphWalker mockExplodedGraphWalker() {
50+
ExplodedGraphWalker explodedGraphWalker = mock(ExplodedGraphWalker.class);
51+
explodedGraphWalker.programPosition = new ExplodedGraph.ProgramPoint(new CFG.Block(1), 0);
52+
explodedGraphWalker.programState = mock(ProgramState.class);
53+
explodedGraphWalker.node = new ExplodedGraph.Node(explodedGraphWalker.programPosition, explodedGraphWalker.programState);
54+
return explodedGraphWalker;
55+
}
56+
57+
private static class CheckTest extends SECheck {
58+
int postStatementExecution = 0;
59+
60+
@Override
61+
public ProgramState checkPostStatement(CheckerContext context, Tree syntaxNode) {
62+
postStatementExecution++;
63+
return mock(ProgramState.class);
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)