Skip to content

Commit 1dcdbe6

Browse files
committed
Merge pull request #485 from GerardPaligot/feat_478
2 parents a1078e3 + 8c4cfab commit 1dcdbe6

File tree

9 files changed

+180
-35
lines changed

9 files changed

+180
-35
lines changed

doc/processor.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ of the processor class. There is also an optional overridable method for queryin
1919
elements at a finer grain.
2020

2121
The process method takes the requested element as input and does the analysis
22-
(here detecting empty catch blocks).
22+
(here detecting empty catch blocks). At any time, you can interrupt the processing
23+
of the model with a call to `interrupt()` (this stops all processors, and proceeds
24+
with the next step which is usually pretty-printing the code to disk).
2325

2426
Since a real world analysis combines multiple queries, multiple processors can
2527
be used at the same time. The launcher applies them in the order they have been declared.

src/main/java/spoon/processing/AbstractManualProcessor.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
*/
1717
package spoon.processing;
1818

19-
import java.util.Set;
20-
2119
import spoon.compiler.Environment;
2220
import spoon.reflect.declaration.CtElement;
2321
import spoon.reflect.factory.Factory;
2422

23+
import java.util.Set;
24+
2525
/**
2626
* This class defines an abstract processor to be subclassed by the user for
2727
* defining new manual processors. A manual processor should override the init
@@ -100,4 +100,9 @@ public final void setFactory(Factory factory) {
100100
public final void initProperties(ProcessorProperties properties) {
101101
AbstractProcessor.initProperties(this, properties);
102102
}
103+
104+
@Override
105+
public void interrupt() {
106+
throw new ProcessInterruption();
107+
}
103108
}

src/main/java/spoon/processing/AbstractProcessor.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@
1616
*/
1717
package spoon.processing;
1818

19-
import java.io.FileNotFoundException;
20-
import java.io.IOException;
21-
import java.lang.reflect.Field;
22-
import java.lang.reflect.Method;
23-
import java.util.HashSet;
24-
import java.util.Set;
25-
2619
import org.apache.log4j.Level;
2720
import spoon.Launcher;
2821
import spoon.compiler.Environment;
2922
import spoon.reflect.declaration.CtElement;
3023
import spoon.reflect.factory.Factory;
3124
import spoon.support.util.RtHelper;
3225

26+
import java.io.FileNotFoundException;
27+
import java.io.IOException;
28+
import java.lang.reflect.Field;
29+
import java.lang.reflect.Method;
30+
import java.util.HashSet;
31+
import java.util.Set;
32+
3333
/**
3434
* This class defines an abstract processor to be subclassed by the user for
3535
* defining new processors.
@@ -172,4 +172,8 @@ public void setFactory(Factory factory) {
172172
this.factory = factory;
173173
}
174174

175+
@Override
176+
public void interrupt() {
177+
throw new ProcessInterruption();
178+
}
175179
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (C) 2006-2015 INRIA and contributors
3+
* Spoon - http://spoon.gforge.inria.fr/
4+
*
5+
* This software is governed by the CeCILL-C License under French law and
6+
* abiding by the rules of distribution of free software. You can use, modify
7+
* and/or redistribute the software under the terms of the CeCILL-C license as
8+
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
9+
*
10+
* This program is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
13+
*
14+
* The fact that you are presently reading this means that you have had
15+
* knowledge of the CeCILL-C license and that you accept its terms.
16+
*/
17+
package spoon.processing;
18+
19+
/**
20+
* This exception is used to interrupt a processor during its processing.
21+
*/
22+
public class ProcessInterruption extends RuntimeException {
23+
public ProcessInterruption() {
24+
}
25+
26+
public ProcessInterruption(String message) {
27+
super(message);
28+
}
29+
30+
public ProcessInterruption(String message, Throwable cause) {
31+
super(message, cause);
32+
}
33+
34+
public ProcessInterruption(Throwable cause) {
35+
super(cause);
36+
}
37+
}

src/main/java/spoon/processing/Processor.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
*/
1717
package spoon.processing;
1818

19-
import java.util.Set;
20-
2119
import spoon.compiler.Environment;
2220
import spoon.reflect.declaration.CtElement;
2321

22+
import java.util.Set;
23+
2424
/**
2525
* This interface defines a generic code processor. To define a new processor,
2626
* the user should subclass {@link spoon.processing.AbstractProcessor}, the
@@ -122,4 +122,10 @@ public interface Processor<E extends CtElement> extends FactoryAccessor {
122122
*/
123123
void initProperties(ProcessorProperties properties);
124124

125+
/**
126+
* Interrupts the processing of this processor but changes on your AST are kept
127+
* and the invocation of this method doesn't interrupt the processing of all
128+
* processors specified in the {@link ProcessingManager}.
129+
*/
130+
void interrupt();
125131
}

src/main/java/spoon/support/QueueProcessingManager.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.apache.log4j.Level;
2020
import spoon.SpoonException;
2121
import spoon.processing.AbstractProcessor;
22+
import spoon.processing.ProcessInterruption;
2223
import spoon.processing.ProcessingManager;
2324
import spoon.processing.Processor;
2425
import spoon.reflect.declaration.CtElement;
@@ -105,26 +106,34 @@ protected ProcessingVisitor getVisitor() {
105106
public void process(Collection<? extends CtElement> elements) {
106107
Processor<?> p;
107108
while ((p = getProcessors().poll()) != null) {
108-
getFactory().getEnvironment().reportProgressMessage(p.getClass().getName());
109-
current = p;
110-
p.initProperties(AbstractProcessor.loadProperties(p));
111-
p.init();
112-
p.process();
113-
for (CtElement e : new ArrayList<CtElement>(elements)) {
114-
process(e, p);
109+
try {
110+
getFactory().getEnvironment().reportProgressMessage(p.getClass().getName());
111+
current = p;
112+
p.initProperties(AbstractProcessor.loadProperties(p));
113+
p.init();
114+
p.process();
115+
for (CtElement e : new ArrayList<CtElement>(elements)) {
116+
process(e, p);
117+
}
118+
} catch (ProcessInterruption ignore) {
119+
} finally {
120+
p.processingDone();
115121
}
116-
p.processingDone();
117122
}
118123
}
119124

120125
public void process(CtElement element) {
121126
Processor<?> p;
122127
while ((p = getProcessors().poll()) != null) {
123-
current = p;
124-
p.init();
125-
p.process();
126-
process(element, p);
127-
p.processingDone();
128+
try {
129+
current = p;
130+
p.init();
131+
p.process();
132+
process(element, p);
133+
} catch (ProcessInterruption ignore) {
134+
} finally {
135+
p.processingDone();
136+
}
128137
}
129138
}
130139

src/main/java/spoon/support/RuntimeProcessingManager.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@
1616
*/
1717
package spoon.support;
1818

19-
import java.util.Collection;
20-
import java.util.LinkedList;
21-
import java.util.List;
22-
2319
import org.apache.log4j.Level;
20+
import spoon.processing.ProcessInterruption;
2421
import spoon.processing.ProcessingManager;
2522
import spoon.processing.Processor;
2623
import spoon.reflect.declaration.CtElement;
@@ -29,6 +26,10 @@
2926
import spoon.support.util.Timer;
3027
import spoon.support.visitor.ProcessingVisitor;
3128

29+
import java.util.Collection;
30+
import java.util.LinkedList;
31+
import java.util.List;
32+
3233
/**
3334
* This processing manager implements a blocking processing policy that consists
3435
* of applying the processors in a FIFO order until no processors remain to be
@@ -114,13 +115,16 @@ public void process(Collection<? extends CtElement> elements) {
114115
* Recursively processes elements and their children with a given processor.
115116
*/
116117
public void process(Collection<? extends CtElement> elements, Processor<?> processor) {
117-
getFactory().getEnvironment().debugMessage("processing with '" + processor.getClass().getName() + "'...");
118-
current = processor;
119-
Timer.start(processor.getClass().getName());
120-
for (CtElement e : elements) {
121-
process(e, processor);
118+
try {
119+
getFactory().getEnvironment().debugMessage("processing with '" + processor.getClass().getName() + "'...");
120+
current = processor;
121+
Timer.start(processor.getClass().getName());
122+
for (CtElement e : elements) {
123+
process(e, processor);
124+
}
125+
Timer.stop(processor.getClass().getName());
126+
} catch (ProcessInterruption ignored) {
122127
}
123-
Timer.stop(processor.getClass().getName());
124128
}
125129

126130
public void process(CtElement element) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (C) 2006-2015 INRIA and contributors
3+
* Spoon - http://spoon.gforge.inria.fr/
4+
*
5+
* This software is governed by the CeCILL-C License under French law and
6+
* abiding by the rules of distribution of free software. You can use, modify
7+
* and/or redistribute the software under the terms of the CeCILL-C license as
8+
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
9+
*
10+
* This program is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
13+
*
14+
* The fact that you are presently reading this means that you have had
15+
* knowledge of the CeCILL-C license and that you accept its terms.
16+
*/
17+
18+
package spoon.processing;
19+
20+
import org.junit.Test;
21+
import spoon.Launcher;
22+
import spoon.processing.processors.MyProcessor;
23+
24+
import static org.junit.Assert.assertFalse;
25+
import static org.junit.Assert.fail;
26+
27+
public class ProcessingTest {
28+
@Test
29+
public void testInterruptAProcessor() throws Exception {
30+
final Launcher launcher = new Launcher();
31+
launcher.getEnvironment().setNoClasspath(true);
32+
launcher.addInputResource("./src/tets/java/spoon/processing/");
33+
launcher.setSourceOutputDirectory("./target/trash");
34+
final MyProcessor processor = new MyProcessor();
35+
launcher.addProcessor(processor);
36+
try {
37+
launcher.run();
38+
} catch (ProcessInterruption e) {
39+
fail("ProcessInterrupt exception must be catch in the ProcessingManager.");
40+
}
41+
assertFalse(processor.isShouldStayAtFalse());
42+
}
43+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (C) 2006-2015 INRIA and contributors
3+
* Spoon - http://spoon.gforge.inria.fr/
4+
*
5+
* This software is governed by the CeCILL-C License under French law and
6+
* abiding by the rules of distribution of free software. You can use, modify
7+
* and/or redistribute the software under the terms of the CeCILL-C license as
8+
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
9+
*
10+
* This program is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
13+
*
14+
* The fact that you are presently reading this means that you have had
15+
* knowledge of the CeCILL-C license and that you accept its terms.
16+
*/
17+
18+
package spoon.processing.processors;
19+
20+
import spoon.processing.AbstractProcessor;
21+
import spoon.reflect.declaration.CtElement;
22+
23+
public class MyProcessor extends AbstractProcessor<CtElement> {
24+
private boolean shouldStayAtFalse;
25+
26+
@Override
27+
public void process(CtElement element) {
28+
interrupt();
29+
shouldStayAtFalse = true;
30+
}
31+
32+
public boolean isShouldStayAtFalse() {
33+
return shouldStayAtFalse;
34+
}
35+
}

0 commit comments

Comments
 (0)