Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS
This commit is contained in:
parent
e23367b022
commit
dfad621d05
@ -34,7 +34,7 @@ public class PBSFrontendThemes {
|
|||||||
new FrontendTokenStyleSpec("pbs-contract", "#79c0ff", false, false, true),
|
new FrontendTokenStyleSpec("pbs-contract", "#79c0ff", false, false, true),
|
||||||
new FrontendTokenStyleSpec("pbs-host", "#c297ff", false, false, false),
|
new FrontendTokenStyleSpec("pbs-host", "#c297ff", false, false, false),
|
||||||
new FrontendTokenStyleSpec("pbs-builtin-type", "#7ee787", true, 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-error", "#ff7b72", false, false, true),
|
||||||
new FrontendTokenStyleSpec("pbs-enum", "#56d4dd", false, true, false),
|
new FrontendTokenStyleSpec("pbs-enum", "#56d4dd", false, true, false),
|
||||||
new FrontendTokenStyleSpec("pbs-callback", "#ffb3e6", false, false, false),
|
new FrontendTokenStyleSpec("pbs-callback", "#ffb3e6", false, false, false),
|
||||||
|
|||||||
@ -11,7 +11,9 @@ import p.studio.compiler.source.identifiers.FileId;
|
|||||||
import p.studio.utilities.structures.ReadOnlyList;
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider {
|
public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider {
|
||||||
@ -21,11 +23,12 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
|||||||
public List<FrontendSemanticToken> tokenize(final String documentText) {
|
public List<FrontendSemanticToken> tokenize(final String documentText) {
|
||||||
final String effectiveText = documentText == null ? "" : documentText;
|
final String effectiveText = documentText == null ? "" : documentText;
|
||||||
final ReadOnlyList<PbsToken> tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty());
|
final ReadOnlyList<PbsToken> tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty());
|
||||||
|
final Map<String, PbsSemanticKind> declaredKindsByName = collectDeclaredKinds(tokens);
|
||||||
final ArrayList<FrontendSemanticToken> semanticTokens = new ArrayList<>();
|
final ArrayList<FrontendSemanticToken> semanticTokens = new ArrayList<>();
|
||||||
|
|
||||||
for (int index = 0; index < tokens.size(); index += 1) {
|
for (int index = 0; index < tokens.size(); index += 1) {
|
||||||
final PbsToken token = tokens.get(index);
|
final PbsToken token = tokens.get(index);
|
||||||
final PbsSemanticKind semanticKind = classifyToken(tokens, index);
|
final PbsSemanticKind semanticKind = classifyToken(tokens, index, declaredKindsByName);
|
||||||
if (semanticKind == null) {
|
if (semanticKind == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -37,7 +40,8 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
|||||||
|
|
||||||
private PbsSemanticKind classifyToken(
|
private PbsSemanticKind classifyToken(
|
||||||
final ReadOnlyList<PbsToken> tokens,
|
final ReadOnlyList<PbsToken> tokens,
|
||||||
final int index) {
|
final int index,
|
||||||
|
final Map<String, PbsSemanticKind> declaredKindsByName) {
|
||||||
final PbsToken token = tokens.get(index);
|
final PbsToken token = tokens.get(index);
|
||||||
final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token);
|
final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token);
|
||||||
if (lexicalKind != null) {
|
if (lexicalKind != null) {
|
||||||
@ -47,7 +51,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
|||||||
if (isLifecycleToken(tokens, index, token)) {
|
if (isLifecycleToken(tokens, index, token)) {
|
||||||
return PbsSemanticKind.LIFECYCLE;
|
return PbsSemanticKind.LIFECYCLE;
|
||||||
}
|
}
|
||||||
return classifyIdentifierToken(tokens, index, token);
|
return classifyIdentifierToken(tokens, index, token, declaredKindsByName);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -55,7 +59,8 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
|||||||
private PbsSemanticKind classifyIdentifierToken(
|
private PbsSemanticKind classifyIdentifierToken(
|
||||||
final ReadOnlyList<PbsToken> tokens,
|
final ReadOnlyList<PbsToken> tokens,
|
||||||
final int index,
|
final int index,
|
||||||
final PbsToken token) {
|
final PbsToken token,
|
||||||
|
final Map<String, PbsSemanticKind> declaredKindsByName) {
|
||||||
final PbsTokenKind previousKind = previousSignificantKind(tokens, index);
|
final PbsTokenKind previousKind = previousSignificantKind(tokens, index);
|
||||||
final PbsTokenKind nextKind = nextSignificantKind(tokens, index);
|
final PbsTokenKind nextKind = nextSignificantKind(tokens, index);
|
||||||
|
|
||||||
@ -89,6 +94,17 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
|||||||
if (previousKind == PbsTokenKind.BUILTIN) {
|
if (previousKind == PbsTokenKind.BUILTIN) {
|
||||||
return PbsSemanticKind.BUILTIN_TYPE;
|
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) {
|
if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) {
|
||||||
return PbsSemanticKind.METHOD;
|
return PbsSemanticKind.METHOD;
|
||||||
}
|
}
|
||||||
@ -101,6 +117,39 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
|
|||||||
return PbsSemanticKind.IDENTIFIER;
|
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(
|
private boolean isTypeReferenceContext(
|
||||||
final PbsTokenKind previousKind,
|
final PbsTokenKind previousKind,
|
||||||
final String lexeme) {
|
final String lexeme) {
|
||||||
|
|||||||
@ -24,6 +24,7 @@ final class PbsSemanticPresentationContractTest {
|
|||||||
assertEquals("PBS Default", presentation.defaultTheme().displayName());
|
assertEquals("PBS Default", presentation.defaultTheme().displayName());
|
||||||
assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground());
|
assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground());
|
||||||
assertEquals("#d2a8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground());
|
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-builtin-type").italic());
|
||||||
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic());
|
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic());
|
||||||
assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId());
|
assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId());
|
||||||
@ -58,11 +59,17 @@ final class PbsSemanticPresentationContractTest {
|
|||||||
void shouldPublishPbsOwnedSemanticTokenProvider() {
|
void shouldPublishPbsOwnedSemanticTokenProvider() {
|
||||||
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
|
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
|
||||||
struct Vec2 {}
|
struct Vec2 {}
|
||||||
|
service Log {}
|
||||||
|
host Input {}
|
||||||
|
enum ResultKind { Ok = 1; }
|
||||||
|
|
||||||
fn main() -> void {
|
fn main() -> void {
|
||||||
const answer: int = 42;
|
const answer: int = 42;
|
||||||
let value = new Vec2();
|
let value = new Vec2();
|
||||||
value.length();
|
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.BUILTIN_TYPE.semanticKey())));
|
||||||
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONSTRUCTOR.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.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())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,10 +52,17 @@ class CompilerLanguageServiceBridgeTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
service Log {}
|
||||||
|
host Input {}
|
||||||
|
enum ResultKind { Ok = 1; }
|
||||||
|
|
||||||
fn main() -> void {
|
fn main() -> void {
|
||||||
const answer: int = 42;
|
const answer: int = 42;
|
||||||
let value = new Vec2();
|
let value = new Vec2();
|
||||||
value.length();
|
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-const")));
|
||||||
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type")));
|
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-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
|
@Test
|
||||||
|
|||||||
2
test-projects/main/.vscode/settings.json
vendored
2
test-projects/main/.vscode/settings.json
vendored
@ -36,7 +36,7 @@
|
|||||||
"italic": true
|
"italic": true
|
||||||
},
|
},
|
||||||
"pbs-service:pbs": {
|
"pbs-service:pbs": {
|
||||||
"foreground": "#c297ff",
|
"foreground": "#ff8e7a",
|
||||||
"bold": true
|
"bold": true
|
||||||
},
|
},
|
||||||
"pbs-error:pbs": {
|
"pbs-error:pbs": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user