Highlight color adjustments
This commit is contained in:
parent
dfad621d05
commit
905d92afe7
@ -39,6 +39,7 @@ public final class PBSFrontendHostProjections {
|
||||
case HOST -> projection(HOST.semanticKey(), "class", "type", "defaultLibrary");
|
||||
case BUILTIN_TYPE -> projection(BUILTIN_TYPE.semanticKey(), "type", "variable", "defaultLibrary");
|
||||
case SERVICE -> projection(SERVICE.semanticKey(), "class", "type", "defaultLibrary");
|
||||
case ASSET -> projection(ASSET.semanticKey(), "variable", "string", "readonly");
|
||||
case ERROR -> projection(ERROR.semanticKey(), "enum", "type");
|
||||
case ENUM -> projection(ENUM.semanticKey(), "enum", "type");
|
||||
case CALLBACK -> projection(CALLBACK.semanticKey(), "interface", "type");
|
||||
|
||||
@ -20,21 +20,22 @@ public class PBSFrontendThemes {
|
||||
"#f5efff"),
|
||||
List.of(
|
||||
new FrontendTokenStyleSpec("pbs-comment", "#8b949e", true, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-string", "#7ee787", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-number", "#ffa657", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-literal", "#79c0ff", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-string", "#d8b86a", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-number", "#ff8cc6", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-literal", "#7fb8ff", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-lifecycle", "#ff7b72", false, true, false),
|
||||
new FrontendTokenStyleSpec("pbs-keyword", "#d2a8ff", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-keyword", "#7fb8ff", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-operator", "#c9d1d9", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-punctuation", "#8b949e", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-function", "#ffa657", false, true, false),
|
||||
new FrontendTokenStyleSpec("pbs-method", "#ffd580", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-constructor", "#e3b341", false, true, false),
|
||||
new FrontendTokenStyleSpec("pbs-struct", "#56d4dd", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-function", "#7ee787", false, true, false),
|
||||
new FrontendTokenStyleSpec("pbs-method", "#7ee787", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-constructor", "#7ee787", false, true, false),
|
||||
new FrontendTokenStyleSpec("pbs-struct", "#56d4dd", true, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-contract", "#79c0ff", false, false, true),
|
||||
new FrontendTokenStyleSpec("pbs-host", "#c297ff", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-builtin-type", "#7ee787", true, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-builtin-type", "#56d4dd", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-service", "#ff8e7a", false, true, false),
|
||||
new FrontendTokenStyleSpec("pbs-asset", "#c297ff", false, false, false),
|
||||
new FrontendTokenStyleSpec("pbs-error", "#ff7b72", false, false, true),
|
||||
new FrontendTokenStyleSpec("pbs-enum", "#56d4dd", false, true, false),
|
||||
new FrontendTokenStyleSpec("pbs-callback", "#ffb3e6", false, false, false),
|
||||
|
||||
@ -2,33 +2,44 @@ package p.studio.compiler;
|
||||
|
||||
import p.studio.compiler.models.FrontendSemanticToken;
|
||||
import p.studio.compiler.models.FrontendSemanticTokenProvider;
|
||||
import p.studio.compiler.pbs.ast.PbsAst;
|
||||
import p.studio.compiler.pbs.PbsSemanticKind;
|
||||
import p.studio.compiler.pbs.lexer.PbsLexer;
|
||||
import p.studio.compiler.pbs.lexer.PbsToken;
|
||||
import p.studio.compiler.pbs.lexer.PbsTokenKind;
|
||||
import p.studio.compiler.pbs.parser.PbsBarrelParser;
|
||||
import p.studio.compiler.pbs.parser.PbsParser;
|
||||
import p.studio.compiler.pbs.stdlib.ResourceStdlibEnvironmentResolver;
|
||||
import p.studio.compiler.pbs.stdlib.StdlibModuleSource;
|
||||
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||
import p.studio.compiler.source.identifiers.FileId;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider {
|
||||
private static final Set<String> BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "string", "i32", "i64", "f32", "f64");
|
||||
private static final int DEFAULT_STDLIB_VERSION = 1;
|
||||
private static final ResourceStdlibEnvironmentResolver STDLIB_RESOLVER = new ResourceStdlibEnvironmentResolver();
|
||||
private static final Map<PbsTokenKind, PbsSemanticKind> DECLARATION_KINDS = declarationKinds();
|
||||
|
||||
@Override
|
||||
public List<FrontendSemanticToken> tokenize(final String documentText) {
|
||||
final String effectiveText = documentText == null ? "" : documentText;
|
||||
final ReadOnlyList<PbsToken> tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty());
|
||||
final Map<String, PbsSemanticKind> declaredKindsByName = collectDeclaredKinds(tokens);
|
||||
final Set<Integer> assetReferenceTokenIndexes = collectAssetReferenceTokenIndexes(tokens);
|
||||
final ArrayList<FrontendSemanticToken> semanticTokens = new ArrayList<>();
|
||||
|
||||
for (int index = 0; index < tokens.size(); index += 1) {
|
||||
final PbsToken token = tokens.get(index);
|
||||
final PbsSemanticKind semanticKind = classifyToken(tokens, index, declaredKindsByName);
|
||||
final PbsSemanticKind semanticKind = classifyToken(tokens, index, declaredKindsByName, assetReferenceTokenIndexes);
|
||||
if (semanticKind == null) {
|
||||
continue;
|
||||
}
|
||||
@ -41,13 +52,17 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
||||
private PbsSemanticKind classifyToken(
|
||||
final ReadOnlyList<PbsToken> tokens,
|
||||
final int index,
|
||||
final Map<String, PbsSemanticKind> declaredKindsByName) {
|
||||
final Map<String, PbsSemanticKind> declaredKindsByName,
|
||||
final Set<Integer> assetReferenceTokenIndexes) {
|
||||
final PbsToken token = tokens.get(index);
|
||||
final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token);
|
||||
if (lexicalKind != null) {
|
||||
return lexicalKind;
|
||||
}
|
||||
if (token.kind() == PbsTokenKind.IDENTIFIER) {
|
||||
if (assetReferenceTokenIndexes.contains(index)) {
|
||||
return PbsSemanticKind.ASSET;
|
||||
}
|
||||
if (isLifecycleToken(tokens, index, token)) {
|
||||
return PbsSemanticKind.LIFECYCLE;
|
||||
}
|
||||
@ -63,6 +78,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
||||
final Map<String, PbsSemanticKind> declaredKindsByName) {
|
||||
final PbsTokenKind previousKind = previousSignificantKind(tokens, index);
|
||||
final PbsTokenKind nextKind = nextSignificantKind(tokens, index);
|
||||
final boolean typeReferenceContext = isTypeReferenceContext(previousKind);
|
||||
|
||||
if (previousKind == PbsTokenKind.STRUCT) {
|
||||
return PbsSemanticKind.STRUCT;
|
||||
@ -101,7 +117,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
||||
}
|
||||
if (nextKind == PbsTokenKind.DOT
|
||||
|| previousKind == PbsTokenKind.NEW
|
||||
|| isTypeReferenceContext(previousKind, token.lexeme())) {
|
||||
|| typeReferenceContext) {
|
||||
return declaredKind;
|
||||
}
|
||||
}
|
||||
@ -111,7 +127,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
||||
if (nextKind == PbsTokenKind.LEFT_PAREN) {
|
||||
return PbsSemanticKind.FUNCTION;
|
||||
}
|
||||
if (isTypeReferenceContext(previousKind, token.lexeme())) {
|
||||
if (typeReferenceContext && BUILTIN_TYPE_NAMES.contains(token.lexeme())) {
|
||||
return PbsSemanticKind.BUILTIN_TYPE;
|
||||
}
|
||||
return PbsSemanticKind.IDENTIFIER;
|
||||
@ -131,28 +147,163 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
||||
}
|
||||
declaredKindsByName.put(nextToken.lexeme(), declarationKind);
|
||||
}
|
||||
declaredKindsByName.putAll(collectStdlibImportedKinds(tokens));
|
||||
return Map.copyOf(declaredKindsByName);
|
||||
}
|
||||
|
||||
private Set<Integer> collectAssetReferenceTokenIndexes(final ReadOnlyList<PbsToken> tokens) {
|
||||
final Set<Integer> indexes = new HashSet<>();
|
||||
for (int index = 0; index < tokens.size(); index += 1) {
|
||||
final PbsToken token = tokens.get(index);
|
||||
if (token.kind() != PbsTokenKind.IDENTIFIER || !"assets".equals(token.lexeme())) {
|
||||
continue;
|
||||
}
|
||||
final Integer firstDotIndex = nextSignificantIndex(tokens, index);
|
||||
if (firstDotIndex == null || tokens.get(firstDotIndex).kind() != PbsTokenKind.DOT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
indexes.add(index);
|
||||
Integer cursor = firstDotIndex;
|
||||
while (cursor != null && tokens.get(cursor).kind() == PbsTokenKind.DOT) {
|
||||
final Integer memberIndex = nextSignificantIndex(tokens, cursor);
|
||||
if (memberIndex == null || tokens.get(memberIndex).kind() != PbsTokenKind.IDENTIFIER) {
|
||||
break;
|
||||
}
|
||||
indexes.add(memberIndex);
|
||||
cursor = nextSignificantIndex(tokens, memberIndex);
|
||||
}
|
||||
}
|
||||
return Set.copyOf(indexes);
|
||||
}
|
||||
|
||||
private PbsSemanticKind declarationKind(final PbsTokenKind kind) {
|
||||
return switch (kind) {
|
||||
case STRUCT -> PbsSemanticKind.STRUCT;
|
||||
case CONTRACT -> PbsSemanticKind.CONTRACT;
|
||||
case HOST -> PbsSemanticKind.HOST;
|
||||
case SERVICE -> PbsSemanticKind.SERVICE;
|
||||
case ENUM, ERROR -> PbsSemanticKind.ENUM;
|
||||
case CALLBACK -> PbsSemanticKind.CALLBACK;
|
||||
case GLOBAL -> PbsSemanticKind.GLOBAL;
|
||||
case CONST -> PbsSemanticKind.CONST;
|
||||
case CTOR -> PbsSemanticKind.CONSTRUCTOR;
|
||||
case BUILTIN -> PbsSemanticKind.BUILTIN_TYPE;
|
||||
default -> null;
|
||||
return DECLARATION_KINDS.get(kind);
|
||||
}
|
||||
|
||||
private Map<String, PbsSemanticKind> collectStdlibImportedKinds(final ReadOnlyList<PbsToken> tokens) {
|
||||
final DiagnosticSink diagnostics = DiagnosticSink.empty();
|
||||
final PbsAst.File file = PbsParser.parse(tokens, FileId.none(), diagnostics);
|
||||
final Map<String, PbsSemanticKind> importedKindsByLocalName = new HashMap<>();
|
||||
for (final PbsAst.ImportDecl importDecl : file.imports()) {
|
||||
if (importDecl.items().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
final Map<String, PbsSemanticKind> exportedKinds = resolveStdlibExportKinds(importDecl.moduleRef());
|
||||
if (exportedKinds.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (final Map.Entry<String, PbsSemanticKind> entry : exportedKinds.entrySet()) {
|
||||
if (entry.getValue() == PbsSemanticKind.BUILTIN_TYPE) {
|
||||
importedKindsByLocalName.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
for (final PbsAst.ImportItem item : importDecl.items()) {
|
||||
final PbsSemanticKind semanticKind = exportedKinds.get(item.name());
|
||||
if (semanticKind == null) {
|
||||
continue;
|
||||
}
|
||||
importedKindsByLocalName.put(item.alias() == null ? item.name() : item.alias(), semanticKind);
|
||||
}
|
||||
}
|
||||
return importedKindsByLocalName;
|
||||
}
|
||||
|
||||
private Map<String, PbsSemanticKind> resolveStdlibExportKinds(final PbsAst.ModuleRef moduleRef) {
|
||||
final var stdlibEnvironment = STDLIB_RESOLVER.resolve(DEFAULT_STDLIB_VERSION);
|
||||
return stdlibEnvironment.resolveModule(moduleRef.project(), moduleRef.pathSegments())
|
||||
.map(this::parseStdlibVisibleKinds)
|
||||
.orElseGet(Map::of);
|
||||
}
|
||||
|
||||
private Map<String, PbsSemanticKind> parseStdlibVisibleKinds(final StdlibModuleSource moduleSource) {
|
||||
final Map<String, PbsSemanticKind> visibleKinds = new HashMap<>(parseBarrelExportKinds(moduleSource.barrelSource()));
|
||||
for (final StdlibModuleSource.SourceFile sourceFile : moduleSource.sourceFiles()) {
|
||||
visibleKinds.putAll(parseBuiltinTypeKinds(sourceFile.source()));
|
||||
}
|
||||
return visibleKinds;
|
||||
}
|
||||
|
||||
private Map<String, PbsSemanticKind> parseBarrelExportKinds(final String barrelSource) {
|
||||
final ReadOnlyList<PbsToken> barrelTokens = PbsLexer.lex(barrelSource, FileId.none(), DiagnosticSink.empty());
|
||||
final PbsAst.BarrelFile barrelFile = PbsBarrelParser.parse(barrelTokens, FileId.none(), DiagnosticSink.empty());
|
||||
final Map<String, PbsSemanticKind> exportedKinds = new HashMap<>();
|
||||
for (final PbsAst.BarrelItem item : barrelFile.items()) {
|
||||
final PbsSemanticKind semanticKind = semanticKindForBarrelItem(item);
|
||||
if (semanticKind == null) {
|
||||
continue;
|
||||
}
|
||||
if (item instanceof PbsAst.BarrelStructItem structItem && structItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(structItem.name(), semanticKind);
|
||||
} else if (item instanceof PbsAst.BarrelContractItem contractItem && contractItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(contractItem.name(), semanticKind);
|
||||
} else if (item instanceof PbsAst.BarrelHostItem hostItem && hostItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(hostItem.name(), semanticKind);
|
||||
} else if (item instanceof PbsAst.BarrelErrorItem errorItem && errorItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(errorItem.name(), semanticKind);
|
||||
} else if (item instanceof PbsAst.BarrelEnumItem enumItem && enumItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(enumItem.name(), semanticKind);
|
||||
} else if (item instanceof PbsAst.BarrelServiceItem serviceItem && serviceItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(serviceItem.name(), semanticKind);
|
||||
} else if (item instanceof PbsAst.BarrelGlobalItem globalItem && globalItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(globalItem.name(), semanticKind);
|
||||
} else if (item instanceof PbsAst.BarrelConstItem constItem && constItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(constItem.name(), semanticKind);
|
||||
} else if (item instanceof PbsAst.BarrelCallbackItem callbackItem && callbackItem.visibility() == PbsAst.Visibility.PUB) {
|
||||
exportedKinds.put(callbackItem.name(), semanticKind);
|
||||
}
|
||||
}
|
||||
return exportedKinds;
|
||||
}
|
||||
|
||||
private Map<String, PbsSemanticKind> parseBuiltinTypeKinds(final String source) {
|
||||
final ReadOnlyList<PbsToken> sourceTokens = PbsLexer.lex(source, FileId.none(), DiagnosticSink.empty());
|
||||
final PbsAst.File file = PbsParser.parse(
|
||||
sourceTokens,
|
||||
FileId.none(),
|
||||
DiagnosticSink.empty(),
|
||||
PbsParser.ParseMode.INTERFACE_MODULE);
|
||||
final Map<String, PbsSemanticKind> builtinKinds = new HashMap<>();
|
||||
for (final PbsAst.TopDecl topDecl : file.topDecls()) {
|
||||
if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) {
|
||||
builtinKinds.put(builtinTypeDecl.name(), PbsSemanticKind.BUILTIN_TYPE);
|
||||
}
|
||||
}
|
||||
return builtinKinds;
|
||||
}
|
||||
|
||||
private PbsSemanticKind semanticKindForBarrelItem(final PbsAst.BarrelItem item) {
|
||||
return switch (item) {
|
||||
case PbsAst.BarrelStructItem ignored -> PbsSemanticKind.STRUCT;
|
||||
case PbsAst.BarrelContractItem ignored -> PbsSemanticKind.CONTRACT;
|
||||
case PbsAst.BarrelHostItem ignored -> PbsSemanticKind.HOST;
|
||||
case PbsAst.BarrelErrorItem ignored -> PbsSemanticKind.ENUM;
|
||||
case PbsAst.BarrelEnumItem ignored -> PbsSemanticKind.ENUM;
|
||||
case PbsAst.BarrelServiceItem ignored -> PbsSemanticKind.SERVICE;
|
||||
case PbsAst.BarrelGlobalItem ignored -> PbsSemanticKind.GLOBAL;
|
||||
case PbsAst.BarrelConstItem ignored -> PbsSemanticKind.CONST;
|
||||
case PbsAst.BarrelCallbackItem ignored -> PbsSemanticKind.CALLBACK;
|
||||
case PbsAst.BarrelFunctionItem ignored -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private boolean isTypeReferenceContext(
|
||||
final PbsTokenKind previousKind,
|
||||
final String lexeme) {
|
||||
private static Map<PbsTokenKind, PbsSemanticKind> declarationKinds() {
|
||||
final Map<PbsTokenKind, PbsSemanticKind> kinds = new EnumMap<>(PbsTokenKind.class);
|
||||
kinds.put(PbsTokenKind.STRUCT, PbsSemanticKind.STRUCT);
|
||||
kinds.put(PbsTokenKind.CONTRACT, PbsSemanticKind.CONTRACT);
|
||||
kinds.put(PbsTokenKind.HOST, PbsSemanticKind.HOST);
|
||||
kinds.put(PbsTokenKind.SERVICE, PbsSemanticKind.SERVICE);
|
||||
kinds.put(PbsTokenKind.ENUM, PbsSemanticKind.ENUM);
|
||||
kinds.put(PbsTokenKind.ERROR, PbsSemanticKind.ENUM);
|
||||
kinds.put(PbsTokenKind.CALLBACK, PbsSemanticKind.CALLBACK);
|
||||
kinds.put(PbsTokenKind.GLOBAL, PbsSemanticKind.GLOBAL);
|
||||
kinds.put(PbsTokenKind.CONST, PbsSemanticKind.CONST);
|
||||
kinds.put(PbsTokenKind.CTOR, PbsSemanticKind.CONSTRUCTOR);
|
||||
kinds.put(PbsTokenKind.BUILTIN, PbsSemanticKind.BUILTIN_TYPE);
|
||||
return Map.copyOf(kinds);
|
||||
}
|
||||
|
||||
private boolean isTypeReferenceContext(final PbsTokenKind previousKind) {
|
||||
if (previousKind == null) {
|
||||
return false;
|
||||
}
|
||||
@ -162,7 +313,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
||||
&& previousKind != PbsTokenKind.IMPLEMENTS) {
|
||||
return false;
|
||||
}
|
||||
return BUILTIN_TYPE_NAMES.contains(lexeme);
|
||||
return true;
|
||||
}
|
||||
|
||||
private PbsTokenKind previousSignificantKind(
|
||||
@ -181,12 +332,19 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
||||
private PbsTokenKind nextSignificantKind(
|
||||
final ReadOnlyList<PbsToken> tokens,
|
||||
final int index) {
|
||||
final Integer cursor = nextSignificantIndex(tokens, index);
|
||||
return cursor == null ? null : tokens.get(cursor).kind();
|
||||
}
|
||||
|
||||
private Integer nextSignificantIndex(
|
||||
final ReadOnlyList<PbsToken> tokens,
|
||||
final int index) {
|
||||
for (int cursor = index + 1; cursor < tokens.size(); cursor += 1) {
|
||||
final PbsTokenKind kind = tokens.get(cursor).kind();
|
||||
if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) {
|
||||
continue;
|
||||
}
|
||||
return kind;
|
||||
return cursor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ public enum PbsSemanticKind {
|
||||
HOST("pbs-host"),
|
||||
BUILTIN_TYPE("pbs-builtin-type"),
|
||||
SERVICE("pbs-service"),
|
||||
ASSET("pbs-asset"),
|
||||
ERROR("pbs-error"),
|
||||
ENUM("pbs-enum"),
|
||||
CALLBACK("pbs-callback"),
|
||||
|
||||
@ -23,9 +23,19 @@ final class PbsSemanticPresentationContractTest {
|
||||
assertEquals(1, presentation.themes().size());
|
||||
assertEquals("PBS Default", presentation.defaultTheme().displayName());
|
||||
assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground());
|
||||
assertEquals("#d2a8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground());
|
||||
assertEquals("#7fb8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground());
|
||||
assertEquals("#d8b86a", presentation.defaultTheme().requireTokenStyle("pbs-string").foreground());
|
||||
assertEquals("#ff8cc6", presentation.defaultTheme().requireTokenStyle("pbs-number").foreground());
|
||||
assertEquals("#7fb8ff", presentation.defaultTheme().requireTokenStyle("pbs-literal").foreground());
|
||||
assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-function").foreground());
|
||||
assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-method").foreground());
|
||||
assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-constructor").foreground());
|
||||
assertEquals("#56d4dd", presentation.defaultTheme().requireTokenStyle("pbs-struct").foreground());
|
||||
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-struct").italic());
|
||||
assertEquals("#56d4dd", presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").foreground());
|
||||
assertFalse(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic());
|
||||
assertEquals("#ff8e7a", presentation.defaultTheme().requireTokenStyle("pbs-service").foreground());
|
||||
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic());
|
||||
assertEquals("#c297ff", presentation.defaultTheme().requireTokenStyle("pbs-asset").foreground());
|
||||
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic());
|
||||
assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId());
|
||||
}
|
||||
@ -50,6 +60,7 @@ final class PbsSemanticPresentationContractTest {
|
||||
vscodeProjection.tokenProjections().stream().map(tokenProjection -> tokenProjection.semanticKey()).toList());
|
||||
assertEquals("keyword", vscodeProjection.requireProjection(PbsSemanticKind.KEYWORD.semanticKey()).hostTokenType());
|
||||
assertEquals("type", vscodeProjection.requireProjection(PbsSemanticKind.STRUCT.semanticKey()).fallbackTokenType());
|
||||
assertEquals("variable", vscodeProjection.requireProjection(PbsSemanticKind.ASSET.semanticKey()).hostTokenType());
|
||||
assertEquals(
|
||||
java.util.List.of("readonly"),
|
||||
vscodeProjection.requireProjection(PbsSemanticKind.GLOBAL.semanticKey()).hostTokenModifiers());
|
||||
@ -73,7 +84,7 @@ final class PbsSemanticPresentationContractTest {
|
||||
}
|
||||
""");
|
||||
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.STRUCT.semanticKey())));
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())));
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.FUNCTION.semanticKey())));
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONST.semanticKey())));
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())));
|
||||
@ -83,4 +94,53 @@ final class PbsSemanticPresentationContractTest {
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.HOST.semanticKey())));
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.ENUM.semanticKey())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldClassifyStdlibImportsUsingTheirPublishedBarrelKinds() {
|
||||
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
|
||||
import { Log } from @sdk:log;
|
||||
import { Composer } from @sdk:composer;
|
||||
import { Color as Paint } from @core:color;
|
||||
|
||||
fn main() -> void {
|
||||
Log.info("hello");
|
||||
Composer.emit_sprite(0, 0, 0, 0, 0, 0, false, false, 0);
|
||||
let paint: Paint;
|
||||
}
|
||||
""");
|
||||
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.SERVICE.semanticKey())));
|
||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldClassifyAssetRootedAliasesUsingDedicatedSemanticKind() {
|
||||
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
|
||||
import { Assets } from @sdk:asset;
|
||||
|
||||
fn main() -> void {
|
||||
Assets.load(assets.ui.atlas2, 3);
|
||||
}
|
||||
""");
|
||||
|
||||
final long assetTokenCount = semanticTokens.stream()
|
||||
.filter(token -> token.semanticKey().equals(PbsSemanticKind.ASSET.semanticKey()))
|
||||
.count();
|
||||
|
||||
assertEquals(3, assetTokenCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldClassifyBuiltinTypesExposedByImportedStdlibModules() {
|
||||
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
|
||||
import { Input } from @sdk:input;
|
||||
|
||||
fn main() -> void {
|
||||
let touch : InputTouch = Input.touch();
|
||||
let pad : InputPad = Input.pad();
|
||||
}
|
||||
""");
|
||||
|
||||
assertTrue(semanticTokens.stream().filter(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())).count() >= 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,6 +80,24 @@ class CompilerLanguageServiceBridgeTest {
|
||||
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-enum")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void semanticTokensClassifyBuiltinTypesExposedByImportedStdlibModules() {
|
||||
final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge();
|
||||
|
||||
final var semanticTokens = bridge.semanticTokens(
|
||||
new LspProjectContext("main", "pbs", Path.of(".")),
|
||||
Path.of("demo.pbs").toUri().toString(),
|
||||
"""
|
||||
import { Input } from @sdk:input;
|
||||
|
||||
fn main() -> void {
|
||||
let touch : InputTouch = Input.touch();
|
||||
}
|
||||
""");
|
||||
|
||||
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void describeServerPublishesFrontendVisualThemes() {
|
||||
final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge();
|
||||
@ -98,7 +116,7 @@ class CompilerLanguageServiceBridgeTest {
|
||||
assertEquals("#d9e2ec", description.visualThemes().getFirst().editorPalette().baseForeground());
|
||||
assertTrue(description.visualThemes().getFirst().tokenStyles().stream()
|
||||
.anyMatch(tokenStyle -> tokenStyle.semanticKey().equals("pbs-keyword")
|
||||
&& tokenStyle.foreground().equals("#d2a8ff")));
|
||||
&& tokenStyle.foreground().equals("#7fb8ff")));
|
||||
}
|
||||
|
||||
private Path findRepoRoot(final Path start) {
|
||||
|
||||
64
test-projects/main/.vscode/settings.json
vendored
64
test-projects/main/.vscode/settings.json
vendored
@ -6,35 +6,35 @@
|
||||
"foreground": "#8b949e",
|
||||
"italic": true
|
||||
},
|
||||
"pbs-string:pbs": "#7ee787",
|
||||
"pbs-number:pbs": "#ffa657",
|
||||
"pbs-literal:pbs": "#79c0ff",
|
||||
"pbs-string:pbs": "#d8b86a",
|
||||
"pbs-number:pbs": "#ff8cc6",
|
||||
"pbs-literal:pbs": "#7fb8ff",
|
||||
"pbs-lifecycle:pbs": {
|
||||
"foreground": "#ff7b72",
|
||||
"bold": true
|
||||
},
|
||||
"pbs-keyword:pbs": "#d2a8ff",
|
||||
"pbs-keyword:pbs": "#7fb8ff",
|
||||
"pbs-operator:pbs": "#c9d1d9",
|
||||
"pbs-punctuation:pbs": "#8b949e",
|
||||
"pbs-function:pbs": {
|
||||
"foreground": "#ffa657",
|
||||
"foreground": "#7ee787",
|
||||
"bold": true
|
||||
},
|
||||
"pbs-method:pbs": "#ffd580",
|
||||
"pbs-method:pbs": "#7ee787",
|
||||
"pbs-constructor:pbs": {
|
||||
"foreground": "#e3b341",
|
||||
"foreground": "#7ee787",
|
||||
"bold": true
|
||||
},
|
||||
"pbs-struct:pbs": "#56d4dd",
|
||||
"pbs-struct:pbs": {
|
||||
"foreground": "#56d4dd",
|
||||
"italic": true
|
||||
},
|
||||
"pbs-contract:pbs": {
|
||||
"foreground": "#79c0ff",
|
||||
"underline": true
|
||||
},
|
||||
"pbs-host:pbs": "#c297ff",
|
||||
"pbs-builtin-type:pbs": {
|
||||
"foreground": "#7ee787",
|
||||
"italic": true
|
||||
},
|
||||
"pbs-builtin-type:pbs": "#56d4dd",
|
||||
"pbs-service:pbs": {
|
||||
"foreground": "#ff8e7a",
|
||||
"bold": true
|
||||
@ -62,10 +62,10 @@
|
||||
"foreground": "#8b949e",
|
||||
"italic": true
|
||||
},
|
||||
"string:pbs": "#7ee787",
|
||||
"number:pbs": "#ffa657",
|
||||
"enumMember:pbs": "#79c0ff",
|
||||
"variable:pbs": "#79c0ff",
|
||||
"string:pbs": "#d8b86a",
|
||||
"number:pbs": "#ff8cc6",
|
||||
"enumMember:pbs": "#7fb8ff",
|
||||
"variable:pbs": "#7fb8ff",
|
||||
"function.async:pbs": {
|
||||
"foreground": "#ff7b72",
|
||||
"bold": true
|
||||
@ -74,41 +74,43 @@
|
||||
"foreground": "#ff7b72",
|
||||
"bold": true
|
||||
},
|
||||
"keyword:pbs": "#d2a8ff",
|
||||
"keyword:pbs": "#7fb8ff",
|
||||
"operator:pbs": "#c9d1d9",
|
||||
"function:pbs": {
|
||||
"foreground": "#ffa657",
|
||||
"foreground": "#7ee787",
|
||||
"bold": true
|
||||
},
|
||||
"method:pbs": "#ffd580",
|
||||
"method:pbs": "#7ee787",
|
||||
"class.declaration:pbs": {
|
||||
"foreground": "#e3b341",
|
||||
"foreground": "#7ee787",
|
||||
"bold": true
|
||||
},
|
||||
"type.declaration:pbs": {
|
||||
"foreground": "#e3b341",
|
||||
"foreground": "#7ee787",
|
||||
"bold": true
|
||||
},
|
||||
"struct:pbs": "#56d4dd",
|
||||
"type:pbs": "#56d4dd",
|
||||
"struct:pbs": {
|
||||
"foreground": "#56d4dd",
|
||||
"italic": true
|
||||
},
|
||||
"type:pbs": {
|
||||
"foreground": "#56d4dd",
|
||||
"italic": true
|
||||
},
|
||||
"interface:pbs": {
|
||||
"foreground": "#79c0ff",
|
||||
"underline": true
|
||||
},
|
||||
"class.defaultLibrary:pbs": "#c297ff",
|
||||
"type.defaultLibrary:pbs": "#c297ff",
|
||||
"variable.defaultLibrary:pbs": {
|
||||
"foreground": "#7ee787",
|
||||
"italic": true
|
||||
},
|
||||
"variable.defaultLibrary:pbs": "#56d4dd",
|
||||
"enum:pbs": {
|
||||
"foreground": "#ff7b72",
|
||||
"underline": true
|
||||
},
|
||||
"variable.readonly:pbs": {
|
||||
"foreground": "#f778ba",
|
||||
"italic": true
|
||||
}
|
||||
"variable.readonly:pbs": "#c297ff",
|
||||
"pbs-asset:pbs": "#c297ff",
|
||||
"string.readonly:pbs": "#c297ff"
|
||||
}
|
||||
},
|
||||
"workbench.colorCustomizations": {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,8 @@ declare global camera_mult: int = 1;
|
||||
declare const MAX_FRAMES: int = 4;
|
||||
declare const CAMERA_SPEED: int = 1;
|
||||
|
||||
declare struct Bla (a: int) {}
|
||||
|
||||
[Init]
|
||||
fn init() -> void
|
||||
{
|
||||
@ -25,6 +27,7 @@ fn init() -> void
|
||||
camera_x = 0;
|
||||
camera_mult = 1;
|
||||
Composer.bind_scene(0);
|
||||
let bla: Bla = new Bla(1);
|
||||
}
|
||||
|
||||
[Frame]
|
||||
@ -55,9 +58,8 @@ fn frame() -> void
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
let touch : InputTouch = Input.touch();
|
||||
let pad : InputPad = Input.pad();
|
||||
|
||||
if (touch.button().released())
|
||||
{
|
||||
@ -93,15 +95,15 @@ fn frame() -> void
|
||||
let b : int = 15;
|
||||
let total : int = a + b;
|
||||
|
||||
if (Input.pad().a().pressed())
|
||||
if (pad.a().pressed())
|
||||
{
|
||||
total += 25;
|
||||
}
|
||||
else if (Input.pad().b().pressed())
|
||||
else if (pad.b().pressed())
|
||||
{
|
||||
total += 5;
|
||||
}
|
||||
else if (Input.pad().x().pressed())
|
||||
else if (pad.x().pressed())
|
||||
{
|
||||
total -= 10;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user