Skip to content

Commit 48f7834

Browse files
Jason Faustgnodet
Jason Faust
authored andcommitted
Allow -log argument for Eclipse compiler
If the -log argument is used, the resulting log file is scanned for compiler output, both text and xml formatting supported. Otherwise a temporary log file is used to capture compiler output. * Unit tests refactored * Output emitted as "INFO" are reported as Kind.NOTE * Column count adjusted to be 1-based index
1 parent 1b578f4 commit 48f7834

27 files changed

+2060
-101
lines changed

plexus-compiler-test/src/main/java/org/codehaus/plexus/compiler/AbstractCompilerTest.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@ protected List<String> getClasspath() throws Exception {
128128

129129
protected void configureCompilerConfig(CompilerConfiguration compilerConfig) {}
130130

131+
/**
132+
* Called once per compile iteration to allow configuration customization for
133+
* tests.
134+
*
135+
* @param compilerConfig
136+
* configuration used for this compile iteration.
137+
* @param filename
138+
* file about to be compiled this iteration.
139+
* @since 2.14.0
140+
*/
141+
protected void configureCompilerConfig(CompilerConfiguration compilerConfig, String filename) {
142+
configureCompilerConfig(compilerConfig);
143+
}
144+
131145
@Test
132146
public void testCompilingSources() throws Exception {
133147
List<CompilerMessage> messages = new ArrayList<>();
@@ -257,7 +271,7 @@ private List<CompilerConfiguration> getCompilerConfigurations() throws Exception
257271

258272
compilerConfig.setForceJavacCompilerUse(this.forceJavacCompilerUse);
259273

260-
configureCompilerConfig(compilerConfig);
274+
configureCompilerConfig(compilerConfig, filename);
261275

262276
String target = getTargetVersion();
263277
if (StringUtils.isNotEmpty(target)) {
@@ -319,6 +333,12 @@ protected int expectedWarnings() {
319333
return 0;
320334
}
321335

336+
/**
337+
* Count of output generated at the {@link Kind#NOTE} level.
338+
*
339+
* @return count
340+
* @since 2.14.0
341+
*/
322342
protected int expectedNotes() {
323343
return 0;
324344
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2005, The Codehaus
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
7+
* this software and associated documentation files (the "Software"), to deal in
8+
* the Software without restriction, including without limitation the rights to
9+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10+
* of the Software, and to permit persons to whom the Software is furnished to do
11+
* so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package org.codehaus.plexus.compiler.eclipse;
25+
26+
import java.io.File;
27+
import java.util.List;
28+
29+
import org.codehaus.plexus.compiler.CompilerMessage;
30+
31+
/**
32+
* Log parser interface.
33+
*
34+
* @author <a href="mailto:[email protected]">Jason Faust</a>
35+
* @since 2.14.0
36+
*/
37+
public interface EcjLogParser {
38+
39+
/**
40+
* Pares an Eclipse Compiler log file.
41+
*
42+
* @param logFile file to parse.
43+
* @param errorsAsWarnings if errors should be down-graded to warnings.
44+
* @return the messages.
45+
* @throws Exception on parse errors.
46+
*/
47+
List<CompilerMessage> parse(File logFile, boolean errorsAsWarnings) throws Exception;
48+
}

plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EcjResponseParser.java

+20-5
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818

1919
/**
2020
* @author <a href="mailto:[email protected]">Frits Jalvingh</a>
21+
* @author <a href="mailto:[email protected]">Jason Faust</a>
2122
* Created on 31-3-18.
2223
*/
23-
public class EcjResponseParser {
24+
public class EcjResponseParser implements EcjLogParser {
2425
/*--------------------------------------------------------------*/
2526
/* CODING: Decode ECJ -log format results. */
2627
/*--------------------------------------------------------------*/
@@ -40,6 +41,7 @@ private static XMLInputFactory getStreamFactory() {
4041
* @param errorsAsWarnings should we treat errors as warnings
4142
* Scan the specified response file for compilation messages.
4243
*/
44+
@Override
4345
public List<CompilerMessage> parse(File xmltf, boolean errorsAsWarnings) throws Exception {
4446
// if(xmltf.length() < 80)
4547
// return;
@@ -106,20 +108,33 @@ private void decodeProblem(
106108
throws Exception {
107109
String id = xsr.getAttributeValue(null, "optionKey"); // Key for the problem
108110
int startline = getInt(xsr, "line");
109-
int column = getInt(xsr, "charStart");
110-
int endCol = getInt(xsr, "charEnd");
111+
int column = 0;
112+
int endCol = 0;
111113
String sev = xsr.getAttributeValue(null, "severity");
112114
String message = "Unknown message?";
113115

114-
// -- Go watch for "message"
116+
// -- Go watch for "message" and "source_context"
115117
while (xsr.hasNext()) {
116118
int type = xsr.nextTag();
117119
if (type == XMLStreamConstants.START_ELEMENT) {
118120
if ("message".equals(xsr.getLocalName())) {
119121
message = xsr.getAttributeValue(null, "value");
120122
}
123+
if ("source_context".equals(xsr.getLocalName())) {
124+
column = getInt(xsr, "sourceStart");
125+
if (column != -1) {
126+
column += 1; // Offset to 1-based index
127+
} else {
128+
column = 0;
129+
}
130+
endCol = getInt(xsr, "sourceEnd");
131+
if (endCol != -1) {
132+
endCol += 1; // Offset to 1-based index
133+
} else {
134+
endCol = 0;
135+
}
136+
}
121137
ignoreTillEnd(xsr);
122-
123138
} else if (type == XMLStreamConstants.END_ELEMENT) {
124139
break;
125140
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2005, The Codehaus
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
7+
* this software and associated documentation files (the "Software"), to deal in
8+
* the Software without restriction, including without limitation the rights to
9+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10+
* of the Software, and to permit persons to whom the Software is furnished to do
11+
* so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package org.codehaus.plexus.compiler.eclipse;
25+
26+
import java.io.BufferedReader;
27+
import java.io.File;
28+
import java.io.FileInputStream;
29+
import java.io.InputStreamReader;
30+
import java.nio.charset.StandardCharsets;
31+
import java.util.ArrayList;
32+
import java.util.LinkedList;
33+
import java.util.List;
34+
import java.util.regex.Matcher;
35+
import java.util.regex.Pattern;
36+
37+
import org.codehaus.plexus.compiler.CompilerMessage;
38+
import org.codehaus.plexus.compiler.CompilerMessage.Kind;
39+
40+
/**
41+
* Parser for non-XML Eclipse Compiler output.
42+
*
43+
* @author <a href="mailto:[email protected]">Jason Faust</a>
44+
* @since 2.14.0
45+
*/
46+
public class EcjTextLogParser implements EcjLogParser {
47+
48+
private static final String TEN_DASH = "----------";
49+
private static final String PATTERN_LEVEL_FILE = "^\\d+\\.\\s+(\\w+)\\s+in\\s+(.*)\\s+\\(at line (\\d+)\\)$";
50+
51+
private Pattern levelFile = Pattern.compile(PATTERN_LEVEL_FILE);
52+
53+
@Override
54+
public List<CompilerMessage> parse(File logFile, boolean errorsAsWarnings) throws Exception {
55+
List<CompilerMessage> ret = new ArrayList<>();
56+
try (BufferedReader in =
57+
new BufferedReader(new InputStreamReader(new FileInputStream(logFile), StandardCharsets.UTF_8))) {
58+
String line;
59+
List<String> buffer = new LinkedList<>();
60+
boolean header = true;
61+
62+
while ((line = in.readLine()) != null) {
63+
if (header) {
64+
if (!line.startsWith(TEN_DASH)) {
65+
continue;
66+
}
67+
header = false;
68+
}
69+
if (line.startsWith(TEN_DASH)) {
70+
if (!buffer.isEmpty()) {
71+
ret.add(parse(buffer, errorsAsWarnings));
72+
}
73+
buffer.clear();
74+
} else {
75+
buffer.add(line);
76+
}
77+
}
78+
}
79+
return ret;
80+
}
81+
82+
private CompilerMessage parse(List<String> buffer, boolean errorsAsWarnings) {
83+
84+
Kind kind = null;
85+
String file = null;
86+
int lineNum = 0;
87+
int startCol = 0;
88+
int endCol = 0;
89+
String message = null;
90+
91+
// First line, kind, file, lineNum
92+
if (buffer.size() > 1) {
93+
String str = buffer.get(0);
94+
Matcher matcher = levelFile.matcher(str);
95+
if (matcher.find()) {
96+
file = matcher.group(2);
97+
kind = decodeKind(matcher.group(1), errorsAsWarnings);
98+
lineNum = Integer.parseInt(matcher.group(3));
99+
}
100+
}
101+
102+
// Last line, message
103+
if (buffer.size() >= 2) {
104+
String str = buffer.get(buffer.size() - 1);
105+
message = str.trim();
106+
}
107+
108+
// 2nd to last line, columns
109+
if (buffer.size() >= 3) {
110+
String str = buffer.get(buffer.size() - 2);
111+
startCol = str.indexOf('^');
112+
endCol = str.lastIndexOf('^');
113+
}
114+
115+
return new CompilerMessage(file, kind, lineNum, startCol, lineNum, endCol, message);
116+
}
117+
118+
private Kind decodeKind(String str, boolean errorsAsWarnings) {
119+
if (str.equals("ERROR")) {
120+
return errorsAsWarnings ? Kind.WARNING : Kind.ERROR;
121+
}
122+
if (str.equals("INFO")) {
123+
return Kind.NOTE;
124+
}
125+
return Kind.WARNING;
126+
}
127+
}

plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java

+36-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
package org.codehaus.plexus.compiler.eclipse;
2-
31
/**
42
* The MIT License
53
* <p>
@@ -23,6 +21,8 @@
2321
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2422
* SOFTWARE.
2523
*/
24+
package org.codehaus.plexus.compiler.eclipse;
25+
2626
import javax.inject.Named;
2727
import javax.inject.Singleton;
2828
import javax.tools.Diagnostic;
@@ -32,6 +32,7 @@
3232
import javax.tools.StandardJavaFileManager;
3333

3434
import java.io.File;
35+
import java.io.IOException;
3536
import java.io.PrintWriter;
3637
import java.io.StringWriter;
3738
import java.nio.charset.Charset;
@@ -42,6 +43,7 @@
4243
import java.util.Iterator;
4344
import java.util.List;
4445
import java.util.Locale;
46+
import java.util.Map;
4547
import java.util.Map.Entry;
4648
import java.util.ServiceLoader;
4749

@@ -198,6 +200,28 @@ public CompilerResult performCompile(CompilerConfiguration config) throws Compil
198200
}
199201
}
200202

203+
// Check for custom -log
204+
boolean tempLog;
205+
File logFile;
206+
EcjLogParser logParser;
207+
Map<String, String> extras = config.getCustomCompilerArgumentsAsMap();
208+
if (extras.containsKey("-log")) {
209+
String key = extras.get("-log");
210+
logFile = new File(key);
211+
tempLog = false;
212+
logParser = key.endsWith(".xml") ? new EcjResponseParser() : new EcjTextLogParser();
213+
} else {
214+
try {
215+
logFile = File.createTempFile("ecjerr-", ".xml");
216+
} catch (IOException e) {
217+
throw new CompilerException("Unable to create temporary file for compiler output", e);
218+
}
219+
args.add("-log");
220+
args.add(logFile.toString());
221+
tempLog = true;
222+
logParser = new EcjResponseParser();
223+
}
224+
201225
// -- classpath
202226
List<String> classpathEntries = new ArrayList<>(config.getClasspathEntries());
203227
classpathEntries.add(config.getOutputLocation());
@@ -343,29 +367,31 @@ public void worked(int i, int i1) {}
343367
});
344368
log.debug(sw.toString());
345369

346-
if (errorF.length() < 80) {
370+
if (logFile.length() < 80) {
347371
throw new EcjFailureException(sw.toString());
348372
}
349-
messageList = new EcjResponseParser().parse(errorF, errorsAsWarnings);
373+
messageList = logParser.parse(errorF, errorsAsWarnings);
350374
} finally {
351-
if (null != errorF) {
375+
if (tempLog) {
352376
try {
353-
errorF.delete();
377+
logFile.delete();
354378
} catch (Exception x) {
355379
}
356380
}
357381
}
358382
}
359383
boolean hasError = false;
360384
for (CompilerMessage compilerMessage : messageList) {
361-
if (compilerMessage.isError()) {
385+
if (compilerMessage.isError()
386+
|| (compilerMessage.getKind() == CompilerMessage.Kind.WARNING
387+
|| compilerMessage.getKind() == CompilerMessage.Kind.MANDATORY_WARNING)
388+
&& config.isFailOnWarning()) {
362389
hasError = true;
363390
break;
364391
}
365392
}
366393
if (!hasError && !success && !errorsAsWarnings) {
367-
CompilerMessage.Kind kind =
368-
errorsAsWarnings ? CompilerMessage.Kind.WARNING : CompilerMessage.Kind.ERROR;
394+
CompilerMessage.Kind kind = CompilerMessage.Kind.ERROR;
369395

370396
// -- Compiler reported failure but we do not seem to have one -> probable
371397
// exception
@@ -437,7 +463,7 @@ static boolean processCustomArguments(CompilerConfiguration config, List<String>
437463
if (null != optionValue) {
438464
File propFile = new File(optionValue);
439465
if (!propFile.exists() || !propFile.isFile()) {
440-
throw new IllegalArgumentException(
466+
throw new EcjFailureException(
441467
"Properties file specified by -properties " + propFile + " does not exist");
442468
}
443469
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.codehaus.foo;
2+
3+
public class Info {
4+
{
5+
"".equals(Integer.valueOf(1));
6+
}
7+
}

0 commit comments

Comments
 (0)