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

Semantic tokenizer improvements: tests, simplification, syntax-in-syntax bugfix #497

Merged
merged 39 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4cee25d
Add first tests for the semantic highlighter
sungshik Oct 30, 2024
c588d7c
Remove unused imports
sungshik Oct 30, 2024
42af05f
Sort tokens by location before comparing them with expected categories
sungshik Oct 30, 2024
2552ca8
Improve test utilities for semantic highlighter
sungshik Oct 30, 2024
ee18e05
Add semantic tokenizer tests for nested categories
sungshik Oct 30, 2024
52f6de9
Improve test utilities for semantic tokenizer
sungshik Oct 30, 2024
4ce36dc
Improve test utilities for semantic tokenizer
sungshik Oct 30, 2024
c52aff9
Add semantic tokenizer tests for unicode (surrogate pair counting)
sungshik Oct 30, 2024
8b2ccf5
Add license
sungshik Oct 30, 2024
32d5ff7
Improve `testKeywordLastLine` (semantic tokenizer)
sungshik Nov 1, 2024
a69585c
Merge pull request #494 from usethesource/semantic-tokenizer-fall2024…
sungshik Nov 1, 2024
6c2ed04
Refactor class `TokenCollector` of the semantic tokenizer
sungshik Nov 1, 2024
5b7b264
Simplify code to collect ambiguity semantic tokens
sungshik Nov 4, 2024
a7aa3f9
Make diff smaller
sungshik Nov 4, 2024
41cfe99
Make diff smaller
sungshik Nov 4, 2024
f921a8f
Add support for three token collector modes to the semantic tokenizer
sungshik Nov 4, 2024
4931b7d
Merge pull request #500 from usethesource/semantic-tokenizer-fall2024…
sungshik Nov 4, 2024
cf2e8cc
Merge branch 'semantic-tokenizer-fall2024' into semantic-tokenizer-fa…
sungshik Nov 4, 2024
8d7da6b
Fix identation
sungshik Nov 4, 2024
4266b26
Add comment to test
sungshik Nov 4, 2024
9ce5e9e
Fix comments
sungshik Nov 4, 2024
08cfe20
Fix indentation
sungshik Nov 4, 2024
fac4f05
Fix typos
sungshik Nov 5, 2024
0435743
Add `useLegacyHighlighting` parameter to the `LanguageService` ADT (a…
sungshik Nov 5, 2024
75e8b30
Add support for `useLegacyHighlighting` in the semantic tokenizer
sungshik Nov 5, 2024
161d638
Update the semantic tokenizer tests for `useLegacyHighlighting`
sungshik Nov 5, 2024
e3e12b9
Fix typos, shorten names
sungshik Nov 5, 2024
29e222f
Update Pico demo language server to not use legacy highlighting
sungshik Nov 5, 2024
9175367
Rename `legacyHighlighting` to `specialCaseHighlighting`
sungshik Nov 6, 2024
22f28d9
Fix support for special-case-highlighting in `ParserOnlyContribution`
sungshik Nov 6, 2024
cb5a1a3
Merge pull request #502 from usethesource/semantic-tokenizer-fall2024…
sungshik Nov 6, 2024
69ab630
Use `IListWriter` instead of writing a list
sungshik Nov 6, 2024
59cb6da
Merge branch 'main' into semantic-tokenizer-fall2024
sungshik Nov 6, 2024
8ece553
Improve formatting
sungshik Nov 8, 2024
e3ae8e5
Clarify documentation of property `specialCaseHighlighting` in TS
sungshik Nov 8, 2024
726ace4
Move value factory to class field
sungshik Nov 8, 2024
92497d0
Use the special-case highlighting status of the first contribution
sungshik Nov 8, 2024
62a8c05
Merge branch 'main' into semantic-tokenizer-fall2024
sungshik Nov 8, 2024
3f4e303
Move value factory to constructor
sungshik Nov 8, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public interface ILanguageContributions {
public CompletableFuture<Boolean> hasImplementation();
public CompletableFuture<Boolean> hasCodeAction();

public CompletableFuture<Boolean> specialCaseHighlighting();

public CompletableFuture<SummaryConfig> getAnalyzerSummaryConfig();
public CompletableFuture<SummaryConfig> getBuilderSummaryConfig();
public CompletableFuture<SummaryConfig> getOndemandSummaryConfig();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ public class InterpretedLanguageContributions implements ILanguageContributions
private final CompletableFuture<Boolean> hasImplementation;
private final CompletableFuture<Boolean> hasCodeAction;

private final CompletableFuture<Boolean> specialCaseHighlighting;

private final CompletableFuture<SummaryConfig> analyzerSummaryConfig;
private final CompletableFuture<SummaryConfig> builderSummaryConfig;
private final CompletableFuture<SummaryConfig> ondemandSummaryConfig;
Expand Down Expand Up @@ -151,6 +153,10 @@ public InterpretedLanguageContributions(LanguageParameter lang, IBaseTextDocumen
this.hasImplementation = nonNull(this.implementation);
this.hasCodeAction = nonNull(this.codeAction);

this.specialCaseHighlighting = getContributionParameter(contributions,
LanguageContributions.PARSING,
LanguageContributions.Parameters.USES_SPECIAL_CASE_HIGHLIGHTING);

this.analyzerSummaryConfig = scheduledSummaryConfig(contributions, LanguageContributions.ANALYSIS);
this.builderSummaryConfig = scheduledSummaryConfig(contributions, LanguageContributions.BUILD);
this.ondemandSummaryConfig = ondemandSummaryConfig(contributions);
Expand All @@ -170,10 +176,10 @@ private static CompletableFuture<SummaryConfig> scheduledSummaryConfig(Completab
var constructor = getContribution(c, summarizer);
if (constructor != null) {
return new SummaryConfig(
isTrue(constructor, LanguageContributions.Summarizers.PROVIDES_HOVERS),
isTrue(constructor, LanguageContributions.Summarizers.PROVIDES_DEFINITIONS),
isTrue(constructor, LanguageContributions.Summarizers.PROVIDES_REFERENCES),
isTrue(constructor, LanguageContributions.Summarizers.PROVIDES_IMPLEMENTATIONS));
isTrue(constructor, LanguageContributions.Parameters.PROVIDES_HOVERS),
isTrue(constructor, LanguageContributions.Parameters.PROVIDES_DEFINITIONS),
isTrue(constructor, LanguageContributions.Parameters.PROVIDES_REFERENCES),
isTrue(constructor, LanguageContributions.Parameters.PROVIDES_IMPLEMENTATIONS));
} else {
return SummaryConfig.FALSY;
}
Expand Down Expand Up @@ -202,6 +208,12 @@ private static boolean hasContribution(ISet contributions, String name) {
return getContribution(contributions, name) != null;
}

private static CompletableFuture<Boolean> getContributionParameter(
CompletableFuture<ISet> contributions, String name, String parameter) {

return contributions.thenApply(c -> isTrue(getContribution(c, name), parameter));
}

private static boolean isTrue(@Nullable IConstructor constructor, String parameter) {
if (constructor == null) {
return false;
Expand Down Expand Up @@ -388,6 +400,11 @@ public CompletableFuture<Boolean> hasBuild() {
return hasBuild;
}

@Override
public CompletableFuture<Boolean> specialCaseHighlighting() {
return specialCaseHighlighting;
}

@Override
public CompletableFuture<SummaryConfig> getAnalyzerSummaryConfig() {
return analyzerSummaryConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ private static final <T> CompletableFuture<T> failedInitialization() {
private volatile CompletableFuture<Boolean> hasImplementation = failedInitialization();
private volatile CompletableFuture<Boolean> hasCodeAction = failedInitialization();

private volatile CompletableFuture<Boolean> specialCaseHighlighting = failedInitialization();

private volatile CompletableFuture<SummaryConfig> analyzerSummaryConfig;
private volatile CompletableFuture<SummaryConfig> builderSummaryConfig;
private volatile CompletableFuture<SummaryConfig> ondemandSummaryConfig;
Expand Down Expand Up @@ -159,6 +161,11 @@ private synchronized void calculateRouting() {
hasReferences = anyTrue(ILanguageContributions::hasReferences);
hasImplementation = anyTrue(ILanguageContributions::hasImplementation);

// Always use the special-case highlighting status of *the first*
// contribution (possibly using the default value in the Rascal ADT if
// it's not explicitly set), just as for `parsing` itself
specialCaseHighlighting = firstOrFail().specialCaseHighlighting();

analyzerSummaryConfig = anyTrue(ILanguageContributions::getAnalyzerSummaryConfig, SummaryConfig.FALSY, SummaryConfig::or);
builderSummaryConfig = anyTrue(ILanguageContributions::getBuilderSummaryConfig, SummaryConfig.FALSY, SummaryConfig::or);
ondemandSummaryConfig = anyTrue(ILanguageContributions::getOndemandSummaryConfig, SummaryConfig.FALSY, SummaryConfig::or);
Expand Down Expand Up @@ -343,6 +350,11 @@ public CompletableFuture<Boolean> hasInlayHint() {
return hasInlayHint;
}

@Override
public CompletableFuture<Boolean> specialCaseHighlighting() {
return specialCaseHighlighting;
}

@Override
public CompletableFuture<SummaryConfig> getAnalyzerSummaryConfig() {
return analyzerSummaryConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,10 @@ public void shutdown() {
}

private CompletableFuture<SemanticTokens> getSemanticTokens(TextDocumentIdentifier doc) {
var specialCaseHighlighting = contributions(doc).specialCaseHighlighting();
return recoverExceptions(getFile(doc).getCurrentTreeAsync()
.thenApply(Versioned::get)
.thenApplyAsync(tokenizer::semanticTokensFull, ownExecuter)
.thenCombineAsync(specialCaseHighlighting, tokenizer::semanticTokensFull, ownExecuter)
.whenComplete((r, e) ->
logger.trace("Semantic tokens success, reporting {} tokens back", r == null ? 0 : r.getData().size() / 5)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class ParserOnlyContribution implements ILanguageContributions {
private final String name;
private final @Nullable Exception loadingParserError;
private final @Nullable IFunction parser;
private final CompletableFuture<Boolean> specialCaseHighlighting;

public ParserOnlyContribution(String name, ParserSpecification spec) {
this.name = name;
Expand All @@ -67,6 +68,7 @@ public ParserOnlyContribution(String name, ParserSpecification spec) {
Either<IFunction,Exception> result = loadParser(spec);
this.parser = result.getLeft();
this.loadingParserError = result.getRight();
this.specialCaseHighlighting = CompletableFuture.completedFuture(spec.getSpecialCaseHighlighting());
}

@Override
Expand Down Expand Up @@ -228,6 +230,11 @@ public CompletableFuture<Boolean> hasInlayHint() {
return CompletableFuture.completedFuture(false);
}

@Override
public CompletableFuture<Boolean> specialCaseHighlighting() {
return specialCaseHighlighting;
}

@Override
public CompletableFuture<SummaryConfig> getAnalyzerSummaryConfig() {
return CompletableFuture.completedFuture(SummaryConfig.FALSY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ private LanguageContributions () {}
public static final String IMPLEMENTATION = "implementation";
public static final String CODE_ACTION = "codeAction";

public static class Summarizers {
private Summarizers() {}
public static class Parameters {
private Parameters() {}

public static final String USES_SPECIAL_CASE_HIGHLIGHTING = "usesSpecialCaseHighlighting";

public static final String PROVIDES_HOVERS = "providesHovers";
public static final String PROVIDES_DEFINITIONS = "providesDefinitions";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,10 @@ public void shutdown() {
}

private CompletableFuture<SemanticTokens> getSemanticTokens(TextDocumentIdentifier doc) {
var specialCaseHighlighting = CompletableFuture.completedFuture(false);
return getFile(doc).getCurrentTreeAsync()
.thenApply(Versioned::get)
.thenApplyAsync(tokenizer::semanticTokensFull, ownExecuter)
.thenCombineAsync(specialCaseHighlighting, tokenizer::semanticTokensFull, ownExecuter)
.exceptionally(e -> {
logger.error("Tokenization failed", e);
return new SemanticTokens(Collections.emptyList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,13 +528,17 @@ public static class ParserSpecification {
private final @Nullable Boolean nonTerminalIsStart;
/** allowAmbiguity (default is false) */
private final @Nullable Boolean allowAmbiguity;
/** apply the special case for highlighting syntax-in-syntax, default: true */
private final @Nullable Boolean specialCaseHighlighting;


public ParserSpecification(String parserLocation, String nonTerminalName, @Nullable Boolean nonTerminalIsStart, @Nullable Boolean allowAmbiguity) {
public ParserSpecification(String parserLocation, String nonTerminalName,
@Nullable Boolean nonTerminalIsStart, @Nullable Boolean allowAmbiguity, @Nullable Boolean specialCaseHighlighting) {
this.parserLocation = parserLocation;
this.nonTerminalName = nonTerminalName;
this.nonTerminalIsStart = nonTerminalIsStart;
this.allowAmbiguity = allowAmbiguity;
this.specialCaseHighlighting = specialCaseHighlighting;
}

public ISourceLocation getParserLocation() throws FactTypeUseException {
Expand All @@ -553,6 +557,10 @@ public boolean getAllowAmbiguity() {
return allowAmbiguity != null && allowAmbiguity;
}

public boolean getSpecialCaseHighlighting() {
return specialCaseHighlighting == null || specialCaseHighlighting;
}

@Override
public String toString() {
return "ParserSpecification [parserLocation=" + parserLocation + ", nonTerminalName=" + nonTerminalName
Expand Down
Loading
Loading