-
Notifications
You must be signed in to change notification settings - Fork 12
Remember files opened as Parametric Rascal LSP
before language registration
#809
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
base: main
Are you sure you want to change the base?
Changes from all commits
01fa185
ec1363b
2d7b93c
ce5aee8
ab6e7c6
1a0da53
8d8b675
65bd32f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,16 +28,17 @@ | |
|
||
import java.io.IOException; | ||
import java.io.Reader; | ||
import java.net.URI; | ||
import java.time.Duration; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.function.BiFunction; | ||
import java.util.function.Function; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Collectors; | ||
|
@@ -316,7 +317,7 @@ public void didDeleteFiles(DeleteFilesParams params) { | |
ownExecuter.submit(() -> { | ||
// if a file is deleted, and we were tracking it, we remove our diagnostics | ||
for (var f : params.getFiles()) { | ||
if (registeredExtensions.containsKey(extension(URIUtil.assumeCorrectLocation(f.getUri())))) { | ||
if (isLanguageRegistered(URIUtil.assumeCorrectLocation(f.getUri()))) { | ||
client.publishDiagnostics(new PublishDiagnosticsParams(f.getUri(), List.of())); | ||
} | ||
} | ||
|
@@ -327,12 +328,19 @@ public void didDeleteFiles(DeleteFilesParams params) { | |
private void triggerAnalyzer(TextDocumentItem doc, Duration delay) { | ||
triggerAnalyzer(new VersionedTextDocumentIdentifier(doc.getUri(), doc.getVersion()), delay); | ||
} | ||
|
||
private void triggerAnalyzer(VersionedTextDocumentIdentifier doc, Duration delay) { | ||
logger.trace("Triggering analyzer for {}", doc.getUri()); | ||
var location = Locations.toLoc(doc); | ||
triggerAnalyzer(location, doc.getVersion(), delay); | ||
} | ||
|
||
private void triggerAnalyzer(ISourceLocation location, int version, Duration delay) { | ||
logger.trace("Triggering analyzer for {}", location); | ||
var fileFacts = facts(location); | ||
fileFacts.invalidateAnalyzer(location); | ||
fileFacts.calculateAnalyzer(location, getFile(location).getCurrentTreeAsync(true), doc.getVersion(), delay); | ||
if (isLanguageRegistered(location)) { | ||
fileFacts.invalidateAnalyzer(location); | ||
fileFacts.calculateAnalyzer(location, getFile(location).getCurrentTreeAsync(true), version, delay); | ||
} | ||
} | ||
|
||
private void triggerBuilder(TextDocumentIdentifier doc) { | ||
|
@@ -343,12 +351,11 @@ private void triggerBuilder(TextDocumentIdentifier doc) { | |
fileFacts.calculateBuilder(location, getFile(location).getCurrentTreeAsync(true)); | ||
} | ||
|
||
private TextDocumentState updateContents(VersionedTextDocumentIdentifier doc, String newContents, long timestamp) { | ||
TextDocumentState file = getFile(Locations.toLoc(doc)); | ||
private void updateContents(VersionedTextDocumentIdentifier doc, String newContents, long timestamp) { | ||
logger.trace("New contents for {}", doc); | ||
TextDocumentState file = getFile(Locations.toLoc(doc)); | ||
columns.clear(file.getLocation()); | ||
handleParsingErrors(file, file.update(doc.getVersion(), newContents, timestamp)); | ||
return file; | ||
} | ||
|
||
private void handleParsingErrors(TextDocumentState file, CompletableFuture<Versioned<List<Diagnostics.Template>>> diagnosticsAsync) { | ||
|
@@ -522,8 +529,9 @@ public void didRenameFiles(RenameFilesParams params, List<WorkspaceFolder> works | |
private Map<ILanguageContributions, List<FileRename>> bundleRenamesByContribution(List<FileRename> allRenames) { | ||
Map<ILanguageContributions, List<FileRename>> bundled = new HashMap<>(); | ||
for (FileRename rename : allRenames) { | ||
String language = registeredExtensions.get(extension(URIUtil.assumeCorrectLocation(rename.getNewUri()))); | ||
if (language != null) { | ||
var l = URIUtil.assumeCorrectLocation(rename.getNewUri()); | ||
if (isLanguageRegistered(l)) { | ||
var language = language(l); | ||
ILanguageContributions contrib = contributions.get(language); | ||
if (contrib != null) { | ||
bundled.computeIfAbsent(contrib, k -> new ArrayList<>()).add(rename); | ||
|
@@ -597,38 +605,53 @@ private static <T> T last(List<T> l) { | |
return l.get(l.size() - 1); | ||
} | ||
|
||
private boolean isLanguageRegistered(ISourceLocation loc) { | ||
return registeredExtensions.containsKey(extension(loc)); | ||
} | ||
|
||
private String language(ISourceLocation loc) { | ||
var ext = extension(loc); | ||
var language = registeredExtensions.get(ext); | ||
if (language == null) { | ||
throw new UnsupportedOperationException(String.format("Rascal Parametric LSP has no support for this file, since no language is registered for extension '%s': %s", ext, loc)); | ||
} | ||
return language; | ||
} | ||
|
||
private ILanguageContributions contributions(ISourceLocation doc) { | ||
String language = registeredExtensions.get(extension(doc)); | ||
if (language != null) { | ||
ILanguageContributions contrib = contributions.get(language); | ||
ILanguageContributions contrib = contributions.get(language(doc)); | ||
|
||
if (contrib != null) { | ||
return contrib; | ||
} | ||
if (contrib == null) { | ||
throw new UnsupportedOperationException("Rascal Parametric LSP has no support for this file: " + doc); | ||
} | ||
|
||
throw new UnsupportedOperationException("Rascal Parametric LSP has no support for this file: " + doc); | ||
return contrib; | ||
} | ||
|
||
private static String extension(ISourceLocation doc) { | ||
return URIUtil.getExtension(doc); | ||
} | ||
|
||
private ParametricFileFacts facts(ISourceLocation doc) { | ||
String language = registeredExtensions.get(extension(doc)); | ||
if (language != null) { | ||
ParametricFileFacts fact = facts.get(language); | ||
if (fact != null) { | ||
return fact; | ||
} | ||
ParametricFileFacts fact = facts.get(language(doc)); | ||
|
||
if (fact == null) { | ||
throw new UnsupportedOperationException("Rascal Parametric LSP has no support for this file: " + doc); | ||
} | ||
throw new UnsupportedOperationException("Rascal Parametric LSP has no support for this file: " + doc); | ||
|
||
return fact; | ||
} | ||
|
||
private TextDocumentState open(TextDocumentItem doc, long timestamp) { | ||
return files.computeIfAbsent(Locations.toLoc(doc), | ||
l -> new TextDocumentState(contributions(l)::parsing, l, doc.getVersion(), doc.getText(), timestamp) | ||
); | ||
var loc = Locations.toLoc(doc); | ||
BiFunction<ISourceLocation, String, CompletableFuture<ITree>> parser | ||
= isLanguageRegistered(loc) | ||
? contributions(loc)::parsing | ||
// Language not (yet) registered; plug in an incomplete parse future | ||
: (l, s) -> new CompletableFuture<>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this future will never complete, won't that cause issues? like any down stream jobs? |
||
|
||
return files.computeIfAbsent(loc, | ||
l -> new TextDocumentState(parser, l, doc.getVersion(), doc.getText(), timestamp)); | ||
} | ||
|
||
private TextDocumentState getFile(ISourceLocation loc) { | ||
|
@@ -851,6 +874,21 @@ public synchronized void registerLanguage(LanguageParameter lang) { | |
if (client != null) { | ||
fact.setClient(client); | ||
} | ||
|
||
// If we opened any files with this extension before, now associate them with contributions | ||
var extensions = Arrays.asList(lang.getExtensions()); | ||
for (var e : files.entrySet()) { | ||
var f = e.getKey(); | ||
var state = e.getValue(); | ||
if (extensions.contains(extension(f))) { | ||
logger.trace("Open file of language {} - updating state: {}", lang.getName(), f); | ||
var c = state.getCurrentContent(); | ||
state = files.replace(f, new TextDocumentState(contributions(f)::parsing, f, c.version(), state.getCurrentContent().get(), state.getLastModified())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should have a function on |
||
// Update open editor | ||
triggerAnalyzer(f, c.version(), NORMAL_DEBOUNCE); | ||
handleParsingErrors(state, state.getCurrentDiagnosticsAsync()); | ||
} | ||
} | ||
} | ||
|
||
private static String buildContributionKey(LanguageParameter lang) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this log should be inside the if, and an else branch that logs why we're not triggering an analyzer?