Skip to content

Commit 13f1c27

Browse files
committed
[INTERNAL] ComponentAnalyzer: Fix detection of rootView
Fixes: UI5/cli#624 JIRA: CPOUI5FOUNDATION-484 (cherry picked from commit 57a7b89)
1 parent e99d58d commit 13f1c27

File tree

2 files changed

+233
-13
lines changed

2 files changed

+233
-13
lines changed

lib/lbt/analyzer/ComponentAnalyzer.js

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,53 @@ class ComponentAnalyzer {
6666
return info;
6767
}
6868

69+
_getRootViewModule(rootView) {
70+
// For runtime logic see sap/ui/core/UIComponent#createContent and sap/ui/core/mvc/View#_getModuleName
71+
72+
if (typeof rootView === "string") {
73+
rootView = {
74+
viewName: rootView
75+
};
76+
}
77+
if (!rootView.type) {
78+
rootView.type = "XML";
79+
}
80+
81+
if (!rootView.viewName) {
82+
log.warn(`Unable to analyze sap.ui5/rootView: Missing viewName`);
83+
return null;
84+
}
85+
86+
if (rootView.viewName.startsWith("module:")) {
87+
return rootView.viewName.slice("module:".length) + ".js";
88+
}
89+
90+
let viewTypeExtension;
91+
92+
switch (rootView.type) {
93+
case "JS":
94+
viewTypeExtension = ".view.js";
95+
break;
96+
case "JSON":
97+
viewTypeExtension = ".view.json";
98+
break;
99+
case "Template":
100+
viewTypeExtension = ".view.tmpl";
101+
break;
102+
case "XML":
103+
viewTypeExtension = ".view.xml";
104+
break;
105+
case "HTML":
106+
viewTypeExtension = ".view.html";
107+
break;
108+
default:
109+
log.warn(`Unable to analyze sap.ui5/rootView: Unknown type '${rootView.type}'`);
110+
return null;
111+
}
112+
113+
return fromUI5LegacyName(rootView.viewName, viewTypeExtension);
114+
}
115+
69116
/**
70117
* Evaluates a manifest after it has been read and parsed
71118
* and adds any newly found dependencies to the given info object.
@@ -88,20 +135,11 @@ class ComponentAnalyzer {
88135
}
89136

90137
if ( ui5.rootView ) {
91-
let rootView;
92-
if ( typeof ui5.rootView === "string" ) {
93-
rootView = {
94-
viewName: ui5.rootView,
95-
type: "XML"
96-
};
97-
} else {
98-
rootView = ui5.rootView;
138+
const module = this._getRootViewModule(ui5.rootView);
139+
if (module) {
140+
log.verbose("adding root view dependency ", module);
141+
info.addDependency( module );
99142
}
100-
const module = fromUI5LegacyName(
101-
rootView.viewName,
102-
".view." + rootView.type.toLowerCase() );
103-
log.verbose("adding root view dependency ", module);
104-
info.addDependency( module );
105143
}
106144

107145
each( ui5.dependencies && ui5.dependencies.libs, (options, lib) => {

test/lib/lbt/analyzer/ComponentAnalyzer.js

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,32 @@ test("rootView with object", async (t) => {
304304
t.deepEqual(mockInfo.deps, ["test/view/App.view.js"], "dependencies should be correct");
305305
});
306306

307+
test("rootView with object (without type, defaults to XML)", async (t) => {
308+
const mockManifest = {
309+
"sap.ui5": {
310+
rootView: {
311+
viewName: "test.view.App",
312+
async: true
313+
}
314+
}
315+
};
316+
317+
const mockPool = createMockPool("test/", mockManifest);
318+
319+
const mockInfo = {
320+
deps: [],
321+
addDependency(name) {
322+
this.deps.push(name);
323+
}
324+
};
325+
326+
const subject = new ComponentAnalyzer(mockPool);
327+
await subject.analyze({name: path.join("test", "Component.js")}, mockInfo);
328+
t.deepEqual(mockInfo.deps, [
329+
"test/view/App.view.xml",
330+
], "dependencies should be correct");
331+
});
332+
307333
test("rootView with string", async (t) => {
308334
const mockManifest = {
309335
"sap.ui5": {
@@ -325,6 +351,162 @@ test("rootView with string", async (t) => {
325351
t.deepEqual(mockInfo.deps, ["test/view/App.view.xml"], "dependencies should be correct");
326352
});
327353

354+
test("rootView with Typed View ('module:' prefix)", async (t) => {
355+
const mockManifest = {
356+
"sap.ui5": {
357+
"rootView": {
358+
"viewName": "module:myapp/views/MyView",
359+
"async": true
360+
}
361+
}
362+
};
363+
364+
const mockPool = createMockPool("test/", mockManifest);
365+
366+
const mockInfo = {
367+
deps: [],
368+
addDependency(name) {
369+
this.deps.push(name);
370+
}
371+
};
372+
373+
const subject = new ComponentAnalyzer(mockPool);
374+
await subject.analyze({name: path.join("test", "Component.js")}, mockInfo);
375+
t.deepEqual(mockInfo.deps, [
376+
"myapp/views/MyView.js",
377+
], "dependencies should be correct");
378+
});
379+
380+
test("rootView with Template View", async (t) => {
381+
const mockManifest = {
382+
"sap.ui5": {
383+
"rootView": {
384+
"viewName": "myapp.views.MyView",
385+
"type": "Template",
386+
"async": true
387+
}
388+
}
389+
};
390+
391+
const mockPool = createMockPool("test/", mockManifest);
392+
393+
const mockInfo = {
394+
deps: [],
395+
addDependency(name) {
396+
this.deps.push(name);
397+
}
398+
};
399+
400+
const subject = new ComponentAnalyzer(mockPool);
401+
await subject.analyze({name: path.join("test", "Component.js")}, mockInfo);
402+
t.deepEqual(mockInfo.deps, [
403+
"myapp/views/MyView.view.tmpl",
404+
], "dependencies should be correct");
405+
});
406+
407+
test("rootView with JSON View", async (t) => {
408+
const mockManifest = {
409+
"sap.ui5": {
410+
"rootView": {
411+
"viewName": "myapp.views.MyView",
412+
"type": "JSON",
413+
"async": true
414+
}
415+
}
416+
};
417+
418+
const mockPool = createMockPool("test/", mockManifest);
419+
420+
const mockInfo = {
421+
deps: [],
422+
addDependency(name) {
423+
this.deps.push(name);
424+
}
425+
};
426+
427+
const subject = new ComponentAnalyzer(mockPool);
428+
await subject.analyze({name: path.join("test", "Component.js")}, mockInfo);
429+
t.deepEqual(mockInfo.deps, [
430+
"myapp/views/MyView.view.json",
431+
], "dependencies should be correct");
432+
});
433+
434+
test("rootView with HTML View", async (t) => {
435+
const mockManifest = {
436+
"sap.ui5": {
437+
"rootView": {
438+
"viewName": "myapp.views.MyView",
439+
"type": "HTML",
440+
"async": true
441+
}
442+
}
443+
};
444+
445+
const mockPool = createMockPool("test/", mockManifest);
446+
447+
const mockInfo = {
448+
deps: [],
449+
addDependency(name) {
450+
this.deps.push(name);
451+
}
452+
};
453+
454+
const subject = new ComponentAnalyzer(mockPool);
455+
await subject.analyze({name: path.join("test", "Component.js")}, mockInfo);
456+
t.deepEqual(mockInfo.deps, [
457+
"myapp/views/MyView.view.html",
458+
], "dependencies should be correct");
459+
});
460+
461+
test("rootView with unknown view type", async (t) => {
462+
const mockManifest = {
463+
"sap.ui5": {
464+
"rootView": {
465+
"viewName": "myapp.views.MyView",
466+
"type": "InvalidType",
467+
"async": true
468+
}
469+
}
470+
};
471+
472+
const mockPool = createMockPool("test/", mockManifest);
473+
474+
const mockInfo = {
475+
deps: [],
476+
addDependency(name) {
477+
this.deps.push(name);
478+
}
479+
};
480+
481+
const subject = new ComponentAnalyzer(mockPool);
482+
await subject.analyze({name: path.join("test", "Component.js")}, mockInfo);
483+
t.deepEqual(mockInfo.deps, [], "dependencies should be correct");
484+
});
485+
486+
test("rootView without viewName", async (t) => {
487+
const mockManifest = {
488+
"sap.ui5": {
489+
"rootView": {
490+
"type": "XML",
491+
"async": true
492+
}
493+
}
494+
};
495+
496+
const mockPool = createMockPool("test/", mockManifest);
497+
498+
const mockInfo = {
499+
deps: [],
500+
addDependency(name) {
501+
this.deps.push(name);
502+
}
503+
};
504+
505+
const subject = new ComponentAnalyzer(mockPool);
506+
await subject.analyze({name: path.join("test", "Component.js")}, mockInfo);
507+
t.deepEqual(mockInfo.deps, [], "dependencies should be correct");
508+
});
509+
328510

329511
test("analyze: with Component.js", async (t) => {
330512
const emptyPool = {};

0 commit comments

Comments
 (0)