Skip to content

Commit f71fd2a

Browse files
committed
fix(ts-interface-generator): fix usage with UI5 types 1.115.0
Changes in the 1.115 types made the recognition fail whether a class inherits from ManagedObject etc.; now this is not resolved via (shaky) name, but via symbols. fix #397
1 parent 97bd879 commit f71fd2a

File tree

2 files changed

+63
-11
lines changed

2 files changed

+63
-11
lines changed

packages/ts-interface-generator/src/interfaceGenerationHelper.ts

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,63 @@ import Preferences from "./preferences";
1515

1616
const factory = ts.factory;
1717

18-
const interestingBaseClasses: {
19-
[key: string]: "ManagedObject" | "Element" | "Control" | undefined;
20-
} = {
21-
'"sap/ui/base/ManagedObject".ManagedObject': "ManagedObject",
22-
'"sap/ui/core/Element".UI5Element': "Element",
23-
'"sap/ui/core/Control".Control': "Control",
24-
};
18+
let ManagedObjectSymbol: ts.Symbol,
19+
ElementSymbol: ts.Symbol,
20+
ControlSymbol: ts.Symbol;
21+
function interestingBaseClassForSymbol(
22+
typeChecker: ts.TypeChecker,
23+
symbol: ts.Symbol
24+
): "ManagedObject" | "Element" | "Control" | undefined {
25+
if (!ManagedObjectSymbol) {
26+
// cache - TODO: needs to be refreshed when the UI5 type definitions are updated during a run of the tool!
27+
// identify the symbols for the interesting classes
28+
const managedObjectModuleDeclaration = typeChecker
29+
.getAmbientModules()
30+
.filter((m) => m.name === '"sap/ui/base/ManagedObject"')[0]
31+
.declarations[0] as ts.ModuleDeclaration;
32+
const managedObjectClassDeclaration = (
33+
managedObjectModuleDeclaration.body as ts.ModuleBlock
34+
).statements.filter(
35+
(s) => ts.isClassDeclaration(s) && s.name?.text === "ManagedObject"
36+
)[0] as ts.ClassDeclaration;
37+
ManagedObjectSymbol = typeChecker.getSymbolAtLocation(
38+
managedObjectClassDeclaration.name
39+
);
40+
41+
const elementModuleDeclaration = typeChecker
42+
.getAmbientModules()
43+
.filter((m) => m.name === '"sap/ui/core/Element"')[0]
44+
.declarations[0] as ts.ModuleDeclaration;
45+
const elementClassDeclaration = (
46+
elementModuleDeclaration.body as ts.ModuleBlock
47+
).statements.filter(
48+
(s) => ts.isClassDeclaration(s) && s.name?.text === "UI5Element"
49+
)[0] as ts.ClassDeclaration;
50+
ElementSymbol = typeChecker.getSymbolAtLocation(
51+
elementClassDeclaration.name
52+
);
53+
54+
const controlModuleDeclaration = typeChecker
55+
.getAmbientModules()
56+
.filter((m) => m.name === '"sap/ui/core/Control"')[0]
57+
.declarations[0] as ts.ModuleDeclaration;
58+
const controlClassDeclaration = (
59+
controlModuleDeclaration.body as ts.ModuleBlock
60+
).statements.filter(
61+
(s) => ts.isClassDeclaration(s) && s.name?.text === "Control"
62+
)[0] as ts.ClassDeclaration;
63+
ControlSymbol = typeChecker.getSymbolAtLocation(
64+
controlClassDeclaration.name
65+
);
66+
}
67+
if (symbol === ControlSymbol) {
68+
return "Control";
69+
} else if (symbol === ElementSymbol) {
70+
return "Element";
71+
} else if (symbol === ManagedObjectSymbol) {
72+
return "ManagedObject";
73+
}
74+
}
2575

2676
const interestingBaseSettingsClasses: {
2777
[key: string]:
@@ -405,8 +455,10 @@ function getInterestingBaseClass(
405455
//const typeName = typeChecker.typeToString(type);
406456
//log.debug("-> " + typeName + " (" + typeChecker.getFullyQualifiedName(type.getSymbol()) + ")");
407457

408-
let interestingBaseClass =
409-
interestingBaseClasses[typeChecker.getFullyQualifiedName(type.getSymbol())];
458+
let interestingBaseClass = interestingBaseClassForSymbol(
459+
typeChecker,
460+
type.getSymbol()
461+
);
410462
if (interestingBaseClass) {
411463
return interestingBaseClass;
412464
}
@@ -533,7 +585,6 @@ function extractJSDoc(jsDocs: (ts.JSDoc | ts.JSDocTag)[]) {
533585
deprecation: handleTag(jsDocs, "deprecated"),
534586
};
535587
}
536-
537588
// for a single definition in the metadata (a single property, a single aggregation, ...), this method extracts all needed info into the returned APIMember instance
538589
function getMemberFromPropertyAssignment<T extends MetadataSectionName>(
539590
propertyAssignment: ts.PropertyAssignment,

packages/ts-interface-generator/src/typeScriptEnvironment.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,12 @@ function initialize(
7575
host.afterProgramCreate = (program) => {
7676
// in run-once mode we immediately trigger generation and then close the watch
7777
if (!options.watchMode) {
78+
log.info("Run-once mode: running generation now.");
7879
onProgramChanged(program, []);
7980
// TODO: shut down the watcher
80-
log.info("\n\nDone. Exiting.");
8181
setTimeout(function () {
8282
// must be asynchronously because createWatchProgram(...) below triggers this synchronously, so the return value "watch" is not yet assigned
83+
log.info("\n\nDone. Exiting.");
8384
watch.close();
8485
}, 0);
8586
}

0 commit comments

Comments
 (0)