implements PLN-0069
This commit is contained in:
parent
54f8c0d6d8
commit
41bcd8c52a
@ -0,0 +1,33 @@
|
|||||||
|
package p.studio.lsp.messages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public record BaselineEditorPalette(
|
||||||
|
String baseForeground,
|
||||||
|
String selectionBackground,
|
||||||
|
String activeHighlightBackground,
|
||||||
|
String lineNumberForeground,
|
||||||
|
String statusChipBackground,
|
||||||
|
String statusChipBorder,
|
||||||
|
String statusChipForeground) {
|
||||||
|
|
||||||
|
public BaselineEditorPalette {
|
||||||
|
baseForeground = requireText(baseForeground, "baseForeground");
|
||||||
|
selectionBackground = requireText(selectionBackground, "selectionBackground");
|
||||||
|
activeHighlightBackground = requireText(activeHighlightBackground, "activeHighlightBackground");
|
||||||
|
lineNumberForeground = requireText(lineNumberForeground, "lineNumberForeground");
|
||||||
|
statusChipBackground = requireText(statusChipBackground, "statusChipBackground");
|
||||||
|
statusChipBorder = requireText(statusChipBorder, "statusChipBorder");
|
||||||
|
statusChipForeground = requireText(statusChipForeground, "statusChipForeground");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String requireText(
|
||||||
|
final String value,
|
||||||
|
final String field) {
|
||||||
|
final String candidate = Objects.requireNonNull(value, field).trim();
|
||||||
|
if (candidate.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(field + " must not be blank");
|
||||||
|
}
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,12 +7,19 @@ public record BaselineServerDescription(
|
|||||||
String name,
|
String name,
|
||||||
String version,
|
String version,
|
||||||
boolean hoverSupported,
|
boolean hoverSupported,
|
||||||
List<String> semanticTokenTypes) {
|
List<String> semanticTokenTypes,
|
||||||
|
List<BaselineVisualTheme> visualThemes,
|
||||||
|
String activeVisualThemeId) {
|
||||||
|
|
||||||
public BaselineServerDescription {
|
public BaselineServerDescription {
|
||||||
name = requireText(name, "name");
|
name = requireText(name, "name");
|
||||||
version = requireText(version, "version");
|
version = requireText(version, "version");
|
||||||
semanticTokenTypes = List.copyOf(Objects.requireNonNull(semanticTokenTypes, "semanticTokenTypes"));
|
semanticTokenTypes = List.copyOf(Objects.requireNonNull(semanticTokenTypes, "semanticTokenTypes"));
|
||||||
|
visualThemes = List.copyOf(Objects.requireNonNull(visualThemes, "visualThemes"));
|
||||||
|
activeVisualThemeId = requireText(activeVisualThemeId, "activeVisualThemeId");
|
||||||
|
if (visualThemes.stream().map(BaselineVisualTheme::themeId).noneMatch(activeVisualThemeId::equals)) {
|
||||||
|
throw new IllegalArgumentException("activeVisualThemeId must reference one of the declared visual themes");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String requireText(
|
private static String requireText(
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
package p.studio.lsp.messages;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public record BaselineTokenStyle(
|
||||||
|
String semanticKey,
|
||||||
|
String foreground,
|
||||||
|
boolean italic,
|
||||||
|
boolean bold,
|
||||||
|
boolean underline) {
|
||||||
|
|
||||||
|
public BaselineTokenStyle {
|
||||||
|
semanticKey = requireText(semanticKey, "semanticKey");
|
||||||
|
foreground = requireText(foreground, "foreground");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String requireText(
|
||||||
|
final String value,
|
||||||
|
final String field) {
|
||||||
|
final String candidate = Objects.requireNonNull(value, field).trim();
|
||||||
|
if (candidate.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(field + " must not be blank");
|
||||||
|
}
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package p.studio.lsp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public record BaselineVisualTheme(
|
||||||
|
String themeId,
|
||||||
|
String displayName,
|
||||||
|
BaselineEditorPalette editorPalette,
|
||||||
|
List<BaselineTokenStyle> tokenStyles) {
|
||||||
|
|
||||||
|
public BaselineVisualTheme {
|
||||||
|
themeId = requireText(themeId, "themeId");
|
||||||
|
displayName = requireText(displayName, "displayName");
|
||||||
|
editorPalette = Objects.requireNonNull(editorPalette, "editorPalette");
|
||||||
|
tokenStyles = List.copyOf(Objects.requireNonNull(tokenStyles, "tokenStyles"));
|
||||||
|
if (tokenStyles.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("tokenStyles must not be empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String requireText(
|
||||||
|
final String value,
|
||||||
|
final String field) {
|
||||||
|
final String candidate = Objects.requireNonNull(value, field).trim();
|
||||||
|
if (candidate.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(field + " must not be blank");
|
||||||
|
}
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,7 +5,10 @@ import p.studio.compiler.messages.BuilderPipelineConfig;
|
|||||||
import p.studio.compiler.messages.BuildingIssue;
|
import p.studio.compiler.messages.BuildingIssue;
|
||||||
import p.studio.compiler.models.AnalysisSnapshot;
|
import p.studio.compiler.models.AnalysisSnapshot;
|
||||||
import p.studio.compiler.models.BuilderPipelineContext;
|
import p.studio.compiler.models.BuilderPipelineContext;
|
||||||
|
import p.studio.compiler.models.FrontendEditorPaletteSpec;
|
||||||
import p.studio.compiler.PBSDefinitions;
|
import p.studio.compiler.PBSDefinitions;
|
||||||
|
import p.studio.compiler.models.FrontendTokenStyleSpec;
|
||||||
|
import p.studio.compiler.models.FrontendVisualThemeSpec;
|
||||||
import p.studio.compiler.pbs.PbsSemanticKind;
|
import p.studio.compiler.pbs.PbsSemanticKind;
|
||||||
import p.studio.compiler.pbs.lexer.PbsLexer;
|
import p.studio.compiler.pbs.lexer.PbsLexer;
|
||||||
import p.studio.compiler.pbs.lexer.PbsToken;
|
import p.studio.compiler.pbs.lexer.PbsToken;
|
||||||
@ -34,7 +37,9 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge {
|
|||||||
"Prometeu Studio LSP",
|
"Prometeu Studio LSP",
|
||||||
"0.1.0",
|
"0.1.0",
|
||||||
true,
|
true,
|
||||||
PBSDefinitions.PBS.getSemanticPresentation().semanticKeys());
|
PBSDefinitions.PBS.getSemanticPresentation().semanticKeys(),
|
||||||
|
PBSDefinitions.PBS.getSemanticPresentation().themes().stream().map(this::mapVisualTheme).toList(),
|
||||||
|
PBSDefinitions.PBS.getSemanticPresentation().defaultThemeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -190,4 +195,32 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge {
|
|||||||
return tokens.get(index - 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.LEFT_BRACKET
|
return tokens.get(index - 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.LEFT_BRACKET
|
||||||
&& tokens.get(index + 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.RIGHT_BRACKET;
|
&& tokens.get(index + 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.RIGHT_BRACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BaselineVisualTheme mapVisualTheme(final FrontendVisualThemeSpec theme) {
|
||||||
|
return new BaselineVisualTheme(
|
||||||
|
theme.themeId(),
|
||||||
|
theme.displayName(),
|
||||||
|
mapEditorPalette(theme.editorPalette()),
|
||||||
|
theme.tokenStyles().stream().map(this::mapTokenStyle).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaselineEditorPalette mapEditorPalette(final FrontendEditorPaletteSpec palette) {
|
||||||
|
return new BaselineEditorPalette(
|
||||||
|
palette.baseForeground(),
|
||||||
|
palette.selectionBackground(),
|
||||||
|
palette.activeHighlightBackground(),
|
||||||
|
palette.lineNumberForeground(),
|
||||||
|
palette.statusChipBackground(),
|
||||||
|
palette.statusChipBorder(),
|
||||||
|
palette.statusChipForeground());
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaselineTokenStyle mapTokenStyle(final FrontendTokenStyleSpec tokenStyle) {
|
||||||
|
return new BaselineTokenStyle(
|
||||||
|
tokenStyle.semanticKey(),
|
||||||
|
tokenStyle.foreground(),
|
||||||
|
tokenStyle.italic(),
|
||||||
|
tokenStyle.bold(),
|
||||||
|
tokenStyle.underline());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
class CompilerLanguageServiceBridgeTest {
|
class CompilerLanguageServiceBridgeTest {
|
||||||
@ -55,6 +56,21 @@ class CompilerLanguageServiceBridgeTest {
|
|||||||
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-number")));
|
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-number")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void describeServerPublishesFrontendVisualThemes() {
|
||||||
|
final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge();
|
||||||
|
|
||||||
|
final var description = bridge.describeServer(new LspProjectContext("main", "pbs", Path.of(".")));
|
||||||
|
|
||||||
|
assertEquals("pbs-default", description.activeVisualThemeId());
|
||||||
|
assertEquals(1, description.visualThemes().size());
|
||||||
|
assertEquals("PBS Default", description.visualThemes().getFirst().displayName());
|
||||||
|
assertEquals("#d9e2ec", description.visualThemes().getFirst().editorPalette().baseForeground());
|
||||||
|
assertTrue(description.visualThemes().getFirst().tokenStyles().stream()
|
||||||
|
.anyMatch(tokenStyle -> tokenStyle.semanticKey().equals("pbs-keyword")
|
||||||
|
&& tokenStyle.foreground().equals("#569cd6")));
|
||||||
|
}
|
||||||
|
|
||||||
private Path findRepoRoot(final Path start) {
|
private Path findRepoRoot(final Path start) {
|
||||||
var current = start;
|
var current = start;
|
||||||
while (current != null) {
|
while (current != null) {
|
||||||
|
|||||||
@ -12,9 +12,12 @@ import org.eclipse.lsp4j.services.LanguageClient;
|
|||||||
import org.eclipse.lsp4j.services.TextDocumentService;
|
import org.eclipse.lsp4j.services.TextDocumentService;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import p.studio.lsp.messages.BaselineDocumentAnalysis;
|
import p.studio.lsp.messages.BaselineDocumentAnalysis;
|
||||||
|
import p.studio.lsp.messages.BaselineEditorPalette;
|
||||||
import p.studio.lsp.messages.BaselineHover;
|
import p.studio.lsp.messages.BaselineHover;
|
||||||
import p.studio.lsp.messages.BaselineSemanticTokens;
|
import p.studio.lsp.messages.BaselineSemanticTokens;
|
||||||
import p.studio.lsp.messages.BaselineServerDescription;
|
import p.studio.lsp.messages.BaselineServerDescription;
|
||||||
|
import p.studio.lsp.messages.BaselineTokenStyle;
|
||||||
|
import p.studio.lsp.messages.BaselineVisualTheme;
|
||||||
import p.studio.lsp.messages.LspProjectContext;
|
import p.studio.lsp.messages.LspProjectContext;
|
||||||
import p.studio.lsp.services.LanguageServiceBridge;
|
import p.studio.lsp.services.LanguageServiceBridge;
|
||||||
import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper;
|
import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper;
|
||||||
@ -79,7 +82,17 @@ class PrometeuLanguageServerTest {
|
|||||||
|
|
||||||
private static final class RecordingBridge implements LanguageServiceBridge {
|
private static final class RecordingBridge implements LanguageServiceBridge {
|
||||||
private int describeServerCalls;
|
private int describeServerCalls;
|
||||||
private final BaselineServerDescription serverDescription = new BaselineServerDescription("demo", "1", true, List.of());
|
private final BaselineServerDescription serverDescription = new BaselineServerDescription(
|
||||||
|
"demo",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
List.of(),
|
||||||
|
List.of(new BaselineVisualTheme(
|
||||||
|
"demo-default",
|
||||||
|
"Demo Default",
|
||||||
|
new BaselineEditorPalette("#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777"),
|
||||||
|
List.of(new BaselineTokenStyle("demo-keyword", "#888888", false, false, false)))),
|
||||||
|
"demo-default");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaselineServerDescription describeServer(final LspProjectContext project) {
|
public BaselineServerDescription describeServer(final LspProjectContext project) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user