diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fee07c..c970492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Fix issue [#336](https://github.com/intersystems/language-server/issues/336): Add intellisense for variables set to the returned value of a method, or a property, with a declared type - Fix issue [#337](https://github.com/intersystems/language-server/issues/337): Improve Hover headers - Fix issue [#338](https://github.com/intersystems/language-server/issues/338): Add intellisense for macros in Embedded SQL +- Fix issue [#339](https://github.com/intersystems/language-server/issues/339): Macro intellisense doesn't respect `#undef` directive ## [2.5.1] - 2024-07-09 - Fix issue [#328](https://github.com/intersystems/language-server/issues/328): Fix namespace detection for Diagnostic computation diff --git a/server/src/providers/completion.ts b/server/src/providers/completion.ts index 30f04dd..bd78897 100644 --- a/server/src/providers/completion.ts +++ b/server/src/providers/completion.ts @@ -1,4 +1,4 @@ -import { CompletionItem, CompletionItemKind, CompletionItemTag, CompletionParams, InsertTextFormat, Position, Range, TextEdit } from 'vscode-languageserver/node'; +import { CompletionItem, CompletionItemKind, CompletionItemTag, CompletionParams, InsertTextFormat, MarkupKind, Position, Range, TextEdit } from 'vscode-languageserver/node'; import { getServerSpec, getLanguageServerSettings, getMacroContext, makeRESTRequest, normalizeSystemName, getImports, findFullRange, getClassMemberContext, quoteUDLIdentifier, documaticHtmlToMarkdown, determineClassNameParameterClass, storageKeywordsKeyForToken, getParsedDocument, currentClass, normalizeClassname } from '../utils/functions'; import { ServerSpec, QueryData, KeywordDoc, MacroContext, compressedline } from '../utils/types'; import { documents, corePropertyParams } from '../utils/variables'; @@ -759,20 +759,24 @@ export async function onCompletion(params: CompletionParams): Promise= 0; ln--) { - if (parsed[ln].length < 4) { - continue; - } - if (parsed[ln][0].l == ld.cos_langindex && parsed[ln][0].s == ld.cos_ppc_attrindex) { + if (!parsed[ln]?.length) continue; + if (parsed[ln].length > 1 && parsed[ln][0].l == ld.cos_langindex && parsed[ln][0].s == ld.cos_ppc_attrindex) { // This line begins with a preprocessor command const ppctext = doc.getText(Range.create( ln,parsed[ln][1].p, ln,parsed[ln][1].p+parsed[ln][1].c )).toLowerCase(); - if (ppctext == "define" || ppctext == "def1arg") { + if (parsed[ln].length > 3 && ["define","def1arg"].includes(ppctext)) { // This is a macro definition + const macro = doc.getText(Range.create(ln,parsed[ln][2].p,ln,parsed[ln][2].p+parsed[ln][2].c)); + if (undefs.includes(macro)) { + // Don't suggest this macro because it was #undef'd before the completion line + continue; + } const macrodef: CompletionItem = { - label: doc.getText(Range.create(ln,parsed[ln][2].p,ln,parsed[ln][2].p+parsed[ln][2].c)), + label: macro, kind: CompletionItemKind.Text, data: ["macro",doc.uri] }; @@ -830,7 +834,7 @@ export async function onCompletion(params: CompletionParams): Promise 2 && ppctext == "undef") { + // This is a macro un-definition + undefs.push(doc.getText(Range.create(ln,parsed[ln][2].p,ln,parsed[ln][2].p+parsed[ln][2].c))); } } + if (parsed[ln].some((t) => t.l == ld.cls_langindex)) break; } } else if (prevline.slice(-1) === "$" && prevline.charAt(prevline.length-2) !== "$" && triggerlang === ld.cos_langindex) { @@ -2127,7 +2135,7 @@ export async function onCompletionResolve(item: CompletionItem): Promise 0) { // The class was found item.documentation = { - kind: "markdown", + kind: MarkupKind.Markdown, value: documaticHtmlToMarkdown(respdata.data.result.content[0].Description) }; } @@ -2156,7 +2164,7 @@ export async function onCompletionResolve(item: CompletionItem): Promise= 0; ln--) { - if (parsed[ln].length < 4) { - continue; - } - if (parsed[ln][0].l == ld.cos_langindex && parsed[ln][0].s == ld.cos_ppc_attrindex) { + if (!parsed[ln]?.length) continue; + if (parsed[ln].length > 1 && parsed[ln][0].l == ld.cos_langindex && parsed[ln][0].s == ld.cos_ppc_attrindex) { // This line begins with a preprocessor command const ppctext = doc.getText(Range.create( - Position.create(ln,parsed[ln][1].p), - Position.create(ln,parsed[ln][1].p+parsed[ln][1].c) + ln,parsed[ln][1].p, + ln,parsed[ln][1].p+parsed[ln][1].c )).toLowerCase(); - if (ppctext === "define" || ppctext === "def1arg") { - // This is a macro definition - const macrotext = doc.getText(Range.create( - Position.create(ln,parsed[ln][2].p), - Position.create(ln,parsed[ln][2].p+parsed[ln][2].c) - )); - if (macrotext === macro) { - // We found the definition for the selected macro - result = ln; - break; - } + if ( + parsed[ln].length > 2 && ["define","def1arg","undef"].includes(ppctext) && doc.getText(Range.create( + ln,parsed[ln][2].p, + ln,parsed[ln][2].p+parsed[ln][2].c + )) == macro + ) { + // We found the (un-)definition for the selected macro + if (ppctext != "undef") result = ln; + break; } } + if (parsed[ln].some((t) => t.l == ld.cls_langindex)) break; } return result;