in pxtlib/service.ts [837:997]
export function parseCommentString(cmt: string): CommentAttrs {
let res: CommentAttrs = {
paramDefl: {},
callingConvention: ir.CallingConvention.Plain,
_source: cmt
}
let didSomething = true
while (didSomething) {
didSomething = false
cmt = cmt.replace(/\/\/%[ \t]*([\w\.-]+)(=(("[^"\n]*")|'([^'\n]*)'|([^\s]*)))?/,
(f: string, n: string, d0: string, d1: string,
v0: string, v1: string, v2: string) => {
let v = v0 ? JSON.parse(v0) : (d0 ? (v0 || v1 || v2) : "true");
if (!v) v = "";
if (U.startsWith(n, "block.loc.")) {
if (!res.locs) res.locs = {};
res.locs[n.slice("block.loc.".length).toLowerCase() + "|block"] = v;
} else if (U.startsWith(n, "jsdoc.loc.")) {
if (!res.locs) res.locs = {};
res.locs[n.slice("jsdoc.loc.".length).toLowerCase() + "|jsdoc"] = v;
} else if (U.contains(n, ".loc.")) {
if (!res.locs) res.locs = {};
const p = n.slice(0, n.indexOf('.loc.'));
const l = n.slice(n.indexOf('.loc.') + '.loc.'.length);
res.locs[l + "|param|" + p] = v;
} else if (U.endsWith(n, ".defl")) {
if (v.indexOf(" ") > -1) {
res.paramDefl[n.slice(0, n.length - 5)] = `"${v}"`
} else {
res.paramDefl[n.slice(0, n.length - 5)] = v
}
if (!res.explicitDefaults) res.explicitDefaults = []
res.explicitDefaults.push(n.slice(0, n.length - 5))
} else if (U.endsWith(n, ".shadow")) {
if (!res._shadowOverrides) res._shadowOverrides = {};
res._shadowOverrides[n.slice(0, n.length - 7)] = v;
} else if (U.endsWith(n, ".fieldEditor")) {
if (!res.paramFieldEditor) res.paramFieldEditor = {}
res.paramFieldEditor[n.slice(0, n.length - 12)] = v
} else if (U.contains(n, ".fieldOptions.")) {
if (!res.paramFieldEditorOptions) res.paramFieldEditorOptions = {}
const field = n.slice(0, n.indexOf('.fieldOptions.'));
const key = n.slice(n.indexOf('.fieldOptions.') + 14, n.length);
if (!res.paramFieldEditorOptions[field]) res.paramFieldEditorOptions[field] = {};
res.paramFieldEditorOptions[field][key] = v
} else if (U.contains(n, ".shadowOptions.")) {
if (!res.paramShadowOptions) res.paramShadowOptions = {}
const field = n.slice(0, n.indexOf('.shadowOptions.'));
const key = n.slice(n.indexOf('.shadowOptions.') + 15, n.length);
if (!res.paramShadowOptions[field]) res.paramShadowOptions[field] = {};
res.paramShadowOptions[field][key] = v
} else if (U.endsWith(n, ".min")) {
if (!res.paramMin) res.paramMin = {}
res.paramMin[n.slice(0, n.length - 4)] = v
} else if (U.endsWith(n, ".max")) {
if (!res.paramMax) res.paramMax = {}
res.paramMax[n.slice(0, n.length - 4)] = v
} else {
(<any>res)[n] = v;
}
didSomething = true
return "//% "
})
}
for (let n of numberAttributes) {
if (typeof (res as any)[n] == "string")
(res as any)[n] = parseInt((res as any)[n])
}
for (let n of booleanAttributes) {
if (typeof (res as any)[n] == "string")
(res as any)[n] = (res as any)[n] == 'true' || (res as any)[n] == '1' ? true : false;
}
if (res.trackArgs) {
res.trackArgs = ((res.trackArgs as any) as string).split(/[ ,]+/).map(s => parseInt(s) || 0)
}
if (res.enumInitialMembers) {
res.enumInitialMembers = ((res.enumInitialMembers as any) as string).split(/[ ,]+/);
}
if (res.blockExternalInputs && !res.inlineInputMode) {
res.inlineInputMode = "external";
}
res.paramHelp = {}
res.jsDoc = ""
cmt = cmt.replace(/\/\*\*([^]*?)\*\//g, (full: string, doccmt: string) => {
doccmt = doccmt.replace(/\n\s*(\*\s*)?/g, "\n")
doccmt = doccmt.replace(/^\s*@param\s+(\w+)\s+(.*)$/mg, (full: string, name: string, desc: string) => {
res.paramHelp[name] = desc
if (!res.paramDefl[name]) {
// these don't add to res.explicitDefaults
let m = /\beg\.?:\s*(.+)/.exec(desc);
if (m && m[1]) {
let defaultValue = /(?:"([^"]*)")|(?:'([^']*)')|(?:([^\s,]+))/g.exec(m[1]);
if (defaultValue) {
let val = defaultValue[1] || defaultValue[2] || defaultValue[3];
if (!val) val = "";
// If there are spaces in the value, it means the value was surrounded with quotes, so add them back
if (val.indexOf(" ") > -1) {
res.paramDefl[name] = `"${val}"`;
}
else {
res.paramDefl[name] = val;
}
}
}
}
return ""
})
res.jsDoc += doccmt
return ""
})
res.jsDoc = res.jsDoc.trim()
if (res.async)
res.callingConvention = ir.CallingConvention.Async
if (res.promise)
res.callingConvention = ir.CallingConvention.Promise
if (res.jres)
res.whenUsed = true
if (res.subcategories) {
try {
res.subcategories = JSON.parse(res.subcategories as any);
}
catch (e) {
res.subcategories = undefined;
}
}
if (res.groups) {
try {
res.groups = JSON.parse(res.groups as any);
}
catch (e) {
res.groups = undefined;
}
}
if (res.groupIcons) {
try {
res.groupIcons = JSON.parse(res.groupIcons as any);
}
catch (e) {
res.groupIcons = undefined;
}
}
if (res.groupHelp) {
try {
res.groupHelp = JSON.parse(res.groupHelp as any);
}
catch (e) {
res.groupHelp = undefined;
}
}
updateBlockDef(res);
return res
}