IDEA-207490, IDEA-207493 - fix navigation and kotlin files

This commit is contained in:
Alexander Bubenchikov
2019-02-20 12:50:23 +03:00
parent 85fc490df4
commit 0482006f9d
8 changed files with 111 additions and 34 deletions
@@ -11,7 +11,6 @@ import java.util.function.Consumer;
@ApiStatus.Experimental
public interface MavenLoggedEventParser {
String COMPILER_MESSAGES_GROUP = "Java compiler";
boolean supportsType(@Nullable LogMessageType type);
@@ -29,10 +29,11 @@ public class MavenOutputParserProvider implements ExternalSystemOutputParserProv
return new MavenLogOutputParser(taskId,
ContainerUtil.list(
new ArtifactDownloadScanning(),
new BuildErrorNotification(),
new JavaBuildErrorNotification(),
new KotlinBuildErrorNotification(),
new ProjectScanning(),
new WarningNotifier(),
new OOMEventParser()
new CommonErrorParser()
));
}
}
@@ -7,6 +7,8 @@ import com.intellij.build.events.MessageEvent;
import com.intellij.build.events.impl.FileMessageEventImpl;
import com.intellij.build.events.impl.MessageEventImpl;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.externalSystemIntegration.output.LogMessageType;
@@ -18,8 +20,17 @@ import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BuildErrorNotification implements MavenLoggedEventParser {
private static final Pattern LINE_AND_COLUMN = Pattern.compile("[^\\d]*?(\\d+)[^\\d]*(\\d*)[^\\d]*");
public abstract class BuildErrorNotification implements MavenLoggedEventParser {
private static final Pattern LINE_AND_COLUMN = Pattern.compile("[^\\d]*?(\\d+)[^\\d]*(\\d*)[])]");
private final String myLanguage;
private final String myExtension;
private final String myMessageGroup;
protected BuildErrorNotification(String language, String extension, String messageGroup) {
myLanguage = language;
myExtension = extension;
myMessageGroup = messageGroup;
}
@Override
public boolean supportsType(@Nullable LogMessageType type) {
@@ -31,38 +42,61 @@ public class BuildErrorNotification implements MavenLoggedEventParser {
@NotNull MavenLogEntryReader.MavenLogEntry logLine,
@NotNull MavenLogEntryReader logEntryReader,
@NotNull Consumer<? super BuildEvent> messageConsumer) {
String line = logLine.getLine();
int fileNameIdx = line.indexOf(".java:");
if (line.endsWith("java.lang.OutOfMemoryError")) {
messageConsumer.accept(new MessageEventImpl(id, MessageEvent.Kind.ERROR, myMessageGroup,
"Out of memory.", line));
return true;
}
int fileNameIdx = line.indexOf("." + myExtension + ":");
if (fileNameIdx < 0) {
return notifyError(id, line, messageConsumer);
return false;
}
int fullFileNameIdx = line.indexOf(":", fileNameIdx);
if (fullFileNameIdx < 0) {
return notifyError(id, line, messageConsumer);
return false;
}
File parsedFile = new File(line.substring(0, fileNameIdx) + ".java");
int messageIdx = line.indexOf(' ', fullFileNameIdx);
FilePosition position = withLineAndColumn(parsedFile, line.substring(fullFileNameIdx, messageIdx), messageIdx, fullFileNameIdx);
int start = SystemInfo.isWindows && line.charAt(0) == '/' ? 1 : 0;
String filename = FileUtil.toSystemDependentName(line.substring(start, fileNameIdx) + "." + myExtension);
File parsedFile = new File(filename);
String lineWithPosition = line.substring(fullFileNameIdx);
Matcher matcher = LINE_AND_COLUMN.matcher(lineWithPosition);
String message;
FilePosition position;
if (matcher.find()) {
position = withLineAndColumn(parsedFile, matcher);
message = lineWithPosition.substring(matcher.end());
}
else {
position = new FilePosition(parsedFile, 0, 0);
message = lineWithPosition;
}
String errorMessage = getErrorMessage(position, message);
messageConsumer
.accept(new FileMessageEventImpl(id, MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP, line.substring(messageIdx), line,
.accept(new FileMessageEventImpl(id, MessageEvent.Kind.ERROR, myMessageGroup, errorMessage, errorMessage,
position));
return true;
}
private static boolean notifyError(ExternalSystemTaskId id,
String line,
Consumer<? super BuildEvent> messageConsumer) {
messageConsumer
.accept(new MessageEventImpl(id, MessageEvent.Kind.ERROR, null, line, line));
return true;
@NotNull
private String getErrorMessage(@NotNull FilePosition position, @NotNull String message) {
if (position.getStartLine() == 0) {
return "Error: " + myLanguage + ":" + message;
}
if (position.getStartColumn() == 0) {
return "Error:(" + (position.getStartLine() + 1) + ") " + myLanguage + ":" + message;
}
return "Error:(" + (position.getStartLine() + 1) + "," + (position.getStartColumn() + 1) + ") " + myLanguage + ":" + message;
}
@NotNull
private static FilePosition withLineAndColumn(File toTest, String line, int spaceAfterFileIdx, int fullFileNameIdx) {
if (spaceAfterFileIdx < 0) return new FilePosition(toTest, 0, 0);
Matcher matcher = LINE_AND_COLUMN.matcher(line);
private static FilePosition withLineAndColumn(File toTest, Matcher matcher) {
try {
if (matcher.matches() && matcher.groupCount() == 2) {
if (matcher.groupCount() == 2) {
if (matcher.start(2) < 0) {
return new FilePosition(toTest, Integer.valueOf(matcher.group(1)) - 1, 0);
}
@@ -70,7 +104,6 @@ public class BuildErrorNotification implements MavenLoggedEventParser {
return new FilePosition(toTest, Integer.valueOf(matcher.group(1)) - 1, Integer.valueOf(matcher.group(2)) - 1);
}
}
return new FilePosition(toTest, 0, 0);
}
catch (NumberFormatException ignore) {
@@ -1,10 +1,10 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.externalSystemIntegration.output.events;
import com.intellij.build.events.BuildEvent;
import com.intellij.build.events.MessageEvent;
import com.intellij.build.events.impl.MessageEventImpl;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.externalSystemIntegration.output.LogMessageType;
@@ -13,10 +13,10 @@ import org.jetbrains.idea.maven.externalSystemIntegration.output.MavenLoggedEven
import java.util.function.Consumer;
public class OOMEventParser implements MavenLoggedEventParser {
public class CommonErrorParser implements MavenLoggedEventParser {
@Override
public boolean supportsType(@Nullable LogMessageType type) {
return true;
return type == LogMessageType.ERROR;
}
@Override
@@ -24,12 +24,10 @@ public class OOMEventParser implements MavenLoggedEventParser {
@NotNull MavenLogEntryReader.MavenLogEntry logLine,
@NotNull MavenLogEntryReader logEntryReader,
@NotNull Consumer<? super BuildEvent> messageConsumer) {
String line = logLine.getLine();
if (line.endsWith("java.lang.OutOfMemoryError")) {
messageConsumer.accept(new MessageEventImpl(id, MessageEvent.Kind.ERROR, COMPILER_MESSAGES_GROUP,
"Out of memory.", line));
return true;
}
return false;
String line = logLine.getLine().trim();
line = StringUtil.trimEnd(line, ":");
messageConsumer
.accept(new MessageEventImpl(id, MessageEvent.Kind.ERROR, null, line, line));
return true;
}
}
@@ -0,0 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.externalSystemIntegration.output.events;
public class JavaBuildErrorNotification extends BuildErrorNotification {
public JavaBuildErrorNotification() {
super("java", "java", "Java compiler");
}
}
@@ -0,0 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.externalSystemIntegration.output.events;
public class KotlinBuildErrorNotification extends BuildErrorNotification {
public KotlinBuildErrorNotification() {
super("kotlin", "kt", "Kotlin compiler plugin");
}
}
@@ -215,7 +215,7 @@ public abstract class MavenBuildToolLogTestUtils extends UsefulTestCase {
@Override
public void describeTo(@NotNull Description description) {
description.appendText("Expected FileEvent " + myMessage + "at " + myFileName + ":" + myLine + ":" + myColumn);
description.appendText("Expected FileMessageEventImpl \"" + myMessage + "\" at " + myFileName + ":" + myLine + ":" + myColumn);
}
}
@@ -0,0 +1,30 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.externalSystemIntegration.output.events;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.idea.maven.externalSystemIntegration.output.MavenBuildToolLogTestUtils;
public class TestBuildErrorNotification extends MavenBuildToolLogTestUtils {
public void testParseJavaError() {
String expectedFileName = FileUtil.toSystemDependentName("C:/path/to/MyFile.java");
String expectedMessage = "Error:(13,21) java: ';' expected";
testCase("[INFO] -------------------------------------------------------------\n" +
"[ERROR] /C:/path/to/MyFile.java:[13,21] ';' expected\n" +
"[INFO] 1 error")
.withParsers(new JavaBuildErrorNotification())
.expect(expectedMessage, new FileEventMatcher(expectedMessage, expectedFileName, 12, 20))
.check();
}
public void testParseKotlinError() {
String expectedFileName = FileUtil.toSystemDependentName("C:\\path\\to\\MyFile.kt");
String expectedMessage = "Error:(3,16) kotlin: Data class primary constructor must have only property (val / var) parameters";
testCase("[INFO] --- kotlin-maven-plugin:1.3.21:compile (compile) @ test-11 ---\n" +
"[ERROR] C:\\path\\to\\MyFile.kt: (3, 16) Data class primary constructor must have only property (val / var) parameters\n" +
"[INFO] ------------------------------------------------------------------------")
.withParsers(new KotlinBuildErrorNotification())
.expect(expectedMessage, new FileEventMatcher(expectedMessage, expectedFileName, 2, 15))
.check();
}
}