From 19250c1a5885c1c91635a0475e425447796ec4bd Mon Sep 17 00:00:00 2001 From: Maruf Rasully <100434800+marufrasully@users.noreply.github.com> Date: Tue, 9 Jan 2024 18:04:15 +0100 Subject: [PATCH 1/2] fix: no code completion or diagnostic for contextPath or metaPath of macros namespace --- .changeset/brown-cows-thank.md | 7 + .../services/completion/providers/binding.ts | 125 ++++++++++-------- .../validators/binding-validator.ts | 5 +- packages/binding/src/utils/element.ts | 17 +++ packages/binding/src/utils/index.ts | 1 + .../completion/property-binding-info.test.ts | 12 ++ .../property-binding-info-validator.test.ts | 12 ++ 7 files changed, 122 insertions(+), 57 deletions(-) create mode 100644 .changeset/brown-cows-thank.md diff --git a/.changeset/brown-cows-thank.md b/.changeset/brown-cows-thank.md new file mode 100644 index 000000000..7900f7606 --- /dev/null +++ b/.changeset/brown-cows-thank.md @@ -0,0 +1,7 @@ +--- +"@ui5-language-assistant/vscode-ui5-language-assistant-bas-ext": patch +"vscode-ui5-language-assistant": patch +"@ui5-language-assistant/binding": patch +--- + +No code completion or diagnostic for contextPath or metaPath of macros namespace diff --git a/packages/binding/src/services/completion/providers/binding.ts b/packages/binding/src/services/completion/providers/binding.ts index 05a4aad5e..c45e8d131 100644 --- a/packages/binding/src/services/completion/providers/binding.ts +++ b/packages/binding/src/services/completion/providers/binding.ts @@ -16,7 +16,11 @@ import { import { BindContext } from "../../../types"; import { createInitialSnippet } from "./create-initial-snippet"; -import { getCursorContext } from "../../../utils"; +import { + getCursorContext, + getLogger, + isMacrosMetaContextPath, +} from "../../../utils"; import { createAllSupportedElements } from "./create-all-supported-elements"; import { createKeyProperties } from "./create-key-properties"; import { createValue } from "./create-value"; @@ -69,64 +73,73 @@ export function bindingSuggestions({ context, }: AttributeValueCompletionOptions): CompletionItem[] { const completionItems: CompletionItem[] = []; - const ui5Property = getUI5PropertyByXMLAttributeKey( - attribute, - context.ui5Model - ); - const ui5Aggregation = getUI5AggregationByXMLAttributeKey( - attribute, - context.ui5Model - ); - if (!ui5Property && !ui5Aggregation) { - return completionItems; - } - const propBinding = getBindingElements(context, !!ui5Aggregation, false); - const properties = propBinding.map((i) => i.name); - const value = attribute.syntax.value; - const startChar = value && value.image.charAt(0); - context.doubleQuotes = startChar === '"'; - /* istanbul ignore next */ - const text = attribute.value ?? ""; - const extractedBindings = extractBindingSyntax(text); - for (const bindingSyntax of extractedBindings) { - const { expression, startIndex } = bindingSyntax; - if (isBindingExpression(expression)) { - continue; - } - /* istanbul ignore next */ - const position: Position = { - character: (value?.startColumn ?? 0) + startIndex, - line: value?.startLine ? value.startLine - 1 : 0, // zero based index - }; - const { ast, errors } = parseBinding(expression, position); - const input = expression; - if (input.trim() === "") { - completionItems.push(...createInitialSnippet()); - continue; + try { + // `metaPath` and `contextPath` of 'sap.fe.macros' is static + if (isMacrosMetaContextPath(attribute)) { + return completionItems; } - /* istanbul ignore next */ - const cursorPos = context.textDocumentPosition?.position; - const binding = ast.bindings.find( - (b) => - cursorPos && - b.range && - rangeContained(b.range, { start: cursorPos, end: cursorPos }) + const ui5Property = getUI5PropertyByXMLAttributeKey( + attribute, + context.ui5Model ); - if (!binding) { - continue; + const ui5Aggregation = getUI5AggregationByXMLAttributeKey( + attribute, + context.ui5Model + ); + if (!ui5Property && !ui5Aggregation) { + return completionItems; } - if (!isBindingAllowed(text, binding, errors, properties)) { - continue; + const propBinding = getBindingElements(context, !!ui5Aggregation, false); + const properties = propBinding.map((i) => i.name); + const value = attribute.syntax.value; + const startChar = value && value.image.charAt(0); + context.doubleQuotes = startChar === '"'; + /* istanbul ignore next */ + const text = attribute.value ?? ""; + const extractedBindings = extractBindingSyntax(text); + for (const bindingSyntax of extractedBindings) { + const { expression, startIndex } = bindingSyntax; + if (isBindingExpression(expression)) { + continue; + } + /* istanbul ignore next */ + const position: Position = { + character: (value?.startColumn ?? 0) + startIndex, + line: value?.startLine ? value.startLine - 1 : 0, // zero based index + }; + const { ast, errors } = parseBinding(expression, position); + const input = expression; + if (input.trim() === "") { + completionItems.push(...createInitialSnippet()); + continue; + } + /* istanbul ignore next */ + const cursorPos = context.textDocumentPosition?.position; + const binding = ast.bindings.find( + (b) => + cursorPos && + b.range && + rangeContained(b.range, { start: cursorPos, end: cursorPos }) + ); + if (!binding) { + continue; + } + if (!isBindingAllowed(text, binding, errors, properties)) { + continue; + } + completionItems.push( + ...getCompletionItems( + context, + binding, + ast.spaces, + !!ui5Aggregation, + propBinding + ) + ); } - completionItems.push( - ...getCompletionItems( - context, - binding, - ast.spaces, - !!ui5Aggregation, - propBinding - ) - ); + return completionItems; + } catch (error) { + getLogger().debug("bindingSuggestions failed:", error); + return completionItems; } - return completionItems; } diff --git a/packages/binding/src/services/diagnostics/validators/binding-validator.ts b/packages/binding/src/services/diagnostics/validators/binding-validator.ts index af627dadd..c95e83868 100644 --- a/packages/binding/src/services/diagnostics/validators/binding-validator.ts +++ b/packages/binding/src/services/diagnostics/validators/binding-validator.ts @@ -6,7 +6,7 @@ import { } from "@ui5-language-assistant/logic-utils"; import { BindingIssue } from "../../../types"; import { BINDING_ISSUE_TYPE } from "../../../constant"; -import { getLogger } from "../../../utils"; +import { getLogger, isMacrosMetaContextPath } from "../../../utils"; import { Position } from "vscode-languageserver-types"; import { parseBinding, @@ -25,6 +25,9 @@ export function validateBinding( ): BindingIssue[] { const issues: BindingIssue[] = []; try { + if (isMacrosMetaContextPath(attribute)) { + return issues; + } const ui5Property = getUI5PropertyByXMLAttributeKey( attribute, context.ui5Model diff --git a/packages/binding/src/utils/element.ts b/packages/binding/src/utils/element.ts index 976d08bb0..c12c7ac45 100644 --- a/packages/binding/src/utils/element.ts +++ b/packages/binding/src/utils/element.ts @@ -15,6 +15,7 @@ import { } from "@ui5-language-assistant/binding-parser"; import { PARTS } from "../constant"; import { Range } from "vscode-languageserver-types"; +import type { XMLAttribute } from "@xml-tools/ast"; const isNumber = (input: number | undefined): input is number => { return input !== undefined; }; @@ -129,3 +130,19 @@ export const getPropertyTypeWithPossibleValue = ( return undefined; }; + +/** + * Return turn if it is `metaPath` or `contextPath` of `macros` namespace + */ +export const isMacrosMetaContextPath = (attribute: XMLAttribute): boolean => { + if (!attribute.key) { + return false; + } + if ( + ["metaPath", "contextPath"].includes(attribute.key) && + attribute.parent.ns === "macros" + ) { + return true; + } + return false; +}; diff --git a/packages/binding/src/utils/index.ts b/packages/binding/src/utils/index.ts index e4c4002e2..bc0cf5ebc 100644 --- a/packages/binding/src/utils/index.ts +++ b/packages/binding/src/utils/index.ts @@ -6,6 +6,7 @@ export { findRange, defaultRange, getPropertyTypeWithPossibleValue, + isMacrosMetaContextPath, } from "./element"; export { getCursorContext } from "./cursor"; diff --git a/packages/binding/test/unit/services/completion/property-binding-info.test.ts b/packages/binding/test/unit/services/completion/property-binding-info.test.ts index 1d7e84204..436be27fe 100644 --- a/packages/binding/test/unit/services/completion/property-binding-info.test.ts +++ b/packages/binding/test/unit/services/completion/property-binding-info.test.ts @@ -718,5 +718,17 @@ describe("index", () => { }); }); }); + describe("macros static property", () => { + it("no CC for metaPath", async () => { + const snippet = ``; + const result = await getCompletionResult(snippet); + expect(result).toStrictEqual([]); + }); + it("no CC for contextPath", async () => { + const snippet = ``; + const result = await getCompletionResult(snippet); + expect(result).toStrictEqual([]); + }); + }); }); }); diff --git a/packages/binding/test/unit/services/diagnostics/validators/property-binding-info-validator.test.ts b/packages/binding/test/unit/services/diagnostics/validators/property-binding-info-validator.test.ts index 2000716ad..bc60317a3 100644 --- a/packages/binding/test/unit/services/diagnostics/validators/property-binding-info-validator.test.ts +++ b/packages/binding/test/unit/services/diagnostics/validators/property-binding-info-validator.test.ts @@ -900,4 +900,16 @@ describe("property-binding-info-validator", () => { }); }); }); + describe("macros static property", () => { + it("no diagnostic for metaPath", async () => { + const snippet = ``; + const result = await validateView(snippet); + expect(result).toStrictEqual([]); + }); + it("no diagnostic for contextPath", async () => { + const snippet = ``; + const result = await validateView(snippet); + expect(result).toStrictEqual([]); + }); + }); }); From 2b9201018f18253b1aaefadaf4b334a7aa58dc6f Mon Sep 17 00:00:00 2001 From: Maruf Rasully <100434800+marufrasully@users.noreply.github.com> Date: Wed, 10 Jan 2024 16:22:55 +0100 Subject: [PATCH 2/2] fix: review comment --- packages/binding/src/services/completion/providers/binding.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/binding/src/services/completion/providers/binding.ts b/packages/binding/src/services/completion/providers/binding.ts index 8303ec34f..2db2ddffd 100644 --- a/packages/binding/src/services/completion/providers/binding.ts +++ b/packages/binding/src/services/completion/providers/binding.ts @@ -141,6 +141,6 @@ export function bindingSuggestions({ return completionItems; } catch (error) { getLogger().debug("bindingSuggestions failed:", error); - return completionItems; + return []; } }