shrimp/vscode-extension/server/src/server.ts

106 lines
3.0 KiB
TypeScript

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'
const connection = createConnection(ProposedFeatures.all)
const documents = new TextDocuments(TextDocument)
documents.listen(connection)
connection.onInitialize(() => {
connection.console.log('🦐 Server initialized with capabilities')
return {
capabilities: {
textDocumentSync: 1,
semanticTokensProvider: {
legend: {
tokenTypes: TOKEN_TYPES,
tokenModifiers: TOKEN_MODIFIERS,
},
full: true,
},
},
}
})
connection.languages.semanticTokens.on((params) => {
const document = documents.get(params.textDocument.uri)
if (!document) {
return { data: [] }
}
const data = buildSemanticTokens(document)
return { data }
})
documents.onDidChangeContent((change) => {
const textDocument = change.document
const diagnostics = buildDiagnostics(textDocument)
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics })
})
connection.onRequest('shrimp/parseTree', (params: { uri: string }) => {
connection.console.log(`🦐 Parse tree requested for: ${params.uri}`)
const document = documents.get(params.uri)
if (!document) return 'Document not found'
const text = document.getText()
const tree = parser.parse(text)
const treeString = tree.toString()
// Format with indentation, without parentheses
let formatted = ''
let indent = 0
for (let i = 0; i < treeString.length; i++) {
const char = treeString[i]
if (char === '(') {
formatted += '\n'
indent++
formatted += ' '.repeat(indent)
} else if (char === ')') {
indent--
} else if (char === ',') {
formatted += '\n'
formatted += ' '.repeat(indent)
} else {
formatted += char
}
}
return formatted
})
connection.onRequest('shrimp/bytecode', (params: { uri: string }) => {
connection.console.log(`🦐 Bytecode requested for: ${params.uri}`)
const document = documents.get(params.uri)
if (!document) return 'Document not found'
try {
const text = document.getText()
const compiler = new Compiler(text)
// Format bytecode as readable string
let output = 'Bytecode:\n\n'
const bytecode = compiler.bytecode
output += bytecode.instructions
.map((op, i) => `${i.toString().padStart(4)}: ${JSON.stringify(op)}`)
.join('\n')
// Strip ANSI color codes
output = output.replace(/\x1b\[[0-9;]*m/g, '')
return output
} catch (error) {
const errorMsg = error instanceof Error ? error.message : String(error)
// Strip ANSI color codes from error message too
return `Compilation failed: ${errorMsg.replace(/\x1b\[[0-9;]*m/g, '')}`
}
})
connection.listen()