-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[INTERNAL] Create and integrate a new task 'generateLibraryManifest' (#…
…26) The task creates a manifest.json file for libraries that don't have one. It collects the necessary information from the project structure (supported themes, versions of dependencies), from the .library file (name, dependencies, supported themes, thirdparty components, i18n information...) and from an initLibrary call inside the library.js file (implemented controls, elements, types and interfaces, noLibraryCSS flag). An existing manifest.json won't be modified or overwritten. - refactor test scenario 'library.h' so that the sub-components reside in the namespace of the library - add new test scenario 'library.i' to test manifest creation with data from .library and library.js file - add the newly generated manifest.json to the expected content of the other library test scenarios - enhance all library test scenarios with a dependency to a fake 'sap.ui.core' lib. For UI5 libs, this dependency is mandatory and manifest generation needs it to determine the UI5 version - re-classify log message for missing .library file as 'verbose'
- Loading branch information
1 parent
e9823f6
commit 000a6fe
Showing
38 changed files
with
3,100 additions
and
1,796 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
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,94 @@ | ||
"use strict"; | ||
const esprima = require("esprima"); | ||
const {Syntax} = esprima; | ||
const {getPropertyKey, isMethodCall, isIdentifier, getStringArray} = require("../utils/ASTUtils"); | ||
const VisitorKeys = require("estraverse").VisitorKeys; | ||
|
||
const CALL__SAP_UI_GETCORE = ["sap", "ui", "getCore"]; | ||
|
||
/* | ||
* Static Code Analyzer that extracts library information from the sap.ui.getCore().initLibrary() | ||
* call in a library.js module. | ||
*/ | ||
async function analyze(resource) { | ||
let libInfo = { | ||
noLibraryCSS: false, | ||
types: [], | ||
controls: [], | ||
elements: [], | ||
interfaces: [] | ||
}; | ||
|
||
function visit(node) { | ||
if ( node.type == Syntax.CallExpression | ||
&& node.callee.type === Syntax.MemberExpression | ||
&& isMethodCall(node.callee.object, CALL__SAP_UI_GETCORE) | ||
&& isIdentifier(node.callee.property, "initLibrary") | ||
&& node.arguments.length === 1 | ||
&& node.arguments[0].type === Syntax.ObjectExpression ) { | ||
node.arguments[0].properties.forEach( (prop) => { | ||
let key = getPropertyKey(prop); | ||
let value = prop.value; | ||
if ( key === "noLibraryCSS" | ||
&& (value.type === Syntax.Literal && typeof value.value === "boolean") ) { | ||
libInfo.noLibraryCSS = value.value; | ||
} else if ( key === "types" && value.type == Syntax.ArrayExpression ) { | ||
libInfo.types = getStringArray(value, true); | ||
} else if ( key === "interfaces" && value.type == Syntax.ArrayExpression ) { | ||
libInfo.interfaces = getStringArray(value, true); | ||
} else if ( key === "controls" && value.type == Syntax.ArrayExpression ) { | ||
libInfo.controls = getStringArray(value, true); | ||
} else if ( key === "elements" && value.type == Syntax.ArrayExpression ) { | ||
libInfo.elements = getStringArray(value, true); | ||
} | ||
}); | ||
|
||
return true; // abort, we're done | ||
} | ||
|
||
for ( let key of VisitorKeys[node.type] ) { | ||
let child = node[key]; | ||
if ( Array.isArray(child) ) { | ||
if ( child.some(visit) ) { | ||
return true; | ||
} | ||
} else if ( child ) { | ||
if ( visit(child) ) { | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
let code = await resource.getBuffer(); | ||
visit( esprima.parse(code) ); | ||
|
||
return libInfo; | ||
} | ||
|
||
/** | ||
* Creates a new analyzer and executes it on the given resource. | ||
* | ||
* If the resources exists and can be parsed as JavaScript and if an sap.ui.getCore().initLibrary() | ||
* call is found in the code, then the following information will be set: | ||
* <ul> | ||
* <li>noLibraryCSS: false when the noLibraryCSS property had been set in the initLibrary info object)</li> | ||
* <li>types: string array with the names of the types contained in the library</li> | ||
* <li>controls: string array with the names of the controls defined in the library</li> | ||
* <li>elements: string array with the names of the elements defined in the library</li> | ||
* <li>interfaces: string array with the names of the interfaces defined in the library</li> | ||
* </ul> | ||
* | ||
* Note: only the first initLibrary() call that is found with a DFS on the AST, will be evaluated. | ||
* | ||
* @param {Resource} resource library.js resource whose content should be analyzed | ||
* @returns {Promise<object>} A Promise on the extract info object | ||
*/ | ||
module.exports = function(resource) { | ||
if ( resource == null ) { | ||
return Promise.resolve({}); | ||
} | ||
return analyze(resource); | ||
}; |
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.