Compare commits
11 Commits
1fec471da9
...
e4bdddc762
| Author | SHA1 | Date | |
|---|---|---|---|
| e4bdddc762 | |||
| 7feb3cd7b0 | |||
| 13adbe4c0e | |||
| b3ec6995db | |||
| 854ed02625 | |||
| c325bca611 | |||
| 1082cc1281 | |||
| 5b363c833a | |||
| d6aea4b0f9 | |||
| 44b30d2339 | |||
| 3aa75843ac |
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -34,4 +34,6 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
/tmp
|
/tmp
|
||||||
/docs
|
/docs
|
||||||
|
|
||||||
|
*.vsix
|
||||||
4
vscode-extension/.gitignore
vendored
4
vscode-extension/.gitignore
vendored
|
|
@ -1,4 +0,0 @@
|
||||||
node_modules
|
|
||||||
client/dist
|
|
||||||
server/dist
|
|
||||||
*.vsix
|
|
||||||
|
|
@ -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 { parser } from '../../../src/parser/shrimp'
|
import { Tree } from '@lezer/common'
|
||||||
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): Diagnostic[] => {
|
export const buildDiagnostics = (textDocument: TextDocument, tree: Tree): Diagnostic[] => {
|
||||||
const text = textDocument.getText()
|
const text = textDocument.getText()
|
||||||
const diagnostics = getParseErrors(textDocument)
|
const diagnostics = getParseErrors(textDocument, tree)
|
||||||
|
|
||||||
if (diagnostics.length > 0) {
|
if (diagnostics.length > 0) {
|
||||||
return diagnostics
|
return diagnostics
|
||||||
|
|
@ -59,9 +59,7 @@ const unknownDiagnostic = (message: string): Diagnostic => {
|
||||||
return diagnostic
|
return diagnostic
|
||||||
}
|
}
|
||||||
|
|
||||||
const getParseErrors = (textDocument: TextDocument): Diagnostic[] => {
|
const getParseErrors = (textDocument: TextDocument, tree: Tree): 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) {
|
||||||
|
|
|
||||||
|
|
@ -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 } from '@lezer/common'
|
import { SyntaxNode, Tree } from '@lezer/common'
|
||||||
import { TextDocument } from 'vscode-languageserver-textdocument'
|
import { TextDocument } from 'vscode-languageserver-textdocument'
|
||||||
import {
|
import {
|
||||||
SemanticTokensBuilder,
|
SemanticTokensBuilder,
|
||||||
|
|
@ -28,9 +28,7 @@ export const TOKEN_MODIFIERS = [
|
||||||
SemanticTokenModifiers.readonly,
|
SemanticTokenModifiers.readonly,
|
||||||
]
|
]
|
||||||
|
|
||||||
export function buildSemanticTokens(document: TextDocument): number[] {
|
export function buildSemanticTokens(document: TextDocument, tree: Tree): 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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ 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,
|
||||||
|
|
@ -14,7 +15,10 @@ 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)
|
||||||
|
|
@ -23,12 +27,16 @@ 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)
|
||||||
|
|
||||||
|
|
@ -39,10 +47,7 @@ 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 = {
|
||||||
|
|
@ -67,22 +72,42 @@ 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 data = buildSemanticTokens(document)
|
const tree = documentTrees.get(params.textDocument.uri)
|
||||||
|
if (!tree) return { data: [] }
|
||||||
|
|
||||||
|
const data = buildSemanticTokens(document, tree)
|
||||||
return { data }
|
return { data }
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDocumentChange(change: any) {
|
function handleDocumentChange(change: TextDocumentChangeEvent<TextDocument>) {
|
||||||
const textDocument = change.document
|
const document = change.document
|
||||||
const diagnostics = buildDiagnostics(textDocument)
|
|
||||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics })
|
// Parse and cache
|
||||||
|
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')
|
||||||
|
|
@ -98,7 +123,10 @@ 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(`✅ Returning ${contextCompletions.length} completions:`, contextCompletions.map(c => c.label).join(', '))
|
console.log(
|
||||||
|
`✅ Returning ${contextCompletions.length} completions:`,
|
||||||
|
contextCompletions.map((c) => c.label).join(', ')
|
||||||
|
)
|
||||||
return contextCompletions
|
return contextCompletions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,8 +157,13 @@ 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 = ''
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user