Skip to content

Commit 44d780b

Browse files
authored
fix: completion in FragmentDefinition (#567)
1 parent 459cf5e commit 44d780b

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

packages/xml-views-completion/src/providers/elementName/classes.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
getUI5AggregationByXMLElement,
1616
splitQNameByNamespace,
1717
resolveXMLNSFromPrefix,
18+
xmlToFQN,
1819
} from "@ui5-language-assistant/logic-utils";
1920
import { UI5ClassesInXMLTagNameCompletion } from "../../../api";
2021
import { UI5ElementNameCompletionOptions } from "./index";
@@ -99,15 +100,28 @@ function computeClassSuggestionContext({
99100
model: UI5SemanticModel;
100101
}): classSuggestionContext | null {
101102
const parentXMLElement = xmlElement.parent;
103+
102104
// top level class suggestions, it is kind of like an implicit aggregation
103105
if (parentXMLElement.type === "XMLDocument") {
106+
// an xml fragment can contain single control element at a top level
107+
// https://sapui5.hana.ondemand.com/#/topic/2c677b574ea2486a8d5f5414d15e21c5
104108
return {
105-
// TODO: in a fragment xml view an element may possibly be at the top level?
106109
allowedType: model.classes["sap.ui.core.Control"],
107110
cardinality: "0..1",
108111
};
109112
}
110113

114+
const parentFullyQualifiedName = xmlToFQN(parentXMLElement);
115+
if (parentFullyQualifiedName === "sap.ui.core.FragmentDefinition") {
116+
// wrapper for multiple fragment elements
117+
// sap.ui.core.FragmentDefinition does not exist in api.json,
118+
// so we need custom handling here
119+
return {
120+
allowedType: model.classes["sap.ui.core.Control"],
121+
cardinality: "0..n",
122+
parentXMLTag: parentXMLElement,
123+
};
124+
}
111125
// If the parent tag is a class this is an implicit (default) aggregation
112126
const parentUI5Class = getUI5ClassByXMLElement(parentXMLElement, model);
113127
if (parentUI5Class !== undefined) {

packages/xml-views-completion/test/providers/elementName/classes-spec.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,72 @@ describe("The ui5-language-assistant xml-views-completion", () => {
104104
});
105105
});
106106

107+
context("sap.ui.core.FragmentDefinition content", () => {
108+
context("no prefix", () => {
109+
it("will suggest **all** Controls", () => {
110+
const xmlSnippet = `
111+
<core:FragmentDefinition xmlns:core="sap.ui.core">
112+
<⇶
113+
</core:FragmentDefinition>
114+
`;
115+
116+
testSuggestionsScenario({
117+
context: appContext,
118+
xmlText: xmlSnippet,
119+
providers: {
120+
elementName: [classesSuggestions],
121+
},
122+
assertion: (suggestions) => {
123+
const baseControl = ui5Model.classes["sap.ui.core.Control"];
124+
expect(suggestions).to.have.length.greaterThan(200);
125+
forEach(suggestions, (_) => {
126+
expect(_.ui5Node.kind).to.equal("UI5Class");
127+
const superClasses = getSuperClasses(_.ui5Node as UI5Class);
128+
// Chai's `.include` is super slow, we must implement it ourselves...
129+
const doesSuggestionExtendsControl =
130+
find(superClasses, baseControl) !== undefined;
131+
expect(
132+
doesSuggestionExtendsControl || _.ui5Node === baseControl
133+
).to.be.true;
134+
});
135+
},
136+
});
137+
});
138+
});
139+
context("multiple children", () => {
140+
it("will suggest **all** Controls", () => {
141+
const xmlSnippet = `
142+
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m">
143+
<Button></Button>
144+
<⇶
145+
</core:FragmentDefinition>
146+
`;
147+
148+
testSuggestionsScenario({
149+
context: appContext,
150+
xmlText: xmlSnippet,
151+
providers: {
152+
elementName: [classesSuggestions],
153+
},
154+
assertion: (suggestions) => {
155+
const baseControl = ui5Model.classes["sap.ui.core.Control"];
156+
expect(suggestions).to.have.length.greaterThan(200);
157+
forEach(suggestions, (_) => {
158+
expect(_.ui5Node.kind).to.equal("UI5Class");
159+
const superClasses = getSuperClasses(_.ui5Node as UI5Class);
160+
// Chai's `.include` is super slow, we must implement it ourselves...
161+
const doesSuggestionExtendsControl =
162+
find(superClasses, baseControl) !== undefined;
163+
expect(
164+
doesSuggestionExtendsControl || _.ui5Node === baseControl
165+
).to.be.true;
166+
});
167+
},
168+
});
169+
});
170+
});
171+
});
172+
107173
context("classes under (implicit) default aggregations", () => {
108174
context("no prefix", () => {
109175
it("will suggest **all** classes matching the type of the default aggregation", () => {

0 commit comments

Comments
 (0)