Skip to content

Commit 746f069

Browse files
author
Jason Faust
committed
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. * Eclipse compiler updated to 3.17.0 * Unit tests refactored * Output emitted as "INFO" are reported as Kind.NOTE * Column count adjusted to be 1-based index
1 parent 296f33c commit 746f069

26 files changed

+1929
-242
lines changed

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

+75-12
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,10 @@
2929
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
3030
import org.apache.maven.artifact.test.ArtifactTestCase;
3131
import org.apache.maven.artifact.versioning.VersionRange;
32-
32+
import org.codehaus.plexus.compiler.CompilerMessage.Kind;
3333
import org.codehaus.plexus.util.FileUtils;
3434
import org.codehaus.plexus.util.StringUtils;
3535

36-
import javax.print.DocFlavor;
3736
import java.io.File;
3837
import java.util.ArrayList;
3938
import java.util.Collection;
@@ -91,6 +90,22 @@ protected void configureCompilerConfig( CompilerConfiguration compilerConfig )
9190

9291
}
9392

93+
94+
/**
95+
* Called once per compile iteration to allow configuration customization for
96+
* tests.
97+
*
98+
* @param compilerConfig
99+
* configuration used for this compile iteration.
100+
* @param filename
101+
* file about to be compiled this iteration.
102+
* @since 2.8.6
103+
*/
104+
protected void configureCompilerConfig(CompilerConfiguration compilerConfig, String filename)
105+
{
106+
configureCompilerConfig( compilerConfig );
107+
}
108+
94109
public void testCompilingSources()
95110
throws Exception
96111
{
@@ -113,7 +128,9 @@ public void testCompilingSources()
113128

114129
int numCompilerErrors = compilerErrorCount( messages );
115130

116-
int numCompilerWarnings = messages.size() - numCompilerErrors;
131+
int numCompilerWarnings = compilerWarningCount( messages );
132+
133+
int numCompilerNotes = compilerNoteCount( messages );
117134

118135
int expectedErrors = expectedErrors();
119136

@@ -123,7 +140,7 @@ public void testCompilingSources()
123140
List<String> errors = new ArrayList<>();
124141
for ( CompilerMessage error : messages )
125142
{
126-
if ( !error.isError() )
143+
if ( error.getKind() != Kind.ERROR )
127144
{
128145
continue;
129146
}
@@ -146,7 +163,7 @@ public void testCompilingSources()
146163
System.out.println( numCompilerWarnings + " warning(s) found:" );
147164
for ( CompilerMessage error : messages )
148165
{
149-
if ( error.isError() )
166+
if ( error.getKind() == Kind.ERROR || error.getKind() == Kind.NOTE )
150167
{
151168
continue;
152169
}
@@ -162,6 +179,25 @@ public void testCompilingSources()
162179
expectedWarnings, numCompilerWarnings );
163180
}
164181

182+
if ( expectedNotes() != numCompilerNotes )
183+
{
184+
System.out.println( numCompilerWarnings + " notes(s) found:" );
185+
for (CompilerMessage error : messages)
186+
{
187+
if ( error.getKind() != Kind.NOTE )
188+
{
189+
continue;
190+
}
191+
192+
System.out.println( "----" );
193+
System.out.println( error.getFile() );
194+
System.out.println( error.getMessage() );
195+
System.out.println( "----" );
196+
}
197+
198+
assertEquals( "Wrong number of compilation notes.", expectedNotes(), numCompilerNotes );
199+
}
200+
165201
assertEquals( new TreeSet<>( normalizePaths( expectedOutputFiles() ) ), files );
166202
}
167203

@@ -199,7 +235,7 @@ private List<CompilerConfiguration> getCompilerConfigurations()
199235

200236
compilerConfig.setForceJavacCompilerUse( this.forceJavacCompilerUse );
201237

202-
configureCompilerConfig( compilerConfig );
238+
configureCompilerConfig( compilerConfig, filename );
203239

204240
String target = getTargetVersion();
205241
if( StringUtils.isNotEmpty( target) )
@@ -241,16 +277,32 @@ private List<String> normalizePaths( Collection<String> relativePaths )
241277
return normalizedPaths;
242278
}
243279

244-
protected int compilerErrorCount( List<CompilerMessage> messages )
280+
private int compilerErrorCount(List<CompilerMessage> messages)
281+
{
282+
return countKind( messages, Kind.ERROR );
283+
}
284+
285+
private int compilerWarningCount(List<CompilerMessage> messages)
245286
{
246-
int count = 0;
287+
return messages.size() - (compilerErrorCount( messages ) + compilerNoteCount( messages ));
288+
}
289+
290+
private int compilerNoteCount(List<CompilerMessage> messages)
291+
{
292+
return countKind( messages, Kind.NOTE );
293+
}
247294

248-
for ( CompilerMessage message : messages )
295+
private int countKind(List<CompilerMessage> messages, Kind kind)
296+
{
297+
int c = 0;
298+
for (CompilerMessage message : messages)
249299
{
250-
count += message.isError() ? 1 : 0;
300+
if ( message.getKind() == kind )
301+
{
302+
c++;
303+
}
251304
}
252-
253-
return count;
305+
return c;
254306
}
255307

256308
protected int expectedErrors()
@@ -263,6 +315,17 @@ protected int expectedWarnings()
263315
return 0;
264316
}
265317

318+
/**
319+
* Count of output generated at the {@link Kind#NOTE} level.
320+
*
321+
* @return count
322+
* @since 2.8.6
323+
*/
324+
protected int expectedNotes()
325+
{
326+
return 0;
327+
}
328+
266329
protected Collection<String> expectedOutputFiles()
267330
{
268331
return Collections.emptyList();

plexus-compilers/plexus-compiler-eclipse/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<dependency>
2222
<groupId>org.eclipse.jdt</groupId>
2323
<artifactId>ecj</artifactId>
24-
<version>3.15.1</version>
24+
<version>3.17.0</version>
2525
</dependency>
2626
</dependencies>
2727

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.codehaus.plexus.compiler.eclipse;
2+
3+
import java.io.File;
4+
import java.util.List;
5+
6+
import org.codehaus.plexus.compiler.CompilerMessage;
7+
8+
/**
9+
* Log parser interface.
10+
*
11+
* @author <a href="mailto:[email protected]">Jason Faust</a>
12+
* @since 2.8.6
13+
*/
14+
public interface EcjLogParser {
15+
16+
/**
17+
* Pares an Eclipse Compiler log file.
18+
*
19+
* @param logFile file to parse.
20+
* @param errorsAsWarnings if errors should be down-graded to warnings.
21+
* @return the messages.
22+
* @throws Exception on parse errors.
23+
*/
24+
List<CompilerMessage> parse(File logFile, boolean errorsAsWarnings) throws Exception;
25+
26+
}

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

+20-4
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@
1717

1818
/**
1919
* @author <a href="mailto:[email protected]">Frits Jalvingh</a>
20+
* @author <a href="mailto:[email protected]">Jason Faust</a>
2021
* Created on 31-3-18.
2122
*/
22-
public class EcjResponseParser {
23+
public class EcjResponseParser implements EcjLogParser {
2324
/*--------------------------------------------------------------*/
2425
/* CODING: Decode ECJ -log format results. */
2526
/*--------------------------------------------------------------*/
2627
/**
2728
* Scan the specified response file for compilation messages.
2829
*/
30+
@Override
2931
public List<CompilerMessage> parse(File xmltf, boolean errorsAsWarnings) throws Exception {
3032
//if(xmltf.length() < 80)
3133
// return;
@@ -87,18 +89,32 @@ private void decodeProblems(List<CompilerMessage> list, String sourcePath, XMLSt
8789
private void decodeProblem(List<CompilerMessage> list, String sourcePath, XMLStreamReader xsr, boolean errorsAsWarnings) throws Exception {
8890
String id = xsr.getAttributeValue(null, "optionKey"); // Key for the problem
8991
int startline = getInt(xsr, "line");
90-
int column = getInt(xsr, "charStart");
91-
int endCol = getInt(xsr, "charEnd");
92+
int column = 0;
93+
int endCol = 0;
9294
String sev = xsr.getAttributeValue(null, "severity");
9395
String message = "Unknown message?";
9496

95-
//-- Go watch for "message"
97+
//-- Go watch for "message" and "source_context"
9698
while(xsr.hasNext()) {
9799
int type = xsr.nextTag();
98100
if(type == XMLStreamConstants.START_ELEMENT) {
99101
if("message".equals(xsr.getLocalName())) {
100102
message = xsr.getAttributeValue(null, "value");
101103
}
104+
if("source_context".equals(xsr.getLocalName())) {
105+
column = getInt(xsr, "sourceStart");
106+
if (column != -1) {
107+
column += 1; // Offset to 1-based index
108+
} else {
109+
column = 0;
110+
}
111+
endCol = getInt(xsr, "sourceEnd");
112+
if (endCol != -1) {
113+
endCol += 1; // Offset to 1-based index
114+
} else {
115+
endCol = 0;
116+
}
117+
}
102118
ignoreTillEnd(xsr);
103119

104120
} else if(type == XMLStreamConstants.END_ELEMENT) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package org.codehaus.plexus.compiler.eclipse;
2+
3+
import java.io.BufferedReader;
4+
import java.io.File;
5+
import java.io.FileInputStream;
6+
import java.io.InputStreamReader;
7+
import java.nio.charset.StandardCharsets;
8+
import java.util.ArrayList;
9+
import java.util.LinkedList;
10+
import java.util.List;
11+
import java.util.regex.Matcher;
12+
import java.util.regex.Pattern;
13+
14+
import org.codehaus.plexus.compiler.CompilerMessage;
15+
import org.codehaus.plexus.compiler.CompilerMessage.Kind;
16+
17+
/**
18+
* Parser for non-XML Eclipse Compiler output.
19+
*
20+
* @author <a href="mailto:[email protected]">Jason Faust</a>
21+
* @since 2.8.6
22+
*/
23+
public class EcjTextLogParser implements EcjLogParser {
24+
25+
private static final String TEN_DASH = "----------";
26+
private static final String PATTERN_LEVEL_FILE = "^\\d+\\.\\s+(\\w+)\\s+in\\s+(.*)\\s+\\(at line (\\d+)\\)$";
27+
28+
private Pattern levelFile = Pattern.compile(PATTERN_LEVEL_FILE);
29+
30+
@Override
31+
public List<CompilerMessage> parse(File logFile, boolean errorsAsWarnings) throws Exception {
32+
List<CompilerMessage> ret = new ArrayList<>();
33+
try (BufferedReader in = new BufferedReader(
34+
new InputStreamReader(new FileInputStream(logFile), StandardCharsets.UTF_8))) {
35+
String line;
36+
List<String> buffer = new LinkedList<>();
37+
boolean header = true;
38+
39+
while ((line = in.readLine()) != null) {
40+
if (header) {
41+
if (!line.startsWith(TEN_DASH)) {
42+
continue;
43+
}
44+
header = false;
45+
}
46+
if (line.startsWith(TEN_DASH)) {
47+
if (!buffer.isEmpty()) {
48+
ret.add(parse(buffer, errorsAsWarnings));
49+
}
50+
buffer.clear();
51+
} else {
52+
buffer.add(line);
53+
}
54+
}
55+
}
56+
return ret;
57+
}
58+
59+
private CompilerMessage parse(List<String> buffer, boolean errorsAsWarnings) {
60+
61+
Kind kind = null;
62+
String file = null;
63+
int lineNum = 0;
64+
int startCol = 0;
65+
int endCol = 0;
66+
String message = null;
67+
68+
// First line, kind, file, lineNum
69+
if (buffer.size() > 1) {
70+
String str = buffer.get(0);
71+
Matcher matcher = levelFile.matcher(str);
72+
if (matcher.find()) {
73+
file = matcher.group(2);
74+
kind = decodeKind(matcher.group(1), errorsAsWarnings);
75+
lineNum = Integer.parseInt(matcher.group(3));
76+
}
77+
}
78+
79+
// Last line, message
80+
if (buffer.size() >= 2) {
81+
String str = buffer.get(buffer.size() - 1);
82+
message = str.trim();
83+
}
84+
85+
// 2nd to last line, columns
86+
if (buffer.size() >= 3) {
87+
String str = buffer.get(buffer.size() - 2);
88+
startCol = str.indexOf('^');
89+
endCol = str.lastIndexOf('^');
90+
}
91+
92+
return new CompilerMessage(file, kind, lineNum, startCol, lineNum, endCol, message);
93+
}
94+
95+
private Kind decodeKind(String str, boolean errorsAsWarnings) {
96+
if (str.equals("ERROR")) {
97+
return errorsAsWarnings ? Kind.WARNING : Kind.ERROR;
98+
}
99+
if (str.equals("INFO")) {
100+
return Kind.NOTE;
101+
}
102+
return Kind.WARNING;
103+
}
104+
105+
}

0 commit comments

Comments
 (0)