-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(yakshaintellij): show compiler errors
- Loading branch information
Showing
9 changed files
with
267 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
editor/intellij/src/main/java/org/intellij/sdk/language/YakshaCompilerAnnotator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package org.intellij.sdk.language; | ||
|
||
import com.google.gson.JsonObject; | ||
import com.google.gson.JsonParser; | ||
import com.intellij.lang.annotation.AnnotationHolder; | ||
import com.intellij.lang.annotation.ExternalAnnotator; | ||
import com.intellij.lang.annotation.HighlightSeverity; | ||
import com.intellij.openapi.editor.Document; | ||
import com.intellij.openapi.project.DumbAware; | ||
import com.intellij.openapi.project.Project; | ||
import com.intellij.openapi.util.TextRange; | ||
import com.intellij.openapi.vfs.VirtualFile; | ||
import com.intellij.psi.PsiDocumentManager; | ||
import com.intellij.psi.PsiFile; | ||
import com.intellij.psi.PsiManager; | ||
import org.intellij.sdk.language.psi.YakshaFile; | ||
import org.intellij.sdk.language.tw.YakshaToolWindow; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
public class YakshaCompilerAnnotator extends ExternalAnnotator<YakshaFile, List<YakshaCompilerAnnotator.CompilerError>> implements DumbAware { | ||
@Override | ||
public @Nullable YakshaFile collectInformation(@NotNull PsiFile file) { | ||
if (file instanceof YakshaFile) { | ||
return (YakshaFile) file; | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public @NotNull List<CompilerError> doAnnotate(@Nullable YakshaFile collectedInfo) { | ||
if (collectedInfo == null) { | ||
return List.of(); | ||
} | ||
final var project = collectedInfo.getProject(); | ||
final var virtualFile = collectedInfo.getVirtualFile(); | ||
File mainFile = findMainFile(new File(virtualFile.getPath()), 5); | ||
if (mainFile == null) { | ||
return List.of(); | ||
} | ||
|
||
|
||
return runCompiler(mainFile); | ||
} | ||
|
||
@Override | ||
public void apply(@NotNull PsiFile file, List<CompilerError> annotationResult, @NotNull AnnotationHolder holder) { | ||
if (annotationResult == null || annotationResult.isEmpty()) { | ||
return; | ||
} | ||
|
||
final var document = file.getViewProvider().getDocument(); | ||
if (document == null) { | ||
return; | ||
} | ||
|
||
for (CompilerError error : annotationResult) { | ||
var line = error.line - 1; | ||
if (line < 0 || line >= document.getLineCount()) continue; | ||
|
||
var startOffset = document.getLineStartOffset(line) + error.column - 1; | ||
var endOffset = startOffset + error.length; | ||
|
||
holder.newAnnotation(HighlightSeverity.ERROR, error.message).range(new TextRange(startOffset, endOffset)).create(); | ||
} | ||
} | ||
|
||
private @Nullable Document getDoc(Project project, VirtualFile file) { | ||
final var psiFile = PsiManager.getInstance(project).findFile(file); | ||
if (psiFile == null) { | ||
return null; | ||
} | ||
return PsiDocumentManager.getInstance(project).getDocument(psiFile); | ||
} | ||
|
||
public static class CompilerError { | ||
final String message; | ||
final int line; | ||
final int column; | ||
final int length; | ||
|
||
private CompilerError(final String message, final int line, final int column, final int length) { | ||
this.message = message; | ||
this.line = line; | ||
this.column = column; | ||
this.length = length; | ||
} | ||
} | ||
|
||
private File findMainFile(File dir, int maxDepth) { | ||
File currentDir = dir; | ||
for (int i = 0; i <= maxDepth; i++) { | ||
File mainCFile = new File(currentDir, "main.yaka"); | ||
if (mainCFile.exists() && mainCFile.isFile()) { | ||
return mainCFile; | ||
} | ||
currentDir = currentDir.getParentFile(); | ||
if (currentDir == null) break; | ||
} | ||
return null; | ||
} | ||
|
||
private List<CompilerError> runCompiler(File mainFile) { | ||
List<CompilerError> errors = new ArrayList<>(); | ||
final var compiler = YakshaToolWindow.YAKSHA_EXE_PATH; | ||
if (compiler.isBlank()) { | ||
System.out.println("------ yaksha compiler path is not set -----"); | ||
return errors; | ||
} | ||
|
||
System.out.println("----- yaksha compiler: " + compiler); | ||
|
||
List<String> command = List.of(compiler, "compile", "-d", mainFile.getAbsolutePath()); | ||
|
||
try { | ||
Process process = new ProcessBuilder(command) | ||
.directory(mainFile.getParentFile()) | ||
.redirectErrorStream(true) | ||
.start(); | ||
|
||
process.waitFor(60, TimeUnit.SECONDS); | ||
|
||
String output = new String(process.getInputStream().readAllBytes()); | ||
int exitCode = process.exitValue(); | ||
|
||
errors.addAll(parseCompilerErrors(output, mainFile.getAbsolutePath())); | ||
} catch (IOException | InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
return errors; | ||
} | ||
|
||
private List<CompilerError> parseCompilerErrors(String output, String mainFilePath) { | ||
List<CompilerError> errors = new ArrayList<>(); | ||
String[] lines = output.split("\\R"); | ||
|
||
for (String line : lines) { | ||
if (!line.trim().isEmpty()) { | ||
JsonObject json = JsonParser.parseString(line).getAsJsonObject(); | ||
String file = json.has("file") ? json.get("file").getAsString() : mainFilePath; | ||
int lineNumber = json.has("line") ? json.get("line").getAsInt() : 0; | ||
int columnNumber = json.has("pos") ? json.get("pos").getAsInt() : 0; | ||
String message = json.get("message").getAsString(); | ||
int tokenLength = json.has("token") ? json.get("token").getAsString().length() : 1; | ||
|
||
if (mainFilePath.equals(file)) { | ||
errors.add(new CompilerError(message, lineNumber, columnNumber, tokenLength)); | ||
} | ||
} | ||
} | ||
|
||
return errors; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
editor/intellij/src/main/java/org/intellij/sdk/language/tw/ExecutableFileState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package org.intellij.sdk.language.tw; | ||
|
||
public final class ExecutableFileState { | ||
private String executableFilePath = ""; | ||
|
||
public String getExecutableFilePath() { | ||
return executableFilePath; | ||
} | ||
|
||
public void setExecutableFilePath(String executableFilePath) { | ||
this.executableFilePath = executableFilePath; | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
editor/intellij/src/main/java/org/intellij/sdk/language/tw/ExecutableFileStateService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package org.intellij.sdk.language.tw; | ||
|
||
import com.intellij.openapi.components.PersistentStateComponent; | ||
import com.intellij.openapi.components.Service; | ||
import com.intellij.openapi.components.State; | ||
import com.intellij.openapi.components.Storage; | ||
import com.intellij.openapi.project.Project; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
@State( | ||
name = "ExecutableFileStateService", | ||
storages = @Storage("ExecutableFileStateService.xml") | ||
) | ||
@Service | ||
public final class ExecutableFileStateService implements PersistentStateComponent<ExecutableFileState> { | ||
|
||
private ExecutableFileState state = new ExecutableFileState(); | ||
|
||
@Nullable | ||
@Override | ||
public ExecutableFileState getState() { | ||
return state; | ||
} | ||
|
||
@Override | ||
public void loadState(@NotNull ExecutableFileState state) { | ||
this.state = state; | ||
} | ||
|
||
public static ExecutableFileStateService getInstance(Project project) { | ||
return project.getService(ExecutableFileStateService.class); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
editor/intellij/src/main/java/org/intellij/sdk/language/tw/YakshaToolWindowFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters