@boperators/mcp-server 0.2.1 → 0.3.1

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.
Files changed (3) hide show
  1. package/README.md +6 -6
  2. package/dist/index.js +168 -299
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -22,7 +22,7 @@ bun add -D @boperators/mcp-server
22
22
  |------|-------------|:-------------------:|
23
23
  | [`list_overloads`](#list_overloads) | List all registered overloads in the project, with optional filtering by class or operator | ✓ |
24
24
  | [`transform_preview`](#transform_preview) | Preview the transformed output for a file or a line range within it | ✓ |
25
- | [`scaffold_overloads`](#scaffold_overloads) | Generate `as const` boilerplate for a set of operators on a named class | — |
25
+ | [`scaffold_overloads`](#scaffold_overloads) | Generate method boilerplate for a set of operators on a named class | — |
26
26
  | [`validate_overloads`](#validate_overloads) | Validate overload definitions in a single file and return structured diagnostics | ✓ |
27
27
  | [`explain_expression`](#explain_expression) | Reverse-engineer a transformed call expression back to its original operator and overload metadata | optional |
28
28
 
@@ -57,11 +57,11 @@ Transforms a file and returns the original and transformed text side by side, al
57
57
 
58
58
  ### `scaffold_overloads`
59
59
 
60
- Generates ready-to-paste TypeScript property declarations for a list of operators on a given class. Automatically uses the correct form for each operator:
60
+ Generates ready-to-paste TypeScript method declarations for a list of operators on a given class. Automatically uses the correct form for each operator:
61
61
 
62
- - **Static binary** (`+`, `-`, `*`, …) — `static readonly "+" = [(a: T, b: T): T => { … }] as const`
62
+ - **Static binary** (`+`, `-`, `*`, …) — `static "+"(a: T, b: T): T { … }`
63
63
  - **Comparison** (`>`, `==`, …) — static, returns `boolean`
64
- - **Instance compound** (`+=`, `-=`, …) — instance, `function(this: T, rhs: T): void`
64
+ - **Instance compound** (`+=`, `-=`, …) — instance, `"+="(rhs: T): void { … }`
65
65
  - **Prefix unary** (`!`, `~`) — static, one parameter
66
66
  - **Postfix unary** (`++`, `--`) — instance, no parameters, returns `void`
67
67
 
@@ -80,7 +80,7 @@ Does not require a `tsconfig` — it is purely generative.
80
80
 
81
81
  Runs the boperators scanning pipeline against a single file in isolation and returns structured diagnostics without modifying any state. Reports:
82
82
 
83
- - **Errors** — wrong arity, missing `as const`, return type violations
83
+ - **Errors** — wrong arity, return type violations
84
84
  - **Warnings** — duplicate/conflicting overload registrations
85
85
  - The count of successfully parsed overloads
86
86
 
@@ -95,7 +95,7 @@ Runs the boperators scanning pipeline against a single file in isolation and ret
95
95
 
96
96
  ### `explain_expression`
97
97
 
98
- Given a transformed boperators expression (e.g. `Vector3["+"][0](a, b)` or `v["+="][0].call(v, rhs)`), decodes it back to the original operator, identifies whether it is static/instance and binary/unary, and optionally enriches the result with metadata from the project's overload store.
98
+ Given a transformed boperators expression (e.g. `Vector3["+"](a, b)` or `v["+="](rhs)` or `v["++"]( )`), decodes it back to the original operator, identifies whether it is static/instance and binary/unary, and optionally enriches the result with metadata from the project's overload store.
99
99
 
100
100
  **Inputs**
101
101
 
package/dist/index.js CHANGED
@@ -248869,6 +248869,29 @@ Node text: ${this.#forgottenText}`;
248869
248869
  exports.setScopeForNode = setScopeForNode;
248870
248870
  });
248871
248871
 
248872
+ // ../package/dist/core/helpers/getOperatorStringFromMethod.js
248873
+ var require_getOperatorStringFromMethod = __commonJS((exports) => {
248874
+ Object.defineProperty(exports, "__esModule", { value: true });
248875
+ exports.getOperatorStringFromMethod = getOperatorStringFromMethod;
248876
+ var ts_morph_1 = require_ts_morph();
248877
+ function getOperatorStringFromMethod(method) {
248878
+ const nameNode = method.getNameNode();
248879
+ if (nameNode.isKind(ts_morph_1.SyntaxKind.ComputedPropertyName)) {
248880
+ const expression = nameNode.getExpression();
248881
+ if (expression.isKind(ts_morph_1.SyntaxKind.StringLiteral)) {
248882
+ return expression.getLiteralValue();
248883
+ }
248884
+ const literalValue = expression.getType().getLiteralValue();
248885
+ if (typeof literalValue === "string") {
248886
+ return literalValue;
248887
+ }
248888
+ } else if (nameNode.isKind(ts_morph_1.SyntaxKind.StringLiteral)) {
248889
+ return nameNode.getLiteralValue();
248890
+ }
248891
+ return;
248892
+ }
248893
+ });
248894
+
248872
248895
  // ../package/dist/core/helpers/getOperatorStringFromProperty.js
248873
248896
  var require_getOperatorStringFromProperty = __commonJS((exports) => {
248874
248897
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -248899,7 +248922,9 @@ var require_resolveExpressionType = __commonJS((exports) => {
248899
248922
  exports.resolveExpressionType = resolveExpressionType;
248900
248923
  var ts_morph_1 = require_ts_morph();
248901
248924
  function normalizeTypeName(typeName) {
248902
- return typeName.replace(/import\("[^"]*"\)\./g, "");
248925
+ const withoutImport = typeName.replace(/import\("[^"]*"\)\./g, "");
248926
+ const genericIdx = withoutImport.indexOf("<");
248927
+ return genericIdx === -1 ? withoutImport : withoutImport.slice(0, genericIdx);
248903
248928
  }
248904
248929
  function resolveExpressionType(node) {
248905
248930
  var _a;
@@ -249298,7 +249323,7 @@ var require_OverloadInjector = __commonJS((exports) => {
249298
249323
  const overloadDesc = this._overloadStore.findOverload(operatorKind, leftType, rightType);
249299
249324
  if (!overloadDesc)
249300
249325
  continue;
249301
- const { className: classNameRaw, classFilePath, operatorString, index, isStatic } = overloadDesc;
249326
+ const { className: classNameRaw, classFilePath, operatorString, isStatic } = overloadDesc;
249302
249327
  const classSourceFile = this._project.getSourceFileOrThrow(classFilePath);
249303
249328
  const classDecl = classSourceFile.getClassOrThrow(classNameRaw);
249304
249329
  const classSymbol = classDecl.getSymbol();
@@ -249306,7 +249331,7 @@ var require_OverloadInjector = __commonJS((exports) => {
249306
249331
  throw new Error(`No symbol for class "${classNameRaw}"`);
249307
249332
  const classModuleSpecifier = (0, getModuleSpecifier_1.getModuleSpecifier)(sourceFile, classSourceFile);
249308
249333
  const className = (0, ensureImportedName_1.ensureImportedName)(sourceFile, classSymbol, classModuleSpecifier);
249309
- const overloadCall = isStatic ? `${className}["${operatorString}"][${index}](${lhs.getText()}, ${rhs.getText()})` : `${lhs.getText()}["${operatorString}"][${index}].call(${lhs.getText()}, ${rhs.getText()})`;
249334
+ const overloadCall = isStatic ? `${className}["${operatorString}"](${lhs.getText()}, ${rhs.getText()})` : `${lhs.getText()}["${operatorString}"](${rhs.getText()})`;
249310
249335
  this._logger.debug(`${fileName}: ${expression.getText()} => ${overloadCall}`);
249311
249336
  expression.replaceWithText(overloadCall);
249312
249337
  transformCount++;
@@ -249328,7 +249353,7 @@ var require_OverloadInjector = __commonJS((exports) => {
249328
249353
  const overloadDesc = this._overloadStore.findPrefixUnaryOverload(operatorKind, operandType);
249329
249354
  if (!overloadDesc)
249330
249355
  continue;
249331
- const { className: classNameRaw, classFilePath, operatorString, index } = overloadDesc;
249356
+ const { className: classNameRaw, classFilePath, operatorString } = overloadDesc;
249332
249357
  const classSourceFile = this._project.getSourceFileOrThrow(classFilePath);
249333
249358
  const classDecl = classSourceFile.getClassOrThrow(classNameRaw);
249334
249359
  const classSymbol = classDecl.getSymbol();
@@ -249336,7 +249361,7 @@ var require_OverloadInjector = __commonJS((exports) => {
249336
249361
  throw new Error(`No symbol for class "${classNameRaw}"`);
249337
249362
  const classModuleSpecifier = (0, getModuleSpecifier_1.getModuleSpecifier)(sourceFile, classSourceFile);
249338
249363
  const className = (0, ensureImportedName_1.ensureImportedName)(sourceFile, classSymbol, classModuleSpecifier);
249339
- const overloadCall = `${className}["${operatorString}"][${index}](${operand.getText()})`;
249364
+ const overloadCall = `${className}["${operatorString}"](${operand.getText()})`;
249340
249365
  this._logger.debug(`${fileName}: ${expression.getText()} => ${overloadCall}`);
249341
249366
  expression.replaceWithText(overloadCall);
249342
249367
  transformCount++;
@@ -249358,8 +249383,8 @@ var require_OverloadInjector = __commonJS((exports) => {
249358
249383
  const overloadDesc = this._overloadStore.findPostfixUnaryOverload(operatorKind, operandType);
249359
249384
  if (!overloadDesc)
249360
249385
  continue;
249361
- const { operatorString, index } = overloadDesc;
249362
- const overloadCall = `${operand.getText()}["${operatorString}"][${index}].call(${operand.getText()})`;
249386
+ const { operatorString } = overloadDesc;
249387
+ const overloadCall = `${operand.getText()}["${operatorString}"]()`;
249363
249388
  this._logger.debug(`${fileName}: ${expression.getText()} => ${overloadCall}`);
249364
249389
  expression.replaceWithText(overloadCall);
249365
249390
  transformCount++;
@@ -249387,9 +249412,8 @@ var require_OverloadStore = __commonJS((exports) => {
249387
249412
  var ts_morph_1 = require_ts_morph();
249388
249413
  var operatorSymbols_1 = require_operatorSymbols();
249389
249414
  var ErrorManager_1 = require_ErrorManager();
249390
- var getOperatorStringFromProperty_1 = require_getOperatorStringFromProperty();
249415
+ var getOperatorStringFromMethod_1 = require_getOperatorStringFromMethod();
249391
249416
  var resolveExpressionType_1 = require_resolveExpressionType();
249392
- var unwrapInitializer_1 = require_unwrapInitializer();
249393
249417
  var operatorMap_1 = require_operatorMap();
249394
249418
 
249395
249419
  class OverloadStore extends Map {
@@ -249509,15 +249533,29 @@ var require_OverloadStore = __commonJS((exports) => {
249509
249533
  this._parsedFiles.add(filePath);
249510
249534
  const classes = sourceFile.getClasses();
249511
249535
  classes.forEach((classDecl) => {
249536
+ const className = classDecl.getName();
249537
+ if (!className)
249538
+ return;
249512
249539
  const classType = (0, resolveExpressionType_1.normalizeTypeName)(classDecl.getType().getText());
249513
- classDecl.getProperties().forEach((property) => {
249514
- var _a, _b;
249515
- if (!ts_morph_1.Node.isPropertyDeclaration(property))
249516
- return;
249517
- const isStatic = property.isStatic();
249518
- const operatorString = (0, getOperatorStringFromProperty_1.getOperatorStringFromProperty)(property);
249540
+ const methodGroups = new Map;
249541
+ for (const method of classDecl.getMethods()) {
249542
+ const operatorString = (0, getOperatorStringFromMethod_1.getOperatorStringFromMethod)(method);
249519
249543
  if (!operatorString || !operatorSymbols_1.operatorSymbols.includes(operatorString))
249544
+ continue;
249545
+ let group = methodGroups.get(operatorString);
249546
+ if (!group) {
249547
+ group = [];
249548
+ methodGroups.set(operatorString, group);
249549
+ }
249550
+ const overloadSigs = method.getOverloads();
249551
+ group.push(...overloadSigs.length > 0 ? overloadSigs : [method]);
249552
+ }
249553
+ methodGroups.forEach((methods, operatorString) => {
249554
+ const overloadSigs = methods.filter((m) => !m.hasBody());
249555
+ const sigsToProcess = overloadSigs.length > 0 ? overloadSigs : methods;
249556
+ if (sigsToProcess.length === 0)
249520
249557
  return;
249558
+ const isStatic = sigsToProcess[0].isStatic();
249521
249559
  const binarySyntaxKind = operatorMap_1.operatorMap[operatorString];
249522
249560
  const prefixUnarySyntaxKind = operatorMap_1.prefixUnaryOperatorMap[operatorString];
249523
249561
  const postfixUnarySyntaxKind = operatorMap_1.postfixUnaryOperatorMap[operatorString];
@@ -249526,93 +249564,74 @@ var require_OverloadStore = __commonJS((exports) => {
249526
249564
  const shouldBeStatic = binarySyntaxKind != null && !operatorMap_1.instanceOperators.has(binarySyntaxKind) || prefixUnarySyntaxKind != null;
249527
249565
  const shouldBeInstance = binarySyntaxKind != null && operatorMap_1.instanceOperators.has(binarySyntaxKind) || postfixUnarySyntaxKind != null;
249528
249566
  if (isStatic && !shouldBeStatic || !isStatic && !shouldBeInstance) {
249529
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Expected overload for operator ${operatorString} ` + `to be ${isStatic ? "a static" : "an instance"} field.`, property.getSourceFile().getFilePath(), property.getStartLineNumber(), property.getText().split(`
249530
- `)[0]));
249531
- return;
249532
- }
249533
- const rawInitializer = property.getInitializer();
249534
- if (!rawInitializer) {
249535
- this._addOverloadsFromTypeAnnotation(property, classDecl, classType, filePath, isStatic, operatorString, binarySyntaxKind, prefixUnarySyntaxKind, postfixUnarySyntaxKind);
249567
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Expected overload for operator "${operatorString}" ` + `to be ${isStatic ? "a static" : "an instance"} method.`, sigsToProcess[0].getSourceFile().getFilePath(), sigsToProcess[0].getStartLineNumber(), this._minifyString(sigsToProcess[0].getText().split(`
249568
+ `)[0])));
249536
249569
  return;
249537
249570
  }
249538
- const hasAsConst = ts_morph_1.Node.isAsExpression(rawInitializer) && ((_a = rawInitializer.getTypeNode()) === null || _a === undefined ? undefined : _a.getText()) === "const";
249539
- const initializer3 = (0, unwrapInitializer_1.unwrapInitializer)(rawInitializer);
249540
- if (!initializer3 || !ts_morph_1.Node.isArrayLiteralExpression(initializer3)) {
249541
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload field for operator ${operatorString} ` + "must be an array of overload functions.", property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(property.getName())));
249542
- return;
249543
- }
249544
- if (!hasAsConst) {
249545
- this._errorManager.addError(new ErrorManager_1.ErrorDescription(`Overload array for operator ${operatorString} must use "as const". ` + "Without it, TypeScript widens the array type and loses individual " + "function signatures, causing type errors in generated code.", property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString((_b = property.getText().split(`
249546
- `)[0]) !== null && _b !== undefined ? _b : "")));
249547
- return;
249548
- }
249549
- initializer3.getElements().forEach((element, index) => {
249550
- if (element.isKind(ts_morph_1.SyntaxKind.ArrowFunction) && !isStatic) {
249551
- this._errorManager.addError(new ErrorManager_1.ErrorDescription(`Overload ${index} for operator ${operatorString} must not be an arrow function. ` + "Use a function expression instead, as arrow functions cannot bind `this` correctly for instance operators.", element.getSourceFile().getFilePath(), element.getStartLineNumber(), this._minifyString(element.getText())));
249552
- return;
249553
- }
249554
- if (!element.isKind(ts_morph_1.SyntaxKind.FunctionExpression) && !element.isKind(ts_morph_1.SyntaxKind.FunctionDeclaration) && !element.isKind(ts_morph_1.SyntaxKind.ArrowFunction)) {
249555
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Expected overload ${index} for operator ${operatorString} to be a function.`, element.getSourceFile().getFilePath(), element.getStartLineNumber(), this._minifyString(element.getText())));
249556
- return;
249557
- }
249558
- const funcElement = element;
249559
- const parameters = funcElement.getParameters().filter((p) => p.getName() !== "this");
249571
+ sigsToProcess.forEach((method) => {
249572
+ const parameters = method.getParameters().filter((p) => p.getName() !== "this");
249560
249573
  const paramCount = parameters.length;
249561
249574
  if (paramCount === 2 && isStatic && binarySyntaxKind && !operatorMap_1.instanceOperators.has(binarySyntaxKind)) {
249562
- this._addBinaryOverload(binarySyntaxKind, classDecl, classType, filePath, property, funcElement, parameters, operatorString, index, true);
249575
+ this._addBinaryOverload(binarySyntaxKind, className, classType, filePath, method, parameters, operatorString, true);
249563
249576
  } else if (paramCount === 1 && !isStatic && binarySyntaxKind && operatorMap_1.instanceOperators.has(binarySyntaxKind)) {
249564
- this._addBinaryOverload(binarySyntaxKind, classDecl, classType, filePath, property, funcElement, parameters, operatorString, index, false);
249577
+ this._addBinaryOverload(binarySyntaxKind, className, classType, filePath, method, parameters, operatorString, false);
249565
249578
  } else if (paramCount === 1 && isStatic && prefixUnarySyntaxKind) {
249566
- this._addPrefixUnaryOverload(prefixUnarySyntaxKind, classDecl, classType, filePath, property, funcElement, parameters, operatorString, index);
249579
+ this._addPrefixUnaryOverload(prefixUnarySyntaxKind, className, classType, filePath, method, parameters, operatorString);
249567
249580
  } else if (paramCount === 0 && !isStatic && postfixUnarySyntaxKind) {
249568
- this._addPostfixUnaryOverload(postfixUnarySyntaxKind, classDecl, classType, filePath, property, funcElement, operatorString, index);
249581
+ this._addPostfixUnaryOverload(postfixUnarySyntaxKind, className, classType, filePath, method, operatorString);
249569
249582
  } else {
249570
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload function ${index} for operator ${operatorString} ` + `has invalid parameter count (${paramCount}) for this operator context.`, property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(funcElement.getText())));
249583
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload signature for operator "${operatorString}" ` + `has invalid parameter count (${paramCount}) for this operator context.`, method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249584
+ `)[0])));
249571
249585
  }
249572
249586
  });
249573
249587
  });
249574
249588
  });
249575
249589
  }
249576
- _addBinaryOverload(syntaxKind, classDecl, classType, filePath, property, element, parameters, operatorString, index, isStatic) {
249577
- var _a, _b, _c, _d, _e, _f, _g, _h;
249590
+ _addBinaryOverload(syntaxKind, className, classType, filePath, method, parameters, operatorString, isStatic) {
249591
+ var _a, _b;
249578
249592
  let hasWarning = false;
249579
- const lhsType = isStatic ? (0, resolveExpressionType_1.normalizeTypeName)((_b = (_a = parameters[0]) === null || _a === undefined ? undefined : _a.getType().getText()) !== null && _b !== undefined ? _b : "") : classType;
249580
- const rhsType = isStatic ? (0, resolveExpressionType_1.normalizeTypeName)((_d = (_c = parameters[1]) === null || _c === undefined ? undefined : _c.getType().getText()) !== null && _d !== undefined ? _d : "") : (0, resolveExpressionType_1.normalizeTypeName)((_f = (_e = parameters[0]) === null || _e === undefined ? undefined : _e.getType().getText()) !== null && _f !== undefined ? _f : "");
249593
+ const getParamTypeName = (p) => {
249594
+ var _a2, _b2, _c;
249595
+ return (0, resolveExpressionType_1.normalizeTypeName)((_c = (_b2 = (_a2 = p === null || p === undefined ? undefined : p.getTypeNode()) === null || _a2 === undefined ? undefined : _a2.getText()) !== null && _b2 !== undefined ? _b2 : p === null || p === undefined ? undefined : p.getType().getText()) !== null && _c !== undefined ? _c : "");
249596
+ };
249597
+ const lhsType = isStatic ? getParamTypeName(parameters[0]) : classType;
249598
+ const rhsType = isStatic ? getParamTypeName(parameters[1]) : getParamTypeName(parameters[0]);
249581
249599
  if (isStatic && lhsType !== classType && rhsType !== classType) {
249582
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload for operator ${operatorString} ` + "must have either LHS or RHS parameter matching its class type.", property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(element.getText())));
249600
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload for operator "${operatorString}" ` + "must have either LHS or RHS parameter matching its class type.", method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249601
+ `)[0])));
249583
249602
  hasWarning = true;
249584
249603
  }
249585
- const returnType = element.getReturnType().getText();
249604
+ const returnType = method.getReturnType().getText();
249586
249605
  if (operatorMap_1.comparisonOperators.has(syntaxKind) && returnType !== "boolean") {
249587
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload function ${index} for comparison operator ${operatorString} ` + `must have a return type of 'boolean', got '${returnType}'.`, property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(element.getText())));
249606
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload for comparison operator "${operatorString}" ` + `must have a return type of 'boolean', got '${returnType}'.`, method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249607
+ `)[0])));
249588
249608
  hasWarning = true;
249589
249609
  }
249590
249610
  if (!isStatic && returnType !== "void") {
249591
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload function ${index} for instance operator ${operatorString} ` + `must have a return type of 'void', got '${returnType}'.`, property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(element.getText())));
249611
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload for instance operator "${operatorString}" ` + `must have a return type of 'void', got '${returnType}'.`, method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249612
+ `)[0])));
249592
249613
  hasWarning = true;
249593
249614
  }
249594
- const operatorOverloads = (_g = this.get(syntaxKind)) !== null && _g !== undefined ? _g : new Map;
249595
- const lhsMap = (_h = operatorOverloads.get(lhsType)) !== null && _h !== undefined ? _h : new Map;
249615
+ const operatorOverloads = (_a = this.get(syntaxKind)) !== null && _a !== undefined ? _a : new Map;
249616
+ const lhsMap = (_b = operatorOverloads.get(lhsType)) !== null && _b !== undefined ? _b : new Map;
249596
249617
  if (lhsMap.has(rhsType)) {
249597
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Duplicate overload for operator ${operatorString} with LHS type ${lhsType} and RHS type ${rhsType}`, property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(element.getText())));
249618
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Duplicate overload for operator "${operatorString}" with LHS type ${lhsType} and RHS type ${rhsType}`, method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249619
+ `)[0])));
249598
249620
  hasWarning = true;
249599
249621
  }
249600
249622
  if (hasWarning)
249601
249623
  return;
249602
249624
  lhsMap.set(rhsType, {
249603
249625
  isStatic,
249604
- className: classDecl.getName(),
249626
+ className,
249605
249627
  classFilePath: filePath,
249606
249628
  operatorString,
249607
- index,
249608
249629
  returnType
249609
249630
  });
249610
249631
  operatorOverloads.set(lhsType, lhsMap);
249611
249632
  this.set(syntaxKind, operatorOverloads);
249612
- const funcName = ts_morph_1.Node.isFunctionExpression(element) ? element.getName() : undefined;
249613
249633
  const sl = this._shortTypeName.bind(this);
249614
- const label = funcName ? `${funcName}(${sl(lhsType)}, ${sl(rhsType)})` : `(${sl(lhsType)}, ${sl(rhsType)})`;
249615
- this._logger.debug(`Loaded ${classDecl.getName()}["${operatorString}"][${index}]: ${label} => ${sl(element.getReturnType().getText())}${isStatic ? " (static)" : " (instance)"}`);
249634
+ this._logger.debug(`Loaded ${className}["${operatorString}"]: (${sl(lhsType)}, ${sl(rhsType)}) => ${sl(returnType)}${isStatic ? " (static)" : " (instance)"}`);
249616
249635
  let fileEntries = this._fileEntries.get(filePath);
249617
249636
  if (!fileEntries) {
249618
249637
  fileEntries = [];
@@ -249620,35 +249639,34 @@ var require_OverloadStore = __commonJS((exports) => {
249620
249639
  }
249621
249640
  fileEntries.push({ syntaxKind, lhsType, rhsType });
249622
249641
  }
249623
- _addPrefixUnaryOverload(syntaxKind, classDecl, classType, filePath, property, element, parameters, operatorString, index) {
249624
- var _a, _b, _c;
249642
+ _addPrefixUnaryOverload(syntaxKind, className, classType, filePath, method, parameters, operatorString) {
249643
+ var _a, _b, _c, _d, _e, _f;
249625
249644
  let hasWarning = false;
249626
- const operandType = (0, resolveExpressionType_1.normalizeTypeName)((_b = (_a = parameters[0]) === null || _a === undefined ? undefined : _a.getType().getText()) !== null && _b !== undefined ? _b : "");
249645
+ const operandType = (0, resolveExpressionType_1.normalizeTypeName)((_e = (_c = (_b = (_a = parameters[0]) === null || _a === undefined ? undefined : _a.getTypeNode()) === null || _b === undefined ? undefined : _b.getText()) !== null && _c !== undefined ? _c : (_d = parameters[0]) === null || _d === undefined ? undefined : _d.getType().getText()) !== null && _e !== undefined ? _e : "");
249627
249646
  if (operandType !== classType) {
249628
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Prefix unary overload for operator ${operatorString} ` + "must have its parameter matching its class type.", property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(element.getText())));
249647
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Prefix unary overload for operator "${operatorString}" ` + "must have its parameter matching its class type.", method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249648
+ `)[0])));
249629
249649
  hasWarning = true;
249630
249650
  }
249631
- const operatorOverloads = (_c = this._prefixUnaryOverloads.get(syntaxKind)) !== null && _c !== undefined ? _c : new Map;
249651
+ const operatorOverloads = (_f = this._prefixUnaryOverloads.get(syntaxKind)) !== null && _f !== undefined ? _f : new Map;
249632
249652
  if (operatorOverloads.has(operandType)) {
249633
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Duplicate prefix unary overload for operator ${operatorString} with operand type ${operandType}`, property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(element.getText())));
249653
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Duplicate prefix unary overload for operator "${operatorString}" with operand type ${operandType}`, method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249654
+ `)[0])));
249634
249655
  hasWarning = true;
249635
249656
  }
249636
249657
  if (hasWarning)
249637
249658
  return;
249638
- const returnType = element.getReturnType().getText();
249659
+ const returnType = method.getReturnType().getText();
249639
249660
  operatorOverloads.set(operandType, {
249640
249661
  isStatic: true,
249641
- className: classDecl.getName(),
249662
+ className,
249642
249663
  classFilePath: filePath,
249643
249664
  operatorString,
249644
- index,
249645
249665
  returnType
249646
249666
  });
249647
249667
  this._prefixUnaryOverloads.set(syntaxKind, operatorOverloads);
249648
- const funcName = ts_morph_1.Node.isFunctionExpression(element) ? element.getName() : undefined;
249649
249668
  const sl = this._shortTypeName.bind(this);
249650
- const label = funcName ? `${funcName}(${sl(operandType)})` : `(${sl(operandType)})`;
249651
- this._logger.debug(`Loaded ${classDecl.getName()}["${operatorString}"][${index}]: ${operatorString}${label} => ${sl(returnType)} (prefix unary)`);
249669
+ this._logger.debug(`Loaded ${className}["${operatorString}"]: ${operatorString}(${sl(operandType)}) => ${sl(returnType)} (prefix unary)`);
249652
249670
  let fileEntries = this._prefixUnaryFileEntries.get(filePath);
249653
249671
  if (!fileEntries) {
249654
249672
  fileEntries = [];
@@ -249656,34 +249674,33 @@ var require_OverloadStore = __commonJS((exports) => {
249656
249674
  }
249657
249675
  fileEntries.push({ syntaxKind, operandType });
249658
249676
  }
249659
- _addPostfixUnaryOverload(syntaxKind, classDecl, classType, filePath, property, element, operatorString, index) {
249677
+ _addPostfixUnaryOverload(syntaxKind, className, classType, filePath, method, operatorString) {
249660
249678
  var _a;
249661
249679
  let hasWarning = false;
249662
- const returnType = element.getReturnType().getText();
249680
+ const returnType = method.getReturnType().getText();
249663
249681
  if (returnType !== "void") {
249664
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload function ${index} for postfix operator ${operatorString} ` + `must have a return type of 'void', got '${returnType}'.`, property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(element.getText())));
249682
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload for postfix operator "${operatorString}" ` + `must have a return type of 'void', got '${returnType}'.`, method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249683
+ `)[0])));
249665
249684
  hasWarning = true;
249666
249685
  }
249667
249686
  const operandType = classType;
249668
249687
  const operatorOverloads = (_a = this._postfixUnaryOverloads.get(syntaxKind)) !== null && _a !== undefined ? _a : new Map;
249669
249688
  if (operatorOverloads.has(operandType)) {
249670
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Duplicate postfix unary overload for operator ${operatorString} with operand type ${operandType}`, property.getSourceFile().getFilePath(), property.getStartLineNumber(), this._minifyString(element.getText())));
249689
+ this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Duplicate postfix unary overload for operator "${operatorString}" with operand type ${operandType}`, method.getSourceFile().getFilePath(), method.getStartLineNumber(), this._minifyString(method.getText().split(`
249690
+ `)[0])));
249671
249691
  hasWarning = true;
249672
249692
  }
249673
249693
  if (hasWarning)
249674
249694
  return;
249675
249695
  operatorOverloads.set(operandType, {
249676
249696
  isStatic: false,
249677
- className: classDecl.getName(),
249697
+ className,
249678
249698
  classFilePath: filePath,
249679
249699
  operatorString,
249680
- index,
249681
249700
  returnType
249682
249701
  });
249683
249702
  this._postfixUnaryOverloads.set(syntaxKind, operatorOverloads);
249684
- const funcName = ts_morph_1.Node.isFunctionExpression(element) ? element.getName() : undefined;
249685
- const label = funcName ? `${funcName}()` : "()";
249686
- this._logger.debug(`Loaded ${classDecl.getName()}["${operatorString}"][${index}]: ${this._shortTypeName(operandType)}${operatorString} ${label} (postfix unary)`);
249703
+ this._logger.debug(`Loaded ${className}["${operatorString}"]: ${this._shortTypeName(operandType)}${operatorString} () (postfix unary)`);
249687
249704
  let fileEntries = this._postfixUnaryFileEntries.get(filePath);
249688
249705
  if (!fileEntries) {
249689
249706
  fileEntries = [];
@@ -249691,155 +249708,6 @@ var require_OverloadStore = __commonJS((exports) => {
249691
249708
  }
249692
249709
  fileEntries.push({ syntaxKind, operandType });
249693
249710
  }
249694
- _addOverloadsFromTypeAnnotation(property, classDecl, classType, filePath, isStatic, operatorString, binarySyntaxKind, prefixUnarySyntaxKind, postfixUnarySyntaxKind) {
249695
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
249696
- const propertyType = property.getType();
249697
- if (!propertyType.isTuple())
249698
- return;
249699
- const tupleElements = propertyType.getTupleElements();
249700
- const className = classDecl.getName();
249701
- if (!className)
249702
- return;
249703
- const sl = this._shortTypeName.bind(this);
249704
- for (let index = 0;index < tupleElements.length; index++) {
249705
- const elementType = tupleElements[index];
249706
- const callSigs = elementType.getCallSignatures();
249707
- if (callSigs.length === 0)
249708
- continue;
249709
- const sig = callSigs[0];
249710
- const params = [];
249711
- for (const sym of sig.getParameters()) {
249712
- const name = sym.getName();
249713
- if (name === "this")
249714
- continue;
249715
- const decl = sym.getValueDeclaration();
249716
- if (!decl)
249717
- continue;
249718
- params.push({
249719
- name,
249720
- type: (0, resolveExpressionType_1.normalizeTypeName)(decl.getType().getText())
249721
- });
249722
- }
249723
- const paramCount = params.length;
249724
- const returnType = sig.getReturnType().getText();
249725
- if (paramCount === 2 && isStatic && binarySyntaxKind && !operatorMap_1.instanceOperators.has(binarySyntaxKind)) {
249726
- const lhsType = params[0].type;
249727
- const rhsType = params[1].type;
249728
- if (lhsType !== classType && rhsType !== classType) {
249729
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload for operator ${operatorString} ` + "must have either LHS or RHS parameter matching its class type.", filePath, property.getStartLineNumber(), this._minifyString((_a = property.getText().split(`
249730
- `)[0]) !== null && _a !== undefined ? _a : "")));
249731
- continue;
249732
- }
249733
- if (operatorMap_1.comparisonOperators.has(binarySyntaxKind) && returnType !== "boolean") {
249734
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload function ${index} for comparison operator ${operatorString} ` + `must have a return type of 'boolean', got '${returnType}'.`, filePath, property.getStartLineNumber(), this._minifyString((_b = property.getText().split(`
249735
- `)[0]) !== null && _b !== undefined ? _b : "")));
249736
- continue;
249737
- }
249738
- const operatorOverloads = (_c = this.get(binarySyntaxKind)) !== null && _c !== undefined ? _c : new Map;
249739
- const lhsMap = (_d = operatorOverloads.get(lhsType)) !== null && _d !== undefined ? _d : new Map;
249740
- if (lhsMap.has(rhsType))
249741
- continue;
249742
- lhsMap.set(rhsType, {
249743
- isStatic: true,
249744
- className,
249745
- classFilePath: filePath,
249746
- operatorString,
249747
- index,
249748
- returnType
249749
- });
249750
- operatorOverloads.set(lhsType, lhsMap);
249751
- this.set(binarySyntaxKind, operatorOverloads);
249752
- this._logger.debug(`Loaded ${className}["${operatorString}"][${index}]: (${sl(lhsType)}, ${sl(rhsType)}) => ${sl(returnType)} (static, from .d.ts)`);
249753
- let fileEntries = this._fileEntries.get(filePath);
249754
- if (!fileEntries) {
249755
- fileEntries = [];
249756
- this._fileEntries.set(filePath, fileEntries);
249757
- }
249758
- fileEntries.push({ syntaxKind: binarySyntaxKind, lhsType, rhsType });
249759
- } else if (paramCount === 1 && !isStatic && binarySyntaxKind && operatorMap_1.instanceOperators.has(binarySyntaxKind)) {
249760
- const lhsType = classType;
249761
- const rhsType = params[0].type;
249762
- if (returnType !== "void") {
249763
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload function ${index} for instance operator ${operatorString} ` + `must have a return type of 'void', got '${returnType}'.`, filePath, property.getStartLineNumber(), this._minifyString((_e = property.getText().split(`
249764
- `)[0]) !== null && _e !== undefined ? _e : "")));
249765
- continue;
249766
- }
249767
- const operatorOverloads = (_f = this.get(binarySyntaxKind)) !== null && _f !== undefined ? _f : new Map;
249768
- const lhsMap = (_g = operatorOverloads.get(lhsType)) !== null && _g !== undefined ? _g : new Map;
249769
- if (lhsMap.has(rhsType))
249770
- continue;
249771
- lhsMap.set(rhsType, {
249772
- isStatic: false,
249773
- className,
249774
- classFilePath: filePath,
249775
- operatorString,
249776
- index,
249777
- returnType
249778
- });
249779
- operatorOverloads.set(lhsType, lhsMap);
249780
- this.set(binarySyntaxKind, operatorOverloads);
249781
- this._logger.debug(`Loaded ${className}["${operatorString}"][${index}]: (${sl(lhsType)}, ${sl(rhsType)}) => void (instance, from .d.ts)`);
249782
- let fileEntries = this._fileEntries.get(filePath);
249783
- if (!fileEntries) {
249784
- fileEntries = [];
249785
- this._fileEntries.set(filePath, fileEntries);
249786
- }
249787
- fileEntries.push({ syntaxKind: binarySyntaxKind, lhsType, rhsType });
249788
- } else if (paramCount === 1 && isStatic && prefixUnarySyntaxKind) {
249789
- const operandType = params[0].type;
249790
- if (operandType !== classType) {
249791
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Prefix unary overload for operator ${operatorString} ` + "must have its parameter matching its class type.", filePath, property.getStartLineNumber(), this._minifyString((_h = property.getText().split(`
249792
- `)[0]) !== null && _h !== undefined ? _h : "")));
249793
- continue;
249794
- }
249795
- const operatorOverloads = (_j = this._prefixUnaryOverloads.get(prefixUnarySyntaxKind)) !== null && _j !== undefined ? _j : new Map;
249796
- if (operatorOverloads.has(operandType))
249797
- continue;
249798
- operatorOverloads.set(operandType, {
249799
- isStatic: true,
249800
- className,
249801
- classFilePath: filePath,
249802
- operatorString,
249803
- index,
249804
- returnType
249805
- });
249806
- this._prefixUnaryOverloads.set(prefixUnarySyntaxKind, operatorOverloads);
249807
- this._logger.debug(`Loaded ${className}["${operatorString}"][${index}]: ${operatorString}(${sl(operandType)}) => ${sl(returnType)} (prefix unary, from .d.ts)`);
249808
- let fileEntries = this._prefixUnaryFileEntries.get(filePath);
249809
- if (!fileEntries) {
249810
- fileEntries = [];
249811
- this._prefixUnaryFileEntries.set(filePath, fileEntries);
249812
- }
249813
- fileEntries.push({ syntaxKind: prefixUnarySyntaxKind, operandType });
249814
- } else if (paramCount === 0 && !isStatic && postfixUnarySyntaxKind) {
249815
- if (returnType !== "void") {
249816
- this._errorManager.addWarning(new ErrorManager_1.ErrorDescription(`Overload function ${index} for postfix operator ${operatorString} ` + `must have a return type of 'void', got '${returnType}'.`, filePath, property.getStartLineNumber(), this._minifyString((_k = property.getText().split(`
249817
- `)[0]) !== null && _k !== undefined ? _k : "")));
249818
- continue;
249819
- }
249820
- const operandType = classType;
249821
- const operatorOverloads = (_l = this._postfixUnaryOverloads.get(postfixUnarySyntaxKind)) !== null && _l !== undefined ? _l : new Map;
249822
- if (operatorOverloads.has(operandType))
249823
- continue;
249824
- operatorOverloads.set(operandType, {
249825
- isStatic: false,
249826
- className,
249827
- classFilePath: filePath,
249828
- operatorString,
249829
- index,
249830
- returnType
249831
- });
249832
- this._postfixUnaryOverloads.set(postfixUnarySyntaxKind, operatorOverloads);
249833
- this._logger.debug(`Loaded ${className}["${operatorString}"][${index}]: ${sl(operandType)}${operatorString} () (postfix unary, from .d.ts)`);
249834
- let fileEntries = this._postfixUnaryFileEntries.get(filePath);
249835
- if (!fileEntries) {
249836
- fileEntries = [];
249837
- this._postfixUnaryFileEntries.set(filePath, fileEntries);
249838
- }
249839
- fileEntries.push({ syntaxKind: postfixUnarySyntaxKind, operandType });
249840
- }
249841
- }
249842
- }
249843
249711
  _getTypeChain(typeName) {
249844
249712
  var _a, _b;
249845
249713
  const cached2 = this._typeChainCache.get(typeName);
@@ -250085,7 +249953,7 @@ var require_validateExports = __commonJS((exports) => {
250085
249953
  // ../package/dist/index.js
250086
249954
  var require_dist4 = __commonJS((exports) => {
250087
249955
  Object.defineProperty(exports, "__esModule", { value: true });
250088
- exports.SyntaxKind = exports.Project = exports.Node = exports.operatorSymbols = exports.Operator = exports.validateExports = exports.toV3SourceMap = exports.computeEdits = exports.isPrefixUnaryOperatorSyntaxKind = exports.isPostfixUnaryOperatorSyntaxKind = exports.isOperatorSyntaxKind = exports.OverloadStore = exports.OverloadInjector = exports.unwrapInitializer = exports.resolveExpressionType = exports.getOperatorStringFromProperty = exports.ErrorManager = exports.ErrorDescription = exports.loadConfig = exports.ConsoleLogger = undefined;
249956
+ exports.SyntaxKind = exports.Project = exports.Node = exports.operatorSymbols = exports.Operator = exports.validateExports = exports.toV3SourceMap = exports.computeEdits = exports.isPrefixUnaryOperatorSyntaxKind = exports.isPostfixUnaryOperatorSyntaxKind = exports.isOperatorSyntaxKind = exports.OverloadStore = exports.OverloadInjector = exports.unwrapInitializer = exports.resolveExpressionType = exports.getOperatorStringFromProperty = exports.getOperatorStringFromMethod = exports.ErrorManager = exports.ErrorDescription = exports.loadConfig = exports.ConsoleLogger = undefined;
250089
249957
  var BopConfig_1 = require_BopConfig();
250090
249958
  Object.defineProperty(exports, "ConsoleLogger", { enumerable: true, get: function() {
250091
249959
  return BopConfig_1.ConsoleLogger;
@@ -250100,6 +249968,10 @@ var require_dist4 = __commonJS((exports) => {
250100
249968
  Object.defineProperty(exports, "ErrorManager", { enumerable: true, get: function() {
250101
249969
  return ErrorManager_1.ErrorManager;
250102
249970
  } });
249971
+ var getOperatorStringFromMethod_1 = require_getOperatorStringFromMethod();
249972
+ Object.defineProperty(exports, "getOperatorStringFromMethod", { enumerable: true, get: function() {
249973
+ return getOperatorStringFromMethod_1.getOperatorStringFromMethod;
249974
+ } });
250103
249975
  var getOperatorStringFromProperty_1 = require_getOperatorStringFromProperty();
250104
249976
  Object.defineProperty(exports, "getOperatorStringFromProperty", { enumerable: true, get: function() {
250105
249977
  return getOperatorStringFromProperty_1.getOperatorStringFromProperty;
@@ -263293,58 +263165,48 @@ var postfixUnaryOperatorStrings = new Set(["++", "--"]);
263293
263165
  function generateOverloadProperty(className, operator) {
263294
263166
  if (postfixUnaryOperatorStrings.has(operator)) {
263295
263167
  return [
263296
- ` public readonly "${operator}" = [`,
263297
- ` function (this: ${className}): void {`,
263298
- "\t\t\t// TODO: implement",
263299
- "\t\t},",
263300
- "\t] as const;"
263168
+ ` public "${operator}"(): void {`,
263169
+ "\t\t// TODO: implement",
263170
+ "\t}"
263301
263171
  ].join(`
263302
263172
  `);
263303
263173
  }
263304
263174
  if (exclusivePrefixUnaryStrings.has(operator)) {
263305
263175
  return [
263306
- ` public static readonly "${operator}" = [`,
263307
- ` (a: ${className}): ${className} => {`,
263308
- "\t\t\t// TODO: implement",
263309
- ` return new ${className}();`,
263310
- "\t\t},",
263311
- "\t] as const;"
263176
+ ` public static "${operator}"(a: ${className}): ${className} {`,
263177
+ "\t\t// TODO: implement",
263178
+ ` return new ${className}();`,
263179
+ "\t}"
263312
263180
  ].join(`
263313
263181
  `);
263314
263182
  }
263315
263183
  if (instanceOperatorStrings.has(operator)) {
263316
263184
  return [
263317
- ` public readonly "${operator}" = [`,
263318
- ` function (this: ${className}, other: ${className}): void {`,
263319
- "\t\t\t// TODO: implement",
263320
- "\t\t},",
263321
- "\t] as const;"
263185
+ ` public "${operator}"(other: ${className}): void {`,
263186
+ "\t\t// TODO: implement",
263187
+ "\t}"
263322
263188
  ].join(`
263323
263189
  `);
263324
263190
  }
263325
263191
  if (comparisonOperatorStrings.has(operator)) {
263326
263192
  return [
263327
- ` public static readonly "${operator}" = [`,
263328
- ` (a: ${className}, b: ${className}): boolean => {`,
263329
- "\t\t\t// TODO: implement",
263330
- "\t\t\treturn false;",
263331
- "\t\t},",
263332
- "\t] as const;"
263193
+ ` public static "${operator}"(a: ${className}, b: ${className}): boolean {`,
263194
+ "\t\t// TODO: implement",
263195
+ "\t\treturn false;",
263196
+ "\t}"
263333
263197
  ].join(`
263334
263198
  `);
263335
263199
  }
263336
263200
  return [
263337
- ` public static readonly "${operator}" = [`,
263338
- ` (a: ${className}, b: ${className}): ${className} => {`,
263339
- "\t\t\t// TODO: implement",
263340
- ` return new ${className}();`,
263341
- "\t\t},",
263342
- "\t] as const;"
263201
+ ` public static "${operator}"(a: ${className}, b: ${className}): ${className} {`,
263202
+ "\t\t// TODO: implement",
263203
+ ` return new ${className}();`,
263204
+ "\t}"
263343
263205
  ].join(`
263344
263206
  `);
263345
263207
  }
263346
263208
  server2.registerTool("scaffold_overloads", {
263347
- description: "Generate TypeScript boilerplate for operator overload definitions on a class. " + "Returns code ready to paste into a class body, with correct static/instance " + "placement, as const assertions, and this parameters for instance operators.",
263209
+ description: "Generate TypeScript boilerplate for operator overload definitions on a class. " + "Returns code ready to paste into a class body, with correct static/instance " + "placement and parameter types.",
263348
263210
  inputSchema: {
263349
263211
  className: exports_external.string().describe("The class name to generate overloads for."),
263350
263212
  operators: exports_external.array(exports_external.string()).describe(`Array of operator strings. Valid operators: ${import_boperators2.operatorSymbols.join(", ")}`)
@@ -263384,7 +263246,7 @@ function createCapturingLogger(warnings) {
263384
263246
  };
263385
263247
  }
263386
263248
  server2.registerTool("validate_overloads", {
263387
- description: "Validate operator overload definitions in a single file. " + "Returns structured diagnostics: errors (wrong arity, bad types, missing as const) " + "and warnings (e.g. conflicting overloads). Does not transform the file.",
263249
+ description: "Validate operator overload definitions in a single file. " + "Returns structured diagnostics: errors (wrong arity, bad types) " + "and warnings (e.g. conflicting overloads). Does not transform the file.",
263388
263250
  inputSchema: {
263389
263251
  tsconfig: exports_external.string().describe("Absolute path to tsconfig.json for the project."),
263390
263252
  filePath: exports_external.string().describe("Absolute path to the TypeScript file to validate.")
@@ -263436,75 +263298,83 @@ server2.registerTool("validate_overloads", {
263436
263298
  };
263437
263299
  }
263438
263300
  });
263439
- var instanceCallPattern = /\["([^"]+)"\]\[(\d+)\]\.call\(/;
263440
- var staticCallPattern = /^(\w+)\["([^"]+)"\]\[(\d+)\]\(/;
263301
+ var postfixCallPattern = /\["([^"]+)"\]\(\)$/;
263302
+ var instanceCallPattern = /^([a-z_$]\w*)\["([^"]+)"\]\(/;
263303
+ var staticCallPattern = /^([A-Z]\w*)\["([^"]+)"\]\(/;
263441
263304
  server2.registerTool("explain_expression", {
263442
- description: "Explain a transformed boperators expression. " + 'Given an expression like Vector3["+"][0](a, b) or v["++"][0].call(v), ' + "identifies the operator kind, class, and overload entry. " + "Optionally looks up full overload metadata when tsconfig is provided.",
263305
+ description: "Explain a transformed boperators expression. " + 'Given an expression like Vec2["+"](a, b) or a["+="](b) or a["++"](), ' + "identifies the operator kind, class, and overload entry. " + "Optionally looks up full overload metadata when tsconfig is provided.",
263443
263306
  inputSchema: {
263444
- expression: exports_external.string().describe(`The transformed expression to explain, e.g. 'Vector3["+"][0](a, b)'.`),
263307
+ expression: exports_external.string().describe(`The transformed expression to explain, e.g. 'Vec2["+"](a, b)'.`),
263445
263308
  tsconfig: exports_external.string().optional().describe("Absolute path to tsconfig.json. When provided, the overload is looked up " + "in the project for richer metadata (file path, parameter types).")
263446
263309
  }
263447
263310
  }, async ({ expression, tsconfig }) => {
263448
263311
  try {
263449
263312
  const trimmed = expression.trim();
263313
+ const postfixMatch = trimmed.match(postfixCallPattern);
263314
+ if (postfixMatch) {
263315
+ const [, operator] = postfixMatch;
263316
+ const result = {
263317
+ kind: "postfix unary",
263318
+ operator,
263319
+ isStatic: false,
263320
+ originalExpression: `operand${operator}`,
263321
+ explanation: `Postfix unary operator "${operator}": mutates the operand in place.`
263322
+ };
263323
+ if (tsconfig) {
263324
+ const overloadInfo = lookupOverload(tsconfig, operator, false);
263325
+ if (overloadInfo)
263326
+ Object.assign(result, overloadInfo);
263327
+ }
263328
+ return {
263329
+ content: [
263330
+ { type: "text", text: JSON.stringify(result, null, 2) }
263331
+ ]
263332
+ };
263333
+ }
263450
263334
  const instanceMatch = trimmed.match(instanceCallPattern);
263451
263335
  if (instanceMatch) {
263452
- const [, operator, indexStr] = instanceMatch;
263453
- const index = Number.parseInt(indexStr, 10);
263454
- const callArgs = trimmed.slice(trimmed.indexOf(".call(") + 6, trimmed.lastIndexOf(")"));
263455
- const hasSecondArg = callArgs.includes(",");
263456
- const kind = hasSecondArg ? "instance binary" : "postfix unary";
263457
- const originalPattern = hasSecondArg ? `lhs ${operator} rhs` : `operand${operator}`;
263336
+ const [, , operator] = instanceMatch;
263458
263337
  const result = {
263459
- kind,
263338
+ kind: "instance binary",
263460
263339
  operator,
263461
- index,
263462
263340
  isStatic: false,
263463
- originalExpression: originalPattern,
263464
- explanation: hasSecondArg ? `Instance binary operator "${operator}": mutates the left-hand side in place (e.g. compound assignment).` : `Postfix unary operator "${operator}": mutates the operand in place.`
263341
+ originalExpression: `lhs ${operator} rhs`,
263342
+ explanation: `Instance binary operator "${operator}": mutates the left-hand side in place (e.g. compound assignment).`
263465
263343
  };
263466
263344
  if (tsconfig) {
263467
- const overloadInfo = lookupOverload(tsconfig, operator, index, false);
263345
+ const overloadInfo = lookupOverload(tsconfig, operator, false);
263468
263346
  if (overloadInfo)
263469
263347
  Object.assign(result, overloadInfo);
263470
263348
  }
263471
263349
  return {
263472
263350
  content: [
263473
- {
263474
- type: "text",
263475
- text: JSON.stringify(result, null, 2)
263476
- }
263351
+ { type: "text", text: JSON.stringify(result, null, 2) }
263477
263352
  ]
263478
263353
  };
263479
263354
  }
263480
263355
  const staticMatch = trimmed.match(staticCallPattern);
263481
263356
  if (staticMatch) {
263482
- const [, className, operator, indexStr] = staticMatch;
263483
- const index = Number.parseInt(indexStr, 10);
263357
+ const [, className, operator] = staticMatch;
263484
263358
  const argsStr = trimmed.slice(trimmed.indexOf("](") + 2, trimmed.lastIndexOf(")"));
263485
- const argCount = argsStr.split(",").length;
263359
+ const argCount = argsStr.trim() === "" ? 0 : argsStr.split(",").length;
263486
263360
  const kind = argCount >= 2 ? "static binary" : "prefix unary";
263487
263361
  const originalPattern = argCount >= 2 ? `lhs ${operator} rhs` : `${operator}operand`;
263488
263362
  const result = {
263489
263363
  kind,
263490
263364
  operator,
263491
- index,
263492
263365
  className,
263493
263366
  isStatic: true,
263494
263367
  originalExpression: originalPattern,
263495
263368
  explanation: argCount >= 2 ? `Static binary operator "${operator}": returns a new value from two operands.` : `Prefix unary operator "${operator}": returns a new value from a single operand.`
263496
263369
  };
263497
263370
  if (tsconfig) {
263498
- const overloadInfo = lookupOverload(tsconfig, operator, index, true, className);
263371
+ const overloadInfo = lookupOverload(tsconfig, operator, true, className);
263499
263372
  if (overloadInfo)
263500
263373
  Object.assign(result, overloadInfo);
263501
263374
  }
263502
263375
  return {
263503
263376
  content: [
263504
- {
263505
- type: "text",
263506
- text: JSON.stringify(result, null, 2)
263507
- }
263377
+ { type: "text", text: JSON.stringify(result, null, 2) }
263508
263378
  ]
263509
263379
  };
263510
263380
  }
@@ -263513,8 +263383,9 @@ server2.registerTool("explain_expression", {
263513
263383
  {
263514
263384
  type: "text",
263515
263385
  text: `Could not parse expression as a boperators transformed call. ` + `Expected patterns:
263516
- ` + ` Static: ClassName["op"][index](args)
263517
- ` + ` Instance: expr["op"][index].call(expr, args)`
263386
+ ` + ` Static: ClassName["op"](args)
263387
+ ` + ` Instance: expr["op"](other)
263388
+ ` + ` Postfix: expr["op"]()`
263518
263389
  }
263519
263390
  ],
263520
263391
  isError: true
@@ -263531,15 +263402,13 @@ server2.registerTool("explain_expression", {
263531
263402
  };
263532
263403
  }
263533
263404
  });
263534
- function lookupOverload(tsconfig, operator, index, isStatic, className) {
263405
+ function lookupOverload(tsconfig, operator, isStatic, className) {
263535
263406
  try {
263536
263407
  projectManager.initialize(tsconfig);
263537
263408
  const allOverloads = projectManager.overloadStore.getAllOverloads();
263538
263409
  const match = allOverloads.find((o) => {
263539
263410
  if (o.operatorString !== operator)
263540
263411
  return false;
263541
- if (o.index !== index)
263542
- return false;
263543
263412
  if (className && o.className !== className)
263544
263413
  return false;
263545
263414
  if (o.isStatic !== isStatic)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boperators/mcp-server",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "license": "MIT",
5
5
  "description": "MCP server for boperators - gives AI assistants access to operator overload information.",
6
6
  "repository": {
@@ -42,7 +42,7 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "@modelcontextprotocol/sdk": "^1.12.1",
45
- "boperators": "0.2.1",
45
+ "boperators": "0.3.1",
46
46
  "zod": "^3.25.0"
47
47
  },
48
48
  "devDependencies": {