generated from SAP/repository-template
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add type support for Controller#byId
This feature adds type definitions for `byId` within controllers so that the usage of deprecated functionality can be detected when controls or elements from the view are accessed by their ID. Previously, only the base element class was known, which is still the case as a fallback. JIRA: CPOUI5FOUNDATION-843
- Loading branch information
Showing
21 changed files
with
754 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Multiple views/fragments can use the same ID and link to the same controller, | ||
// so we need to store a set of module names for each ID. | ||
export type IdModulesMap = Map<string, Set<string>>; | ||
|
||
type ControllerElementsMap = Map<string, IdModulesMap>; | ||
|
||
export default class ControllerByIdInfo { | ||
private map: ControllerElementsMap = new Map(); | ||
|
||
private getControllerMapping(controllerName: string) { | ||
let controllerMap = this.map.get(controllerName); | ||
if (!controllerMap) { | ||
controllerMap = new Map(); | ||
this.map.set(controllerName, controllerMap); | ||
} | ||
return controllerMap; | ||
} | ||
|
||
public addMappings(controllerName: string, idModuleMap: Map<string, string>) { | ||
const controllerMapping = this.getControllerMapping(controllerName); | ||
for (const [id, module] of idModuleMap) { | ||
let existingModules = controllerMapping.get(id); | ||
if (!existingModules) { | ||
existingModules = new Set(); | ||
controllerMapping.set(id, existingModules); | ||
} | ||
existingModules.add(module); | ||
} | ||
} | ||
|
||
public getMappings() { | ||
return this.map; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
src/linter/xmlTemplate/generator/ControllerByIdDtsGenerator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import ControllerByIdInfo, {IdModulesMap} from "../ControllerByIdInfo.js"; | ||
|
||
interface Import { | ||
localName: string; | ||
moduleName: string; | ||
} | ||
export class ControllerByIdDtsGenerator { | ||
private imports = new Set<Import>(); | ||
|
||
constructor(private controllerByIdInfo: ControllerByIdInfo) { | ||
} | ||
|
||
generate() { | ||
let out = ""; | ||
this.controllerByIdInfo.getMappings().forEach((idToModules, controllerName) => { | ||
out += this.generateModuleDeclaration(controllerName, idToModules); | ||
}); | ||
return this.generateCollectedImports() + out; | ||
} | ||
|
||
generateCollectedImports() { | ||
let out = ""; | ||
this.imports.forEach((moduleImport) => { | ||
out += `import ${moduleImport.localName} from "${moduleImport.moduleName}";\n`; | ||
}); | ||
out += "\n"; | ||
return out; | ||
} | ||
|
||
generateByIdMapping(idToModules: IdModulesMap) { | ||
let out = "\tinterface ByIdMapping {\n"; | ||
idToModules.forEach((modules, id) => { | ||
const localNames: string[] = []; | ||
modules.forEach((moduleName) => { | ||
const localName = this.getLocalModuleName(moduleName); | ||
localNames.push(localName); | ||
this.imports.add({localName, moduleName}); | ||
}); | ||
out += `\t\t"${id}": ${localNames.join(" | ")};\n`; | ||
}); | ||
out += "\t}\n"; | ||
return out; | ||
} | ||
|
||
generateModuleDeclaration(controllerName: string, idToModules: IdModulesMap) { | ||
const moduleName = controllerName.replace(/\./g, "/") + ".controller"; | ||
// The interface name actually does not really matter as the declaration refers to the default export | ||
const controllerClassName = controllerName.split(".").pop(); | ||
let out = `declare module "${moduleName}" {\n`; | ||
out += this.generateByIdMapping(idToModules); | ||
out += `\texport default interface ${controllerClassName} {\n`; | ||
out += `\t\tbyId<T extends keyof ByIdMapping>(sId: T): ByIdMapping[T];\n`; | ||
out += `\t\tbyId(sId: string): UI5Element;\n`; | ||
out += `\t};\n`; | ||
out += `};\n\n`; | ||
return out; | ||
} | ||
|
||
getLocalModuleName(moduleName: string) { | ||
return moduleName.replace(/[/.]/g, "_"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/view/DesktopMain.view.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<!-- | ||
This file is a partial copy of Main.view.xml but uses other controls. | ||
Its purpose is to cover the case where multiple views refer to | ||
the same controller (controllerName) and contain controls with | ||
the same ID but a different type. The resulting type for the | ||
controller byId() call should be the union of the types. | ||
--> | ||
<mvc:View | ||
controllerName="com.ui5.troublesome.app.controller.Main" | ||
displayBlock="true" | ||
xmlns="sap.ui.commons" | ||
xmlns:mvc="sap.ui.core.mvc" | ||
xmlns:core="sap.ui.core"> | ||
|
||
<Button id="testButton" /> | ||
|
||
</mvc:View> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,4 +23,6 @@ | |
</buttons> | ||
</MessagePage> | ||
|
||
<Button id="testButton" /> | ||
|
||
</mvc:View> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.