Skip to content

Commit

Permalink
Merge pull request #88 from takemikami/lsp-bugfixes
Browse files Browse the repository at this point in the history
language server protocol: bugfix, performance tuning
  • Loading branch information
takemikami authored Jan 25, 2020
2 parents 5695f11 + e13213f commit 3a4315e
Show file tree
Hide file tree
Showing 14 changed files with 427 additions and 171 deletions.
9 changes: 5 additions & 4 deletions src/main/java/com/github/imas/rdflint/LintProblem.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ public enum ErrorLevel {
*/
public LintProblem(ErrorLevel level, RdfValidator validator, LintProblemLocation location,
String key, Object... arguments) {
String pkgName = "";
if (validator != null) {
pkgName = validator.getClass().getPackage().getName();
if (validator == null || key == null) {
this.key = "com.github.imas.rdflint.validator.impl.parseWarning";
} else {
String pkgName = validator.getClass().getPackage().getName();
this.key = pkgName + "." + key;
}
this.location = location;
this.level = level;
this.key = pkgName + "." + key;
this.arguments = arguments.clone();
}

Expand Down
10 changes: 8 additions & 2 deletions src/main/java/com/github/imas/rdflint/LintProblemFormatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ public class LintProblemFormatter {

private static Map<String, ResourceBundle> messagesMap = new ConcurrentHashMap<>();

private static String dumpMessage(String key, Locale locale, Object... args) {
/**
* dump problem message.
*/
public static String dumpMessage(String key, Locale locale, Object... args) {
final String keyName = key.substring(key.lastIndexOf('.') + 1);
final String pkgName = key.substring(0, key.lastIndexOf('.'));
final String bundleKey = locale == null ? pkgName : pkgName + "_" + locale.toString();
Expand All @@ -44,7 +47,10 @@ private static String dumpMessage(String key, Locale locale, Object... args) {
return StringUtils.join(args, ", ");
}

private static Object[] buildArguments(LintProblem problem) {
/**
* build problem message arguments. 1st argument is location string.
*/
public static Object[] buildArguments(LintProblem problem) {
List<Object> args = new LinkedList<>();
if (problem.getLocationString() != null) {
args.add(problem.getLocationString());
Expand Down
244 changes: 205 additions & 39 deletions src/main/java/com/github/imas/rdflint/RdfLintLanguageServer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.imas.rdflint;

import com.github.imas.rdflint.LintProblem.ErrorLevel;
import com.github.imas.rdflint.config.RdfLintParameters;
import com.github.imas.rdflint.parser.RdflintParser;
import com.github.imas.rdflint.parser.RdflintParserRdfxml;
Expand Down Expand Up @@ -33,7 +34,10 @@
import org.apache.jena.graph.Triple;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFParser;
import org.apache.jena.riot.RiotException;
import org.apache.jena.riot.system.ErrorHandler;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.DidChangeConfigurationParams;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
Expand Down Expand Up @@ -139,6 +143,18 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
rdflintParams = lint.loadConfig(configPath);
rdflintParams.setTargetDir(rootPath);
rdflintParams.setOutputDir(rootPath);
if (rdflintParams.getSuppressPath() == null) {
for (String fn : new String[]{
"rdflint-suppress.yml",
".rdflint-suppress.yml",
".circleci/rdflint-suppress.yml"}) {
Path path = Paths.get(rootPath + "/" + fn);
if (Files.exists(path)) {
rdflintParams.setSuppressPath(path.toAbsolutePath().toString());
break;
}
}
}
} catch (IOException ex) {
showException("Error cannot initialize rdflint", ex);
}
Expand All @@ -149,6 +165,7 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
validators.forEach(v ->
v.setParameters(rdflintParams)
);
refreshFileTripleSet();

ServerCapabilities capabilities = new ServerCapabilities();
capabilities.setTextDocumentSync(TextDocumentSyncKind.Full);
Expand All @@ -175,12 +192,77 @@ public WorkspaceService getWorkspaceService() {
return this;
}

void diagnostics() {
private DiagnosticSeverity convertLintProblemLevel2DiagnosticSeverity(ErrorLevel lv) {
DiagnosticSeverity severity;
switch (lv) {
case ERROR:
severity = DiagnosticSeverity.Error;
break;
case WARN:
severity = DiagnosticSeverity.Warning;
break;
default:
severity = DiagnosticSeverity.Information;
}
return severity;
}

private List<Diagnostic> convertLintProblem2DiagnosticList(List<LintProblem> problems) {
return problems.stream()
.map(p -> new Diagnostic(
new Range(
new Position((int) p.getLocation().getBeginLine() - 1,
(int) p.getLocation().getBeginCol() - 1),
new Position((int) p.getLocation().getEndLine() - 1,
(int) p.getLocation().getEndCol() - 1)),
LintProblemFormatter
.dumpMessage(p.getKey(), null, LintProblemFormatter.buildArguments(p)),
convertLintProblemLevel2DiagnosticSeverity(p.getLevel()),
"rdflint")
).collect(Collectors.toList());
}

Map<String, List<Triple>> fileTripleSet;

static class MyErrorHandler implements ErrorHandler {

List<LintProblem> problems;

public MyErrorHandler(List<LintProblem> problems) {
this.problems = problems;
}

private void addDiagnostic(String message, long line, long col, ErrorLevel lv) {
problems.add(new LintProblem(
lv,
null,
new LintProblemLocation(line, 1, line, col),
null,
message));
}

@Override
public void warning(String message, long line, long col) {
addDiagnostic(message, line, col, ErrorLevel.WARN);
}

@Override
public void error(String message, long line, long col) {
addDiagnostic(message, line, col, ErrorLevel.ERROR);
}

@Override
public void fatal(String message, long line, long col) {
addDiagnostic(message, line, col, ErrorLevel.ERROR);
}
}

void refreshFileTripleSet() {
try {
// load triple
String parentPath = rdflintParams.getTargetDir();
String baseUri = rdflintParams.getBaseUri();
Map<String, List<Triple>> fileTripleSet = Files // NOPMD
fileTripleSet = Files // NOPMD
.walk(Paths.get(parentPath))
.filter(e -> e.toString().endsWith(".rdf") || e.toString().endsWith(".ttl"))
.collect(Collectors.toConcurrentMap(
Expand All @@ -191,49 +273,128 @@ void diagnostics() {
String subdir = filename.substring(0, filename.lastIndexOf('/') + 1);
Lang lang = e.toString().endsWith(".ttl") ? Lang.TURTLE : Lang.RDFXML;
String text = sourceTextMap.get(convertFilePath2Uri(e.toString()));
if (text != null) {
InputStream prepareIn = new ByteArrayInputStream(
text.getBytes(StandardCharsets.UTF_8));
RDFParser.source(prepareIn).lang(lang).base(baseUri + subdir).parse(g);
} else {
RDFParser.source(e.toString()).lang(lang).base(baseUri + subdir).parse(g);
List<Triple> lst;
try {
List<LintProblem> problems = new LinkedList<>();
if (text != null) {
InputStream prepareIn = new ByteArrayInputStream(
text.getBytes(StandardCharsets.UTF_8));
RDFParser.source(prepareIn)
.lang(lang)
.base(baseUri + subdir)
.errorHandler(new MyErrorHandler(problems))
.parse(g);
} else {
RDFParser.source(e.toString())
.lang(lang)
.base(baseUri + subdir)
.errorHandler(new MyErrorHandler(problems))
.parse(g);
}
lst = g.find().toList();
} catch (RiotException ex) {
lst = new LinkedList<>();
} finally {
g.close();
}
List<Triple> lst = g.find().toList();
g.close();
return lst;
}
));
validators.forEach(v -> {
v.prepareValidationResource(fileTripleSet);
});

sourceTextMap.forEach((uri, source) -> {
// parse
String filepath = convertUri2FilePath(uri);
String filename = filepath.substring(parentPath.length() + 1);
String subdir = filename.substring(0, filename.lastIndexOf('/') + 1);
RdflintParser parser = uri.endsWith(".ttl")
? new RdflintParserTurtle() : new RdflintParserRdfxml(baseUri + subdir);
validators.forEach(parser::addRdfValidator);
List<Diagnostic> diagnosticList = parser.parse(source).stream()
.map(p -> new Diagnostic(
new Range(
new Position((int) p.getLocation().getBeginLine(),
(int) p.getLocation().getBeginCol()),
new Position((int) p.getLocation().getEndLine(),
(int) p.getLocation().getEndCol())),
p.getKey())
).collect(Collectors.toList());

// publish
} catch (IOException ex) {
showException("Error cannot diagnostics", ex);
}
}

void diagnostics(String changedUri) {
// load triple
String changedFilePath = convertUri2FilePath(changedUri);
String parentPath = rdflintParams.getTargetDir();
String baseUri = rdflintParams.getBaseUri();
{
Graph g = Factory.createGraphMem();
String filename = changedFilePath.substring(parentPath.length() + 1);
String subdir = filename.substring(0, filename.lastIndexOf('/') + 1);
Lang lang = changedFilePath.endsWith(".ttl") ? Lang.TURTLE : Lang.RDFXML;
String text = sourceTextMap.get(convertFilePath2Uri(changedFilePath));
List<LintProblem> problems = new LinkedList<>();
try {
if (text != null) {
InputStream prepareIn = new ByteArrayInputStream(
text.getBytes(StandardCharsets.UTF_8));
RDFParser.source(prepareIn)
.lang(lang)
.base(baseUri + subdir)
.errorHandler(new MyErrorHandler(problems))
.parse(g);
} else {
RDFParser.source(changedFilePath)
.lang(lang)
.base(baseUri + subdir)
.errorHandler(new MyErrorHandler(problems))
.parse(g);
}
List<Triple> tripleSet = g.find().toList();
String key = changedFilePath.substring(parentPath.length() + 1);
fileTripleSet.put(key, tripleSet);
} catch (Exception ex) {
if (problems.isEmpty()) {
problems.add(new LintProblem(
ErrorLevel.WARN,
null,
new LintProblemLocation(1, 1, 1, 1),
null,
ex.getMessage()));
}
} finally {
g.close();
}
if (!problems.isEmpty()) {
List<Diagnostic> diagnosticList = convertLintProblem2DiagnosticList(problems);
PublishDiagnosticsParams diagnostics = new PublishDiagnosticsParams();
diagnostics.setUri(uri);
diagnostics.setUri(changedUri);
diagnostics.setDiagnostics(diagnosticList);
this.client.publishDiagnostics(diagnostics);
});
} catch (IOException ex) {
showException("Error cannot diagnostics", ex);
return;
}
}
// diagnostics
validators.forEach(v -> {
v.prepareValidationResource(fileTripleSet);
});
sourceTextMap.forEach((uri, source) -> {
// parse
String filepath = convertUri2FilePath(uri);
String filename = filepath.substring(parentPath.length() + 1);
String subdir = filename.substring(0, filename.lastIndexOf('/') + 1);
RdflintParser parser = uri.endsWith(".ttl")
? new RdflintParserTurtle() : new RdflintParserRdfxml(baseUri + subdir);
validators.forEach(parser::addRdfValidator);
List<LintProblem> problems = parser.parse(source);
LintProblemSet problemSet = new LintProblemSet();
problems.forEach(p -> {
problemSet.addProblem(filename, p);
}
);

// suppress problems
try {
LintProblemSet filtered = ValidationRunner
.suppressProblems(problemSet, rdflintParams.getSuppressPath());
problems = filtered.getProblemSet().get(filename);
if (problems == null) {
problems = new LinkedList<>();
}
} catch (IOException ex) {
// pass
}
List<Diagnostic> diagnosticList = convertLintProblem2DiagnosticList(problems);

// publish
PublishDiagnosticsParams diagnostics = new PublishDiagnosticsParams();
diagnostics.setUri(uri);
diagnostics.setDiagnostics(diagnosticList);
this.client.publishDiagnostics(diagnostics);
});
}

@Override
Expand All @@ -242,7 +403,7 @@ public void didOpen(DidOpenTextDocumentParams params) {
sourceTextMap.put(params.getTextDocument().getUri(), params.getTextDocument().getText());

// diagnostics
diagnostics();
diagnostics(params.getTextDocument().getUri());
}

@Override
Expand All @@ -253,7 +414,7 @@ public void didChange(DidChangeTextDocumentParams params) {
sourceTextMap.put(params.getTextDocument().getUri(), sourceText);

// diagnostics
diagnostics();
diagnostics(params.getTextDocument().getUri());
}

@Override
Expand All @@ -266,10 +427,15 @@ public void didClose(DidCloseTextDocumentParams params) {
diagnostics.setUri(params.getTextDocument().getUri());
diagnostics.setDiagnostics(new LinkedList<>());
this.client.publishDiagnostics(diagnostics);

// diagnostics
diagnostics(params.getTextDocument().getUri());
}

@Override
public void didSave(DidSaveTextDocumentParams params) {
// refresh all tripleset
refreshFileTripleSet();
}

@Override
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/com/github/imas/rdflint/ValidationRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ private Map<String, List<Triple>> loadFileTripleSet(String parentPath, String ba
));
}

private LintProblemSet suppressProblems(LintProblemSet problemSet, String suppressPath)
/**
* suppress problems.
*/
public static LintProblemSet suppressProblems(LintProblemSet problemSet, String suppressPath)
throws IOException {

if (suppressPath == null) {
Expand Down
Loading

0 comments on commit 3a4315e

Please sign in to comment.