mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
api(dotnet): generate options (#6630)
This commit is contained in:
parent
9592486225
commit
d2938d0a30
@ -35,6 +35,8 @@ const modelTypes = new Map(); // this will hold types that we discover, because
|
|||||||
const documentedResults = new Map(); // will hold documentation for new types
|
const documentedResults = new Map(); // will hold documentation for new types
|
||||||
/** @type {Map<string, string[]>} */
|
/** @type {Map<string, string[]>} */
|
||||||
const enumTypes = new Map();
|
const enumTypes = new Map();
|
||||||
|
/** @type {Map<string, Documentation.Type>} */
|
||||||
|
const optionTypes = new Map();
|
||||||
const nullableTypes = ['int', 'bool', 'decimal', 'float'];
|
const nullableTypes = ['int', 'bool', 'decimal', 'float'];
|
||||||
const customTypeNames = new Map([
|
const customTypeNames = new Map([
|
||||||
['domcontentloaded', 'DOMContentLoaded'],
|
['domcontentloaded', 'DOMContentLoaded'],
|
||||||
@ -43,10 +45,11 @@ const customTypeNames = new Map([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const typesDir = process.argv[2] || path.join(__dirname, 'generate_types', 'csharp');
|
const typesDir = process.argv[2] || path.join(__dirname, 'generate_types', 'csharp');
|
||||||
const modelsDir = path.join(typesDir, "models");
|
const modelsDir = path.join(typesDir, 'Models');
|
||||||
const enumsDir = path.join(typesDir, "enums");
|
const enumsDir = path.join(typesDir, 'Enums');
|
||||||
|
const optionsDir = path.join(typesDir, 'Options');
|
||||||
|
|
||||||
for (const dir of [typesDir, modelsDir, enumsDir])
|
for (const dir of [typesDir, modelsDir, enumsDir, optionsDir])
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
|
||||||
const documentation = parseApi(path.join(PROJECT_DIR, 'docs', 'src', 'api'));
|
const documentation = parseApi(path.join(PROJECT_DIR, 'docs', 'src', 'api'));
|
||||||
@ -115,6 +118,9 @@ function writeFile(kind, name, spec, body, folder, extendsName = null) {
|
|||||||
if (extendsName === 'IEventEmitter')
|
if (extendsName === 'IEventEmitter')
|
||||||
extendsName = null;
|
extendsName = null;
|
||||||
|
|
||||||
|
if (body[0] === '')
|
||||||
|
body = body.slice(1);
|
||||||
|
|
||||||
out.push(`public ${kind} ${name}${extendsName ? ` : ${extendsName}` : ''}`);
|
out.push(`public ${kind} ${name}${extendsName ? ` : ${extendsName}` : ''}`);
|
||||||
out.push('{');
|
out.push('{');
|
||||||
out.push(...body);
|
out.push(...body);
|
||||||
@ -189,6 +195,17 @@ function renderEnum(name, literals) {
|
|||||||
writeFile('enum', name, null, body, enumsDir);
|
writeFile('enum', name, null, body, enumsDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name
|
||||||
|
* @param {Documentation.Type} type
|
||||||
|
*/
|
||||||
|
function renderOptionType(name, type) {
|
||||||
|
const body = [];
|
||||||
|
for (const member of type.properties)
|
||||||
|
renderMember(member, type, body);
|
||||||
|
writeFile('class', name, null, body, optionsDir);
|
||||||
|
}
|
||||||
|
|
||||||
for (const element of documentation.classesArray)
|
for (const element of documentation.classesArray)
|
||||||
renderClass(element);
|
renderClass(element);
|
||||||
|
|
||||||
@ -198,6 +215,9 @@ for (let [name, type] of modelTypes)
|
|||||||
for (let [name, literals] of enumTypes)
|
for (let [name, literals] of enumTypes)
|
||||||
renderEnum(name, literals);
|
renderEnum(name, literals);
|
||||||
|
|
||||||
|
for (let [name, type] of optionTypes)
|
||||||
|
renderOptionType(name, type);
|
||||||
|
|
||||||
if (process.argv[3] !== "--skip-format") {
|
if (process.argv[3] !== "--skip-format") {
|
||||||
// run the formatting tool for .net, to ensure the files are prepped
|
// run the formatting tool for .net, to ensure the files are prepped
|
||||||
execSync(`dotnet format -f "${typesDir}" --include-generated --fix-whitespace`);
|
execSync(`dotnet format -f "${typesDir}" --include-generated --fix-whitespace`);
|
||||||
@ -253,42 +273,57 @@ function toTitleCase(name) {
|
|||||||
* @param {string[]} out
|
* @param {string[]} out
|
||||||
*/
|
*/
|
||||||
function renderMember(member, parent, out) {
|
function renderMember(member, parent, out) {
|
||||||
|
out.push('');
|
||||||
let name = toMemberName(member);
|
let name = toMemberName(member);
|
||||||
if (member.kind === 'method') {
|
if (member.kind === 'method') {
|
||||||
renderMethod(member, parent, name, out);
|
renderMethod(member, parent, name, out);
|
||||||
} else {
|
return;
|
||||||
/** @type string */
|
}
|
||||||
let type = translateType(member.type, parent, t => generateNameDefault(member, name, t, parent));
|
|
||||||
if (member.kind === 'event') {
|
|
||||||
if (!member.type)
|
|
||||||
throw new Error(`No Event Type for ${name} in ${parent.name}`);
|
|
||||||
if (member.spec)
|
|
||||||
out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));
|
|
||||||
out.push(`event EventHandler<${type}> ${name};`);
|
|
||||||
} else if (member.kind === 'property') {
|
|
||||||
if (member.spec)
|
|
||||||
out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));
|
|
||||||
let propertyOrigin = member.name;
|
|
||||||
if (member.type.expression === '[string]|[float]')
|
|
||||||
propertyOrigin = `${member.name}String`;
|
|
||||||
if (!member.clazz)
|
|
||||||
out.push(`[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}>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/** @type string */
|
||||||
|
let type = translateType(member.type, parent, t => generateNameDefault(member, name, t, parent));
|
||||||
|
if (member.kind === 'event') {
|
||||||
|
if (!member.type)
|
||||||
|
throw new Error(`No Event Type for ${name} in ${parent.name}`);
|
||||||
|
if (member.spec)
|
||||||
|
out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));
|
||||||
|
out.push(`event EventHandler<${type}> ${name};`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (member.kind === 'property') {
|
||||||
|
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}>`;
|
||||||
|
}
|
||||||
|
const overloads = [];
|
||||||
|
if (type) {
|
||||||
|
let jsonName = member.name;
|
||||||
|
if (member.type.expression === '[string]|[float]')
|
||||||
|
jsonName = `${member.name}String`;
|
||||||
|
overloads.push({ type, name, jsonName });
|
||||||
|
} else {
|
||||||
|
for (const overload of member.type.union) {
|
||||||
|
const t = translateType(overload, parent, t => generateNameDefault(member, name, t, parent));
|
||||||
|
const suffix = toTitleCase(t.replace(/[<].*[>]/, '').replace(/[^a-zA-Z]/g, ''));
|
||||||
|
overloads.push({ type: t, name: name + suffix, jsonName: member.name + suffix });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let { type, name, jsonName } of overloads) {
|
||||||
|
if (member.spec)
|
||||||
|
out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));
|
||||||
|
if (!member.clazz)
|
||||||
|
out.push(`[JsonPropertyName("${jsonName}")]`)
|
||||||
if (!type.endsWith('?') && !member.required && nullableTypes.includes(type))
|
if (!type.endsWith('?') && !member.required && nullableTypes.includes(type))
|
||||||
type = `${type}?`;
|
type = `${type}?`;
|
||||||
if (member.clazz)
|
if (member.clazz)
|
||||||
out.push(`public ${type} ${name} { get; }`);
|
out.push(`public ${type} ${name} { get; }`);
|
||||||
else
|
else
|
||||||
out.push(`public ${type} ${name} { get; set; }`);
|
out.push(`public ${type} ${name} { get; set; }`);
|
||||||
} else {
|
return;
|
||||||
throw new Error(`Problem rendering a member: ${type} - ${name} (${member.kind})`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.push('');
|
throw new Error(`Problem rendering a member: ${type} - ${name} (${member.kind})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -485,8 +520,16 @@ function renderMethod(member, parent, name, out) {
|
|||||||
* @param {Documentation.Member} arg
|
* @param {Documentation.Member} arg
|
||||||
*/
|
*/
|
||||||
function processArg(arg) {
|
function processArg(arg) {
|
||||||
if (arg.name === "options") {
|
if (arg.name === 'options') {
|
||||||
arg.type.properties.forEach(processArg);
|
if (process.env.OPTIONS) {
|
||||||
|
const optionsType = member.clazz.name + toTitleCase(member.name) + 'Options';
|
||||||
|
optionTypes.set(optionsType, arg.type);
|
||||||
|
args.push(`${optionsType} options = default`);
|
||||||
|
argTypeMap.set(`${optionsType} options = default`, 'options');
|
||||||
|
addParamsDoc('options', ['Call options']);
|
||||||
|
} else {
|
||||||
|
arg.type.properties.forEach(processArg);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +570,7 @@ function renderMethod(member, parent, name, out) {
|
|||||||
let argDocumentation = XmlDoc.renderTextOnly(arg.spec, maxDocumentationColumnWidth);
|
let argDocumentation = XmlDoc.renderTextOnly(arg.spec, maxDocumentationColumnWidth);
|
||||||
for (const newArg of translatedArguments) {
|
for (const newArg of translatedArguments) {
|
||||||
let nonGenericType = newArg.replace(/\IEnumerable<(.*)\>/g, (m, v) => 'Enumerable' + v[0].toUpperCase() + v.substring(1))
|
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 sanitizedArgName = nonGenericType.match(/(?<=^[\s"']*)(\w+)/g)[0] || nonGenericType;
|
||||||
const newArgName = `${argName}${sanitizedArgName[0].toUpperCase() + sanitizedArgName.substring(1)}`;
|
const newArgName = `${argName}${sanitizedArgName[0].toUpperCase() + sanitizedArgName.substring(1)}`;
|
||||||
pushArg(newArg, newArgName, arg, true); // push the exploded arg
|
pushArg(newArg, newArgName, arg, true); // push the exploded arg
|
||||||
addParamsDoc(newArgName, argDocumentation);
|
addParamsDoc(newArgName, argDocumentation);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user