chore(dotnet): split unions into multiple overloads (#6400)

This commit is contained in:
Anže Vodovnik 2021-05-06 10:23:10 +02:00 committed by GitHub
parent 9433cae4fe
commit 67f98d00eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -200,7 +200,7 @@ const customTypeNames = new Map([
out.push(`\t${escapedName},`);
});
}, enumsDir));
if (process.argv[3] !== "--skip-format") {
// run the formatting tool for .net, to ensure the files are prepped
execSync(`dotnet format -f "${typesDir}" --include-generated --fix-whitespace`);
@ -294,16 +294,16 @@ function renderMember(member, parent, out) {
let propertyOrigin = member.name;
if (member.type.expression === '[string]|[float]')
propertyOrigin = `${member.name}String`;
if(!member.clazz)
if (!member.clazz)
output(`[JsonPropertyName("${propertyOrigin}")]`)
if (parent && member && member.name === 'children') { // this is a special hack for Accessibility
console.warn(`children property found in ${parent.name}, assuming array.`);
type = `IEnumerable<${parent.name}>`;
}
if(!type.endsWith('?') && !member.required && nullableTypes.includes(type))
if (!type.endsWith('?') && !member.required && nullableTypes.includes(type))
type = `${type}?`;
if(member.clazz)
if (member.clazz)
output(`public ${type} ${name} { get; }`);
else
output(`public ${type} ${name} { get; set; }`);
@ -484,19 +484,28 @@ function renderMethod(member, parent, output, name) {
// render args
let args = [];
let explodedArgs = [];
let argTypeMap = new Map([]);
/**
*
* @param {string} innerArgType
* @param {string} innerArgName
* @param {Documentation.Member} argument
* @param {boolean} isExploded
*/
const pushArg = (innerArgType, innerArgName, argument) => {
const pushArg = (innerArgType, innerArgName, argument, isExploded = false) => {
let isNullable = nullableTypes.includes(innerArgType);
const requiredPrefix = argument.required ? "" : isNullable ? "?" : "";
const requiredSuffix = argument.required ? "" : " = default";
args.push(`${innerArgType}${requiredPrefix} ${innerArgName}${requiredSuffix}`);
const requiredPrefix = (argument.required || isExploded) ? "" : isNullable ? "?" : "";
const requiredSuffix = (argument.required || isExploded) ? "" : " = default";
var push = `${innerArgType}${requiredPrefix} ${innerArgName}${requiredSuffix}`;
if (isExploded)
explodedArgs.push(push)
else
args.push(push);
argTypeMap.set(push, innerArgName);
};
let parseArg = (/** @type {Documentation.Member} */ arg) => {
if (arg.name === "options") {
arg.type.properties.forEach(parseArg);
@ -539,11 +548,13 @@ function renderMethod(member, parent, output, name) {
let argDocumentation = XmlDoc.renderTextOnly(arg.spec, maxDocumentationColumnWidth);
for (const newArg of translatedArguments) {
const sanitizedArgName = newArg.match(/(?<=^[\s"']*)(\w+)/g, '')[0] || newArg;
let nonGenericType = newArg.replace(/\IEnumerable<(.*)\>/g, (m, v) => 'Enumerable' + v[0].toUpperCase() + v.substring(1))
const sanitizedArgName = nonGenericType.match(/(?<=^[\s"']*)(\w+)/g, '')[0] || nonGenericType;
const newArgName = `${argName}${sanitizedArgName[0].toUpperCase() + sanitizedArgName.substring(1)}`;
pushArg(newArg, newArgName, arg);
pushArg(newArg, newArgName, arg, true); // push the exploded arg
addParamsDoc(newArgName, argDocumentation);
}
args.push(arg.required ? 'EXPLODED_ARG' : 'OPTIONAL_EXPLODED_ARG');
return;
}
@ -561,8 +572,7 @@ function renderMethod(member, parent, output, name) {
.sort((a, b) => b.alias === 'options' ? -1 : 0) //move options to the back to the arguments list
.forEach(parseArg);
output(XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));
paramDocs.forEach((val, ind) => {
let printArgDoc = function (val, ind) {
if (val && val.length === 1)
output(`/// <param name="${ind}">${val}</param>`);
else {
@ -570,8 +580,56 @@ function renderMethod(member, parent, output, name) {
output(val.map(l => `/// ${l}`));
output(`/// </param>`);
}
});
output(`${type} ${name}(${args.join(', ')});`);
}
let getArgType = function (argType) {
var type = argTypeMap.get(argType);
return type;
}
if (!explodedArgs.length) {
output(XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));
paramDocs.forEach((val, ind) => printArgDoc(val, ind));
output(`${type} ${name}(${args.join(', ')});`);
} else {
let containsOptionalExplodedArgs = false;
explodedArgs.forEach((explodedArg, argIndex) => {
output(XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));
let overloadedArgs = [];
for (var i = 0; i < args.length; i++) {
let arg = args[i];
if (arg === 'EXPLODED_ARG' || arg === 'OPTIONAL_EXPLODED_ARG') {
containsOptionalExplodedArgs = arg === 'OPTIONAL_EXPLODED_ARG';
let argType = getArgType(explodedArg);
printArgDoc(paramDocs.get(argType), argType);
overloadedArgs.push(explodedArg);
} else {
let argType = getArgType(arg);
printArgDoc(paramDocs.get(argType), argType);
overloadedArgs.push(arg);
}
}
output(`${type} ${name}(${overloadedArgs.join(', ')});`);
if (argIndex < explodedArgs.length - 1)
output(``); // output a special blank line
});
// If the exploded union arguments are optional, we also output a special
// signature, to help prevent compilation errors with ambigious overloads.
// That particular overload only contains the required arguments, or rather
// contains all the arguments *except* the exploded ones.
if (containsOptionalExplodedArgs) {
var filteredArgs = args.filter(x => x !== 'OPTIONAL_EXPLODED_ARG');
output(XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));
filteredArgs.forEach((arg) => {
if (arg === 'EXPLODED_ARG')
throw new Error(`Unsupported required union arg combined an optional union inside ${member.name}`);
let argType = getArgType(arg);
printArgDoc(paramDocs.get(argType), argType);
});
output(`${type} ${name}(${filteredArgs.join(', ')});`);
}
}
}
/**
@ -652,9 +710,7 @@ function translateType(type, parent, generateNameCallback = t => t.name) {
} else if (type.union.length == 2 && type.union[1].name === 'Array' && type.union[1].templates[0].name === type.union[0].name)
return `IEnumerable<${type.union[0].name}>`; // an example of this is [string]|[Array]<[string]>
else if (type.union[0].name === 'path')
// we don't support path, but we know it's usually an object on the other end, and we expect
// the dotnet folks to use [NameOfTheObject].LoadFromPath(); method which we can provide separately
return translateType(type.union[1], parent, generateNameCallback);
return null;
else if (type.expression === '[float]|"raf"')
return `Polling`; // hardcoded because there's no other way to denote this