Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS

This commit is contained in:
bQUARKz 2026-05-06 17:20:38 +01:00
parent e23367b022
commit dfad621d05
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
5 changed files with 75 additions and 6 deletions

View File

@ -34,7 +34,7 @@ public class PBSFrontendThemes {
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-service", "#c297ff", false, true, false),
new FrontendTokenStyleSpec("pbs-service", "#ff8e7a", false, true, 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),

View File

@ -11,7 +11,9 @@ import p.studio.compiler.source.identifiers.FileId;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider {
@ -21,11 +23,12 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
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 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);
final PbsSemanticKind semanticKind = classifyToken(tokens, index, declaredKindsByName);
if (semanticKind == null) {
continue;
}
@ -37,7 +40,8 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
private PbsSemanticKind classifyToken(
final ReadOnlyList<PbsToken> tokens,
final int index) {
final int index,
final Map<String, PbsSemanticKind> declaredKindsByName) {
final PbsToken token = tokens.get(index);
final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token);
if (lexicalKind != null) {
@ -47,7 +51,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
if (isLifecycleToken(tokens, index, token)) {
return PbsSemanticKind.LIFECYCLE;
}
return classifyIdentifierToken(tokens, index, token);
return classifyIdentifierToken(tokens, index, token, declaredKindsByName);
}
return null;
}
@ -55,7 +59,8 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
private PbsSemanticKind classifyIdentifierToken(
final ReadOnlyList<PbsToken> tokens,
final int index,
final PbsToken token) {
final PbsToken token,
final Map<String, PbsSemanticKind> declaredKindsByName) {
final PbsTokenKind previousKind = previousSignificantKind(tokens, index);
final PbsTokenKind nextKind = nextSignificantKind(tokens, index);
@ -89,6 +94,17 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
if (previousKind == PbsTokenKind.BUILTIN) {
return PbsSemanticKind.BUILTIN_TYPE;
}
final PbsSemanticKind declaredKind = declaredKindsByName.get(token.lexeme());
if (declaredKind != null) {
if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) {
return PbsSemanticKind.METHOD;
}
if (nextKind == PbsTokenKind.DOT
|| previousKind == PbsTokenKind.NEW
|| isTypeReferenceContext(previousKind, token.lexeme())) {
return declaredKind;
}
}
if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) {
return PbsSemanticKind.METHOD;
}
@ -101,6 +117,39 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
return PbsSemanticKind.IDENTIFIER;
}
private Map<String, PbsSemanticKind> collectDeclaredKinds(final ReadOnlyList<PbsToken> tokens) {
final Map<String, PbsSemanticKind> declaredKindsByName = new HashMap<>();
for (int index = 0; index < tokens.size() - 1; index += 1) {
final PbsToken token = tokens.get(index);
final PbsToken nextToken = tokens.get(index + 1);
if (nextToken.kind() != PbsTokenKind.IDENTIFIER) {
continue;
}
final PbsSemanticKind declarationKind = declarationKind(token.kind());
if (declarationKind == null) {
continue;
}
declaredKindsByName.put(nextToken.lexeme(), declarationKind);
}
return Map.copyOf(declaredKindsByName);
}
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;
};
}
private boolean isTypeReferenceContext(
final PbsTokenKind previousKind,
final String lexeme) {

View File

@ -24,6 +24,7 @@ final class PbsSemanticPresentationContractTest {
assertEquals("PBS Default", presentation.defaultTheme().displayName());
assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground());
assertEquals("#d2a8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground());
assertEquals("#ff8e7a", presentation.defaultTheme().requireTokenStyle("pbs-service").foreground());
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic());
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic());
assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId());
@ -58,11 +59,17 @@ final class PbsSemanticPresentationContractTest {
void shouldPublishPbsOwnedSemanticTokenProvider() {
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
struct Vec2 {}
service Log {}
host Input {}
enum ResultKind { Ok = 1; }
fn main() -> void {
const answer: int = 42;
let value = new Vec2();
value.length();
Log.info();
Input.read();
let kind: ResultKind;
}
""");
@ -72,5 +79,8 @@ final class PbsSemanticPresentationContractTest {
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONSTRUCTOR.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.METHOD.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.SERVICE.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.HOST.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.ENUM.semanticKey())));
}
}

View File

@ -52,10 +52,17 @@ class CompilerLanguageServiceBridgeTest {
}
}
service Log {}
host Input {}
enum ResultKind { Ok = 1; }
fn main() -> void {
const answer: int = 42;
let value = new Vec2();
value.length();
Log.info();
Input.read();
let kind: ResultKind;
}
""");
@ -68,6 +75,9 @@ class CompilerLanguageServiceBridgeTest {
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-const")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-constructor")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-service")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-host")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-enum")));
}
@Test

View File

@ -36,7 +36,7 @@
"italic": true
},
"pbs-service:pbs": {
"foreground": "#c297ff",
"foreground": "#ff8e7a",
"bold": true
},
"pbs-error:pbs": {