diff --git a/src/native-compiler-lib.ts b/src/native-compiler-lib.ts index 2785f144..28262ad5 100644 --- a/src/native-compiler-lib.ts +++ b/src/native-compiler-lib.ts @@ -2,7 +2,7 @@ // This file is compiled by ChadScript itself, so it uses the native runtime // declarations rather than Node.js imports. import { parseSource } from "./parser-native/index.js"; -import { transformTree } from "./parser-native/transformer.js"; +import { transformTree, setCurrentFile } from "./parser-native/transformer.js"; import { LLVMGenerator, LLVMGeneratorOptions, SemaSymbolData } from "./codegen/llvm-generator.js"; import { SemanticAnalyzer } from "./analysis/semantic-analyzer.js"; import { AST, ImportDeclaration, FunctionNode, ClassNode, ClassMethod } from "./ast/types.js"; @@ -176,6 +176,7 @@ export function parseFileToAST(inputFile: string): string { __gc_disable(); const absPath = path.resolve(inputFile); const code = fs.readFileSync(absPath); + setCurrentFile(absPath); const tree = parseSource(code); const ast = transformTree(tree); @@ -618,6 +619,7 @@ export function compileMultiFile(entryFile: string, compiledFiles: string[]): AS console.log("Parsing: " + absPath); } const code = fs.readFileSync(absPath); + setCurrentFile(absPath); const tree = parseSource(code); const ast = transformTree(tree); diff --git a/src/parser-native/transformer.ts b/src/parser-native/transformer.ts index cb5a8110..efe1f3ce 100644 --- a/src/parser-native/transformer.ts +++ b/src/parser-native/transformer.ts @@ -72,6 +72,20 @@ function getExprType(expr: Expression | null | undefined): string { return (expr as ExprBase).type; } +let currentFile = ""; + +export function setCurrentFile(file: string): void { + currentFile = file; +} + +function getLineFromIndex(source: string, index: number): number { + let line = 1; + for (let i = 0; i < index && i < source.length; i++) { + if (source[i] === "\n") line = line + 1; + } + return line; +} + export function transformTree(tree: TreeSitterTree): AST { return transformProgram(tree.rootNode); } @@ -2684,14 +2698,31 @@ function transformClassMethod(node: TreeSitterNode): ClassMethod | null { const bodyNode = getChildByFieldName(node, "body"); const returnTypeNode = getChildByFieldName(node, "return_type"); - // Detect static keyword (unnamed child) let isStatic = false; + let accessorKind = ""; for (let i = 0; i < node.childCount; i++) { const child = getChild(node, i); - if (child && !(child as NodeBase).isNamed && (child as NodeBase).type === "static") { - isStatic = true; - break; - } + if (child && !(child as NodeBase).isNamed) { + const childType = (child as NodeBase).type; + if (childType === "static") isStatic = true; + else if (childType === "get" || childType === "set") accessorKind = childType; + } + } + + if (accessorKind !== "") { + const nameText = nameNode ? (nameNode as NodeBase).text : "?"; + const line = getLineFromIndex((node as NodeBase).source, (node as NodeBase).startIndex); + console.error( + currentFile + + ":" + + line + + ": error: '" + + accessorKind + + " " + + nameText + + "()' is not supported; use a regular public method instead", + ); + process.exit(1); } const name = nameNode ? (nameNode as NodeBase).text : ""; diff --git a/src/parser-ts/handlers/declarations.ts b/src/parser-ts/handlers/declarations.ts index 3b50fa0d..eb33316c 100644 --- a/src/parser-ts/handlers/declarations.ts +++ b/src/parser-ts/handlers/declarations.ts @@ -129,16 +129,14 @@ export function transformClassDeclaration( methods.push(result.method); fields.push(...result.parameterProperties); } - } else if (ts.isGetAccessorDeclaration(member)) { - const method = transformAccessorDeclaration(member, checker, "get"); - if (method) { - methods.push(method); - } - } else if (ts.isSetAccessorDeclaration(member)) { - const method = transformAccessorDeclaration(member, checker, "set"); - if (method) { - methods.push(method); - } + } else if (ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)) { + const kind = ts.isGetAccessorDeclaration(member) ? "get" : "set"; + const memberName = ts.isIdentifier(member.name) ? member.name.text : "?"; + const loc = getLoc(member); + console.error( + `${loc.file}:${loc.line}:${loc.column}: error: '${kind} ${memberName}()' is not supported; use a regular public method instead`, + ); + process.exit(1); } } diff --git a/tests/fixtures/classes/getter-setter-error.ts b/tests/fixtures/classes/getter-setter-error.ts new file mode 100644 index 00000000..5638e995 --- /dev/null +++ b/tests/fixtures/classes/getter-setter-error.ts @@ -0,0 +1,11 @@ +// @test-compile-error: 'get value()' is not supported +// @test-description: getters and setters are a compile error +class Counter { + private _value: number = 0; + + get value(): number { + return this._value; + } +} + +const c = new Counter();