Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

language server protocol: bugfix, performance tuning #88

Merged
merged 1 commit into from
Jan 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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