Skip to content

Commit 90cd9d0

Browse files
committed
[FIX] generateResourcesJson: Make resources.json generation deterministic
Stop analyzing debug-resources if they correspond to a non-debug resource. However, try to analyze the "source" version of a resource's content if possible. In some cases the dependency analysis has problems with minified code. Finally, copy any dependency information of a non-debug resource to the corresponding debug-resource. This ensures that we generate the same resources.json, independently from the order of debug and non-debug resources supplied to the resourceListCreator processor. Resolves SAP/ui5-tooling#274
1 parent 773c534 commit 90cd9d0

File tree

4 files changed

+73
-52
lines changed

4 files changed

+73
-52
lines changed

lib/lbt/resources/ResourceCollector.js

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,14 @@ class ResourceCollector {
107107
}
108108
}
109109

110-
async enrichWithDependencyInfo(resourceInfo) {
111-
return this._pool.getModuleInfo(resourceInfo.name).then((moduleInfo) => {
110+
async enrichWithDependencyInfo({resourceInfo, debugBundleFilter}) {
111+
return this._pool.getModuleInfo(resourceInfo.name, {
112+
// While analyzing non-debug resources, try to analyze the content of the corresponding
113+
// debug resource instead
114+
preferDebugResources: true,
115+
// Provide the debugBundleFilter to prevent that debug bundles are "preferred"
116+
debugBundleFilter
117+
}).then((moduleInfo) => {
112118
if ( moduleInfo.name ) {
113119
resourceInfo.module = moduleInfo.name;
114120
}
@@ -149,16 +155,25 @@ class ResourceCollector {
149155
});
150156
}
151157

152-
async determineResourceDetails({pool, debugResources, mergedResources, designtimeResources, supportResources}) {
158+
async determineResourceDetails({
159+
debugResources, mergedResources, designtimeResources, supportResources, debugBundles
160+
}) {
153161
const baseNames = new Set();
154162
const debugFilter = new ResourceFilterList(debugResources);
155163
const mergeFilter = new ResourceFilterList(mergedResources);
156164
const designtimeFilter = new ResourceFilterList(designtimeResources);
157165
const supportFilter = new ResourceFilterList(supportResources);
166+
const debugBundleFilter = new ResourceFilterList(debugBundles);
158167

159168
const promises = [];
169+
const nonBundledDebugResources = [];
160170

161171
for (const [name, info] of this._resources.entries()) {
172+
if ( debugFilter.matches(name) ) {
173+
info.isDebug = true;
174+
log.verbose(` found potential debug resource '${name}'`);
175+
}
176+
162177
// log.verbose(` checking ${name}`);
163178
let m;
164179
if ( m = LOCALE.exec(name) ) {
@@ -179,9 +194,17 @@ class ResourceCollector {
179194
}
180195

181196
if ( /(?:\.js|\.view\.xml|\.control\.xml|\.fragment\.xml)$/.test(name) ) {
182-
promises.push(
183-
this.enrichWithDependencyInfo(info)
184-
);
197+
if ( (!info.isDebug || debugBundleFilter.matches(name)) ) {
198+
// Only analyze non-debug files which are not special debug bundles (like sap-ui-core-dbg.js)
199+
promises.push(
200+
this.enrichWithDependencyInfo({
201+
resourceInfo: info,
202+
debugBundleFilter
203+
})
204+
);
205+
} else {
206+
nonBundledDebugResources.push(info);
207+
}
185208
}
186209

187210
// set the module name for .properties and .json
@@ -196,11 +219,6 @@ class ResourceCollector {
196219
}));
197220
}
198221

199-
if ( debugFilter.matches(name) ) {
200-
info.isDebug = true;
201-
log.verbose(` found potential debug resource '${name}'`);
202-
}
203-
204222
if ( mergeFilter.matches(name) ) {
205223
info.merged = true;
206224
log.verbose(` found potential merged resource '${name}'`);
@@ -225,7 +243,17 @@ class ResourceCollector {
225243
}
226244
}
227245

228-
return Promise.all(promises);
246+
await Promise.all(promises);
247+
248+
for (let i = nonBundledDebugResources.length - 1; i >= 0; i--) {
249+
const dbgInfo = nonBundledDebugResources[i];
250+
const nonDebugName = ResourceInfoList.getNonDebugName(dbgInfo.name);
251+
const nonDbgInfo = this._resources.get(nonDebugName);
252+
const newDbgInfo = new ResourceInfo(dbgInfo.name);
253+
newDbgInfo.copyFrom(null, nonDbgInfo);
254+
newDbgInfo.copyFrom(null, dbgInfo);
255+
this._resources.set(dbgInfo.name, newDbgInfo);
256+
}
229257
}
230258

231259
createOrphanFilters() {
@@ -251,18 +279,16 @@ class ResourceCollector {
251279

252280
groupResourcesByComponents(options) {
253281
const orphanFilters = this.createOrphanFilters();
254-
const debugBundlesFilter = new ResourceFilterList(options.debugBundles);
255282
for (const resource of this._resources.values()) {
256283
let contained = false;
257284
for (const [prefix, list] of this._components.entries()) {
258-
const isDebugBundle = debugBundlesFilter.matches(resource.name);
259285
if ( resource.name.startsWith(prefix) ) {
260-
list.add(resource, !isDebugBundle);
286+
list.add(resource);
261287
contained = true;
262288
} else if ( orphanFilters.has(prefix) ) {
263289
// log.verbose(` checking '${resource.name}' against orphan filter '${orphanFilters.get(prefix)}' (${prefix})`);
264290
if ( orphanFilters.get(prefix).matches(resource.name) ) {
265-
list.add(resource, !isDebugBundle);
291+
list.add(resource);
266292
contained = true;
267293
}
268294
}

lib/lbt/resources/ResourceInfoList.js

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,37 +39,12 @@ class ResourceInfoList {
3939
* Add ResourceInfo to list
4040
*
4141
* @param {ResourceInfo} info
42-
* @param {boolean} shareDebugInformation
4342
*/
44-
add(info, shareDebugInformation=true) {
43+
add(info) {
4544
const relativeName = ResourceInfoList.makePathRelativeTo(this.name, info.name);
46-
4745
// search for a resource with the same name
4846
let myInfo = this.resourcesByName.get(relativeName);
4947

50-
if ( myInfo == null && shareDebugInformation) {
51-
// when not found, check if the given resource is a debug resource and
52-
// share the information with the non-dbg version
53-
const nonDbgName = ResourceInfoList.getNonDebugName(relativeName);
54-
const dbgName = ResourceInfoList.getDebugName(relativeName);
55-
if ( nonDbgName != null && this.resourcesByName.has(nonDbgName) ) {
56-
// copy from source
57-
myInfo = new ResourceInfo(relativeName);
58-
const source = this.resourcesByName.get(nonDbgName);
59-
myInfo.copyFrom(this.name, source);
60-
this.resources.push(myInfo);
61-
this.resourcesByName.set(relativeName, myInfo);
62-
} else if (dbgName != null && this.resourcesByName.has(dbgName)) {
63-
// copy from debug
64-
myInfo = new ResourceInfo(relativeName);
65-
const source = this.resourcesByName.get(dbgName);
66-
myInfo.copyFrom(this.name, source);
67-
myInfo.module = ResourceInfoList.getNonDebugName(source.module);
68-
this.resources.push(myInfo);
69-
this.resourcesByName.set(relativeName, myInfo);
70-
}
71-
}
72-
7348
// this is the assumption, that the debug one is the same as the non-dbg one
7449
if ( myInfo == null ) {
7550
myInfo = new ResourceInfo(relativeName);

lib/lbt/resources/ResourcePool.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const XMLTemplateAnalyzer = require("../analyzer/XMLTemplateAnalyzer");
1515
const LibraryFileAnalyzer = require("./LibraryFileAnalyzer");
1616
const ModuleInfo = require("./ModuleInfo");
1717
const ResourceFilterList = require("./ResourceFilterList");
18+
const ResourceInfoList = require("./ResourceInfoList");
1819
/*
1920
const Resource = require("./Resource");
2021
*/
@@ -57,12 +58,15 @@ function scanFileOrDir(fileOrDir, name, pool) {
5758
}
5859
*/
5960

60-
async function determineDependencyInfo(resource, rawInfo, pool) {
61+
async function determineDependencyInfo(resource, dbgResource, rawInfo, pool) {
6162
const info = new ModuleInfo(resource.name);
6263
info.size = resource.fileSize;
6364
if ( /\.js$/.test(resource.name) ) {
64-
// console.log("analyzing %s", resource.file);
65-
const code = await resource.buffer();
65+
// console.log("analyzing %s", resource.name);
66+
67+
// Retrieve the content from the "debug resource".
68+
// Note that in many cases "resource" and "dbgResource" are the same object
69+
const code = await dbgResource.buffer();
6670
info.size = code.length;
6771
const promises = [];
6872
let ast;
@@ -177,14 +181,30 @@ class ResourcePool {
177181
* Retrieves the module info
178182
*
179183
* @param {string} name module name
184+
* @param {object} options
185+
* @param {boolean} options.preferDebugResources
186+
* @param {ResourceFilterList} options.debugBundleFilter
180187
* @returns {Promise<ModuleInfo>}
181188
*/
182-
async getModuleInfo(name) {
189+
async getModuleInfo(name, options) {
183190
let info = this._dependencyInfos.get(name);
184191
if ( info == null ) {
185192
// console.log("analyzing ", name);
193+
let dbgResource;
194+
if (options && options.preferDebugResources) {
195+
// If requested, try to retrieve the corresponding debug-resource (xyz-dbg.js) and pass it to
196+
// determineDependencyInfo as well. Its dependency analysis will perform better with the
197+
// not-minified content of a resource.
198+
const dbgName = ResourceInfoList.getDebugName(name);
199+
if (dbgName && (!options.debugBundleFilter || !options.debugBundleFilter.matches(dbgName))) {
200+
dbgResource = this._resourcesByName.get(dbgName);
201+
}
202+
}
186203
const resource = await this.findResource(name);
187-
info = await determineDependencyInfo( resource, this._rawModuleInfos.get(name), this );
204+
if (!dbgResource) {
205+
dbgResource = resource;
206+
}
207+
info = await determineDependencyInfo(resource, dbgResource, this._rawModuleInfos.get(name), this);
188208
// console.log("finished analyzing ", name);
189209
this._dependencyInfos.set(name, info);
190210
}

lib/processors/resourceListCreator.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ const DEFAULT_SUPPORT_RESOURCES_FILTER = [
7373
* @type {string[]}
7474
*/
7575
const DEBUG_BUNDLES = [
76-
"sap-ui-core-dbg.js"
76+
"sap-ui-core-dbg.js",
77+
"sap-ui-core-nojQuery-dbg.js"
7778
];
7879

7980
/**
@@ -159,13 +160,12 @@ module.exports = async function({resources, options}) {
159160
debugResources: options.debugResources,
160161
mergedResources: options.mergedResources,
161162
designtimeResources: options.designtimeResources,
162-
supportResources: options.supportResources
163+
supportResources: options.supportResources,
164+
debugBundles: options.debugBundles
163165
});
164166

165167
// group resources by components and create ResourceInfoLists
166-
collector.groupResourcesByComponents({
167-
debugBundles: options.debugBundles
168-
});
168+
collector.groupResourcesByComponents();
169169

170170
const resourceLists = [];
171171

0 commit comments

Comments
 (0)