Compare commits

..

No commits in common. "e4bdddc762e66b8290a847c79252c3f6c8def20f" and "1fec471da98da62a6b3c815236c085af1b208fa4" have entirely different histories.

5 changed files with 26 additions and 53 deletions

4
.gitignore vendored
View File

@ -34,6 +34,4 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
.DS_Store .DS_Store
/tmp /tmp
/docs /docs
*.vsix

4
vscode-extension/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
node_modules
client/dist
server/dist
*.vsix

View File

@ -1,12 +1,12 @@
import { TextDocument, Position } from 'vscode-languageserver-textdocument' import { TextDocument, Position } from 'vscode-languageserver-textdocument'
import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver/node' import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver/node'
import { Tree } from '@lezer/common' import { parser } from '../../../src/parser/shrimp'
import { Compiler } from '../../../src/compiler/compiler' import { Compiler } from '../../../src/compiler/compiler'
import { CompilerError } from '../../../src/compiler/compilerError' import { CompilerError } from '../../../src/compiler/compilerError'
export const buildDiagnostics = (textDocument: TextDocument, tree: Tree): Diagnostic[] => { export const buildDiagnostics = (textDocument: TextDocument): Diagnostic[] => {
const text = textDocument.getText() const text = textDocument.getText()
const diagnostics = getParseErrors(textDocument, tree) const diagnostics = getParseErrors(textDocument)
if (diagnostics.length > 0) { if (diagnostics.length > 0) {
return diagnostics return diagnostics
@ -59,7 +59,9 @@ const unknownDiagnostic = (message: string): Diagnostic => {
return diagnostic return diagnostic
} }
const getParseErrors = (textDocument: TextDocument, tree: Tree): Diagnostic[] => { const getParseErrors = (textDocument: TextDocument): Diagnostic[] => {
const tree = parser.parse(textDocument.getText())
const ranges: { start: Position; end: Position }[] = [] const ranges: { start: Position; end: Position }[] = []
tree.iterate({ tree.iterate({
enter(n) { enter(n) {

View File

@ -1,6 +1,6 @@
import { parser } from '../../../src/parser/shrimp' import { parser } from '../../../src/parser/shrimp'
import * as Terms from '../../../src/parser/shrimp.terms' import * as Terms from '../../../src/parser/shrimp.terms'
import { SyntaxNode, Tree } from '@lezer/common' import { SyntaxNode } from '@lezer/common'
import { TextDocument } from 'vscode-languageserver-textdocument' import { TextDocument } from 'vscode-languageserver-textdocument'
import { import {
SemanticTokensBuilder, SemanticTokensBuilder,
@ -28,7 +28,9 @@ export const TOKEN_MODIFIERS = [
SemanticTokenModifiers.readonly, SemanticTokenModifiers.readonly,
] ]
export function buildSemanticTokens(document: TextDocument, tree: Tree): number[] { export function buildSemanticTokens(document: TextDocument): number[] {
const text = document.getText()
const tree = parser.parse(text)
const builder = new SemanticTokensBuilder() const builder = new SemanticTokensBuilder()
const scopeTracker = new EditorScopeAnalyzer(document) const scopeTracker = new EditorScopeAnalyzer(document)

View File

@ -7,7 +7,6 @@ import { PRELUDE_NAMES } from './metadata/prelude-names'
import { parser } from '../../../src/parser/shrimp' import { parser } from '../../../src/parser/shrimp'
import { setGlobals } from '../../../src/parser/tokenizer' import { setGlobals } from '../../../src/parser/tokenizer'
import { Compiler } from '../../../src/compiler/compiler' import { Compiler } from '../../../src/compiler/compiler'
import { Tree } from '@lezer/common'
import { import {
InitializeResult, InitializeResult,
TextDocuments, TextDocuments,
@ -15,10 +14,7 @@ import {
createConnection, createConnection,
ProposedFeatures, ProposedFeatures,
CompletionItemKind, CompletionItemKind,
TextDocumentChangeEvent,
} from 'vscode-languageserver/node' } from 'vscode-languageserver/node'
import { setGlobals } from '../../../src/parser/tokenizer'
import { globals } from '../../../src/prelude'
// Initialize parser with prelude globals so it knows dict/list/str are in scope // Initialize parser with prelude globals so it knows dict/list/str are in scope
setGlobals(PRELUDE_NAMES) setGlobals(PRELUDE_NAMES)
@ -27,16 +23,12 @@ const connection = createConnection(ProposedFeatures.all)
const documents = new TextDocuments(TextDocument) const documents = new TextDocuments(TextDocument)
documents.listen(connection) documents.listen(connection)
const documentTrees = new Map<string, Tree>()
// Server capabilities // Server capabilities
connection.onInitialize(handleInitialize) connection.onInitialize(handleInitialize)
// Language features // Language features
connection.languages.semanticTokens.on(handleSemanticTokens) connection.languages.semanticTokens.on(handleSemanticTokens)
documents.onDidOpen(handleDocumentOpen)
documents.onDidChangeContent(handleDocumentChange) documents.onDidChangeContent(handleDocumentChange)
documents.onDidClose(handleDocumentClose)
connection.onCompletion(handleCompletion) connection.onCompletion(handleCompletion)
connection.onSignatureHelp(handleSignatureHelp) connection.onSignatureHelp(handleSignatureHelp)
@ -47,7 +39,10 @@ connection.onRequest('shrimp/bytecode', handleBytecode)
// Start listening // Start listening
connection.listen() connection.listen()
// ============================================================================
// Handler implementations // Handler implementations
// ============================================================================
function handleInitialize(): InitializeResult { function handleInitialize(): InitializeResult {
connection.console.log('🦐 Server initialized with capabilities') connection.console.log('🦐 Server initialized with capabilities')
const result: InitializeResult = { const result: InitializeResult = {
@ -72,42 +67,22 @@ function handleInitialize(): InitializeResult {
return result return result
} }
function handleDocumentOpen(event: TextDocumentChangeEvent<TextDocument>) {
const document = event.document
setGlobals(Object.keys(globals))
const tree = parser.parse(document.getText())
documentTrees.set(document.uri, tree)
}
function handleSemanticTokens(params: any) { function handleSemanticTokens(params: any) {
const document = documents.get(params.textDocument.uri) const document = documents.get(params.textDocument.uri)
if (!document) return { data: [] } if (!document) return { data: [] }
const tree = documentTrees.get(params.textDocument.uri) const data = buildSemanticTokens(document)
if (!tree) return { data: [] }
const data = buildSemanticTokens(document, tree)
return { data } return { data }
} }
function handleDocumentChange(change: TextDocumentChangeEvent<TextDocument>) { function handleDocumentChange(change: any) {
const document = change.document const textDocument = change.document
const diagnostics = buildDiagnostics(textDocument)
// Parse and cache connection.sendDiagnostics({ uri: textDocument.uri, diagnostics })
setGlobals(Object.keys(globals))
const tree = parser.parse(document.getText())
documentTrees.set(document.uri, tree)
// Build diagnostics using cached tree
const diagnostics = buildDiagnostics(document, tree)
connection.sendDiagnostics({ uri: document.uri, diagnostics })
}
function handleDocumentClose(event: TextDocumentChangeEvent<TextDocument>) {
documentTrees.delete(event.document.uri)
} }
function handleCompletion(params: any) { function handleCompletion(params: any) {
console.log(`🌭 YOU ARE COMPLETING at position`, params.position)
const document = documents.get(params.textDocument.uri) const document = documents.get(params.textDocument.uri)
if (!document) { if (!document) {
console.log('❌ No document found') console.log('❌ No document found')
@ -123,10 +98,7 @@ function handleCompletion(params: any) {
const contextCompletions = provideCompletions(document, position) const contextCompletions = provideCompletions(document, position)
console.log(`🎯 Context completions count: ${contextCompletions.length}`) console.log(`🎯 Context completions count: ${contextCompletions.length}`)
if (contextCompletions.length > 0) { if (contextCompletions.length > 0) {
console.log( console.log(`✅ Returning ${contextCompletions.length} completions:`, contextCompletions.map(c => c.label).join(', '))
`✅ Returning ${contextCompletions.length} completions:`,
contextCompletions.map((c) => c.label).join(', ')
)
return contextCompletions return contextCompletions
} }
@ -157,13 +129,8 @@ function handleParseTree(params: { uri: string }) {
const document = documents.get(params.uri) const document = documents.get(params.uri)
if (!document) return 'Document not found' if (!document) return 'Document not found'
const tree = documentTrees.get(params.uri)
if (!tree) {
connection.console.error(`🦐 No cached tree for ${params.uri}`)
return 'No cached parse tree available'
}
const text = document.getText() const text = document.getText()
const tree = parser.parse(text)
const cursor = tree.cursor() const cursor = tree.cursor()
let formatted = '' let formatted = ''