Skip to content

Commit

Permalink
Allow -log argument for Eclipse compiler
Browse files Browse the repository at this point in the history
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.15.0
* Unit tests refactored
* Output emitted as "INFO" are reported as Kind.NOTE
* Column count adjusted to be 1-based index
  • Loading branch information
Jason Faust committed Oct 18, 2018
1 parent acbb668 commit a42abc8
Show file tree
Hide file tree
Showing 25 changed files with 1,704 additions and 265 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
package org.codehaus.plexus.compiler;

/**
/*
* The MIT License
*
* Copyright (c) 2004, The Codehaus
Expand All @@ -23,17 +21,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.codehaus.plexus.compiler;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.test.ArtifactTestCase;
import org.apache.maven.artifact.versioning.VersionRange;

import org.codehaus.plexus.compiler.CompilerMessage.Kind;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;

import javax.print.DocFlavor;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -42,9 +40,6 @@
import java.util.List;
import java.util.TreeSet;

/**
*
*/
public abstract class AbstractCompilerTest
extends ArtifactTestCase
{
Expand Down Expand Up @@ -91,6 +86,22 @@ protected void configureCompilerConfig( CompilerConfiguration compilerConfig )

}


/**
* Called once per compile iteration to allow configuration customization for
* tests.
*
* @param compilerConfig
* configuration used for this compile iteration.
* @param filename
* file about to be compiled this iteration.
* @since 2.8.6
*/
protected void configureCompilerConfig(CompilerConfiguration compilerConfig, String filename)
{
configureCompilerConfig( compilerConfig );
}

public void testCompilingSources()
throws Exception
{
Expand All @@ -113,14 +124,16 @@ public void testCompilingSources()

int numCompilerErrors = compilerErrorCount( messages );

int numCompilerWarnings = messages.size() - numCompilerErrors;
int numCompilerWarnings = compilerWarningCount( messages );

int numCompilerNotes = compilerNoteCount( messages );

if ( expectedErrors() != numCompilerErrors )
{
System.out.println( numCompilerErrors + " error(s) found:" );
for ( CompilerMessage error : messages )
{
if ( !error.isError() )
if ( error.getKind() != Kind.ERROR )
{
continue;
}
Expand All @@ -139,7 +152,7 @@ public void testCompilingSources()
System.out.println( numCompilerWarnings + " warning(s) found:" );
for ( CompilerMessage error : messages )
{
if ( error.isError() )
if ( error.getKind() == Kind.ERROR || error.getKind() == Kind.NOTE )
{
continue;
}
Expand All @@ -153,6 +166,25 @@ public void testCompilingSources()
assertEquals( "Wrong number of compilation warnings.", expectedWarnings(), numCompilerWarnings );
}

if ( expectedNotes() != numCompilerNotes )
{
System.out.println( numCompilerWarnings + " notes(s) found:" );
for (CompilerMessage error : messages)
{
if ( error.getKind() != Kind.NOTE )
{
continue;
}

System.out.println( "----" );
System.out.println( error.getFile() );
System.out.println( error.getMessage() );
System.out.println( "----" );
}

assertEquals( "Wrong number of compilation notes.", expectedNotes(), numCompilerNotes );
}

assertEquals( new TreeSet<>( normalizePaths( expectedOutputFiles() ) ), files );
}

Expand Down Expand Up @@ -190,7 +222,7 @@ private List<CompilerConfiguration> getCompilerConfigurations()

compilerConfig.setForceJavacCompilerUse( this.forceJavacCompilerUse );

configureCompilerConfig( compilerConfig );
configureCompilerConfig( compilerConfig, filename );

String target = getTargetVersion();
if( StringUtils.isNotEmpty( target) )
Expand Down Expand Up @@ -221,7 +253,6 @@ public String getSourceVersion()
return null;
}


private List<String> normalizePaths( Collection<String> relativePaths )
{
List<String> normalizedPaths = new ArrayList<String>();
Expand All @@ -232,16 +263,32 @@ private List<String> normalizePaths( Collection<String> relativePaths )
return normalizedPaths;
}

protected int compilerErrorCount( List<CompilerMessage> messages )
private int compilerErrorCount(List<CompilerMessage> messages)
{
return countKind( messages, Kind.ERROR );
}

private int compilerWarningCount(List<CompilerMessage> messages)
{
return messages.size() - (compilerErrorCount( messages ) + compilerNoteCount( messages ));
}

private int compilerNoteCount(List<CompilerMessage> messages)
{
int count = 0;
return countKind( messages, Kind.NOTE );
}

for ( CompilerMessage message : messages )
private int countKind(List<CompilerMessage> messages, Kind kind)
{
int c = 0;
for (CompilerMessage message : messages)
{
count += message.isError() ? 1 : 0;
if ( message.getKind() == kind )
{
c++;
}
}

return count;
return c;
}

protected int expectedErrors()
Expand All @@ -254,6 +301,17 @@ protected int expectedWarnings()
return 0;
}

/**
* Count of output generated at the {@link Kind#NOTE} level.
*
* @return count
* @since 2.8.6
*/
protected int expectedNotes()
{
return 0;
}

protected Collection<String> expectedOutputFiles()
{
return Collections.emptyList();
Expand Down
2 changes: 1 addition & 1 deletion plexus-compilers/plexus-compiler-eclipse/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>ecj</artifactId>
<version>3.13.100</version>
<version>3.15.0</version>
</dependency>
</dependencies>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.codehaus.plexus.compiler.eclipse;

import java.io.File;
import java.util.List;

import org.codehaus.plexus.compiler.CompilerMessage;

/**
* Log parser interface.
*
* @author <a href="mailto:[email protected]">Jason Faust</a>
* @since 2.8.6
*/
public interface EcjLogParser {

/**
* Pares an Eclipse Compiler log file.
*
* @param logFile file to parse.
* @param errorsAsWarnings if errors should be down-graded to warnings.
* @return the messages.
* @throws Exception on parse errors.
*/
List<CompilerMessage> parse(File logFile, boolean errorsAsWarnings) throws Exception;

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@
import java.util.List;

/**
* Created on 2018-03-31.
*
* @author <a href="mailto:[email protected]">Frits Jalvingh</a>
* Created on 31-3-18.
* @author <a href="mailto:[email protected]">Jason Faust</a>
*/
public class EcjResponseParser {
public class EcjResponseParser implements EcjLogParser {
/*--------------------------------------------------------------*/
/* CODING: Decode ECJ -log format results. */
/*--------------------------------------------------------------*/
/**
* Scan the specified response file for compilation messages.
*/
@Override
public List<CompilerMessage> parse(File xmltf, boolean errorsAsWarnings) throws Exception {
//if(xmltf.length() < 80)
// return;
Expand Down Expand Up @@ -87,18 +90,32 @@ private void decodeProblems(List<CompilerMessage> list, String sourcePath, XMLSt
private void decodeProblem(List<CompilerMessage> list, String sourcePath, XMLStreamReader xsr, boolean errorsAsWarnings) throws Exception {
String id = xsr.getAttributeValue(null, "optionKey"); // Key for the problem
int startline = getInt(xsr, "line");
int column = getInt(xsr, "charStart");
int endCol = getInt(xsr, "charEnd");
int column = 0;
int endCol = 0;
String sev = xsr.getAttributeValue(null, "severity");
String message = "Unknown message?";

//-- Go watch for "message"
//-- Go watch for "message" and "source_context"
while(xsr.hasNext()) {
int type = xsr.nextTag();
if(type == XMLStreamConstants.START_ELEMENT) {
if("message".equals(xsr.getLocalName())) {
message = xsr.getAttributeValue(null, "value");
}
if("source_context".equals(xsr.getLocalName())) {
column = getInt(xsr, "sourceStart");
if (column != -1) {
column += 1; // Offset to 1-based index
} else {
column = 0;
}
endCol = getInt(xsr, "sourceEnd");
if (endCol != -1) {
endCol += 2; // Offset to 1-based index with one-after counting
} else {
endCol = 0;
}
}
ignoreTillEnd(xsr);

} else if(type == XMLStreamConstants.END_ELEMENT) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.codehaus.plexus.compiler.eclipse;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.codehaus.plexus.compiler.CompilerMessage;
import org.codehaus.plexus.compiler.CompilerMessage.Kind;

/**
* Parser for non-XML Eclipse Compiler output.
*
* @author <a href="mailto:[email protected]">Jason Faust</a>
* @since 2.8.6
*/
public class EcjTextLogParser implements EcjLogParser {

private static final String TEN_DASH = "----------";
private static final String PATTERN_LEVEL_FILE = "^\\d+\\.\\s+(\\w+)\\s+in\\s+(.*)\\s+\\(at line (\\d+)\\)$";

private Pattern levelFile = Pattern.compile(PATTERN_LEVEL_FILE);

@Override
public List<CompilerMessage> parse(File logFile, boolean errorsAsWarnings) throws Exception {
List<CompilerMessage> ret = new ArrayList<>();
try (BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream(logFile), StandardCharsets.UTF_8))) {
String line;
List<String> buffer = new LinkedList<>();
boolean header = true;

while ((line = in.readLine()) != null) {
if (header) {
if (!line.startsWith(TEN_DASH)) {
continue;
}
header = false;
}
if (line.startsWith(TEN_DASH)) {
if (!buffer.isEmpty()) {
ret.add(parse(buffer, errorsAsWarnings));
}
buffer.clear();
} else {
buffer.add(line);
}
}
}
return ret;
}

private CompilerMessage parse(List<String> buffer, boolean errorsAsWarnings) {

Kind kind = null;
String file = null;
int lineNum = 0;
int startCol = 0;
int endCol = 0;
String message = null;

// First line, kind, file, lineNum
if (buffer.size() > 1) {
String str = buffer.get(0);
Matcher matcher = levelFile.matcher(str);
if (matcher.find()) {
file = matcher.group(2);
kind = decodeKind(matcher.group(1), errorsAsWarnings);
lineNum = Integer.parseInt(matcher.group(3));
}
}

// Last line, message
if (buffer.size() >= 2) {
String str = buffer.get(buffer.size() - 1);
message = str.trim();
}

// 2nd to last line, columns
if (buffer.size() >= 3) {
String str = buffer.get(buffer.size() - 2);
startCol = str.indexOf('^');
endCol = str.lastIndexOf('^') + 1;
}

return new CompilerMessage(file, kind, lineNum, startCol, lineNum, endCol, message);
}

private Kind decodeKind(String str, boolean errorsAsWarnings) {
if (str.equals("ERROR")) {
return errorsAsWarnings ? Kind.WARNING : Kind.ERROR;
}
if (str.equals("INFO")) {
return Kind.NOTE;
}
return Kind.WARNING;
}

}
Loading

0 comments on commit a42abc8

Please sign in to comment.