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

94 lines
2.4 KiB
TypeScript

import { TextDocument, Position } from 'vscode-languageserver-textdocument'
import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver/node'
import { parser } from '../../../src/parser/shrimp'
import { Compiler } from '../../../src/compiler/compiler'
import { CompilerError } from '../../../src/compiler/compilerError'
export const buildDiagnostics = (textDocument: TextDocument): Diagnostic[] => {
const text = textDocument.getText()
const diagnostics = getParseErrors(textDocument)
if (diagnostics.length > 0) {
return diagnostics
}
const diagnostic = getCompilerError(text)
if (diagnostic) return [diagnostic]
return []
}
const getCompilerError = (text: string): Diagnostic | undefined => {
try {
new Compiler(text)
} catch (e) {
if (!(e instanceof CompilerError)) {
return unknownDiagnostic(getErrorMessage(e))
}
const lineInfo = e.lineAtPosition(text)!
const cause = e.cause ? ` Cause: ${e.cause}` : ''
const message = e.message
if (!lineInfo) {
return unknownDiagnostic(message + cause)
}
const diagnostic: Diagnostic = {
severity: DiagnosticSeverity.Error,
range: {
start: { line: lineInfo.lineNumber, character: lineInfo.columnStart },
end: { line: lineInfo.lineNumber, character: lineInfo.columnEnd },
},
message: `Compiler error: ${message}${cause}`,
source: 'shrimp',
}
return diagnostic
}
}
const unknownDiagnostic = (message: string): Diagnostic => {
const diagnostic: Diagnostic = {
severity: DiagnosticSeverity.Error,
range: {
start: { line: 0, character: 0 },
end: { line: -1, character: -1 },
},
message,
source: 'shrimp',
}
return diagnostic
}
const getParseErrors = (textDocument: TextDocument): Diagnostic[] => {
const tree = parser.parse(textDocument.getText())
const ranges: { start: Position; end: Position }[] = []
tree.iterate({
enter(n) {
if (n.type.isError) {
ranges.push({
start: textDocument.positionAt(n.from),
end: textDocument.positionAt(n.to),
})
return false
}
},
})
return ranges.map((range) => {
return {
range,
severity: DiagnosticSeverity.Error,
message: 'Parse error: Invalid syntax',
source: 'shrimp',
}
})
}
const getErrorMessage = (error: unknown): string => {
if (error instanceof Error) {
return error.message
}
return String(error)
}