"use strict";
|
Object.defineProperty(exports, "__esModule", { value: true });
|
const crc_1 = require("crc");
|
const _1 = require(".");
|
const Context_1 = require("./Context");
|
const Labels_1 = require("./Labels");
|
const Language_1 = require("./Language");
|
const errors_1 = require("./util/errors");
|
const PromiseEach_1 = require("./util/PromiseEach");
|
function warnAboutLanguageIDCollisions(kind, errors, context) {
|
return (languageIDs) => {
|
const plural = languageIDs.size !== 1;
|
context.warning(new Error(`More than one ${kind} was assigned to the language${plural ? "s" : ""} ${Array.from(languageIDs)
|
.map(languageID => {
|
const language = Language_1.default.byID[languageID];
|
return `${language.englishName} (${language.langTags.join("; ")})`;
|
})
|
.join(", ")}. ${plural ? "In each case, t" : "T"}he first applicable ${kind} has been used.`), errors);
|
};
|
}
|
function hashAssembledLicense(content) {
|
return [content.body.type, content.body.data, content.labels].reduce((hash, next) => crc_1.crc32(next, hash), 0);
|
}
|
function assembledLicensesEqual(a, b) {
|
return a.body.type === b.body.type
|
&& a.body.data.equals(b.body.data)
|
&& a.labels.equals(b.labels);
|
}
|
async function assembleLoadedLicenses(bodies, labelSets, errors, context) {
|
const assembled = new Map();
|
for (const [languageID, bodyPromise] of bodies) {
|
try {
|
const [body, labels] = await PromiseEach_1.default([
|
bodyPromise,
|
labelSets(Language_1.default.byID[languageID])
|
]);
|
assembled.set(languageID, {
|
body,
|
labels,
|
languageIDs: [languageID]
|
});
|
}
|
catch (e) {
|
errors.add(e);
|
}
|
}
|
const hashes = new Map();
|
for (const license of assembled.values()) {
|
const hash = hashAssembledLicense(license);
|
const withThisHash = hashes.get(hash);
|
if (!withThisHash)
|
hashes.set(hash, [license]);
|
else {
|
let hashCollision = true;
|
for (const other of withThisHash)
|
if (assembledLicensesEqual(license, other)) {
|
hashCollision = false;
|
other.languageIDs.push(...license.languageIDs);
|
for (const languageID of license.languageIDs)
|
assembled.set(languageID, other);
|
break;
|
}
|
if (hashCollision)
|
withThisHash.push(license);
|
}
|
}
|
return assembled;
|
}
|
function chooseDefaultLanguageID(spec, outputs, context) {
|
// Use the configured default language, if available.
|
{
|
const configuredDefaultLanguage = spec.defaultLang;
|
switch (typeof configuredDefaultLanguage) {
|
case "number":
|
return configuredDefaultLanguage;
|
case "string":
|
const lookup = Language_1.default.bySpec(configuredDefaultLanguage, context)[0];
|
if (lookup)
|
return lookup.languageID;
|
}
|
}
|
// Use the first language of the first license body section.
|
for (const body of spec.body)
|
for (const lang of Language_1.default.bySpec(body.lang))
|
return lang.languageID;
|
// Just pick one arbitrarily. This should never happen, but just in case.
|
for (const output of outputs)
|
for (const lang of output.languageIDs)
|
return lang;
|
}
|
function labelCache(spec, errors, context) {
|
const labelSpecs = Language_1.indexByLanguage(function* () {
|
const { labels, rawLabels } = spec;
|
if (labels)
|
for (const label of labels)
|
yield label;
|
if (rawLabels)
|
for (const label of rawLabels)
|
yield label;
|
}(), {
|
onCollisions: warnAboutLanguageIDCollisions("label set", errors, context)
|
});
|
const preparedCache = new Map();
|
return (lang) => {
|
const { languageID } = lang;
|
let result = preparedCache.get(languageID);
|
if (!result) {
|
result = Labels_1.default.prepareSpec(labelSpecs.get(languageID), lang, context);
|
preparedCache.set(languageID, result);
|
}
|
return result;
|
};
|
}
|
async function assembleLicenses(spec, optionsOrContext) {
|
const context = optionsOrContext instanceof Context_1.default ? optionsOrContext : new Context_1.default(optionsOrContext);
|
const errors = new errors_1.ErrorBuffer();
|
const labelSets = labelCache(spec, errors, context);
|
const bodies = Language_1.indexByLanguage(spec.body, {
|
map: (body, lang) => _1.BodySpec.prepare(body, lang, context),
|
onCollisions: warnAboutLanguageIDCollisions("license body", errors, context)
|
});
|
if (!bodies.size)
|
errors.throw(new Error("No license bodies were provided."));
|
let result;
|
try {
|
const assembled = await assembleLoadedLicenses(bodies, labelSets, errors, context);
|
const inOrder = Array.from(assembled.values());
|
const defaultLanguageID = chooseDefaultLanguageID(spec, inOrder, context);
|
result = {
|
byLanguageID: assembled,
|
defaultLanguageID,
|
inOrder
|
};
|
}
|
catch (e) {
|
errors.add(e);
|
}
|
errors.check();
|
return result;
|
}
|
exports.default = assembleLicenses;
|
//# sourceMappingURL=assembleLicenses.js.map
|