diff --git a/server/src/error.ts b/server/src/error.ts deleted file mode 100644 index 2f661f9..0000000 --- a/server/src/error.ts +++ /dev/null @@ -1,5 +0,0 @@ -import CMakeListener from './parser/CMakeListener'; - -export default class CMakeErrorListener extends CMakeListener { - -} \ No newline at end of file diff --git a/server/src/semanticDiagnostics.ts b/server/src/semanticDiagnostics.ts new file mode 100644 index 0000000..ccb0ff8 --- /dev/null +++ b/server/src/semanticDiagnostics.ts @@ -0,0 +1,118 @@ +import { Diagnostic, DiagnosticSeverity } from "vscode-languageserver"; +import Token from "./parser/antlr4/Token"; +import CMakeListener from "./parser/CMakeListener"; + +export default class SemanticDiagnosticsListener extends CMakeListener { + private diagnostics: Diagnostic[] = []; + + enterAddSubDirCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterBreakCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterContinueCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterElseCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterElseIfCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterEndForeachCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterEndFunctionCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterEndIfCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterEndMacroCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterEndWhileCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterForeachCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterFunctionCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterIfCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterIncludeCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterMacroCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterOptionCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterWhileCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterSetCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + enterOtherCmd(ctx: any): void { + this.checkCmdCase(ctx.start); + } + + checkCmdCase(token: Token) { + const text: string = token.text; + const line: number = token.line, column: number = token.column; + const isLowerCase = ((cmdText: string) => { + for (const ch of cmdText) { + if (ch.toLowerCase() !== ch) { + return false; + } + } + return true; + })(text); + + if (!isLowerCase) { + this.diagnostics.push({ + range: { + start: { + line: line - 1, + character: column + }, + end: { + line: line - 1, + character: column + text.length + } + }, + severity: DiagnosticSeverity.Information, + source: 'cmake-intellisence', + message: "cmake encourage lower case command name" + }); + } + } + + getSemanticDiagnostics(): Diagnostic[] { + return this.diagnostics; + } +} \ No newline at end of file diff --git a/server/src/server.ts b/server/src/server.ts index b45b68b..ba3c349 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -19,7 +19,7 @@ import { existsSync } from 'fs'; import { URI, Utils } from 'vscode-uri'; import * as builtinCmds from './builtin-cmds.json'; import { cmakeInfo } from './cmakeInfo'; -import CMakeErrorListener from './diagnostics'; +import SyntaxErrorListener from './syntaxDiagnostics'; import { SymbolListener } from './docSymbols'; import { FormatListener } from './format'; import antlr4 from './parser/antlr4/index.js'; @@ -30,6 +30,7 @@ import { extSettings } from './settings'; import { DefinationListener, incToBaseDir, refToDef, topScope } from './symbolTable/goToDefination'; import { getFileContext } from './utils'; import { createLogger } from './logging'; +import SemanticDiagnosticsListener from './semanticDiagnostics'; type Word = { text: string, @@ -392,14 +393,17 @@ documents.onDidChangeContent((change: TextDocumentChangeEvent) => const tokenStream = new antlr4.CommonTokenStream(lexer); const parser = new CMakeParser(tokenStream); parser.removeErrorListeners(); - const errorListener = new CMakeErrorListener(); - parser.addErrorListener(errorListener); + const syntaxErrorListener = new SyntaxErrorListener(); + parser.addErrorListener(syntaxErrorListener); const tree = parser.file(); - const symbolListener = new SymbolListener(); - antlr4.tree.ParseTreeWalker.DEFAULT.walk(symbolListener, tree); + const semanticListener = new SemanticDiagnosticsListener(); + antlr4.tree.ParseTreeWalker.DEFAULT.walk(semanticListener, tree); connection.sendDiagnostics({ uri: change.document.uri, - diagnostics: errorListener.getDiagnostics() + diagnostics: [ + ...syntaxErrorListener.getSyntaxErrors(), + ...semanticListener.getSemanticDiagnostics() + ] }); }); diff --git a/server/src/diagnostics.ts b/server/src/syntaxDiagnostics.ts similarity index 72% rename from server/src/diagnostics.ts rename to server/src/syntaxDiagnostics.ts index 15c6218..c9dcb69 100644 --- a/server/src/diagnostics.ts +++ b/server/src/syntaxDiagnostics.ts @@ -1,7 +1,7 @@ -import { Diagnostic } from 'vscode-languageserver'; +import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver'; import ErrorListener from './parser/antlr4/error/ErrorListener'; -export default class CMakeErrorListener extends ErrorListener { +export default class SyntaxErrorListener extends ErrorListener { private diagnostics: Diagnostic[] = []; /** @@ -25,15 +25,17 @@ export default class CMakeErrorListener extends ErrorListener { character: column + offendingSymbol.text.length } }, + severity: DiagnosticSeverity.Error, + source: 'cmake-intellisence', message: msg }); } - public getDiagnostics(): Diagnostic[] { + public getSyntaxErrors(): Diagnostic[] { return this.diagnostics; } - public clearDiagnostics() { + public clearSyntaxErrors() { this.diagnostics = []; } } \ No newline at end of file