@markw65/monkeyc-optimizer 1.0.21 → 1.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9858,7 +9858,7 @@ const external_util_cjs_namespaceObject = require("./util.cjs");
9858
9858
  async function build_project(product, options, lineCallback) {
9859
9859
  const { workspace, program, jungleFiles, developerKeyPath, simulatorBuild, releaseBuild, testBuild, compilerOptions, compilerWarnings, typeCheckLevel, returnCommand, } = options;
9860
9860
  const sdk = await (0,external_sdk_util_cjs_namespaceObject.getSdkPath)();
9861
- let extraArgs = [];
9861
+ const extraArgs = [];
9862
9862
  if (compilerOptions) {
9863
9863
  extraArgs.push(...compilerOptions.split(/\s+/));
9864
9864
  }
@@ -9894,6 +9894,9 @@ async function build_project(product, options, lineCallback) {
9894
9894
  else if (testBuild) {
9895
9895
  throw new Error("Building for tests requires a device to build for!");
9896
9896
  }
9897
+ if (!program || !jungleFiles || !developerKeyPath || !workspace) {
9898
+ throw new Error("Required arguments were missing!");
9899
+ }
9897
9900
  const exe = external_path_.resolve(sdk, "bin", external_sdk_util_cjs_namespaceObject.isWin ? "monkeyc.bat" : "monkeyc");
9898
9901
  const args = [
9899
9902
  ["-o", program],
@@ -9928,9 +9931,8 @@ async function readManifest(manifest) {
9928
9931
  return (0,xml2js.parseStringPromise)(data.toString(), { trim: true });
9929
9932
  }
9930
9933
  async function writeManifest(filename, xml) {
9931
- let builder = new xml2js.Builder();
9932
- let text = builder.buildObject(xml);
9933
- return promises_namespaceObject.writeFile(filename, text);
9934
+ const builder = new xml2js.Builder();
9935
+ return promises_namespaceObject.writeFile(filename, builder.buildObject(xml));
9934
9936
  }
9935
9937
  function manifestProducts(manifest) {
9936
9938
  const app = manifest["iq:manifest"]["iq:application"] ||
@@ -10228,7 +10230,7 @@ function resolve_node_by_path(state, path) {
10228
10230
  }
10229
10231
  if (!s[n] && s["."]) {
10230
10232
  const sdot = s["."];
10231
- let resolved = resolve_node_list(state, sdot);
10233
+ const resolved = resolve_node_list(state, sdot);
10232
10234
  if (!resolved.length)
10233
10235
  return undefined;
10234
10236
  const r = resolved[0][n];
@@ -10317,11 +10319,11 @@ async function resolve_literals(qualifier, default_source, deviceInfo) {
10317
10319
  return resolve_file_list(v.values);
10318
10320
  }
10319
10321
  let resolved = resolve_filename(v, default_source);
10320
- if (/[*?\[\]\{\}]/.test(resolved)) {
10322
+ if (/[*?[\]{}]/.test(resolved)) {
10321
10323
  // Jungle files can contain "./**.mc" which is supposed to match
10322
10324
  // any mc file under "./". The standard way to express that
10323
10325
  // is "./**/*.mc", which is what glob expects, so translate.
10324
- resolved = resolved.replace(/[\\\/]\*\*([^\\\/])/g, "/**/*$1");
10326
+ resolved = resolved.replace(/[\\/]\*\*([^\\/])/g, "/**/*$1");
10325
10327
  const match = await (0,external_util_cjs_namespaceObject.globa)(resolved);
10326
10328
  return match.length ? resolved : null;
10327
10329
  }
@@ -10595,7 +10597,7 @@ function resolve_barrel(barrel, barrelDir, products, options) {
10595
10597
  const sha1 = external_crypto_namespaceObject.createHash("sha1")
10596
10598
  .update(barrel, "binary")
10597
10599
  .digest("base64")
10598
- .replace(/[\/=+]/g, "");
10600
+ .replace(/[/=+]/g, "");
10599
10601
  const localPath = external_path_.resolve(barrelDir, `${external_path_.basename(barrel, ".barrel")}-${sha1}`);
10600
10602
  rawBarrel = external_path_.resolve(localPath, "barrel.jungle");
10601
10603
  promise = promise.then(() => promises_namespaceObject.stat(localPath)
@@ -10745,7 +10747,9 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options) {
10745
10747
  targets.push({ product, qualifier, shape });
10746
10748
  return resolve_barrels(product, qualifier, barrels, products, options);
10747
10749
  })
10748
- .then(() => { });
10750
+ .then(() => {
10751
+ return;
10752
+ });
10749
10753
  };
10750
10754
  products.forEach((product) => {
10751
10755
  if ((0,external_api_cjs_namespaceObject.hasProperty)(state, product)) {
@@ -10788,11 +10792,151 @@ function simulateProgram(prg, device, test = false, logger) {
10788
10792
  const args = [prg, device];
10789
10793
  if (test)
10790
10794
  args.push("-t");
10791
- return (0,external_sdk_util_cjs_namespaceObject.getSdkPath)().then((sdk) => (0,external_util_cjs_namespaceObject.spawnByLine)(external_path_.resolve(sdk, "bin", "monkeydo"), args, logger || ((line) => console.log(line))).then(() => { }));
10795
+ return (0,external_sdk_util_cjs_namespaceObject.getSdkPath)().then((sdk) => (0,external_util_cjs_namespaceObject.spawnByLine)(external_path_.resolve(sdk, "bin", "monkeydo"), args, logger || ((line) => console.log(line))).then(() => {
10796
+ return;
10797
+ }));
10798
+ }
10799
+
10800
+ ;// CONCATENATED MODULE: ./src/ast.ts
10801
+ /*
10802
+ * This ensures that mctreeTypeInfo has every key of MCTreeTypeInfo,
10803
+ * and that the corresponding arrays contain every element of the
10804
+ * corresponding type.
10805
+ *
10806
+ * ie, any time mctree.Node changes, we'll get errors here if
10807
+ * mctreeTypeInfo needs updating.
10808
+ *
10809
+ */
10810
+ function _check(x) {
10811
+ const y = x;
10812
+ x = y;
10813
+ }
10814
+ const mctreeTypeInfo = {
10815
+ ArrayExpression: ["elements"],
10816
+ AssignmentExpression: ["left", "right"],
10817
+ AttributeList: ["attributes"],
10818
+ Attributes: ["elements"],
10819
+ BinaryExpression: ["left", "right"],
10820
+ Block: [],
10821
+ BlockStatement: ["body", "innerComments"],
10822
+ BreakStatement: [],
10823
+ CallExpression: ["callee", "arguments"],
10824
+ CatchClause: ["param", "body"],
10825
+ CatchClauses: ["catches"],
10826
+ ClassBody: ["body"],
10827
+ ClassDeclaration: ["attrs", "id", "superClass", "body"],
10828
+ ClassElement: ["item"],
10829
+ ConditionalExpression: ["test", "consequent", "alternate"],
10830
+ ContinueStatement: [],
10831
+ DoWhileStatement: ["body", "test"],
10832
+ EnumDeclaration: ["attrs", "id", "body"],
10833
+ EnumStringBody: ["members"],
10834
+ EnumStringMember: ["id", "init"],
10835
+ ExpressionStatement: ["expression"],
10836
+ ForStatement: ["init", "test", "body", "update"],
10837
+ FunctionDeclaration: ["attrs", "id", "params", "body"],
10838
+ Identifier: [],
10839
+ IfStatement: ["test", "consequent", "alternate"],
10840
+ ImportModule: ["id"],
10841
+ InstanceOfCase: ["id"],
10842
+ Line: [],
10843
+ Literal: [],
10844
+ LogicalExpression: ["left", "right"],
10845
+ MemberExpression: ["object", "property"],
10846
+ MethodDefinition: ["params", "returnType"],
10847
+ ModuleDeclaration: ["attrs", "id", "body"],
10848
+ MultiLine: [],
10849
+ NewExpression: ["callee", "arguments"],
10850
+ ObjectExpression: ["properties"],
10851
+ ParenthesizedExpression: ["expression"],
10852
+ Program: ["body", "comments"],
10853
+ Property: ["key", "value"],
10854
+ ReturnStatement: ["argument"],
10855
+ SequenceExpression: ["expressions"],
10856
+ SizedArrayExpression: ["size", "ts"],
10857
+ SwitchCase: ["test", "consequent"],
10858
+ SwitchStatement: ["discriminant", "cases"],
10859
+ ThisExpression: [],
10860
+ ThrowStatement: ["argument"],
10861
+ TryStatement: ["block", "handler", "finalizer"],
10862
+ TypedefDeclaration: ["attrs", "id", "ts"],
10863
+ TypeSpecList: ["ts"],
10864
+ TypeSpecPart: ["name", "body", "callspec", "generics"],
10865
+ UnaryExpression: ["argument"],
10866
+ UpdateExpression: ["argument"],
10867
+ Using: ["id", "as"],
10868
+ VariableDeclaration: ["attrs", "declarations"],
10869
+ VariableDeclarator: ["id", "init"],
10870
+ WhileStatement: ["test", "body"],
10871
+ };
10872
+ function isMCTreeNode(node) {
10873
+ return node ? typeof node === "object" && "type" in node : false;
10874
+ }
10875
+ /*
10876
+ * Traverse the ast rooted at node, calling pre before
10877
+ * visiting each node, and post after.
10878
+ *
10879
+ * - if pre returns false, the node is not traversed, and
10880
+ * post is not called;
10881
+ * - if pre returns a list of child nodes, only those will
10882
+ * be traversed
10883
+ * - otherwise all child nodes are traversed
10884
+ *
10885
+ * - if post returns false, the node it was called on is
10886
+ * removed.
10887
+ */
10888
+ function traverseAst(node, pre, post) {
10889
+ const nodes = pre && pre(node);
10890
+ if (nodes === false)
10891
+ return;
10892
+ if (!mctreeTypeInfo[node.type]) {
10893
+ throw new Error("what?");
10894
+ }
10895
+ for (const key of nodes || mctreeTypeInfo[node.type]) {
10896
+ const value = node[key];
10897
+ if (!value)
10898
+ continue;
10899
+ if (Array.isArray(value)) {
10900
+ const values = value;
10901
+ const deletions = values.reduce((state, obj, i) => {
10902
+ if (isMCTreeNode(obj)) {
10903
+ const repl = traverseAst(obj, pre, post);
10904
+ if (repl === false) {
10905
+ if (!state)
10906
+ state = {};
10907
+ state[i] = true;
10908
+ }
10909
+ else if (repl != null) {
10910
+ if (!state)
10911
+ state = {};
10912
+ values[i] = repl;
10913
+ }
10914
+ }
10915
+ return state;
10916
+ }, null);
10917
+ if (deletions) {
10918
+ values.splice(0, values.length, ...values.filter((obj, i) => deletions[i] !== true).flat(1));
10919
+ }
10920
+ }
10921
+ else if (isMCTreeNode(value)) {
10922
+ const repl = traverseAst(value, pre, post);
10923
+ if (repl === false) {
10924
+ delete node[key];
10925
+ }
10926
+ else if (repl != null) {
10927
+ if (Array.isArray(repl)) {
10928
+ throw new Error("Array returned by traverseAst in Node context");
10929
+ }
10930
+ node[key] = repl;
10931
+ }
10932
+ }
10933
+ }
10934
+ return post && post(node);
10792
10935
  }
10793
10936
 
10794
10937
  ;// CONCATENATED MODULE: ./src/variable-renamer.ts
10795
10938
 
10939
+
10796
10940
  function renameVariable(state, locals, declName) {
10797
10941
  const map = locals.map;
10798
10942
  if (!(0,external_api_cjs_namespaceObject.hasProperty)(map, declName))
@@ -10809,7 +10953,7 @@ function renameVariable(state, locals, declName) {
10809
10953
  // more conflicts
10810
10954
  locals.inners = {};
10811
10955
  const inners = locals.inners;
10812
- (0,external_api_cjs_namespaceObject.traverseAst)(locals.node, (node) => {
10956
+ traverseAst(locals.node, (node) => {
10813
10957
  if (node.type === "VariableDeclarator") {
10814
10958
  inners[(0,external_api_cjs_namespaceObject.variableDeclarationName)(node.id)] = true;
10815
10959
  }
@@ -10849,6 +10993,7 @@ function renameVariable(state, locals, declName) {
10849
10993
  ;// CONCATENATED MODULE: ./src/inliner.ts
10850
10994
 
10851
10995
 
10996
+
10852
10997
  function getArgSafety(state, func, args, requireAll) {
10853
10998
  // determine whether decl might be changed by a function call
10854
10999
  // or assignment during the evaluation of FunctionStateNode.
@@ -10890,11 +11035,13 @@ function getArgSafety(state, func, args, requireAll) {
10890
11035
  case "Identifier":
10891
11036
  case "MemberExpression": {
10892
11037
  const [, results] = state.lookup(arg);
10893
- if (!results || results.length !== 1) {
11038
+ if (!results ||
11039
+ results.length !== 1 ||
11040
+ results[0].results.length !== 1) {
10894
11041
  safeArgs.push(null);
10895
11042
  return !requireAll;
10896
11043
  }
10897
- const safety = getSafety(results[0]);
11044
+ const safety = getSafety(results[0].results[0]);
10898
11045
  safeArgs.push(safety);
10899
11046
  if (!safety) {
10900
11047
  allSafe = false;
@@ -10914,25 +11061,12 @@ function getArgSafety(state, func, args, requireAll) {
10914
11061
  if (allSafe && requireAll)
10915
11062
  return true;
10916
11063
  let callSeen = false;
10917
- let ok = true;
10918
11064
  const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
10919
- const getLoc = (node) => (Array.isArray(node) ? node[0].start : node.start) || 0;
10920
11065
  // look for uses of "unsafe" args that occur after a call.
10921
11066
  // use post to do the checking, because arguments are evaluated
10922
11067
  // prior to the call, so eg "return f(x.y);" is fine, but
10923
11068
  // "return f()+x.y" is not.
10924
- //
10925
- // We also have to use a "pre" to ensure that child nodes are
10926
- // visited in source order (otherwise we could visit x.y before f()
10927
- // in the above example)
10928
- (0,external_api_cjs_namespaceObject.traverseAst)(func.node.body, (node) => {
10929
- return Object.entries(node)
10930
- .filter((kv) => Array.isArray(kv[1])
10931
- ? kv[1].length !== 0 && (0,external_api_cjs_namespaceObject.hasProperty)(kv[1][0], "type")
10932
- : (0,external_api_cjs_namespaceObject.hasProperty)(kv[1], "type"))
10933
- .sort(([, a], [, b]) => getLoc(a) - getLoc(b))
10934
- .map(([key]) => key);
10935
- }, (node) => {
11069
+ traverseAst(func.node.body, null, (node) => {
10936
11070
  switch (node.type) {
10937
11071
  case "AssignmentExpression":
10938
11072
  case "UpdateExpression": {
@@ -10986,12 +11120,6 @@ function inliningLooksUseful(func, node) {
10986
11120
  }
10987
11121
  return false;
10988
11122
  }
10989
- var InlineStatus;
10990
- (function (InlineStatus) {
10991
- InlineStatus[InlineStatus["Never"] = 0] = "Never";
10992
- InlineStatus[InlineStatus["AsExpression"] = 1] = "AsExpression";
10993
- InlineStatus[InlineStatus["AsStatement"] = 2] = "AsStatement";
10994
- })(InlineStatus || (InlineStatus = {}));
10995
11123
  function inlineRequested(state, func) {
10996
11124
  const excludeAnnotations = (func.node.loc?.source &&
10997
11125
  state.fnMap[func.node.loc?.source]?.excludeAnnotations) ||
@@ -11001,7 +11129,7 @@ function inlineRequested(state, func) {
11001
11129
  func.node.attrs.attributes.elements.some((attr) => attr.type === "UnaryExpression" &&
11002
11130
  (attr.argument.name === "inline" ||
11003
11131
  (attr.argument.name.startsWith("inline_") &&
11004
- (0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name.substring(7)))))) {
11132
+ !(0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name.substring(7)))))) {
11005
11133
  return true;
11006
11134
  }
11007
11135
  return false;
@@ -11171,7 +11299,7 @@ function unused(expression, top) {
11171
11299
  },
11172
11300
  ];
11173
11301
  }
11174
- function diagnostic(state, loc, message) {
11302
+ function diagnostic(state, loc, message, type = "INFO") {
11175
11303
  if (!loc || !loc.source)
11176
11304
  return;
11177
11305
  const source = loc.source;
@@ -11187,7 +11315,7 @@ function diagnostic(state, loc, message) {
11187
11315
  if (message) {
11188
11316
  if (index < 0)
11189
11317
  index = diags.length;
11190
- diags[index] = { type: "INFO", loc, message };
11318
+ diags[index] = { type, loc, message };
11191
11319
  }
11192
11320
  else if (index >= 0) {
11193
11321
  diags.splice(index, 1);
@@ -11211,7 +11339,7 @@ function inlineWithArgs(state, func, call, context) {
11211
11339
  }
11212
11340
  }
11213
11341
  else {
11214
- (0,external_api_cjs_namespaceObject.traverseAst)(func.node.body, (node) => {
11342
+ traverseAst(func.node.body, (node) => {
11215
11343
  node.type === "ReturnStatement" && retStmtCount++;
11216
11344
  });
11217
11345
  if (retStmtCount > 1) {
@@ -11306,23 +11434,25 @@ function fixNodeScope(state, lookupNode, nodeStack) {
11306
11434
  // With a bit more work, we could find the guaranteed shortest
11307
11435
  // reference, and then use this to optimize *all* symbols, not
11308
11436
  // just fix inlined ones.
11309
- if (current &&
11310
- current.length === original.length &&
11311
- current.every((item, index) => item == original[index])) {
11437
+ if (current && (0,external_api_cjs_namespaceObject.sameLookupResult)(original, current)) {
11312
11438
  return lookupNode;
11313
11439
  }
11314
11440
  const node = lookupNode.type === "Identifier"
11315
11441
  ? lookupNode
11316
11442
  : lookupNode.property;
11317
- if (original.length === 1 && original[0].type === "EnumStringMember") {
11318
- return applyTypeIfNeeded(original[0].init);
11443
+ if (original.length === 1 &&
11444
+ original[0].results.length === 1 &&
11445
+ original[0].results[0].type === "EnumStringMember") {
11446
+ return applyTypeIfNeeded(original[0].results[0].init);
11319
11447
  }
11320
- const prefixes = original.map((sn) => {
11448
+ const prefixes = original
11449
+ .map((lookupDef) => lookupDef.results.map((sn) => {
11321
11450
  if ((0,external_api_cjs_namespaceObject.isStateNode)(sn) && sn.fullName) {
11322
11451
  return sn.fullName;
11323
11452
  }
11324
11453
  return "";
11325
- });
11454
+ }))
11455
+ .flat();
11326
11456
  if (prefixes.length &&
11327
11457
  prefixes[0].startsWith("$.") &&
11328
11458
  prefixes.every((prefix, i) => !i || prefix === prefixes[i - 1])) {
@@ -11332,9 +11462,7 @@ function fixNodeScope(state, lookupNode, nodeStack) {
11332
11462
  if (found)
11333
11463
  return current;
11334
11464
  const [, results] = state.lookup(current);
11335
- if (results &&
11336
- results.length === original.length &&
11337
- results.every((result, i) => result === original[i])) {
11465
+ if (results && (0,external_api_cjs_namespaceObject.sameLookupResult)(original, results)) {
11338
11466
  found = true;
11339
11467
  return current;
11340
11468
  }
@@ -11374,6 +11502,99 @@ function fixNodeScope(state, lookupNode, nodeStack) {
11374
11502
  return null;
11375
11503
  }
11376
11504
 
11505
+ ;// CONCATENATED MODULE: ./src/visitor.ts
11506
+
11507
+ function visitReferences(state, ast, name, defn, callback) {
11508
+ const checkResults = ([name, results], node) => {
11509
+ if (name && results) {
11510
+ if (!defn || (0,external_api_cjs_namespaceObject.sameLookupResult)(results, defn)) {
11511
+ if (callback(node, results, false) === false) {
11512
+ return [];
11513
+ }
11514
+ }
11515
+ }
11516
+ else if (defn === false) {
11517
+ if (callback(node, [], results === null) === false) {
11518
+ return [];
11519
+ }
11520
+ }
11521
+ return null;
11522
+ };
11523
+ state.pre = (node) => {
11524
+ switch (node.type) {
11525
+ case "AttributeList":
11526
+ return [];
11527
+ case "UnaryExpression":
11528
+ // a bare symbol isn't a reference
11529
+ if (node.operator === ":")
11530
+ return [];
11531
+ break;
11532
+ case "BinaryExpression":
11533
+ /*
11534
+ * `expr has :symbol` can be treated as a reference
11535
+ * to expr.symbol.
11536
+ */
11537
+ if (node.operator === "has") {
11538
+ if (node.right.type === "UnaryExpression" &&
11539
+ node.right.operator === ":") {
11540
+ if (!name || node.right.argument.name === name) {
11541
+ return checkResults(state.lookup({
11542
+ type: "MemberExpression",
11543
+ object: node.left,
11544
+ property: node.right.argument,
11545
+ computed: false,
11546
+ }), node.right.argument);
11547
+ }
11548
+ }
11549
+ }
11550
+ break;
11551
+ case "CallExpression":
11552
+ // A call expression whose callee is an identifier is looked
11553
+ // up as a non-local. ie even if there's a same named local,
11554
+ // it will be ignored, and the lookup will start as if the
11555
+ // call had been written self.foo() rather than foo().
11556
+ if (node.callee.type === "Identifier") {
11557
+ if (!name || node.callee.name === name) {
11558
+ /* ignore return value */
11559
+ checkResults(state.lookupNonlocal(node.callee), node.callee);
11560
+ }
11561
+ return ["arguments"];
11562
+ }
11563
+ break;
11564
+ case "Identifier":
11565
+ if (!name || node.name === name) {
11566
+ return checkResults(state.lookup(node), node);
11567
+ }
11568
+ break;
11569
+ case "MemberExpression":
11570
+ if (!node.computed && node.property.type === "Identifier") {
11571
+ if (!name || node.property.name === name) {
11572
+ return checkResults(state.lookup(node), node) || ["object"];
11573
+ }
11574
+ return ["object"];
11575
+ }
11576
+ break;
11577
+ case "MethodDefinition": {
11578
+ if (!state.inType) {
11579
+ throw new Error("Method definition outside of type!");
11580
+ }
11581
+ if (node.params) {
11582
+ node.params.forEach((param) => {
11583
+ if (param.type == "BinaryExpression") {
11584
+ state.traverse(param.right);
11585
+ state.inType = true;
11586
+ }
11587
+ });
11588
+ }
11589
+ return ["returnType"];
11590
+ }
11591
+ }
11592
+ return null;
11593
+ };
11594
+ (0,external_api_cjs_namespaceObject.collectNamespaces)(ast, state);
11595
+ delete state.pre;
11596
+ }
11597
+
11377
11598
  ;// CONCATENATED MODULE: ./src/mc-rewrite.ts
11378
11599
 
11379
11600
 
@@ -11381,43 +11602,25 @@ function fixNodeScope(state, lookupNode, nodeStack) {
11381
11602
 
11382
11603
 
11383
11604
 
11384
- function processImports(allImports, lookup) {
11385
- allImports.forEach(({ node, stack }) => {
11386
- const [name, module] = lookup(node.id, ("as" in node && node.as && node.as.name) || null, stack);
11387
- if (name && module) {
11388
- const [parent] = stack.slice(-1);
11389
- if (!parent.decls)
11390
- parent.decls = {};
11391
- const decls = parent.decls;
11392
- if (!(0,external_api_cjs_namespaceObject.hasProperty)(decls, name))
11393
- decls[name] = [];
11394
- module.forEach((m) => {
11395
- if ((0,external_api_cjs_namespaceObject.isStateNode)(m) && m.type == "ModuleDeclaration") {
11396
- (0,external_util_cjs_namespaceObject.pushUnique)(decls[name], m);
11397
- if (!parent.type_decls)
11398
- parent.type_decls = {};
11399
- const tdecls = parent.type_decls;
11400
- if (!(0,external_api_cjs_namespaceObject.hasProperty)(tdecls, name))
11401
- tdecls[name] = [];
11402
- (0,external_util_cjs_namespaceObject.pushUnique)(tdecls[name], m);
11403
- if (node.type == "ImportModule" && m.type_decls) {
11404
- Object.entries(m.type_decls).forEach(([name, decls]) => {
11405
- if (!(0,external_api_cjs_namespaceObject.hasProperty)(tdecls, name))
11406
- tdecls[name] = [];
11407
- decls.forEach((decl) => (0,external_util_cjs_namespaceObject.pushUnique)(tdecls[name], decl));
11408
- });
11409
- }
11410
- }
11411
- });
11412
- }
11413
- });
11414
- }
11605
+
11606
+
11415
11607
  function collectClassInfo(state) {
11608
+ const toybox = state.stack[0].decls["Toybox"][0];
11609
+ const lang = toybox.decls["Lang"][0];
11610
+ const object = lang.decls["Object"];
11416
11611
  state.allClasses.forEach((elm) => {
11612
+ if (elm.stack[elm.stack.length - 1].type === "ClassDeclaration") {
11613
+ // nested classes don't get access to their contained
11614
+ // context. Put them in the global scope instead.
11615
+ elm.stack = elm.stack.slice(0, 1);
11616
+ }
11417
11617
  if (elm.node.superClass) {
11418
- const [name, classes] = state.lookup(elm.node.superClass, null, elm.stack);
11419
- const superClass = classes &&
11420
- classes.filter((c) => (0,external_api_cjs_namespaceObject.isStateNode)(c) && c.type === "ClassDeclaration");
11618
+ const [name, lookupDefns] = state.lookup(elm.node.superClass, null, elm.stack);
11619
+ const superClass = lookupDefns &&
11620
+ lookupDefns
11621
+ .map((lookupDefn) => lookupDefn.results)
11622
+ .flat()
11623
+ .filter((c) => (0,external_api_cjs_namespaceObject.isStateNode)(c) && c.type === "ClassDeclaration");
11421
11624
  // set it "true" if there is a superClass, but we can't find it.
11422
11625
  elm.superClass = superClass && superClass.length ? superClass : true;
11423
11626
  if (name && elm.superClass !== true) {
@@ -11449,6 +11652,9 @@ function collectClassInfo(state) {
11449
11652
  elm.decls[name] = elm.superClass;
11450
11653
  }
11451
11654
  }
11655
+ else if (elm !== object[0]) {
11656
+ elm.superClass = object;
11657
+ }
11452
11658
  });
11453
11659
  const markOverrides = (cls, scls) => {
11454
11660
  if (scls === true)
@@ -11478,7 +11684,9 @@ function getFileSources(fnMap) {
11478
11684
  return (value.monkeyCSource ||
11479
11685
  promises_namespaceObject.readFile(name)
11480
11686
  .then((data) => (value.monkeyCSource = data.toString().replace(/\r\n/g, "\n"))));
11481
- })).then(() => { });
11687
+ })).then(() => {
11688
+ return;
11689
+ });
11482
11690
  }
11483
11691
  function getFileASTs(fnMap) {
11484
11692
  return getFileSources(fnMap).then(() => Object.entries(fnMap).reduce((ok, [name, value]) => {
@@ -11501,11 +11709,12 @@ function getFileASTs(fnMap) {
11501
11709
  return ok;
11502
11710
  }, true));
11503
11711
  }
11504
- async function analyze(fnMap) {
11712
+ async function analyze(fnMap, barrelList, config) {
11505
11713
  let hasTests = false;
11506
- const allImports = [];
11714
+ let markApi = true;
11507
11715
  const preState = {
11508
11716
  fnMap,
11717
+ config,
11509
11718
  allFunctions: [],
11510
11719
  allClasses: [],
11511
11720
  shouldExclude(node) {
@@ -11533,45 +11742,38 @@ async function analyze(fnMap) {
11533
11742
  }
11534
11743
  return false;
11535
11744
  },
11536
- post(node, state) {
11745
+ pre(node, state) {
11537
11746
  switch (node.type) {
11538
11747
  case "FunctionDeclaration":
11748
+ if (markApi) {
11749
+ node.body = null;
11750
+ break;
11751
+ }
11752
+ // falls through
11753
+ case "ModuleDeclaration":
11539
11754
  case "ClassDeclaration": {
11540
11755
  const [scope] = state.stack.slice(-1);
11541
- const stack = state.stack.slice(0, -1);
11542
- scope.stack = stack;
11756
+ scope.stack = state.stackClone().slice(0, -1);
11543
11757
  if (scope.type == "FunctionDeclaration") {
11758
+ scope.isStatic =
11759
+ scope.stack.slice(-1)[0].type !== "ClassDeclaration" ||
11760
+ (scope.node.attrs &&
11761
+ scope.node.attrs.access &&
11762
+ scope.node.attrs.access.includes("static"));
11544
11763
  state.allFunctions.push(scope);
11545
11764
  }
11546
- else {
11765
+ else if (scope.type === "ClassDeclaration") {
11547
11766
  state.allClasses.push(scope);
11548
11767
  }
11549
- return null;
11768
+ break;
11550
11769
  }
11551
- case "Using":
11552
- case "ImportModule":
11553
- allImports.push({ node, stack: state.stack.slice() });
11554
- return null;
11555
- default:
11556
- return null;
11557
11770
  }
11771
+ return null;
11558
11772
  },
11559
11773
  };
11560
- await (0,external_api_cjs_namespaceObject.getApiMapping)(preState);
11774
+ await (0,external_api_cjs_namespaceObject.getApiMapping)(preState, barrelList);
11775
+ markApi = false;
11561
11776
  const state = preState;
11562
- // Mark all functions from api.mir as "special" by
11563
- // setting their bodies to null. In api.mir, they're
11564
- // all empty, which makes it look like they're
11565
- // do-nothing functions.
11566
- const markApi = (node) => {
11567
- if (node.type == "FunctionDeclaration") {
11568
- node.node.body = null;
11569
- }
11570
- if ((0,external_api_cjs_namespaceObject.isStateNode)(node) && node.decls) {
11571
- Object.values(node.decls).forEach((v) => v.forEach(markApi));
11572
- }
11573
- };
11574
- markApi(state.stack[0]);
11575
11777
  await getFileASTs(fnMap);
11576
11778
  Object.entries(fnMap).forEach(([name, value]) => {
11577
11779
  const { ast, parserError } = value;
@@ -11584,8 +11786,28 @@ async function analyze(fnMap) {
11584
11786
  });
11585
11787
  delete state.shouldExclude;
11586
11788
  delete state.post;
11587
- processImports(allImports, state.lookup);
11588
11789
  collectClassInfo(state);
11790
+ const diagnosticType = config?.checkInvalidSymbols !== "OFF"
11791
+ ? config?.checkInvalidSymbols || "WARNING"
11792
+ : null;
11793
+ if (diagnosticType &&
11794
+ !config?.compilerOptions?.includes("--Eno-invalid-symbol")) {
11795
+ const checkTypes = config?.typeCheckLevel && config.typeCheckLevel !== "Off";
11796
+ Object.entries(fnMap).forEach(([, v]) => {
11797
+ visitReferences(state, v.ast, null, false, (node, results, error) => {
11798
+ if (!error)
11799
+ return undefined;
11800
+ const nodeStr = (0,external_api_cjs_namespaceObject.formatAst)(node);
11801
+ if (state.inType) {
11802
+ if (!checkTypes || nodeStr.match(/^Void|Null$/)) {
11803
+ return undefined;
11804
+ }
11805
+ }
11806
+ diagnostic(state, node.loc, `Undefined symbol ${nodeStr}`, diagnosticType);
11807
+ return false;
11808
+ });
11809
+ });
11810
+ }
11589
11811
  return state;
11590
11812
  }
11591
11813
  function compareLiteralLike(a, b) {
@@ -11595,11 +11817,11 @@ function compareLiteralLike(a, b) {
11595
11817
  b = b.left;
11596
11818
  return a.type === "Literal" && b.type === "Literal" && a.value === b.value;
11597
11819
  }
11598
- function getLiteralFromDecls(decls) {
11599
- if (!decls.length)
11820
+ function getLiteralFromDecls(lookupDefns) {
11821
+ if (!lookupDefns.length)
11600
11822
  return null;
11601
11823
  let result = null;
11602
- if (decls.every((d) => {
11824
+ if (lookupDefns.every((lookupDefn) => lookupDefn.results.every((d) => {
11603
11825
  if (d.type === "EnumStringMember" ||
11604
11826
  (d.type === "VariableDeclarator" && d.node.kind === "const")) {
11605
11827
  const init = getLiteralNode(d.type === "EnumStringMember" ? d.init : d.node.init);
@@ -11614,7 +11836,7 @@ function getLiteralFromDecls(decls) {
11614
11836
  }
11615
11837
  }
11616
11838
  return false;
11617
- })) {
11839
+ }))) {
11618
11840
  return result;
11619
11841
  }
11620
11842
  return null;
@@ -11777,7 +11999,7 @@ function evaluateFunction(func, args) {
11777
11999
  ? JSON.parse(JSON.stringify(func.body))
11778
12000
  : func.body;
11779
12001
  try {
11780
- (0,external_api_cjs_namespaceObject.traverseAst)(body, (node) => {
12002
+ traverseAst(body, (node) => {
11781
12003
  switch (node.type) {
11782
12004
  case "BlockStatement":
11783
12005
  case "ReturnStatement":
@@ -11825,20 +12047,23 @@ function markFunctionCalled(state, func) {
11825
12047
  }
11826
12048
  (0,external_util_cjs_namespaceObject.pushUnique)(state.calledFunctions[func.id.name], func);
11827
12049
  }
11828
- async function optimizeMonkeyC(fnMap) {
12050
+ async function optimizeMonkeyC(fnMap, barrelList, config) {
11829
12051
  const state = {
11830
- ...(await analyze(fnMap)),
12052
+ ...(await analyze(fnMap, barrelList, config)),
11831
12053
  localsStack: [{}],
11832
12054
  exposed: {},
11833
12055
  calledFunctions: {},
11834
12056
  };
11835
- const replace = (node) => {
12057
+ const replace = (node, old) => {
11836
12058
  if (node === false || node === null)
11837
12059
  return node;
11838
12060
  const rep = state.traverse(node);
11839
- return rep === false || rep ? rep : node;
12061
+ if (rep === false || Array.isArray(rep))
12062
+ return rep;
12063
+ return { ...(rep || node), loc: old.loc, start: old.start, end: old.end };
11840
12064
  };
11841
12065
  const inPlaceReplacement = (node, obj) => {
12066
+ const { start, end, loc } = node;
11842
12067
  for (const k of Object.keys(node)) {
11843
12068
  delete node[k];
11844
12069
  }
@@ -11846,13 +12071,16 @@ async function optimizeMonkeyC(fnMap) {
11846
12071
  obj = {
11847
12072
  type: "BinaryExpression",
11848
12073
  operator: "as",
11849
- left: obj,
12074
+ left: { ...obj, start, end, loc },
11850
12075
  right: { type: "TypeSpecList", ts: [obj.enumType] },
11851
12076
  };
11852
12077
  }
11853
12078
  for (const [k, v] of Object.entries(obj)) {
11854
12079
  node[k] = v;
11855
12080
  }
12081
+ node.loc = loc;
12082
+ node.start = start;
12083
+ node.end = end;
11856
12084
  };
11857
12085
  const lookupAndReplace = (node) => {
11858
12086
  const [, objects] = state.lookup(node);
@@ -11910,7 +12138,7 @@ async function optimizeMonkeyC(fnMap) {
11910
12138
  case "ConditionalExpression":
11911
12139
  case "IfStatement":
11912
12140
  case "DoWhileStatement":
11913
- case "WhileStatement":
12141
+ case "WhileStatement": {
11914
12142
  const test = (state.traverse(node.test) ||
11915
12143
  node.test);
11916
12144
  const [value, type] = getNodeValue(test);
@@ -11942,6 +12170,7 @@ async function optimizeMonkeyC(fnMap) {
11942
12170
  }
11943
12171
  }
11944
12172
  return null;
12173
+ }
11945
12174
  case "EnumDeclaration":
11946
12175
  return false;
11947
12176
  case "ForStatement": {
@@ -11971,6 +12200,37 @@ async function optimizeMonkeyC(fnMap) {
11971
12200
  }
11972
12201
  return ["init"];
11973
12202
  }
12203
+ case "CatchClause":
12204
+ if (node.param) {
12205
+ state.localsStack.push({ node, map: { ...(topLocals().map || {}) } });
12206
+ const locals = topLocals();
12207
+ const map = locals.map;
12208
+ const declName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(node.param);
12209
+ const name = renameVariable(state, locals, declName);
12210
+ if (name) {
12211
+ if (node.param.type === "Identifier") {
12212
+ node.param.name = name;
12213
+ }
12214
+ else {
12215
+ node.param.left.name = name;
12216
+ }
12217
+ }
12218
+ else {
12219
+ map[declName] = true;
12220
+ }
12221
+ return ["body"];
12222
+ }
12223
+ break;
12224
+ case "BinaryExpression":
12225
+ if (node.operator === "has") {
12226
+ if (node.right.type === "UnaryExpression" &&
12227
+ node.right.operator === ":") {
12228
+ // Using `expr has :symbol` doesn't "expose"
12229
+ // symbol. So skip the right operand.
12230
+ return ["left"];
12231
+ }
12232
+ }
12233
+ break;
11974
12234
  case "UnaryExpression":
11975
12235
  if (node.operator == ":") {
11976
12236
  // If we produce a Symbol, for a given name,
@@ -12053,7 +12313,7 @@ async function optimizeMonkeyC(fnMap) {
12053
12313
  }
12054
12314
  const opt = optimizeNode(node);
12055
12315
  if (opt) {
12056
- return replace(opt);
12316
+ return replace(opt, node);
12057
12317
  }
12058
12318
  switch (node.type) {
12059
12319
  case "ConditionalExpression":
@@ -12063,7 +12323,7 @@ async function optimizeMonkeyC(fnMap) {
12063
12323
  const rep = node.test.value ? node.consequent : node.alternate;
12064
12324
  if (!rep)
12065
12325
  return false;
12066
- return replace(rep);
12326
+ return replace(rep, rep);
12067
12327
  }
12068
12328
  break;
12069
12329
  case "WhileStatement":
@@ -12078,11 +12338,11 @@ async function optimizeMonkeyC(fnMap) {
12078
12338
  break;
12079
12339
  case "ReturnStatement":
12080
12340
  if (node.argument && node.argument.type === "CallExpression") {
12081
- return replace(optimizeCall(state, node.argument, node));
12341
+ return replace(optimizeCall(state, node.argument, node), node.argument);
12082
12342
  }
12083
12343
  break;
12084
12344
  case "CallExpression": {
12085
- return replace(optimizeCall(state, node, null));
12345
+ return replace(optimizeCall(state, node, null), node);
12086
12346
  }
12087
12347
  case "AssignmentExpression":
12088
12348
  if (node.operator === "=" &&
@@ -12094,7 +12354,7 @@ async function optimizeMonkeyC(fnMap) {
12094
12354
  break;
12095
12355
  case "ExpressionStatement":
12096
12356
  if (node.expression.type === "CallExpression") {
12097
- return replace(optimizeCall(state, node.expression, node));
12357
+ return replace(optimizeCall(state, node.expression, node), node.expression);
12098
12358
  }
12099
12359
  else if (node.expression.type === "AssignmentExpression") {
12100
12360
  if (node.expression.right.type === "CallExpression") {
@@ -12106,10 +12366,10 @@ async function optimizeMonkeyC(fnMap) {
12106
12366
  }
12107
12367
  if (!ok && node.expression.operator == "=") {
12108
12368
  const [, result] = state.lookup(node.expression.left);
12109
- ok = result != null;
12369
+ ok = !!result;
12110
12370
  }
12111
12371
  if (ok) {
12112
- return replace(optimizeCall(state, node.expression.right, node.expression));
12372
+ return replace(optimizeCall(state, node.expression.right, node.expression), node.expression.right);
12113
12373
  }
12114
12374
  }
12115
12375
  }
@@ -12117,7 +12377,7 @@ async function optimizeMonkeyC(fnMap) {
12117
12377
  const ret = unused(node.expression, true);
12118
12378
  if (ret) {
12119
12379
  return ret
12120
- .map(replace)
12380
+ .map((r) => replace(r, r))
12121
12381
  .flat(1)
12122
12382
  .filter((s) => !!s);
12123
12383
  }
@@ -12138,6 +12398,9 @@ async function optimizeMonkeyC(fnMap) {
12138
12398
  delete state.post;
12139
12399
  const cleanup = (node) => {
12140
12400
  switch (node.type) {
12401
+ case "ThisExpression":
12402
+ node.text = "self";
12403
+ break;
12141
12404
  case "EnumStringBody":
12142
12405
  if (node.members.every((m) => {
12143
12406
  const name = "name" in m ? m.name : m.id.name;
@@ -12202,11 +12465,24 @@ async function optimizeMonkeyC(fnMap) {
12202
12465
  return false;
12203
12466
  }
12204
12467
  break;
12468
+ case "ClassDeclaration":
12469
+ case "ModuleDeclaration":
12470
+ // none of the attributes means anything on classes and
12471
+ // modules, and the new compiler complains about some
12472
+ // of them. Just drop them all.
12473
+ if (node.attrs && node.attrs.access) {
12474
+ if (node.attrs.attributes) {
12475
+ delete node.attrs.access;
12476
+ }
12477
+ else {
12478
+ delete node.attrs;
12479
+ }
12480
+ }
12205
12481
  }
12206
12482
  return null;
12207
12483
  };
12208
12484
  Object.values(fnMap).forEach((f) => {
12209
- (0,external_api_cjs_namespaceObject.traverseAst)(f.ast, undefined, (node) => {
12485
+ traverseAst(f.ast, undefined, (node) => {
12210
12486
  const ret = cleanup(node);
12211
12487
  if (ret === false) {
12212
12488
  state.removeNodeComments(node, f.ast);
@@ -12217,9 +12493,12 @@ async function optimizeMonkeyC(fnMap) {
12217
12493
  return state.diagnostics;
12218
12494
  }
12219
12495
  function optimizeCall(state, node, context) {
12220
- const [name, results] = state.lookup(node.callee);
12496
+ const [name, results] = state.lookupNonlocal(node.callee);
12221
12497
  const callees = results &&
12222
- results.filter((c) => c.type === "FunctionDeclaration");
12498
+ results
12499
+ .map((r) => r.results)
12500
+ .flat()
12501
+ .filter((c) => c.type === "FunctionDeclaration");
12223
12502
  if (!callees || !callees.length) {
12224
12503
  const n = name ||
12225
12504
  ("name" in node.callee && node.callee.name) ||
@@ -12260,23 +12539,29 @@ function optimizeCall(state, node, context) {
12260
12539
 
12261
12540
  ;// CONCATENATED MODULE: ./src/pragma-checker.ts
12262
12541
 
12263
- function pragmaChecker(ast) {
12542
+
12543
+ function pragmaChecker(ast, diagnostics) {
12264
12544
  const comments = ast.comments;
12265
12545
  if (!comments)
12266
12546
  return;
12547
+ diagnostics = diagnostics
12548
+ ?.slice()
12549
+ .sort((d1, d2) => d1.loc.start < d2.loc.start ? -1 : d1.loc.start == d2.loc.start ? 0 : 1);
12550
+ let diagIndex = 0;
12267
12551
  let index = -1;
12268
12552
  let comment;
12269
12553
  let matchers;
12270
12554
  const next = () => {
12271
12555
  while (++index < comments.length) {
12272
12556
  comment = comments[index];
12273
- let match = comment.value.match(/^\s*@match\s+(.+)/);
12557
+ let match = comment.value.match(/^\s*@(match|expect)\s+(.+)/);
12274
12558
  if (!match)
12275
12559
  continue;
12276
- let str = match[1];
12560
+ const kind = match[1];
12561
+ let str = match[2];
12277
12562
  matchers = [];
12278
12563
  while ((match = str.match(/^([/%&#@"])(.+?(?<!\\)(?:\\{2})*)\1(\s+|$)/))) {
12279
- matchers.push({ quote: match[1], needle: match[2] });
12564
+ matchers.push({ kind, quote: match[1], needle: match[2] });
12280
12565
  str = str.substring(match[0].length);
12281
12566
  if (!str.length)
12282
12567
  break;
@@ -12286,35 +12571,79 @@ function pragmaChecker(ast) {
12286
12571
  if (!matchers.length) {
12287
12572
  match = str.match(/^(\S+)\s+$/);
12288
12573
  if (match) {
12289
- matchers.push({ quote: '"', needle: match[1] });
12574
+ matchers.push({ kind, quote: '"', needle: match[1] });
12290
12575
  break;
12291
12576
  }
12292
12577
  }
12293
12578
  throw new Error(`Build pragma '${comment.value}' is invalid. In ${comment.loc.source}:${comment.loc.start.line}`);
12294
12579
  }
12295
12580
  };
12581
+ const matcher = (quote, needle, haystack) => {
12582
+ if (quote == '"') {
12583
+ return haystack.includes(needle);
12584
+ }
12585
+ const re = new RegExp(needle);
12586
+ return re.test(haystack);
12587
+ };
12296
12588
  next();
12297
- (0,external_api_cjs_namespaceObject.traverseAst)(ast, (node) => {
12589
+ traverseAst(ast, (node) => {
12298
12590
  if (index >= comments.length)
12299
12591
  return false;
12300
12592
  if (node.start && node.start >= (comment.end || Infinity)) {
12301
- const { quote, needle } = matchers.shift();
12302
- const haystack = (0,external_api_cjs_namespaceObject.formatAst)(node).replace(/[\r\n]/g, " ");
12303
- let found = false;
12304
- if (quote == '"') {
12305
- found = haystack.includes(needle);
12306
- }
12307
- else {
12308
- const re = new RegExp(needle);
12309
- found = re.test(haystack);
12593
+ const { kind, quote, needle } = matchers.shift();
12594
+ if (kind === "match") {
12595
+ if (!matcher(quote, needle, (0,external_api_cjs_namespaceObject.formatAst)(node).replace(/([\r\n]|\s)+/g, " "))) {
12596
+ throw new Error(`Didn't find '${needle}' at ${comment.loc.source}:${comment.loc.start.line}`);
12597
+ }
12310
12598
  }
12311
- if (!found) {
12312
- throw new Error(`Didn't find '${needle}' at ${comment.loc.source}:${comment.loc.start.line}`);
12599
+ else if (kind === "expect") {
12600
+ const locCmp = (a, b) => {
12601
+ if (!b)
12602
+ return -1;
12603
+ if (a.start.line < b.start.line)
12604
+ return -1;
12605
+ if (a.start.line === b.start.line &&
12606
+ a.start.column < b.start.column) {
12607
+ return -1;
12608
+ }
12609
+ if (a.end.line > b.end.line)
12610
+ return 1;
12611
+ if (a.end.line === b.end.line && a.end.column >= b.end.column) {
12612
+ return 1;
12613
+ }
12614
+ return 0;
12615
+ };
12616
+ let found = false;
12617
+ if (diagnostics) {
12618
+ while (true) {
12619
+ if (diagIndex >= diagnostics.length) {
12620
+ diagnostics = null;
12621
+ break;
12622
+ }
12623
+ const diag = diagnostics[diagIndex];
12624
+ const cmp = locCmp(diag.loc, node.loc);
12625
+ if (cmp > 0) {
12626
+ break;
12627
+ }
12628
+ diagIndex++;
12629
+ if (cmp < 0)
12630
+ continue;
12631
+ if (matcher(quote, needle, diag.message)) {
12632
+ found = true;
12633
+ diag.type = "INFO";
12634
+ }
12635
+ }
12636
+ }
12637
+ if (!found) {
12638
+ throw new Error(`Missing error message '${needle} at ${comment.loc.source}:${comment.loc.start.line}`);
12639
+ }
12313
12640
  }
12314
- if (!matchers.length) {
12315
- next();
12641
+ if (matchers.length) {
12642
+ // if we're checking a series of nodes, we need
12643
+ // to skip over this one.
12644
+ return false;
12316
12645
  }
12317
- return false;
12646
+ next();
12318
12647
  }
12319
12648
  return null;
12320
12649
  });
@@ -12336,7 +12665,7 @@ function pragmaChecker(ast) {
12336
12665
 
12337
12666
 
12338
12667
  function relative_path_no_dotdot(relative) {
12339
- return relative.replace(/^(\.\.[\\\/])+/, (str) => `__${"dot".repeat(str.length / 3)}__${str.slice(-1)}`);
12668
+ return relative.replace(/^(\.\.[\\/])+/, (str) => `__${"dot".repeat(str.length / 3)}__${str.slice(-1)}`);
12340
12669
  }
12341
12670
  async function getVSCodeSettings(path) {
12342
12671
  try {
@@ -12468,7 +12797,7 @@ async function createLocalBarrels(targets, options) {
12468
12797
  const sha1 = external_crypto_namespaceObject.createHash("sha1")
12469
12798
  .update(rawBarrelDir, "binary")
12470
12799
  .digest("base64")
12471
- .replace(/[\/=+]/g, "");
12800
+ .replace(/[/=+]/g, "");
12472
12801
  const optBarrelDir = external_path_.resolve(barrelDir, `${barrel}-${sha1}`);
12473
12802
  if (!(0,external_api_cjs_namespaceObject.hasProperty)(optBarrels, barrel)) {
12474
12803
  optBarrels[barrel] = {
@@ -12516,7 +12845,9 @@ async function generateOptimizedProject(options) {
12516
12845
  }
12517
12846
  return {
12518
12847
  jungleFiles: config.jungleFiles,
12848
+ xml,
12519
12849
  program: external_path_.basename(external_path_.dirname(manifest)),
12850
+ hasTests: !!config.testBuild,
12520
12851
  };
12521
12852
  }
12522
12853
  let dropBarrels = false;
@@ -12617,7 +12948,7 @@ async function generateOptimizedProject(options) {
12617
12948
  }
12618
12949
  const prefix = `${product}.`;
12619
12950
  process_field(prefix, qualifier, "sourcePath", (s) => external_path_.join(group.dir, "source", relative_path_no_dotdot(external_path_.relative(workspace, s)))
12620
- .replace(/([\\\/]\*\*)[\\\/]\*/g, "$1"));
12951
+ .replace(/([\\/]\*\*)[\\/]\*/g, "$1"));
12621
12952
  if (group.optimizerConfig.optBarrels) {
12622
12953
  parts.push(`${prefix}barrelPath = ${Object.values(group.optimizerConfig.optBarrels)
12623
12954
  .map((value) => `[${value.jungleFiles
@@ -12631,7 +12962,7 @@ async function generateOptimizedProject(options) {
12631
12962
  .map(([barrel, resolvedBarrel]) => {
12632
12963
  const root = external_path_.dirname(resolvedBarrel.jungles[0]);
12633
12964
  return (resolvedBarrel.qualifier.sourcePath || []).map((s) => external_path_.join(group.dir, "barrels", barrel, external_path_.relative(root, s))
12634
- .replace(/([\\\/]\*\*)[\\\/]\*/g, "$1"));
12965
+ .replace(/([\\/]\*\*)[\\/]\*/g, "$1"));
12635
12966
  })
12636
12967
  .flat()
12637
12968
  .sort()
@@ -12702,6 +13033,7 @@ const configOptionsToCheck = [
12702
13033
  "ignoredExcludeAnnotations",
12703
13034
  "ignoredAnnotations",
12704
13035
  "ignoredSourcePaths",
13036
+ "checkInvalidSymbols",
12705
13037
  ];
12706
13038
  /**
12707
13039
  * @param {BuildConfig} config
@@ -12753,21 +13085,21 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
12753
13085
  // the oldest optimized file, we don't need to regenerate
12754
13086
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
12755
13087
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
12756
- if (source_time < opt_time && 1654811717108 < opt_time) {
13088
+ if (source_time < opt_time && 1655680070380 < opt_time) {
12757
13089
  return { hasTests, diagnostics: prevDiagnostics };
12758
13090
  }
12759
13091
  }
12760
13092
  await promises_namespaceObject.rm(output, { recursive: true, force: true });
12761
13093
  await promises_namespaceObject.mkdir(output, { recursive: true });
12762
- const diagnostics = await optimizeMonkeyC(fnMap);
12763
- return Promise.all(Object.values(fnMap).map(async (info) => {
13094
+ const diagnostics = await optimizeMonkeyC(fnMap, Object.keys(buildConfig.barrelMap || {}), config);
13095
+ return Promise.all(Object.entries(fnMap).map(async ([inFile, info]) => {
12764
13096
  const name = info.output;
12765
13097
  const dir = external_path_.dirname(name);
12766
13098
  await promises_namespaceObject.mkdir(dir, { recursive: true });
12767
13099
  const opt_source = (0,external_api_cjs_namespaceObject.formatAst)(info.ast, info.monkeyCSource);
12768
13100
  await promises_namespaceObject.writeFile(name, opt_source);
12769
13101
  if (config.checkBuildPragmas) {
12770
- pragmaChecker(info.ast);
13102
+ pragmaChecker(info.ast, diagnostics?.[inFile]);
12771
13103
  }
12772
13104
  return info.hasTests;
12773
13105
  })).then((results) => {
@@ -12802,7 +13134,13 @@ async function getProjectAnalysis(targets, analysis, options) {
12802
13134
  if (!(await getFileASTs(fnMap))) {
12803
13135
  return { fnMap, paths };
12804
13136
  }
12805
- const state = await analyze(fnMap);
13137
+ const barrelObj = {};
13138
+ targets.forEach((target) => {
13139
+ if (target.qualifier.barrelMap) {
13140
+ Object.keys(target.qualifier.barrelMap).forEach((key) => (barrelObj[key] = true));
13141
+ }
13142
+ });
13143
+ const state = await analyze(fnMap, Object.keys(barrelObj), options);
12806
13144
  return { fnMap: fnMap, paths, state };
12807
13145
  }
12808
13146
  /**