diff --git a/vscode-extension/language-configuration.json b/vscode-extension/language-configuration.json index 271b346..eef8f23 100644 --- a/vscode-extension/language-configuration.json +++ b/vscode-extension/language-configuration.json @@ -20,5 +20,9 @@ ["'", "'"], ["\"", "\""] ], - "wordPattern": "([a-z][a-z0-9-]*)|(-?\\d+\\.?\\d*)" + "wordPattern": "([a-z][a-z0-9-]*)|(-?\\d+\\.?\\d*)", + "indentationRules": { + "increaseIndentPattern": ":\\s*$", + "decreaseIndentPattern": "^\\s*(end|else)\\b" + } } diff --git a/vscode-extension/server/src/server.ts b/vscode-extension/server/src/server.ts index 40ce3fc..cc97e05 100644 --- a/vscode-extension/server/src/server.ts +++ b/vscode-extension/server/src/server.ts @@ -1,20 +1,48 @@ -import { TextDocuments } from 'vscode-languageserver/node' import { TextDocument } from 'vscode-languageserver-textdocument' -import { createConnection, ProposedFeatures } from 'vscode-languageserver/node' import { buildDiagnostics } from './diagnostics' import { buildSemanticTokens, TOKEN_MODIFIERS, TOKEN_TYPES } from './semanticTokens' import { parser } from '../../../src/parser/shrimp' import { Compiler } from '../../../src/compiler/compiler' +import { + InitializeResult, + TextDocuments, + TextDocumentSyncKind, + createConnection, + ProposedFeatures, + CompletionItemKind, +} from 'vscode-languageserver/node' const connection = createConnection(ProposedFeatures.all) const documents = new TextDocuments(TextDocument) documents.listen(connection) -connection.onInitialize(() => { +// Server capabilities +connection.onInitialize(handleInitialize) + +// Language features +connection.languages.semanticTokens.on(handleSemanticTokens) +documents.onDidChangeContent(handleDocumentChange) +connection.onCompletion(handleCompletion) + +// Debug commands +connection.onRequest('shrimp/parseTree', handleParseTree) +connection.onRequest('shrimp/bytecode', handleBytecode) + +// Start listening +connection.listen() + +// ============================================================================ +// Handler implementations +// ============================================================================ + +function handleInitialize(): InitializeResult { connection.console.log('🦐 Server initialized with capabilities') - return { + const result: InitializeResult = { capabilities: { - textDocumentSync: 1, + textDocumentSync: TextDocumentSyncKind.Full, + completionProvider: { + triggerCharacters: ['.'], + }, semanticTokensProvider: { legend: { tokenTypes: TOKEN_TYPES, @@ -24,26 +52,34 @@ connection.onInitialize(() => { }, }, } -}) -connection.languages.semanticTokens.on((params) => { + return result +} + +function handleSemanticTokens(params: any) { const document = documents.get(params.textDocument.uri) - if (!document) { - return { data: [] } - } + if (!document) return { data: [] } const data = buildSemanticTokens(document) return { data } -}) +} -documents.onDidChangeContent((change) => { +function handleDocumentChange(change: any) { const textDocument = change.document - const diagnostics = buildDiagnostics(textDocument) connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }) -}) +} -connection.onRequest('shrimp/parseTree', (params: { uri: string }) => { +function handleCompletion(params: any) { + const keywords = ['if', 'else', 'do', 'end', 'and', 'or', 'true', 'false', 'null'] + + return keywords.map((keyword) => ({ + label: keyword, + kind: CompletionItemKind.Keyword, + })) +} + +function handleParseTree(params: { uri: string }) { connection.console.log(`🦐 Parse tree requested for: ${params.uri}`) const document = documents.get(params.uri) if (!document) return 'Document not found' @@ -72,9 +108,9 @@ connection.onRequest('shrimp/parseTree', (params: { uri: string }) => { } return formatted -}) +} -connection.onRequest('shrimp/bytecode', (params: { uri: string }) => { +function handleBytecode(params: { uri: string }) { connection.console.log(`🦐 Bytecode requested for: ${params.uri}`) const document = documents.get(params.uri) if (!document) return 'Document not found' @@ -100,6 +136,4 @@ connection.onRequest('shrimp/bytecode', (params: { uri: string }) => { // Strip ANSI color codes from error message too return `Compilation failed: ${errorMsg.replace(/\x1b\[[0-9;]*m/g, '')}` } -}) - -connection.listen() +}