From 680585e947d834a2c87aaaa882c6e7995fcba611 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Dec 2019 17:01:40 +0000 Subject: [PATCH 01/42] Add diagnostic reporting and convert forbidden for...in array error --- src/cli/report.ts | 11 ++++------- src/transformation/context/context.ts | 1 + src/transformation/index.ts | 8 ++++++-- src/transformation/utils/diagnostics.ts | 16 ++++++++++++++++ src/transformation/utils/errors.ts | 3 --- src/transformation/visitors/loops/for-in.ts | 5 +++-- test/setup.ts | 10 +++++----- test/unit/__snapshots__/loops.spec.ts.snap | 3 +++ test/unit/loops.spec.ts | 20 ++++++-------------- test/util.ts | 13 +++++++++++++ 10 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 src/transformation/utils/diagnostics.ts create mode 100644 test/unit/__snapshots__/loops.spec.ts.snap diff --git a/src/cli/report.ts b/src/cli/report.ts index 039ca069c..19fd02d1e 100644 --- a/src/cli/report.ts +++ b/src/cli/report.ts @@ -1,12 +1,9 @@ import * as ts from "typescript"; +export const prepareDiagnosticForFormatting = (diagnostic: ts.Diagnostic) => + diagnostic.source === "typescript-to-lua" ? { ...diagnostic, code: "TL" as any } : diagnostic; + export function createDiagnosticReporter(pretty: boolean, system = ts.sys): ts.DiagnosticReporter { const reporter = ts.createDiagnosticReporter(system, pretty); - return diagnostic => { - if (diagnostic.source === "typescript-to-lua") { - diagnostic = { ...diagnostic, code: ("TL" + diagnostic.code) as any }; - } - - reporter(diagnostic); - }; + return diagnostic => reporter(prepareDiagnosticForFormatting(diagnostic)); } diff --git a/src/transformation/context/context.ts b/src/transformation/context/context.ts index 5d9a7ef22..69aa542bb 100644 --- a/src/transformation/context/context.ts +++ b/src/transformation/context/context.ts @@ -18,6 +18,7 @@ export interface DiagnosticsProducingTypeChecker extends ts.TypeChecker { } export class TransformationContext { + public readonly diagnostics: ts.Diagnostic[] = []; public readonly checker: DiagnosticsProducingTypeChecker = (this .program as any).getDiagnosticsProducingTypeChecker(); public readonly resolver: EmitResolver; diff --git a/src/transformation/index.ts b/src/transformation/index.ts index a720a8ffd..ae62ed8d9 100644 --- a/src/transformation/index.ts +++ b/src/transformation/index.ts @@ -53,11 +53,15 @@ export function transformSourceFile( ): TransformSourceFileResult { const context = new TransformationContext(program, sourceFile, visitorMap); + // TODO: Remove once we'll get rid of all `TranspileError`s try { const [luaAst] = context.transformNode(sourceFile) as [lua.Block]; - const luaLibFeatures = getUsedLuaLibFeatures(context); - return { luaAst, luaLibFeatures, diagnostics: [] }; + return { + luaAst, + luaLibFeatures: getUsedLuaLibFeatures(context), + diagnostics: context.diagnostics, + }; } catch (error) { if (!(error instanceof TranspileError)) throw error; diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts new file mode 100644 index 000000000..ec260aa49 --- /dev/null +++ b/src/transformation/utils/diagnostics.ts @@ -0,0 +1,16 @@ +import * as ts from "typescript"; + +const createDiagnosticFactory = ( + message: string | ((...args: TArgs) => string), + category = ts.DiagnosticCategory.Error +) => (node: ts.Node, ...args: TArgs): ts.Diagnostic => ({ + file: node.getSourceFile(), + start: node.getStart(), + length: node.getWidth(), + category, + code: 0, + source: "typescript-to-lua", + messageText: typeof message === "string" ? message : message(...args), +}); + +export const forbiddenForIn = createDiagnosticFactory(`Iterating over arrays with 'for ... in' is not allowed.`); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index bb3f3ce79..22a798716 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -10,9 +10,6 @@ export class TranspileError extends Error { const getLuaTargetName = (version: LuaTarget) => (version === LuaTarget.LuaJIT ? "LuaJIT" : `Lua ${version}`); -export const ForbiddenForIn = (node: ts.Node) => - new TranspileError(`Iterating over arrays with 'for ... in' is not allowed.`, node); - export const ForbiddenLuaTableNonDeclaration = (node: ts.Node) => new TranspileError(`Classes with the '@luaTable' annotation must be declared.`, node); diff --git a/src/transformation/visitors/loops/for-in.ts b/src/transformation/visitors/loops/for-in.ts index b79f18ccf..e2111ff2a 100644 --- a/src/transformation/visitors/loops/for-in.ts +++ b/src/transformation/visitors/loops/for-in.ts @@ -1,14 +1,15 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; import { FunctionVisitor } from "../../context"; -import { ForbiddenForIn, UnsupportedForInVariable } from "../../utils/errors"; +import { forbiddenForIn } from "../../utils/diagnostics"; +import { UnsupportedForInVariable } from "../../utils/errors"; import { isArrayType } from "../../utils/typescript"; import { transformIdentifier } from "../identifier"; import { transformLoopBody } from "./body"; export const transformForInStatement: FunctionVisitor = (statement, context) => { if (isArrayType(context, context.checker.getTypeAtLocation(statement.expression))) { - throw ForbiddenForIn(statement); + context.diagnostics.push(forbiddenForIn(statement)); } // Transpile expression diff --git a/test/setup.ts b/test/setup.ts index 8305ec264..b43c9287a 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,4 +1,5 @@ import * as ts from "typescript"; +import * as tstl from "../src"; import * as util from "./util"; declare global { @@ -35,11 +36,10 @@ expect.extend({ // @ts-ignore const matcherHint = this.utils.matcherHint("toHaveDiagnostics", undefined, "", this); - const diagnosticMessages = ts.formatDiagnosticsWithColorAndContext(diagnostics, { - getCurrentDirectory: () => "", - getCanonicalFileName: fileName => fileName, - getNewLine: () => "\n", - }); + const diagnosticMessages = ts.formatDiagnosticsWithColorAndContext( + diagnostics.map(tstl.prepareDiagnosticForFormatting), + { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } + ); return { pass: diagnostics.length > 0, diff --git a/test/unit/__snapshots__/loops.spec.ts.snap b/test/unit/__snapshots__/loops.spec.ts.snap new file mode 100644 index 000000000..371fdeafc --- /dev/null +++ b/test/unit/__snapshots__/loops.spec.ts.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`forin[Array] 1`] = `"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`; diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index 6e67074d3..5c40003b9 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -1,10 +1,6 @@ import * as ts from "typescript"; import * as tstl from "../../src"; -import { - ForbiddenForIn, - UnsupportedForTarget, - UnsupportedObjectDestructuringInForOf, -} from "../../src/transformation/utils/errors"; +import { UnsupportedForTarget, UnsupportedObjectDestructuringInForOf } from "../../src/transformation/utils/errors"; import * as util from "../util"; test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("while (%p)", ({ inp, expected }) => { @@ -235,15 +231,11 @@ test.each([ expect(JSON.parse(result)).toEqual(expected); }); -test.each([{ inp: [1, 2, 3] }])("forin[Array] (%p)", ({ inp }) => { - expect(() => - util.transpileString( - `let arrTest = ${JSON.stringify(inp)}; - for (let key in arrTest) { - arrTest[key]++; - }` - ) - ).toThrowExactError(ForbiddenForIn(util.nodeStub)); +test("forin[Array]", () => { + util.testFunction` + const array = []; + for (const key in array) {} + `.expectDiagnosticsToMatchSnapshot(); }); test.each([{ inp: { a: 0, b: 1, c: 2, d: 3, e: 4 }, expected: { a: 0, b: 0, c: 2, d: 0, e: 4 } }])( diff --git a/test/util.ts b/test/util.ts index 6ca57509b..305257371 100644 --- a/test/util.ts +++ b/test/util.ts @@ -363,6 +363,19 @@ export abstract class TestBuilder { return this; } + public expectDiagnosticsToMatchSnapshot(): this { + this.expectToHaveDiagnostics(); + + const diagnosticMessages = ts.formatDiagnostics( + this.getLuaDiagnostics().map(tstl.prepareDiagnosticForFormatting), + { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } + ); + + expect(diagnosticMessages.trim()).toMatchSnapshot(); + + return this; + } + public expectNoExecutionError(): this { const luaResult = this.getLuaExecutionResult(); if (luaResult instanceof ExecutionError) { From 6ecdec328d51ecafd80539f95edee6d746d0af91 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Dec 2019 17:26:45 +0000 Subject: [PATCH 02/42] Include generated code in diagnostic snapshots --- test/unit/__snapshots__/loops.spec.ts.snap | 12 +++++++++++- test/util.ts | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/test/unit/__snapshots__/loops.spec.ts.snap b/test/unit/__snapshots__/loops.spec.ts.snap index 371fdeafc..29b609730 100644 --- a/test/unit/__snapshots__/loops.spec.ts.snap +++ b/test/unit/__snapshots__/loops.spec.ts.snap @@ -1,3 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`forin[Array] 1`] = `"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`; +exports[`forin[Array]: code 1`] = ` +"local ____exports = {} +function ____exports.__main(self) + local array = {} + for key in pairs(array) do + end +end +return ____exports" +`; + +exports[`forin[Array]: diagnostics 1`] = `"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`; diff --git a/test/util.ts b/test/util.ts index 305257371..505ffe067 100644 --- a/test/util.ts +++ b/test/util.ts @@ -371,7 +371,8 @@ export abstract class TestBuilder { { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } ); - expect(diagnosticMessages.trim()).toMatchSnapshot(); + expect(this.getMainLuaCodeChunk()).toMatchSnapshot('code'); + expect(diagnosticMessages.trim()).toMatchSnapshot('diagnostics'); return this; } From a3a973258b2513cf424e0aaa3d3026497dd929c4 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Dec 2019 18:33:28 +0000 Subject: [PATCH 03/42] Remove some errors that already have TypeScript diagnostics --- src/transformation/utils/errors.ts | 14 -------------- src/transformation/visitors/class/index.ts | 14 ++++++-------- src/transformation/visitors/function.ts | 14 ++++++-------- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index 22a798716..82ef37adb 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -53,15 +53,9 @@ export const MissingClassName = (node: ts.Node) => new TranspileError(`Class dec export const MissingForOfVariables = (node: ts.Node) => new TranspileError("Transpiled ForOf variable declaration list contains no declarations.", node); -export const MissingFunctionName = (declaration: ts.FunctionLikeDeclaration) => - new TranspileError("Unsupported function declaration without name.", declaration); - export const MissingMetaExtension = (node: ts.Node) => new TranspileError(`'@metaExtension' annotation requires the extension of the metatable class.`, node); -export const NonFlattenableDestructure = (node: ts.Node) => - new TranspileError(`This node cannot be destructured using a standard Lua assignment statement.`, node); - export const UndefinedFunctionDefinition = (functionSymbolId: number) => new Error(`Function definition for function symbol ${functionSymbolId} is undefined.`); @@ -72,11 +66,6 @@ export const UndefinedScope = () => new Error("Expected to pop a scope, but foun export const UndefinedTypeNode = (node: ts.Node) => new TranspileError("Failed to resolve required type node.", node); -export const UnknownSuperType = (node: ts.Node) => - new TranspileError("Unable to resolve type of super expression.", node); - -export const UnsupportedImportType = (node: ts.Node) => new TranspileError(`Unsupported import type.`, node); - export const UnsupportedKind = (description: string, kind: ts.SyntaxKind, node: ts.Node) => new TranspileError(`Unsupported ${description} kind: ${ts.SyntaxKind[kind]}`, node); @@ -86,9 +75,6 @@ export const UnsupportedProperty = (parentName: string, property: string, node: export const UnsupportedForTarget = (functionality: string, version: LuaTarget, node: ts.Node) => new TranspileError(`${functionality} is/are not supported for target ${getLuaTargetName(version)}.`, node); -export const UnsupportedFunctionWithoutBody = (node: ts.FunctionLikeDeclaration) => - new TranspileError("Functions with undefined bodies are not supported.", node); - export const UnsupportedNoSelfFunctionConversion = (node: ts.Node, name?: string) => { const nameReference = name ? ` '${name}'` : ""; return new TranspileError( diff --git a/src/transformation/visitors/class/index.ts b/src/transformation/visitors/class/index.ts index e9c8c108c..bfb137a9f 100644 --- a/src/transformation/visitors/class/index.ts +++ b/src/transformation/visitors/class/index.ts @@ -11,7 +11,6 @@ import { InvalidExtensionMetaExtension, MissingClassName, MissingMetaExtension, - UnknownSuperType, } from "../../utils/errors"; import { createDefaultExportIdentifier, @@ -85,7 +84,9 @@ export function transformClassDeclaration( return lua.createAssignmentStatement(left, right, classDeclaration); } else { - throw MissingClassName(classDeclaration); + // TypeScript error + className = lua.createAnonymousIdentifier(); + classNameText = className.text; } const annotations = getTypeAnnotations(context, context.checker.getTypeAtLocation(classDeclaration)); @@ -317,14 +318,11 @@ export const transformSuperExpression: FunctionVisitor = (ex const classStack = getOrUpdate(classStacks, context, () => []); const classDeclaration = classStack[classStack.length - 1]; const typeNode = getExtendedTypeNode(context, classDeclaration); - if (typeNode === undefined) { - throw UnknownSuperType(expression); - } - - const extendsExpression = typeNode.expression; + // `undefined` is a TypeScript error + const extendsExpression = typeNode?.expression; let baseClassName: lua.AssignmentLeftHandSideExpression | undefined; - if (ts.isIdentifier(extendsExpression)) { + if (extendsExpression && ts.isIdentifier(extendsExpression)) { const symbol = context.checker.getSymbolAtLocation(extendsExpression); if (symbol && !isSymbolExported(context, symbol)) { // Use "baseClassName" if base is a simple identifier diff --git a/src/transformation/visitors/function.ts b/src/transformation/visitors/function.ts index 070097db9..1cdbfcc6f 100644 --- a/src/transformation/visitors/function.ts +++ b/src/transformation/visitors/function.ts @@ -2,7 +2,6 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { FunctionVisitor, TransformationContext } from "../context"; import { isVarArgType } from "../utils/annotations"; -import { MissingFunctionName, UnsupportedFunctionWithoutBody } from "../utils/errors"; import { createDefaultExportStringLiteral, hasDefaultExportModifier } from "../utils/export"; import { ContextType, getFunctionContextType } from "../utils/function-context"; import { @@ -187,7 +186,8 @@ export function transformFunctionLikeDeclaration( let flags = lua.FunctionExpressionFlags.None; if (node.body === undefined) { - throw UnsupportedFunctionWithoutBody(node); + // This code can be reached only from object methods, which is TypeScript error + return lua.createNilLiteral(); } let body: ts.Block; @@ -257,18 +257,16 @@ export const transformFunctionDeclaration: FunctionVisitor Date: Mon, 9 Dec 2019 18:34:43 +0000 Subject: [PATCH 04/42] Replace unactionable errors with assertions --- src/transformation/utils/errors.ts | 10 ---------- src/transformation/utils/scope.ts | 12 ++++-------- src/transformation/visitors/class/index.ts | 7 ++----- src/transformation/visitors/class/setup.ts | 6 ++---- src/transformation/visitors/modules/export.ts | 6 ++---- src/utils.ts | 5 +++++ 6 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index 82ef37adb..98ea7f64c 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -34,9 +34,6 @@ export const InvalidExtensionMetaExtension = (node: ts.Node) => export const InvalidNewExpressionOnExtension = (node: ts.Node) => new TranspileError(`Cannot construct classes with '@extension' or '@metaExtension' annotation.`, node); -export const InvalidExportDeclaration = (declaration: ts.ExportDeclaration) => - new TranspileError("Encountered invalid export declaration without exports and without module.", declaration); - export const InvalidExtendsExtension = (node: ts.Node) => new TranspileError(`Cannot extend classes with '@extension' or '@metaExtension' annotation.`, node); @@ -48,24 +45,17 @@ export const InvalidInstanceOfExtension = (node: ts.Node) => export const InvalidJsonFileContent = (node: ts.Node) => new TranspileError("Invalid JSON file content", node); -export const MissingClassName = (node: ts.Node) => new TranspileError(`Class declarations must have a name.`, node); - export const MissingForOfVariables = (node: ts.Node) => new TranspileError("Transpiled ForOf variable declaration list contains no declarations.", node); export const MissingMetaExtension = (node: ts.Node) => new TranspileError(`'@metaExtension' annotation requires the extension of the metatable class.`, node); -export const UndefinedFunctionDefinition = (functionSymbolId: number) => - new Error(`Function definition for function symbol ${functionSymbolId} is undefined.`); - export const UnsupportedForInVariable = (node: ts.Node) => new TranspileError(`Unsupported for-in variable kind.`, node); export const UndefinedScope = () => new Error("Expected to pop a scope, but found undefined."); -export const UndefinedTypeNode = (node: ts.Node) => new TranspileError("Failed to resolve required type node.", node); - export const UnsupportedKind = (description: string, kind: ts.SyntaxKind, node: ts.Node) => new TranspileError(`Unsupported ${description} kind: ${ts.SyntaxKind[kind]}`, node); diff --git a/src/transformation/utils/scope.ts b/src/transformation/utils/scope.ts index 5077bcc42..6f354b01c 100644 --- a/src/transformation/utils/scope.ts +++ b/src/transformation/utils/scope.ts @@ -1,8 +1,8 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; -import { getOrUpdate, isNonNull } from "../../utils"; +import { assert, getOrUpdate, isNonNull } from "../../utils"; import { TransformationContext } from "../context"; -import { UndefinedFunctionDefinition, UndefinedScope } from "./errors"; +import { UndefinedScope } from "./errors"; import { replaceStatementInParent } from "./lua-ast"; import { getSymbolInfo } from "./symbols"; import { getFirstDeclarationInFile } from "./typescript"; @@ -125,9 +125,7 @@ function shouldHoistSymbol(context: TransformationContext, symbolId: lua.SymbolI if (scope.functionDefinitions) { for (const [functionSymbolId, functionDefinition] of scope.functionDefinitions) { - if (functionDefinition.definition === undefined) { - throw UndefinedFunctionDefinition(functionSymbolId); - } + assert(functionDefinition.definition); const { line, column } = lua.getOriginalPos(functionDefinition.definition); if (line !== undefined && column !== undefined) { @@ -202,9 +200,7 @@ function hoistFunctionDefinitions( const result = [...statements]; const hoistedFunctions: Array = []; for (const [functionSymbolId, functionDefinition] of scope.functionDefinitions) { - if (functionDefinition.definition === undefined) { - throw UndefinedFunctionDefinition(functionSymbolId); - } + assert(functionDefinition.definition); if (shouldHoistSymbol(context, functionSymbolId, scope)) { const index = result.indexOf(functionDefinition.definition); diff --git a/src/transformation/visitors/class/index.ts b/src/transformation/visitors/class/index.ts index bfb137a9f..27fd44cb0 100644 --- a/src/transformation/visitors/class/index.ts +++ b/src/transformation/visitors/class/index.ts @@ -1,6 +1,6 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; -import { getOrUpdate, isNonNull } from "../../../utils"; +import { assert, getOrUpdate, isNonNull } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations"; import { @@ -9,7 +9,6 @@ import { InvalidExtendsExtension, InvalidExtendsLuaTable, InvalidExtensionMetaExtension, - MissingClassName, MissingMetaExtension, } from "../../utils/errors"; import { @@ -331,9 +330,7 @@ export const transformSuperExpression: FunctionVisitor = (ex } if (!baseClassName) { - if (classDeclaration.name === undefined) { - throw MissingClassName(expression); - } + assert(classDeclaration.name); // Use "className.____super" if the base is not a simple identifier baseClassName = lua.createTableIndexExpression( diff --git a/src/transformation/visitors/class/setup.ts b/src/transformation/visitors/class/setup.ts index 2a4a1c8d0..710a459e2 100644 --- a/src/transformation/visitors/class/setup.ts +++ b/src/transformation/visitors/class/setup.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; +import { assert } from "../../../utils"; import { TransformationContext } from "../../context"; -import { UndefinedTypeNode } from "../../utils/errors"; import { createDefaultExportStringLiteral, createExportedIdentifier, @@ -159,9 +159,7 @@ export function createClassSetup( if (extendsType) { const extendedTypeNode = getExtendedTypeNode(context, statement); - if (extendedTypeNode === undefined) { - throw UndefinedTypeNode(statement); - } + assert(extendedTypeNode); // localClassName.____super = extendsExpression const createClassBase = () => diff --git a/src/transformation/visitors/modules/export.ts b/src/transformation/visitors/modules/export.ts index b3a9f3433..c0a75ab21 100644 --- a/src/transformation/visitors/modules/export.ts +++ b/src/transformation/visitors/modules/export.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; +import { assert } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; -import { InvalidExportDeclaration } from "../../utils/errors"; import { createDefaultExportIdentifier, createDefaultExportStringLiteral, @@ -37,9 +37,7 @@ export const transformExportAssignment: FunctionVisitor = ( }; function transformExportAllFrom(context: TransformationContext, node: ts.ExportDeclaration): lua.Statement | undefined { - if (node.moduleSpecifier === undefined) { - throw InvalidExportDeclaration(node); - } + assert(node.moduleSpecifier); if (!context.resolver.moduleExportsSomeValue(node.moduleSpecifier)) { return undefined; diff --git a/src/utils.ts b/src/utils.ts index 7b29b553a..256d5ec94 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,4 @@ +import * as nativeAssert from "assert"; import * as path from "path"; export const normalizeSlashes = (filePath: string) => filePath.replace(/\\/g, "/"); @@ -67,6 +68,10 @@ export function castEach( } } +export function assert(value: any, message?: string | Error): asserts value { + nativeAssert(value, message); +} + export function assertNever(_value: never): never { throw new Error("Value is expected to be never"); } From 4997d61e409def3849ebd7378abc59c316e9772f Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Dec 2019 19:04:35 +0000 Subject: [PATCH 05/42] Replace empty json file diagnostic with runtime error --- src/transformation/utils/errors.ts | 2 -- src/transformation/visitors/sourceFile.ts | 15 ++++++++++----- test/unit/json.spec.ts | 14 ++------------ test/util.ts | 6 ++++-- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index 98ea7f64c..c7a371201 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -43,8 +43,6 @@ export const InvalidExportsExtension = (node: ts.Node) => export const InvalidInstanceOfExtension = (node: ts.Node) => new TranspileError(`Cannot use instanceof on classes with '@extension' or '@metaExtension' annotation.`, node); -export const InvalidJsonFileContent = (node: ts.Node) => new TranspileError("Invalid JSON file content", node); - export const MissingForOfVariables = (node: ts.Node) => new TranspileError("Transpiled ForOf variable declaration list contains no declarations.", node); diff --git a/src/transformation/visitors/sourceFile.ts b/src/transformation/visitors/sourceFile.ts index 064b5200f..539c9f9d7 100644 --- a/src/transformation/visitors/sourceFile.ts +++ b/src/transformation/visitors/sourceFile.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; +import { assert } from "../../utils"; import { FunctionVisitor } from "../context"; -import { InvalidJsonFileContent } from "../utils/errors"; import { createExportsIdentifier } from "../utils/lua-ast"; import { performHoisting, popScope, pushScope, ScopeType } from "../utils/scope"; import { hasExportEquals } from "../utils/typescript"; @@ -10,11 +10,16 @@ export const transformSourceFileNode: FunctionVisitor = (node, co let statements: lua.Statement[] = []; if (node.flags & ts.NodeFlags.JsonFile) { const [statement] = node.statements; - if (!statement || !ts.isExpressionStatement(statement)) { - throw InvalidJsonFileContent(node); - } + if (statement) { + assert(ts.isExpressionStatement(statement)); + statements.push(lua.createReturnStatement([context.transformExpression(statement.expression)])); + } else { + const errorCall = lua.createCallExpression(lua.createIdentifier("error"), [ + lua.createStringLiteral("Unexpected end of JSON input"), + ]); - statements.push(lua.createReturnStatement([context.transformExpression(statement.expression)])); + statements.push(lua.createExpressionStatement(errorCall)); + } } else { pushScope(context, ScopeType.File); statements = performHoisting(context, context.transformStatements(node.statements)); diff --git a/test/unit/json.spec.ts b/test/unit/json.spec.ts index b7b7c27e5..b61e64fd1 100644 --- a/test/unit/json.spec.ts +++ b/test/unit/json.spec.ts @@ -1,23 +1,13 @@ -import * as ts from "typescript"; -import { InvalidJsonFileContent } from "../../src/transformation/utils/errors"; import * as util from "../util"; -const jsonOptions = { - resolveJsonModule: true, - noHeader: true, - moduleResolution: ts.ModuleResolutionKind.NodeJs, -}; - test.each([0, "", [], [1, "2", []], { a: "b" }, { a: { b: "c" } }])("JSON (%p)", json => { util.testModule(JSON.stringify(json)) - .setOptions(jsonOptions) .setMainFileName("main.json") .expectToEqual(json); }); -test("Empty JSON", () => { +test("Empty JSON file error", () => { util.testModule("") - .setOptions(jsonOptions) .setMainFileName("main.json") - .expectToHaveDiagnosticOfError(InvalidJsonFileContent(util.nodeStub)); + .expectToEqual(new util.ExecutionError("Unexpected end of JSON input")); }); diff --git a/test/util.ts b/test/util.ts index 505ffe067..4eb4ef092 100644 --- a/test/util.ts +++ b/test/util.ts @@ -190,6 +190,8 @@ export abstract class TestBuilder { skipLibCheck: true, target: ts.ScriptTarget.ES2017, lib: ["lib.esnext.d.ts"], + moduleResolution: ts.ModuleResolutionKind.NodeJs, + resolveJsonModule: true, experimentalDecorators: true, }; public setOptions(options: tstl.CompilerOptions = {}): this { @@ -371,8 +373,8 @@ export abstract class TestBuilder { { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } ); - expect(this.getMainLuaCodeChunk()).toMatchSnapshot('code'); - expect(diagnosticMessages.trim()).toMatchSnapshot('diagnostics'); + expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); + expect(diagnosticMessages.trim()).toMatchSnapshot("diagnostics"); return this; } From f4673a8e55e9dab703476d6c7a9c2b0d835be535 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Dec 2019 19:39:04 +0000 Subject: [PATCH 06/42] Refactor `@forRange` annotation tests --- test/unit/decorators/forRange.spec.ts | 193 +++++++++++++------------- 1 file changed, 96 insertions(+), 97 deletions(-) diff --git a/test/unit/decorators/forRange.spec.ts b/test/unit/decorators/forRange.spec.ts index ee5cb74d0..14f42ca38 100644 --- a/test/unit/decorators/forRange.spec.ts +++ b/test/unit/decorators/forRange.spec.ts @@ -2,107 +2,106 @@ import * as ts from "typescript"; import { InvalidForRangeCall } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; +const createForRangeDeclaration = (args = "i: number, j: number, k?: number", returns = "number[]") => ` + /** @forRange */ + declare function luaRange(${args}): ${returns}; +`; + test.each([ - { args: [1, 10], expectResult: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, - { args: [1, 10, 2], expectResult: [1, 3, 5, 7, 9] }, - { args: [10, 1, -1], expectResult: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, - { args: [10, 1, -2], expectResult: [10, 8, 6, 4, 2] }, -])("@forRange loop", ({ args, expectResult }) => { - const tsHeader = "/** @forRange **/ declare function luaRange(i: number, j: number, k?: number): number[];"; - const code = ` - const results: number[] = []; + { args: [1, 10], results: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { args: [1, 10, 2], results: [1, 3, 5, 7, 9] }, + { args: [10, 1, -1], results: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }, + { args: [10, 1, -2], results: [10, 8, 6, 4, 2] }, +])("usage in for...of loop", ({ args, results }) => { + util.testModule` + ${createForRangeDeclaration()} + export const results: number[] = []; + for (const i of luaRange(${args})) { results.push(i); } - return JSONStringify(results);`; - - const result = util.transpileAndExecute(code, undefined, undefined, tsHeader); - expect(JSON.parse(result)).toEqual(expectResult); -}); - -test("invalid non-ambient @forRange function", () => { - const code = ` - /** @forRange **/ function luaRange(i: number, j: number, k?: number): number[] { return []; } - for (const i of luaRange(1, 10, 2)) {}`; - - expect(() => util.transpileString(code)).toThrow( - InvalidForRangeCall( - ts.createEmptyStatement(), - "@forRange function can only be used as an iterable in a for...of loop." - ).message - ); -}); - -test.each([[1], [1, 2, 3, 4]])("invalid @forRange argument count", args => { - const code = ` - /** @forRange **/ declare function luaRange(...args: number[]): number[] { return []; } - for (const i of luaRange(${args})) {}`; - - expect(() => util.transpileString(code)).toThrow( - InvalidForRangeCall(ts.createEmptyStatement(), "@forRange function must take 2 or 3 arguments.").message - ); -}); - -test("invalid @forRange control variable", () => { - const code = ` - /** @forRange **/ declare function luaRange(i: number, j: number, k?: number): number[]; - let i: number; - for (i of luaRange(1, 10, 2)) {}`; - - expect(() => util.transpileString(code)).toThrow( - InvalidForRangeCall(ts.createEmptyStatement(), "@forRange loop must declare its own control variable.").message - ); + ` + .setReturnExport("results") + .expectToEqual(results); }); -test("invalid @forRange argument type", () => { - const code = ` - /** @forRange **/ declare function luaRange(i: string, j: number): number[] { return []; } - for (const i of luaRange("foo", 2)) {}`; - - expect(() => util.transpileString(code)).toThrow( - InvalidForRangeCall(ts.createEmptyStatement(), "@forRange arguments must be number types.").message - ); -}); - -test("invalid @forRange destructuring", () => { - const code = ` - /** @forRange **/ declare function luaRange(i: number, j: number, k?: number): number[][]; - for (const [i] of luaRange(1, 10, 2)) {}`; - - expect(() => util.transpileString(code)).toThrow( - InvalidForRangeCall(ts.createEmptyStatement(), "@forRange loop cannot use destructuring.").message - ); -}); - -test("invalid @forRange return type", () => { - const code = ` - /** @forRange **/ declare function luaRange(i: number, j: number, k?: number): string[]; - for (const i of luaRange(1, 10)) {}`; - - expect(() => util.transpileString(code)).toThrow( - InvalidForRangeCall( - ts.createEmptyStatement(), - "@forRange function must return Iterable or Array." - ).message - ); -}); - -test.each([ - "const range = luaRange(1, 10);", - "console.log(luaRange);", - "luaRange.call(null, 0, 0, 0);", - "let array = [0, luaRange, 1];", - "const call: any; call(luaRange);", - "for (const i of [...luaRange(1, 10)]) {}", -])("invalid @forRange reference (%p)", statement => { - const code = ` - /** @forRange **/ declare function luaRange(i: number, j: number, k?: number): number[]; - ${statement}`; - - expect(() => util.transpileString(code)).toThrow( - InvalidForRangeCall( - ts.createEmptyStatement(), - "@forRange function can only be used as an iterable in a for...of loop." - ).message - ); +describe("invalid usage", () => { + test("non-ambient declaration", () => { + util.testModule` + /** @forRange */ + function luaRange() {} + `.expectToHaveDiagnosticOfError( + InvalidForRangeCall( + ts.createEmptyStatement(), + "@forRange function can only be used as an iterable in a for...of loop." + ) + ); + }); + + test.each([[1], [1, 2, 3, 4]])("argument count", args => { + util.testModule` + ${createForRangeDeclaration("...args: number[]")} + for (const i of luaRange(${args})) {} + `.expectToHaveDiagnosticOfError( + InvalidForRangeCall(ts.createEmptyStatement(), "@forRange function must take 2 or 3 arguments.") + ); + }); + + test("non-declared loop variable", () => { + util.testModule` + ${createForRangeDeclaration()} + let i: number; + for (i of luaRange(1, 10, 2)) {} + `.expectToHaveDiagnosticOfError( + InvalidForRangeCall(ts.createEmptyStatement(), "@forRange loop must declare its own control variable.") + ); + }); + + test("argument types", () => { + util.testModule` + ${createForRangeDeclaration("i: string, j: number")} + for (const i of luaRange("foo", 2)) {} + `.expectToHaveDiagnosticOfError( + InvalidForRangeCall(ts.createEmptyStatement(), "@forRange arguments must be number types.") + ); + }); + + test("variable destructuring", () => { + util.testModule` + ${createForRangeDeclaration(undefined, "number[][]")} + for (const [i] of luaRange(1, 10, 2)) {} + `.expectToHaveDiagnosticOfError( + InvalidForRangeCall(ts.createEmptyStatement(), "@forRange loop cannot use destructuring.") + ); + }); + + test("return type", () => { + util.testModule` + ${createForRangeDeclaration(undefined, "string[]")} + for (const i of luaRange(1, 10)) {} + `.expectToHaveDiagnosticOfError( + InvalidForRangeCall( + ts.createEmptyStatement(), + "@forRange function must return Iterable or Array." + ) + ); + }); + + test.each([ + "const range = luaRange(1, 10);", + "luaRange.call(null, 0, 0, 0);", + "let array = [0, luaRange, 1];", + "const call = undefined as any; call(luaRange);", + "for (const i of [...luaRange(1, 10)]) {}", + ])("reference (%p)", statement => { + util.testModule` + ${createForRangeDeclaration()} + ${statement} + `.expectToHaveDiagnosticOfError( + InvalidForRangeCall( + ts.createEmptyStatement(), + "@forRange function can only be used as an iterable in a for...of loop." + ) + ); + }); }); From 95471f3cdcd2fdc7e8fe99bc84f09dfced2de995 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Dec 2019 21:22:18 +0000 Subject: [PATCH 07/42] Move invalid `@forRange` call error to diagnostics --- src/transformation/utils/diagnostics.ts | 2 + src/transformation/utils/errors.ts | 3 - src/transformation/visitors/identifier.ts | 7 +- src/transformation/visitors/loops/for-of.ts | 60 +++++++----- .../__snapshots__/forRange.spec.ts.snap | 93 +++++++++++++++++++ test/unit/decorators/forRange.spec.ts | 41 ++------ 6 files changed, 142 insertions(+), 64 deletions(-) create mode 100644 test/unit/decorators/__snapshots__/forRange.spec.ts.snap diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index ec260aa49..c096f3ae8 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -14,3 +14,5 @@ const createDiagnosticFactory = ( }); export const forbiddenForIn = createDiagnosticFactory(`Iterating over arrays with 'for ... in' is not allowed.`); + +export const invalidForRangeCall = createDiagnosticFactory((message: string) => `Invalid @forRange call: ${message}.`); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index c7a371201..996063da2 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -116,6 +116,3 @@ export const InvalidAmbientIdentifierName = (node: ts.Identifier) => `Invalid ambient identifier name "${node.text}". Ambient identifiers must be valid lua identifiers.`, node ); - -export const InvalidForRangeCall = (node: ts.Node, message: string) => - new TranspileError(`Invalid @forRange call: ${message}`, node); diff --git a/src/transformation/visitors/identifier.ts b/src/transformation/visitors/identifier.ts index 565c0625b..026fdb858 100644 --- a/src/transformation/visitors/identifier.ts +++ b/src/transformation/visitors/identifier.ts @@ -3,7 +3,7 @@ import * as lua from "../../LuaAST"; import { transformBuiltinIdentifierExpression } from "../builtins"; import { FunctionVisitor, TransformationContext } from "../context"; import { isForRangeType } from "../utils/annotations"; -import { InvalidForRangeCall } from "../utils/errors"; +import { invalidForRangeCall } from "../utils/diagnostics"; import { createExportedIdentifier, getIdentifierExportScope } from "../utils/export"; import { createSafeName, hasUnsafeIdentifierName } from "../utils/safe-names"; import { getIdentifierSymbolId } from "../utils/symbols"; @@ -13,9 +13,8 @@ export function transformIdentifier(context: TransformationContext, identifier: if (isForRangeType(context, identifier)) { const callExpression = findFirstNodeAbove(identifier, ts.isCallExpression); if (!callExpression || !callExpression.parent || !ts.isForOfStatement(callExpression.parent)) { - throw InvalidForRangeCall( - identifier, - "@forRange function can only be used as an iterable in a for...of loop." + context.diagnostics.push( + invalidForRangeCall(identifier, "can be used only as an iterable in a for...of loop") ); } } diff --git a/src/transformation/visitors/loops/for-of.ts b/src/transformation/visitors/loops/for-of.ts index 868b2c03d..7c929b91b 100644 --- a/src/transformation/visitors/loops/for-of.ts +++ b/src/transformation/visitors/loops/for-of.ts @@ -1,10 +1,10 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; -import { cast, castEach } from "../../../utils"; +import { assert, cast, castEach } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations, isForRangeType, isLuaIteratorType } from "../../utils/annotations"; +import { invalidForRangeCall } from "../../utils/diagnostics"; import { - InvalidForRangeCall, MissingForOfVariables, UnsupportedNonDestructuringLuaIterator, UnsupportedObjectDestructuringInForOf, @@ -74,38 +74,50 @@ function transformForRangeStatement( statement: ts.ForOfStatement, block: lua.Block ): lua.Statement { - if (!ts.isCallExpression(statement.expression)) { - throw InvalidForRangeCall(statement.expression, "Expression must be a call expression."); - } + assert(ts.isCallExpression(statement.expression)); - if (statement.expression.arguments.length < 2 || statement.expression.arguments.length > 3) { - throw InvalidForRangeCall(statement.expression, "@forRange function must take 2 or 3 arguments."); + const callArguments = statement.expression.arguments; + if (callArguments.length !== 2 && callArguments.length !== 3) { + context.diagnostics.push( + invalidForRangeCall(statement.expression, `Expected 2-3 arguments, but got ${callArguments.length}`) + ); } if (statement.expression.arguments.some(a => !isNumberType(context, context.checker.getTypeAtLocation(a)))) { - throw InvalidForRangeCall(statement.expression, "@forRange arguments must be number types."); + context.diagnostics.push(invalidForRangeCall(statement.expression, "arguments must be numbers")); } - if (!ts.isVariableDeclarationList(statement.initializer)) { - throw InvalidForRangeCall(statement.initializer, "@forRange loop must declare its own control variable."); - } + const controlVariable = getControlVariable() ?? lua.createAnonymousIdentifier(); + function getControlVariable(): lua.Identifier | undefined { + if (!ts.isVariableDeclarationList(statement.initializer)) { + context.diagnostics.push( + invalidForRangeCall(statement.initializer, "loop must declare it's own control variable") + ); + return; + } - const controlDeclaration = statement.initializer.declarations[0]; - if (!ts.isIdentifier(controlDeclaration.name)) { - throw InvalidForRangeCall(statement.initializer, "@forRange loop cannot use destructuring."); - } + const controlDeclaration = statement.initializer.declarations[0]; + if (!ts.isIdentifier(controlDeclaration.name)) { + context.diagnostics.push(invalidForRangeCall(statement.initializer, "destructuring cannot be used")); + return; + } - if (!isNumberType(context, context.checker.getTypeAtLocation(controlDeclaration))) { - throw InvalidForRangeCall( - statement.expression, - "@forRange function must return Iterable or Array." - ); + if (!isNumberType(context, context.checker.getTypeAtLocation(controlDeclaration))) { + context.diagnostics.push( + invalidForRangeCall(statement.expression, "function must return Iterable") + ); + } + + return transformIdentifier(context, controlDeclaration.name); } - const control = transformIdentifier(context, controlDeclaration.name); - const signature = context.checker.getResolvedSignature(statement.expression); - const [start, limit, step] = transformArguments(context, statement.expression.arguments, signature); - return lua.createForStatement(block, control, start, limit, step, statement); + const [start = lua.createNumericLiteral(0), limit = lua.createNumericLiteral(0), step] = transformArguments( + context, + callArguments, + context.checker.getResolvedSignature(statement.expression) + ); + + return lua.createForStatement(block, controlVariable, start, limit, step, statement); } function transformForOfLuaIteratorStatement( diff --git a/test/unit/decorators/__snapshots__/forRange.spec.ts.snap b/test/unit/decorators/__snapshots__/forRange.spec.ts.snap new file mode 100644 index 000000000..568ad7476 --- /dev/null +++ b/test/unit/decorators/__snapshots__/forRange.spec.ts.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`invalid usage argument count ([]): code 1`] = ` +"for i = 0, 0 do +end" +`; + +exports[`invalid usage argument count ([]): diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: Expected 2-3 arguments, but got 0."`; + +exports[`invalid usage argument count ([1, 2, 3, 4]): code 1`] = ` +"for i = 1, 2, 3 do +end" +`; + +exports[`invalid usage argument count ([1, 2, 3, 4]): diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: Expected 2-3 arguments, but got 4."`; + +exports[`invalid usage argument count ([1]): code 1`] = ` +"for i = 1, 0 do +end" +`; + +exports[`invalid usage argument count ([1]): diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: Expected 2-3 arguments, but got 1."`; + +exports[`invalid usage argument types: code 1`] = ` +"for i = \\"foo\\", 2 do +end" +`; + +exports[`invalid usage argument types: diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: arguments must be numbers."`; + +exports[`invalid usage non-ambient declaration: code 1`] = ` +"function luaRange(self) +end" +`; + +exports[`invalid usage non-ambient declaration: diagnostics 1`] = `"main.ts(3,22): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."`; + +exports[`invalid usage non-declared loop variable: code 1`] = ` +"local i +for ____ = 1, 10, 2 do +end" +`; + +exports[`invalid usage non-declared loop variable: diagnostics 1`] = `"main.ts(7,18): error TSTL: Invalid @forRange call: loop must declare it's own control variable."`; + +exports[`invalid usage reference ("const call = undefined as any; call(luaRange);"): code 1`] = ` +"local call = nil +call(_G, luaRange)" +`; + +exports[`invalid usage reference ("const call = undefined as any; call(luaRange);"): diagnostics 1`] = `"main.ts(6,49): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."`; + +exports[`invalid usage reference ("const range = luaRange(1, 10);"): code 1`] = `"local range = luaRange(_G, 1, 10)"`; + +exports[`invalid usage reference ("const range = luaRange(1, 10);"): diagnostics 1`] = `"main.ts(6,27): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."`; + +exports[`invalid usage reference ("for (const i of [...luaRange(1, 10)]) {}"): code 1`] = ` +"for ____, i in ipairs( + { + table.unpack( + luaRange(_G, 1, 10) + ) + } +) do +end" +`; + +exports[`invalid usage reference ("for (const i of [...luaRange(1, 10)]) {}"): diagnostics 1`] = `"main.ts(6,33): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."`; + +exports[`invalid usage reference ("let array = [0, luaRange, 1];"): code 1`] = `"local array = {0, luaRange, 1}"`; + +exports[`invalid usage reference ("let array = [0, luaRange, 1];"): diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."`; + +exports[`invalid usage reference ("luaRange.call(null, 0, 0, 0);"): code 1`] = ` +"require(\\"lualib_bundle\\"); +__TS__FunctionCall(luaRange, nil, 0, 0, 0)" +`; + +exports[`invalid usage reference ("luaRange.call(null, 0, 0, 0);"): diagnostics 1`] = `"main.ts(6,13): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."`; + +exports[`invalid usage return type: code 1`] = ` +"for i = 1, 10 do +end" +`; + +exports[`invalid usage return type: diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: function must return Iterable."`; + +exports[`invalid usage variable destructuring: code 1`] = ` +"for ____ = 1, 10, 2 do +end" +`; + +exports[`invalid usage variable destructuring: diagnostics 1`] = `"main.ts(6,18): error TSTL: Invalid @forRange call: destructuring cannot be used."`; diff --git a/test/unit/decorators/forRange.spec.ts b/test/unit/decorators/forRange.spec.ts index 14f42ca38..1d6dd4198 100644 --- a/test/unit/decorators/forRange.spec.ts +++ b/test/unit/decorators/forRange.spec.ts @@ -1,5 +1,3 @@ -import * as ts from "typescript"; -import { InvalidForRangeCall } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; const createForRangeDeclaration = (args = "i: number, j: number, k?: number", returns = "number[]") => ` @@ -30,21 +28,14 @@ describe("invalid usage", () => { util.testModule` /** @forRange */ function luaRange() {} - `.expectToHaveDiagnosticOfError( - InvalidForRangeCall( - ts.createEmptyStatement(), - "@forRange function can only be used as an iterable in a for...of loop." - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); - test.each([[1], [1, 2, 3, 4]])("argument count", args => { + test.each<[number[]]>([[[]], [[1]], [[1, 2, 3, 4]]])("argument count (%p)", args => { util.testModule` ${createForRangeDeclaration("...args: number[]")} for (const i of luaRange(${args})) {} - `.expectToHaveDiagnosticOfError( - InvalidForRangeCall(ts.createEmptyStatement(), "@forRange function must take 2 or 3 arguments.") - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("non-declared loop variable", () => { @@ -52,39 +43,28 @@ describe("invalid usage", () => { ${createForRangeDeclaration()} let i: number; for (i of luaRange(1, 10, 2)) {} - `.expectToHaveDiagnosticOfError( - InvalidForRangeCall(ts.createEmptyStatement(), "@forRange loop must declare its own control variable.") - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("argument types", () => { util.testModule` ${createForRangeDeclaration("i: string, j: number")} for (const i of luaRange("foo", 2)) {} - `.expectToHaveDiagnosticOfError( - InvalidForRangeCall(ts.createEmptyStatement(), "@forRange arguments must be number types.") - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("variable destructuring", () => { util.testModule` ${createForRangeDeclaration(undefined, "number[][]")} for (const [i] of luaRange(1, 10, 2)) {} - `.expectToHaveDiagnosticOfError( - InvalidForRangeCall(ts.createEmptyStatement(), "@forRange loop cannot use destructuring.") - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("return type", () => { util.testModule` ${createForRangeDeclaration(undefined, "string[]")} for (const i of luaRange(1, 10)) {} - `.expectToHaveDiagnosticOfError( - InvalidForRangeCall( - ts.createEmptyStatement(), - "@forRange function must return Iterable or Array." - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test.each([ @@ -97,11 +77,6 @@ describe("invalid usage", () => { util.testModule` ${createForRangeDeclaration()} ${statement} - `.expectToHaveDiagnosticOfError( - InvalidForRangeCall( - ts.createEmptyStatement(), - "@forRange function can only be used as an iterable in a for...of loop." - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); }); From 05f9f501928c53ac15fad87a748c91b15c0c33f9 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Dec 2019 15:31:49 +0000 Subject: [PATCH 08/42] Make annotation errors diagnostics --- .../utils/assignment-validation.ts | 17 -- src/transformation/utils/diagnostics.ts | 45 ++++++ src/transformation/utils/errors.ts | 33 ---- .../visitors/binary-expression/assignments.ts | 24 ++- .../visitors/binary-expression/index.ts | 8 +- src/transformation/visitors/class/index.ts | 68 ++++---- src/transformation/visitors/class/new.ts | 27 ++-- src/transformation/visitors/lua-table.ts | 78 ++++++--- .../customConstructor.spec.ts.snap | 16 ++ .../__snapshots__/extension.spec.ts.snap | 54 +++++++ .../__snapshots__/luaTable.spec.ts.snap | 149 ++++++++++++++++++ .../__snapshots__/metaExtension.spec.ts.snap | 17 ++ .../unit/decorators/customConstructor.spec.ts | 19 +-- test/unit/decorators/extension.spec.ts | 17 +- test/unit/decorators/luaTable.spec.ts | 49 +++--- test/unit/decorators/metaExtension.spec.ts | 32 ++-- 16 files changed, 449 insertions(+), 204 deletions(-) create mode 100644 test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap create mode 100644 test/unit/decorators/__snapshots__/extension.spec.ts.snap create mode 100644 test/unit/decorators/__snapshots__/luaTable.spec.ts.snap create mode 100644 test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap diff --git a/src/transformation/utils/assignment-validation.ts b/src/transformation/utils/assignment-validation.ts index c8a57dc1d..d67b984bd 100644 --- a/src/transformation/utils/assignment-validation.ts +++ b/src/transformation/utils/assignment-validation.ts @@ -1,30 +1,13 @@ import * as ts from "typescript"; import { getOrUpdate } from "../../utils"; import { TransformationContext } from "../context"; -import { AnnotationKind, getTypeAnnotations } from "./annotations"; import { - ForbiddenLuaTableUseException, UnsupportedNoSelfFunctionConversion, UnsupportedOverloadAssignment, UnsupportedSelfFunctionConversion, } from "./errors"; import { ContextType, getFunctionContextType } from "./function-context"; -// TODO: Make validateAssignment check symbols? -// TODO: Move to LuaTable plugin? -export function validatePropertyAssignment( - context: TransformationContext, - node: ts.AssignmentExpression -): void { - if (!ts.isPropertyAccessExpression(node.left)) return; - - const leftType = context.checker.getTypeAtLocation(node.left.expression); - const annotations = getTypeAnnotations(context, leftType); - if (annotations.has(AnnotationKind.LuaTable) && node.left.name.text === "length") { - throw ForbiddenLuaTableUseException(`A LuaTable object's length cannot be re-assigned.`, node); - } -} - // TODO: Clear if types are reused between compilations const typeValidationCache = new WeakMap>(); diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index c096f3ae8..f3f7f79ca 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -1,4 +1,5 @@ import * as ts from "typescript"; +import { AnnotationKind } from "./annotations"; const createDiagnosticFactory = ( message: string | ((...args: TArgs) => string), @@ -15,4 +16,48 @@ const createDiagnosticFactory = ( export const forbiddenForIn = createDiagnosticFactory(`Iterating over arrays with 'for ... in' is not allowed.`); +export const annotationInvalidArgumentCount = createDiagnosticFactory( + (kind: AnnotationKind, got: number, expected: number) => `'@${kind}' expects ${expected} arguments, but got ${got}.` +); + +export const extensionCannotConstruct = createDiagnosticFactory( + "Cannot construct classes with '@extension' or '@metaExtension' annotation." +); + +export const extensionCannotExtend = createDiagnosticFactory( + `Cannot extend classes with '@extension' or '@metaExtension' annotation.` +); + +export const extensionCannotExport = createDiagnosticFactory( + `Cannot export classes with '@extension' or '@metaExtension' annotation.` +); + +export const extensionInvalidInstanceOf = createDiagnosticFactory( + `Cannot use instanceof on classes with '@extension' or '@metaExtension' annotation.` +); + +export const extensionAndMetaExtensionConflict = createDiagnosticFactory( + `Cannot use both '@extension' and '@metaExtension' annotations on the same class.` +); + +export const metaExtensionMissingExtends = createDiagnosticFactory( + `'@metaExtension' annotation requires the extension of the metatable class.` +); + export const invalidForRangeCall = createDiagnosticFactory((message: string) => `Invalid @forRange call: ${message}.`); + +export const luaTableMustBeAmbient = createDiagnosticFactory( + "Classes with the '@luaTable' annotation must be ambient." +); + +export const luaTableCannotBeExtended = createDiagnosticFactory( + "Cannot extend classes with the '@luaTable' annotation." +); + +export const luaTableInvalidInstanceOf = createDiagnosticFactory( + "The instanceof operator cannot be used with a '@luaTable' class." +); + +export const luaTableForbiddenUsage = createDiagnosticFactory( + (description: string) => `Invalid @luaTable usage: ${description}.` +); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index 996063da2..d2ac16a49 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -10,45 +10,12 @@ export class TranspileError extends Error { const getLuaTargetName = (version: LuaTarget) => (version === LuaTarget.LuaJIT ? "LuaJIT" : `Lua ${version}`); -export const ForbiddenLuaTableNonDeclaration = (node: ts.Node) => - new TranspileError(`Classes with the '@luaTable' annotation must be declared.`, node); - -export const InvalidExtendsLuaTable = (node: ts.Node) => - new TranspileError(`Cannot extend classes with the '@luaTable' annotation.`, node); - -export const InvalidInstanceOfLuaTable = (node: ts.Node) => - new TranspileError(`The instanceof operator cannot be used with a '@luaTable' class.`, node); - -export const ForbiddenLuaTableUseException = (description: string, node: ts.Node) => - new TranspileError(`Invalid @luaTable usage: ${description}`, node); - -export const InvalidAnnotationArgumentNumber = (name: string, got: number, expected: number, node: ts.Node) => - new TranspileError(`'${name}' expects ${expected} argument(s) but got ${got}.`, node); - export const InvalidDecoratorContext = (node: ts.Node) => new TranspileError(`Decorator function cannot have 'this: void'.`, node); -export const InvalidExtensionMetaExtension = (node: ts.Node) => - new TranspileError(`Cannot use both '@extension' and '@metaExtension' annotations on the same class.`, node); - -export const InvalidNewExpressionOnExtension = (node: ts.Node) => - new TranspileError(`Cannot construct classes with '@extension' or '@metaExtension' annotation.`, node); - -export const InvalidExtendsExtension = (node: ts.Node) => - new TranspileError(`Cannot extend classes with '@extension' or '@metaExtension' annotation.`, node); - -export const InvalidExportsExtension = (node: ts.Node) => - new TranspileError(`Cannot export classes with '@extension' or '@metaExtension' annotation.`, node); - -export const InvalidInstanceOfExtension = (node: ts.Node) => - new TranspileError(`Cannot use instanceof on classes with '@extension' or '@metaExtension' annotation.`, node); - export const MissingForOfVariables = (node: ts.Node) => new TranspileError("Transpiled ForOf variable declaration list contains no declarations.", node); -export const MissingMetaExtension = (node: ts.Node) => - new TranspileError(`'@metaExtension' annotation requires the extension of the metatable class.`, node); - export const UnsupportedForInVariable = (node: ts.Node) => new TranspileError(`Unsupported for-in variable kind.`, node); diff --git a/src/transformation/visitors/binary-expression/assignments.ts b/src/transformation/visitors/binary-expression/assignments.ts index acf41aca4..969176032 100644 --- a/src/transformation/visitors/binary-expression/assignments.ts +++ b/src/transformation/visitors/binary-expression/assignments.ts @@ -3,11 +3,12 @@ import * as lua from "../../../LuaAST"; import { cast, castEach } from "../../../utils"; import { TransformationContext } from "../../context"; import { isTupleReturnCall } from "../../utils/annotations"; -import { validateAssignment, validatePropertyAssignment } from "../../utils/assignment-validation"; +import { validateAssignment } from "../../utils/assignment-validation"; import { createImmediatelyInvokedFunctionExpression, createUnpackCall, wrapInTable } from "../../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; import { isArrayType, isDestructuringAssignment } from "../../utils/typescript"; import { transformElementAccessArgument } from "../access"; +import { transformLuaTablePropertyAccessInAssignment } from "../lua-table"; import { isArrayLength, transformDestructuringAssignment } from "./destructuring-assignments"; export function transformAssignment( @@ -29,17 +30,22 @@ export function transformAssignment( ); } - return lua.createAssignmentStatement( - cast(context.transformExpression(lhs), lua.isAssignmentLeftHandSideExpression), - right, - lhs.parent - ); + let left: lua.AssignmentLeftHandSideExpression | undefined; + if (ts.isPropertyAccessExpression(lhs)) { + left = transformLuaTablePropertyAccessInAssignment(context, lhs); + } + + if (!left) { + left = cast(context.transformExpression(lhs), lua.isAssignmentLeftHandSideExpression); + } + + return lua.createAssignmentStatement(left, right, parent); } export function transformAssignmentExpression( context: TransformationContext, expression: ts.AssignmentExpression -): lua.CallExpression | lua.MethodCallExpression { +): lua.Expression { // Validate assignment const rightType = context.checker.getTypeAtLocation(expression.right); const leftType = context.checker.getTypeAtLocation(expression.left); @@ -91,6 +97,9 @@ export function transformAssignmentExpression( const objExpression = context.transformExpression(expression.left.expression); let indexExpression: lua.Expression; if (ts.isPropertyAccessExpression(expression.left)) { + // Called only for validation + transformLuaTablePropertyAccessInAssignment(context, expression.left); + // Property access indexExpression = lua.createStringLiteral(expression.left.name.text); } else { @@ -121,7 +130,6 @@ export function transformAssignmentStatement( const rightType = context.checker.getTypeAtLocation(expression.right); const leftType = context.checker.getTypeAtLocation(expression.left); validateAssignment(context, expression.right, rightType, leftType); - validatePropertyAssignment(context, expression); if (isDestructuringAssignment(expression)) { if ( diff --git a/src/transformation/visitors/binary-expression/index.ts b/src/transformation/visitors/binary-expression/index.ts index 2d0621d78..9715746a6 100644 --- a/src/transformation/visitors/binary-expression/index.ts +++ b/src/transformation/visitors/binary-expression/index.ts @@ -2,7 +2,8 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations"; -import { InvalidInstanceOfExtension, InvalidInstanceOfLuaTable, UnsupportedKind } from "../../utils/errors"; +import { extensionInvalidInstanceOf, luaTableInvalidInstanceOf } from "../../utils/diagnostics"; +import { UnsupportedKind } from "../../utils/errors"; import { createImmediatelyInvokedFunctionExpression, wrapInToStringForConcat } from "../../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; import { isStandardLibraryType, isStringType } from "../../utils/typescript"; @@ -181,12 +182,11 @@ export const transformBinaryExpression: FunctionVisitor = ( const annotations = getTypeAnnotations(context, rhsType); if (annotations.has(AnnotationKind.Extension) || annotations.has(AnnotationKind.MetaExtension)) { - // Cannot use instanceof on extension classes - throw InvalidInstanceOfExtension(node); + context.diagnostics.push(extensionInvalidInstanceOf(node)); } if (annotations.has(AnnotationKind.LuaTable)) { - throw InvalidInstanceOfLuaTable(node); + context.diagnostics.push(luaTableInvalidInstanceOf(node)); } if (isStandardLibraryType(context, rhsType, "ObjectConstructor")) { diff --git a/src/transformation/visitors/class/index.ts b/src/transformation/visitors/class/index.ts index 27fd44cb0..82f16e1fb 100644 --- a/src/transformation/visitors/class/index.ts +++ b/src/transformation/visitors/class/index.ts @@ -4,13 +4,13 @@ import { assert, getOrUpdate, isNonNull } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations"; import { - ForbiddenLuaTableNonDeclaration, - InvalidExportsExtension, - InvalidExtendsExtension, - InvalidExtendsLuaTable, - InvalidExtensionMetaExtension, - MissingMetaExtension, -} from "../../utils/errors"; + extensionAndMetaExtensionConflict, + extensionCannotExport, + extensionCannotExtend, + metaExtensionMissingExtends, + luaTableMustBeAmbient, + luaTableCannotBeExtended, +} from "../../utils/diagnostics"; import { createDefaultExportIdentifier, createExportedIdentifier, @@ -96,15 +96,16 @@ export function transformClassDeclaration( const isMetaExtension = annotations.has(AnnotationKind.MetaExtension); if (isExtension && isMetaExtension) { - throw InvalidExtensionMetaExtension(classDeclaration); + context.diagnostics.push(extensionAndMetaExtensionConflict(classDeclaration)); } if ((isExtension || isMetaExtension) && getIdentifierExportScope(context, className) !== undefined) { // Cannot export extension classes - throw InvalidExportsExtension(classDeclaration); + context.diagnostics.push(extensionCannotExport(classDeclaration)); } // Get type that is extended + const extendsTypeNode = getExtendedTypeNode(context, classDeclaration); const extendsType = getExtendedType(context, classDeclaration); if (extendsType) { @@ -115,7 +116,7 @@ export function transformClassDeclaration( // Non-extensions cannot extend extension classes const extendsAnnotations = getTypeAnnotations(context, extendsType); if (extendsAnnotations.has(AnnotationKind.Extension) || extendsAnnotations.has(AnnotationKind.MetaExtension)) { - throw InvalidExtendsExtension(classDeclaration); + context.diagnostics.push(extensionCannotExtend(classDeclaration)); } } @@ -123,13 +124,12 @@ export function transformClassDeclaration( if (extendsType) { const annotations = getTypeAnnotations(context, extendsType); if (annotations.has(AnnotationKind.LuaTable)) { - throw InvalidExtendsLuaTable(classDeclaration); + context.diagnostics.push(luaTableCannotBeExtended(extendsTypeNode!)); } } - // LuaTable classes must be ambient if (annotations.has(AnnotationKind.LuaTable) && !isAmbientNode(classDeclaration)) { - throw ForbiddenLuaTableNonDeclaration(classDeclaration); + context.diagnostics.push(luaTableMustBeAmbient(classDeclaration)); } // Get all properties with value @@ -143,30 +143,30 @@ export function transformClassDeclaration( // Overwrite the original className with the class we are overriding for extensions if (isMetaExtension) { - if (!extendsType) { - throw MissingMetaExtension(classDeclaration); - } - - const extendsName = lua.createStringLiteral(extendsType.symbol.name as string); - className = lua.createIdentifier("__meta__" + extendsName.value); - - // local className = debug.getregistry()["extendsName"] - const assignDebugCallIndex = lua.createVariableDeclarationStatement( - className, - lua.createTableIndexExpression( - lua.createCallExpression( - lua.createTableIndexExpression( - lua.createIdentifier("debug"), - lua.createStringLiteral("getregistry") + if (extendsType) { + const extendsName = lua.createStringLiteral(extendsType.symbol.name); + className = lua.createIdentifier("__meta__" + extendsName.value); + + // local className = debug.getregistry()["extendsName"] + const assignDebugCallIndex = lua.createVariableDeclarationStatement( + className, + lua.createTableIndexExpression( + lua.createCallExpression( + lua.createTableIndexExpression( + lua.createIdentifier("debug"), + lua.createStringLiteral("getregistry") + ), + [] ), - [] + extendsName ), - extendsName - ), - classDeclaration - ); + classDeclaration + ); - result.push(assignDebugCallIndex); + result.push(assignDebugCallIndex); + } else { + context.diagnostics.push(metaExtensionMissingExtends(classDeclaration)); + } } if (extensionDirective !== undefined) { diff --git a/src/transformation/visitors/class/new.ts b/src/transformation/visitors/class/new.ts index f83329b7a..7db671521 100644 --- a/src/transformation/visitors/class/new.ts +++ b/src/transformation/visitors/class/new.ts @@ -2,7 +2,7 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations"; -import { InvalidAnnotationArgumentNumber, InvalidNewExpressionOnExtension } from "../../utils/errors"; +import { annotationInvalidArgumentCount, extensionCannotConstruct } from "../../utils/diagnostics"; import { importLuaLibFeature, LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; import { transformArguments } from "../call"; import { transformLuaTableNewExpression } from "../lua-table"; @@ -66,20 +66,27 @@ export const transformNewExpression: FunctionVisitor = (node, const annotations = getTypeAnnotations(context, type); if (annotations.has(AnnotationKind.Extension) || annotations.has(AnnotationKind.MetaExtension)) { - throw InvalidNewExpressionOnExtension(node); + context.diagnostics.push(extensionCannotConstruct(node)); } const customConstructorAnnotation = annotations.get(AnnotationKind.CustomConstructor); if (customConstructorAnnotation) { - if (customConstructorAnnotation.args[0] === undefined) { - throw InvalidAnnotationArgumentNumber("@customConstructor", 0, 1, node); + if (customConstructorAnnotation.args.length === 1) { + return lua.createCallExpression( + lua.createIdentifier(customConstructorAnnotation.args[0]), + transformArguments(context, node.arguments ?? []), + node + ); + } else { + context.diagnostics.push( + annotationInvalidArgumentCount( + node, + AnnotationKind.CustomConstructor, + customConstructorAnnotation.args.length, + 1 + ) + ); } - - return lua.createCallExpression( - lua.createIdentifier(customConstructorAnnotation.args[0]), - transformArguments(context, node.arguments ?? []), - node - ); } return transformLuaLibFunction(context, LuaLibFeature.New, node, name, ...params); diff --git a/src/transformation/visitors/lua-table.ts b/src/transformation/visitors/lua-table.ts index ceee50e34..49b0a25ed 100644 --- a/src/transformation/visitors/lua-table.ts +++ b/src/transformation/visitors/lua-table.ts @@ -2,7 +2,8 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; import { AnnotationKind, getTypeAnnotations } from "../utils/annotations"; -import { ForbiddenLuaTableUseException, UnsupportedKind, UnsupportedProperty } from "../utils/errors"; +import { luaTableForbiddenUsage } from "../utils/diagnostics"; +import { UnsupportedKind, UnsupportedProperty } from "../utils/errors"; import { transformArguments } from "./call"; function parseLuaTableExpression( @@ -16,21 +17,32 @@ function parseLuaTableExpression( } } -function validateLuaTableCall(methodName: string, callArguments: ts.NodeArray, original: ts.Node): void { - if (callArguments.some(argument => ts.isSpreadElement(argument))) { - throw ForbiddenLuaTableUseException("Arguments cannot be spread.", original); +function validateLuaTableCall( + context: TransformationContext, + node: ts.Node, + methodName: string, + callArguments: ts.NodeArray +): void { + for (const argument of callArguments) { + if (ts.isSpreadElement(argument)) { + context.diagnostics.push(luaTableForbiddenUsage(argument, "Arguments cannot be spread")); + } } switch (methodName) { case "get": if (callArguments.length !== 1) { - throw ForbiddenLuaTableUseException("One parameter is required for get().", original); + context.diagnostics.push( + luaTableForbiddenUsage(node, `Expected 1 arguments, but got ${callArguments.length}`) + ); } break; case "set": if (callArguments.length !== 2) { - throw ForbiddenLuaTableUseException("Two parameters are required for set().", original); + context.diagnostics.push( + luaTableForbiddenUsage(node, `Expected 2 arguments, but got ${callArguments.length}`) + ); } break; } @@ -41,7 +53,7 @@ function transformLuaTableExpressionAsExpressionStatement( expression: ts.CallExpression ): lua.Statement { const [luaTable, methodName] = parseLuaTableExpression(context, expression.expression); - validateLuaTableCall(methodName, expression.arguments, expression); + validateLuaTableCall(context, expression, methodName, expression.arguments); const signature = context.checker.getResolvedSignature(expression); const params = transformArguments(context, expression.arguments, signature); @@ -49,13 +61,13 @@ function transformLuaTableExpressionAsExpressionStatement( case "get": return lua.createVariableDeclarationStatement( lua.createAnonymousIdentifier(expression), - lua.createTableIndexExpression(luaTable, params[0], expression), + lua.createTableIndexExpression(luaTable, params[0] ?? lua.createNilLiteral(), expression), expression ); case "set": return lua.createAssignmentStatement( - lua.createTableIndexExpression(luaTable, params[0], expression), - params.splice(1), + lua.createTableIndexExpression(luaTable, params[0] ?? lua.createNilLiteral(), expression), + [params[1] ?? lua.createNilLiteral()], expression ); default: @@ -88,13 +100,13 @@ export function transformLuaTableCallExpression( if (annotations.has(AnnotationKind.LuaTable)) { const [luaTable, methodName] = parseLuaTableExpression(context, node.expression); - validateLuaTableCall(methodName, node.arguments, node); + validateLuaTableCall(context, node, methodName, node.arguments); const signature = context.checker.getResolvedSignature(node); const params = transformArguments(context, node.arguments, signature); switch (methodName) { case "get": - return lua.createTableIndexExpression(luaTable, params[0], node); + return lua.createTableIndexExpression(luaTable, params[0] ?? lua.createNilLiteral(), node); default: throw UnsupportedProperty("LuaTable", methodName, node); } @@ -108,15 +120,33 @@ export function transformLuaTablePropertyAccessExpression( ): lua.Expression | undefined { const type = context.checker.getTypeAtLocation(node.expression); const annotations = getTypeAnnotations(context, type); - if (annotations.has(AnnotationKind.LuaTable)) { - const [luaTable, propertyName] = parseLuaTableExpression(context, node); - switch (node.name.text) { - case "length": - return lua.createUnaryExpression(luaTable, lua.SyntaxKind.LengthOperator, node); - default: - throw UnsupportedProperty("LuaTable", propertyName, node); - } + if (!annotations.has(AnnotationKind.LuaTable)) return; + + const [luaTable, propertyName] = parseLuaTableExpression(context, node); + if (propertyName !== "length") { + throw UnsupportedProperty("LuaTable", propertyName, node); } + + return lua.createUnaryExpression(luaTable, lua.SyntaxKind.LengthOperator, node); +} + +export function transformLuaTablePropertyAccessInAssignment( + context: TransformationContext, + node: ts.PropertyAccessExpression +): lua.AssignmentLeftHandSideExpression | undefined { + if (!ts.isPropertyAccessExpression(node)) return; + + const type = context.checker.getTypeAtLocation(node.expression); + const annotations = getTypeAnnotations(context, type); + if (!annotations.has(AnnotationKind.LuaTable)) return; + + const [luaTable, propertyName] = parseLuaTableExpression(context, node); + if (propertyName !== "length") { + throw UnsupportedProperty("LuaTable", propertyName, node); + } + + context.diagnostics.push(luaTableForbiddenUsage(node, `A LuaTable object's length cannot be re-assigned`)); + return lua.createTableIndexExpression(luaTable, lua.createStringLiteral(propertyName), node); } export function transformLuaTableElementAccessExpression( @@ -137,9 +167,11 @@ export function transformLuaTableNewExpression( const annotations = getTypeAnnotations(context, type); if (annotations.has(AnnotationKind.LuaTable)) { if (node.arguments && node.arguments.length > 0) { - throw ForbiddenLuaTableUseException("No parameters are allowed when constructing a LuaTable object.", node); - } else { - return lua.createTableExpression(); + context.diagnostics.push( + luaTableForbiddenUsage(node, "No parameters are allowed when constructing a LuaTable object") + ); } + + return lua.createTableExpression(); } } diff --git a/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap b/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap new file mode 100644 index 000000000..c283485bf --- /dev/null +++ b/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IncorrectUsage: code 1`] = ` +"require(\\"lualib_bundle\\"); +local ____exports = {} +function ____exports.__main(self) + local Point2D = __TS__Class() + Point2D.name = \\"Point2D\\" + function Point2D.prototype.____constructor(self) + end + __TS__New(Point2D) +end +return ____exports" +`; + +exports[`IncorrectUsage: diagnostics 1`] = `"main.ts(5,9): error TSTL: '@customConstructor' expects 1 arguments, but got 0."`; diff --git a/test/unit/decorators/__snapshots__/extension.spec.ts.snap b/test/unit/decorators/__snapshots__/extension.spec.ts.snap new file mode 100644 index 000000000..7ce990102 --- /dev/null +++ b/test/unit/decorators/__snapshots__/extension.spec.ts.snap @@ -0,0 +1,54 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Class construct extension ("extension"): code 1`] = ` +"require(\\"lualib_bundle\\"); +local b = __TS__New(B)" +`; + +exports[`Class construct extension ("extension"): diagnostics 1`] = `"main.ts(5,19): error TSTL: Cannot construct classes with '@extension' or '@metaExtension' annotation."`; + +exports[`Class construct extension ("metaExtension"): code 1`] = ` +"require(\\"lualib_bundle\\"); +local __meta__A = debug.getregistry().A +local b = __TS__New(B)" +`; + +exports[`Class construct extension ("metaExtension"): diagnostics 1`] = `"main.ts(5,19): error TSTL: Cannot construct classes with '@extension' or '@metaExtension' annotation."`; + +exports[`Class extends extension ("extension"): code 1`] = ` +"require(\\"lualib_bundle\\"); +C = __TS__Class() +C.name = \\"C\\" +C.____super = B +setmetatable(C, C.____super) +setmetatable(C.prototype, C.____super.prototype)" +`; + +exports[`Class extends extension ("extension"): diagnostics 1`] = `"main.ts(5,9): error TSTL: Cannot extend classes with '@extension' or '@metaExtension' annotation."`; + +exports[`Class extends extension ("metaExtension"): code 1`] = ` +"require(\\"lualib_bundle\\"); +local __meta__A = debug.getregistry().A +C = __TS__Class() +C.name = \\"C\\" +C.____super = B +setmetatable(C, C.____super) +setmetatable(C.prototype, C.____super.prototype)" +`; + +exports[`Class extends extension ("metaExtension"): diagnostics 1`] = `"main.ts(5,9): error TSTL: Cannot extend classes with '@extension' or '@metaExtension' annotation."`; + +exports[`instanceof extension ("extension"): code 1`] = ` +"require(\\"lualib_bundle\\"); +local result = __TS__InstanceOf(foo, B)" +`; + +exports[`instanceof extension ("extension"): diagnostics 1`] = `"main.ts(6,24): error TSTL: Cannot use instanceof on classes with '@extension' or '@metaExtension' annotation."`; + +exports[`instanceof extension ("metaExtension"): code 1`] = ` +"require(\\"lualib_bundle\\"); +local __meta__A = debug.getregistry().A +local result = __TS__InstanceOf(foo, B)" +`; + +exports[`instanceof extension ("metaExtension"): diagnostics 1`] = `"main.ts(6,24): error TSTL: Cannot use instanceof on classes with '@extension' or '@metaExtension' annotation."`; diff --git a/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap b/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap new file mode 100644 index 000000000..704721806 --- /dev/null +++ b/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap @@ -0,0 +1,149 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Cannot extend LuaTable class ("class Ext extends Table {}"): code 1`] = ` +"require(\\"lualib_bundle\\"); +Ext = __TS__Class() +Ext.name = \\"Ext\\" +Ext.____super = Table +setmetatable(Ext, Ext.____super) +setmetatable(Ext.prototype, Ext.____super.prototype)" +`; + +exports[`Cannot extend LuaTable class ("class Ext extends Table {}"): diagnostics 1`] = `"main.ts(11,19): error TSTL: Cannot extend classes with the '@luaTable' annotation."`; + +exports[`Cannot extend LuaTable class ("const c = class Ext extends Table {}"): code 1`] = ` +"require(\\"lualib_bundle\\"); +local c = (function() + local Ext = __TS__Class() + Ext.name = \\"Ext\\" + Ext.____super = Table + setmetatable(Ext, Ext.____super) + setmetatable(Ext.prototype, Ext.____super.prototype) + return Ext +end)()" +`; + +exports[`Cannot extend LuaTable class ("const c = class Ext extends Table {}"): diagnostics 1`] = `"main.ts(11,29): error TSTL: Cannot extend classes with the '@luaTable' annotation."`; + +exports[`Cannot set LuaTable length: code 1`] = `"tbl.length = 2"`; + +exports[`Cannot set LuaTable length: code 2`] = `"tbl.length = 2"`; + +exports[`Cannot set LuaTable length: diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: A LuaTable object's length cannot be re-assigned."`; + +exports[`Cannot set LuaTable length: diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: A LuaTable object's length cannot be re-assigned."`; + +exports[`Cannot use instanceof on a LuaTable class ("tbl instanceof Table"): code 1`] = ` +"require(\\"lualib_bundle\\"); +__TS__InstanceOf(tbl, Table)" +`; + +exports[`Cannot use instanceof on a LuaTable class ("tbl instanceof Table"): diagnostics 1`] = `"main.ts(11,1): error TSTL: The instanceof operator cannot be used with a '@luaTable' class."`; + +exports[`Forbidden LuaTable use ("tbl.get()"): code 1`] = `"local ____ = tbl[nil]"`; + +exports[`Forbidden LuaTable use ("tbl.get()"): code 2`] = `"local ____ = tbl[nil]"`; + +exports[`Forbidden LuaTable use ("tbl.get()"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 0."`; + +exports[`Forbidden LuaTable use ("tbl.get()"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 0."`; + +exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): code 1`] = `"local ____ = tbl.field"`; + +exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): code 2`] = `"local ____ = tbl.field"`; + +exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 2."`; + +exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 2."`; + +exports[`Forbidden LuaTable use ("tbl.set()"): code 1`] = `"tbl[nil] = nil"`; + +exports[`Forbidden LuaTable use ("tbl.set()"): code 2`] = `"tbl[nil] = nil"`; + +exports[`Forbidden LuaTable use ("tbl.set()"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 0."`; + +exports[`Forbidden LuaTable use ("tbl.set()"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 0."`; + +exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): code 1`] = `"tbl[table.unpack(({\\"field\\", 0}))] = nil"`; + +exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): code 2`] = `"tbl[table.unpack(({\\"field\\", 0}))] = nil"`; + +exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 1`] = ` +"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1. +main.ts(11,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread." +`; + +exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 2`] = ` +"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1. +main.ts(11,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread." +`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): code 1`] = `"tbl.field = nil"`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): code 2`] = `"tbl.field = nil"`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1."`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1."`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): code 1`] = `"tbl.field = table.unpack(({0}))"`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): code 2`] = `"tbl.field = table.unpack(({0}))"`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): diagnostics 1`] = `"main.ts(11,18): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): diagnostics 2`] = `"main.ts(11,18): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): code 1`] = `"tbl.field = 0"`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): code 2`] = `"tbl.field = 0"`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 1`] = ` +"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3. +main.ts(11,21): error TS2554: Expected 0-2 arguments, but got 3." +`; + +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 2`] = ` +"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3. +main.ts(11,21): error TS2554: Expected 0-2 arguments, but got 3." +`; + +exports[`LuaTable classes must be ambient ("/** @luaTable */ class Table {}"): code 1`] = ` +"require(\\"lualib_bundle\\"); +Table = __TS__Class() +Table.name = \\"Table\\" +function Table.prototype.____constructor(self) +end" +`; + +exports[`LuaTable classes must be ambient ("/** @luaTable */ class Table {}"): diagnostics 1`] = `"main.ts(1,18): error TSTL: Classes with the '@luaTable' annotation must be ambient."`; + +exports[`LuaTable classes must be ambient ("/** @luaTable */ const c = class Table {}"): code 1`] = ` +"require(\\"lualib_bundle\\"); +local c = (function() + local Table = __TS__Class() + Table.name = \\"Table\\" + function Table.prototype.____constructor(self) + end + return Table +end)()" +`; + +exports[`LuaTable classes must be ambient ("/** @luaTable */ const c = class Table {}"): diagnostics 1`] = `"main.ts(1,28): error TSTL: Classes with the '@luaTable' annotation must be ambient."`; + +exports[`LuaTable classes must be ambient ("/** @luaTable */ export class Table {}"): code 1`] = ` +"require(\\"lualib_bundle\\"); +local ____exports = {} +____exports.Table = __TS__Class() +local Table = ____exports.Table +Table.name = \\"Table\\" +function Table.prototype.____constructor(self) +end +return ____exports" +`; + +exports[`LuaTable classes must be ambient ("/** @luaTable */ export class Table {}"): diagnostics 1`] = `"main.ts(1,18): error TSTL: Classes with the '@luaTable' annotation must be ambient."`; + +exports[`LuaTables cannot be constructed with arguments: code 1`] = `"local ____table = {}"`; + +exports[`LuaTables cannot be constructed with arguments: diagnostics 1`] = `"main.ts(11,15): error TSTL: Invalid @luaTable usage: No parameters are allowed when constructing a LuaTable object."`; diff --git a/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap b/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap new file mode 100644 index 000000000..2c9611bd0 --- /dev/null +++ b/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DontAllowInstantiation: code 1`] = ` +"require(\\"lualib_bundle\\"); +local __meta___LOADED = debug.getregistry()._LOADED +local e = __TS__New(Ext)" +`; + +exports[`DontAllowInstantiation: diagnostics 1`] = `"main.ts(5,19): error TSTL: Cannot construct classes with '@extension' or '@metaExtension' annotation."`; + +exports[`IncorrectUsage: code 1`] = ` +"function LoadedExt.test(self) + return 5 +end" +`; + +exports[`IncorrectUsage: diagnostics 1`] = `"main.ts(3,9): error TSTL: '@metaExtension' annotation requires the extension of the metatable class."`; diff --git a/test/unit/decorators/customConstructor.spec.ts b/test/unit/decorators/customConstructor.spec.ts index 856a566f0..035ec56fc 100644 --- a/test/unit/decorators/customConstructor.spec.ts +++ b/test/unit/decorators/customConstructor.spec.ts @@ -1,4 +1,3 @@ -import { InvalidAnnotationArgumentNumber } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; test("CustomCreate", () => { @@ -25,16 +24,10 @@ test("CustomCreate", () => { }); test("IncorrectUsage", () => { - expect(() => { - util.transpileString(` - /** @customConstructor */ - class Point2D { - constructor( - public x: number, - public y: number - ) {} - } - return new Point2D(1, 2).x; - `); - }).toThrowExactError(InvalidAnnotationArgumentNumber("@customConstructor", 0, 1, util.nodeStub)); + util.testFunction` + /** @customConstructor */ + class Point2D {} + + new Point2D(); + `.expectDiagnosticsToMatchSnapshot(); }); diff --git a/test/unit/decorators/extension.spec.ts b/test/unit/decorators/extension.spec.ts index 18e41719c..aa297f744 100644 --- a/test/unit/decorators/extension.spec.ts +++ b/test/unit/decorators/extension.spec.ts @@ -1,28 +1,21 @@ -import { - InvalidExtendsExtension, - InvalidInstanceOfExtension, - InvalidNewExpressionOnExtension, -} from "../../../src/transformation/utils/errors"; import * as util from "../../util"; test.each(["extension", "metaExtension"])("Class extends extension (%p)", extensionType => { - const code = ` + util.testModule` declare class A {} /** @${extensionType} **/ class B extends A {} class C extends B {} - `; - expect(() => util.transpileString(code)).toThrowExactError(InvalidExtendsExtension(util.nodeStub)); + `.expectDiagnosticsToMatchSnapshot(); }); test.each(["extension", "metaExtension"])("Class construct extension (%p)", extensionType => { - const code = ` + util.testModule` declare class A {} /** @${extensionType} **/ class B extends A {} const b = new B(); - `; - expect(() => util.transpileString(code)).toThrowExactError(InvalidNewExpressionOnExtension(util.nodeStub)); + `.expectDiagnosticsToMatchSnapshot(); }); test.each(["extension", "metaExtension"])("instanceof extension (%p)", extensionType => { @@ -32,5 +25,5 @@ test.each(["extension", "metaExtension"])("instanceof extension (%p)", extension class B extends A {} declare const foo: any; const result = foo instanceof B; - `.expectToHaveDiagnosticOfError(InvalidInstanceOfExtension(util.nodeStub)); + `.expectDiagnosticsToMatchSnapshot(); }); diff --git a/test/unit/decorators/luaTable.spec.ts b/test/unit/decorators/luaTable.spec.ts index 95813e5ce..3e41ceefb 100644 --- a/test/unit/decorators/luaTable.spec.ts +++ b/test/unit/decorators/luaTable.spec.ts @@ -1,12 +1,5 @@ import * as ts from "typescript"; -import { - ForbiddenLuaTableNonDeclaration, - ForbiddenLuaTableUseException, - InvalidExtendsLuaTable, - InvalidInstanceOfLuaTable, - UnsupportedKind, - UnsupportedProperty, -} from "../../../src/transformation/utils/errors"; +import { UnsupportedKind, UnsupportedProperty } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; const tableLibClass = ` @@ -15,28 +8,27 @@ declare class Table { length: number; constructor(notAllowed?: boolean); set(key?: K, value?: V): void; - get(key?: K): V; + get(key?: K, notAllowed?: K): V; other(): void; } declare let tbl: Table; `; +// TODO: `constructor()` is not valid in interfaces const tableLibInterface = ` /** @luaTable */ declare interface Table { length: number; constructor(notAllowed?: boolean); set(key?: K, value?: V): void; - get(key?: K): V; + get(key?: K, notAllowed?: K): V; other(): void; } declare let tbl: Table; `; test.each([tableLibClass])("LuaTables cannot be constructed with arguments", tableLib => { - expect(() => util.transpileString(tableLib + `const table = new Table(true);`)).toThrowExactError( - ForbiddenLuaTableUseException("No parameters are allowed when constructing a LuaTable object.", util.nodeStub) - ); + util.testModule(tableLib + `const table = new Table(true);`).expectDiagnosticsToMatchSnapshot(); }); test.each([tableLibClass, tableLibInterface])( @@ -72,23 +64,20 @@ test.each([tableLibClass])("LuaTable length", tableLib => { }); test.each([tableLibClass, tableLibInterface])("Cannot set LuaTable length", tableLib => { - expect(() => util.transpileString(tableLib + `tbl.length = 2;`)).toThrowExactError( - ForbiddenLuaTableUseException("A LuaTable object's length cannot be re-assigned.", util.nodeStub) - ); + util.testModule(tableLib + `tbl.length = 2;`).expectDiagnosticsToMatchSnapshot(); }); test.each([tableLibClass, tableLibInterface])("Forbidden LuaTable use", tableLib => { test.each([ - [`tbl.get()`, "One parameter is required for get()."], - [`tbl.get("field", "field2")`, "One parameter is required for get()."], - [`tbl.set()`, "Two parameters are required for set()."], - [`tbl.set("field")`, "Two parameters are required for set()."], - [`tbl.set("field", 0, 1)`, "Two parameters are required for set()."], - [`tbl.set("field", ...[0, 1])`, "Arguments cannot be spread."], - ])("Forbidden LuaTable use (%p)", (invalidCode, errorDescription) => { - expect(() => util.transpileString(tableLib + invalidCode)).toThrowExactError( - ForbiddenLuaTableUseException(errorDescription, util.nodeStub) - ); + "tbl.get()", + 'tbl.get("field", "field2")', + "tbl.set()", + 'tbl.set("field")', + 'tbl.set("field", 0, 1)', + 'tbl.set(...(["field", 0] as const))', + 'tbl.set("field", ...([0] as const))', + ])("Forbidden LuaTable use (%p)", invalidCode => { + util.testModule(tableLib + invalidCode).expectDiagnosticsToMatchSnapshot(); }); }); @@ -96,9 +85,7 @@ test.each([tableLibClass])("Cannot extend LuaTable class", tableLib => { test.each([`class Ext extends Table {}`, `const c = class Ext extends Table {}`])( "Cannot extend LuaTable class (%p)", code => { - expect(() => util.transpileString(tableLib + code)).toThrowExactError( - InvalidExtendsLuaTable(util.nodeStub) - ); + util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot(); } ); }); @@ -108,12 +95,12 @@ test.each([ `/** @luaTable */ export class Table {}`, `/** @luaTable */ const c = class Table {}`, ])("LuaTable classes must be ambient (%p)", code => { - expect(() => util.transpileString(code)).toThrowExactError(ForbiddenLuaTableNonDeclaration(util.nodeStub)); + util.testModule(code).expectDiagnosticsToMatchSnapshot(); }); test.each([tableLibClass])("Cannot extend LuaTable class", tableLib => { test.each([`tbl instanceof Table`])("Cannot use instanceof on a LuaTable class (%p)", code => { - expect(() => util.transpileString(tableLib + code)).toThrowExactError(InvalidInstanceOfLuaTable(util.nodeStub)); + util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot(); }); }); diff --git a/test/unit/decorators/metaExtension.spec.ts b/test/unit/decorators/metaExtension.spec.ts index 76b40c791..c2a83b6fe 100644 --- a/test/unit/decorators/metaExtension.spec.ts +++ b/test/unit/decorators/metaExtension.spec.ts @@ -1,4 +1,3 @@ -import { InvalidNewExpressionOnExtension, MissingMetaExtension } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; test("MetaExtension", () => { @@ -26,26 +25,21 @@ test("MetaExtension", () => { }); test("IncorrectUsage", () => { - expect(() => { - util.transpileString(` - /** @metaExtension */ - class LoadedExt { - public static test() { - return 5; - } + util.testModule` + /** @metaExtension */ + class LoadedExt { + public static test() { + return 5; } - `); - }).toThrowExactError(MissingMetaExtension(util.nodeStub)); + } + `.expectDiagnosticsToMatchSnapshot(); }); test("DontAllowInstantiation", () => { - expect(() => { - util.transpileString(` - declare class _LOADED {} - /** @metaExtension */ - class Ext extends _LOADED { - } - const e = new Ext(); - `); - }).toThrowExactError(InvalidNewExpressionOnExtension(util.nodeStub)); + util.testModule` + declare class _LOADED {} + /** @metaExtension */ + class Ext extends _LOADED {} + const e = new Ext(); + `.expectDiagnosticsToMatchSnapshot(); }); From a08e239c80fd3c5c5c1b9abae7e151398b1b9d6c Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Dec 2019 15:32:30 +0000 Subject: [PATCH 09/42] Make unsupported `luaIterator` usage error a diagnostic --- src/transformation/utils/diagnostics.ts | 6 ++ src/transformation/utils/errors.ts | 8 -- src/transformation/visitors/loops/for-of.ts | 63 ++++++------- .../__snapshots__/luaIterator.spec.ts.snap | 16 ++++ test/unit/decorators/luaIterator.spec.ts | 90 +++---------------- 5 files changed, 63 insertions(+), 120 deletions(-) create mode 100644 test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index f3f7f79ca..595ca7e10 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -61,3 +61,9 @@ export const luaTableInvalidInstanceOf = createDiagnosticFactory( export const luaTableForbiddenUsage = createDiagnosticFactory( (description: string) => `Invalid @luaTable usage: ${description}.` ); + +export const luaIteratorForbiddenUsage = createDiagnosticFactory( + "Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. " + + "You must use a destructuring statement to catch results from a lua iterator with " + + "the '@tupleReturn' annotation." +); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index d2ac16a49..2d83b43ff 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -57,14 +57,6 @@ export const UnsupportedOverloadAssignment = (node: ts.Node, name?: string) => { ); }; -export const UnsupportedNonDestructuringLuaIterator = (node: ts.Node) => - new TranspileError( - "Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. " + - "You must use a destructuring statement to catch results from a lua iterator with " + - "the '@tupleReturn' annotation.", - node - ); - export const UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => new TranspileError(`${reason}. TypeScript path: ${path}.`, node); diff --git a/src/transformation/visitors/loops/for-of.ts b/src/transformation/visitors/loops/for-of.ts index 7c929b91b..cbdd29767 100644 --- a/src/transformation/visitors/loops/for-of.ts +++ b/src/transformation/visitors/loops/for-of.ts @@ -3,12 +3,8 @@ import * as lua from "../../../LuaAST"; import { assert, cast, castEach } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations, isForRangeType, isLuaIteratorType } from "../../utils/annotations"; -import { invalidForRangeCall } from "../../utils/diagnostics"; -import { - MissingForOfVariables, - UnsupportedNonDestructuringLuaIterator, - UnsupportedObjectDestructuringInForOf, -} from "../../utils/errors"; +import { invalidForRangeCall, luaIteratorForbiddenUsage } from "../../utils/diagnostics"; +import { MissingForOfVariables, UnsupportedObjectDestructuringInForOf } from "../../utils/errors"; import { createUnpackCall } from "../../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; import { isArrayType, isNumberType } from "../../utils/typescript"; @@ -128,47 +124,42 @@ function transformForOfLuaIteratorStatement( const luaIterator = context.transformExpression(statement.expression); const type = context.checker.getTypeAtLocation(statement.expression); const tupleReturn = getTypeAnnotations(context, type).has(AnnotationKind.TupleReturn); + let identifiers: lua.Identifier[] = []; + if (tupleReturn) { // LuaIterator + TupleReturn if (ts.isVariableDeclarationList(statement.initializer)) { // Variables declared in for loop // for ${initializer} in ${iterable} do const initializerVariable = statement.initializer.declarations[0].name; + if (ts.isArrayBindingPattern(initializerVariable)) { - const identifiers = castEach( + identifiers = castEach( initializerVariable.elements.map(e => transformArrayBindingElement(context, e)), lua.isIdentifier ); - if (identifiers.length === 0) { - identifiers.push(lua.createAnonymousIdentifier()); - } - return lua.createForInStatement(block, identifiers, [luaIterator]); } else { - // Single variable is not allowed - throw UnsupportedNonDestructuringLuaIterator(statement.initializer); + context.diagnostics.push(luaIteratorForbiddenUsage(initializerVariable)); } } else { // Variables NOT declared in for loop - catch iterator values in temps and assign // for ____value0 in ${iterable} do // ${initializer} = ____value0 if (ts.isArrayLiteralExpression(statement.initializer)) { - const tmps = statement.initializer.elements.map((_, i) => lua.createIdentifier(`____value${i}`)); - if (tmps.length > 0) { - const assign = lua.createAssignmentStatement( - castEach( - statement.initializer.elements.map(e => context.transformExpression(e)), - lua.isAssignmentLeftHandSideExpression - ), - tmps + identifiers = statement.initializer.elements.map((_, i) => lua.createIdentifier(`____value${i}`)); + if (identifiers.length > 0) { + block.statements.unshift( + lua.createAssignmentStatement( + castEach( + statement.initializer.elements.map(e => context.transformExpression(e)), + lua.isAssignmentLeftHandSideExpression + ), + identifiers + ) ); - block.statements.splice(0, 0, assign); - } else { - tmps.push(lua.createAnonymousIdentifier()); } - return lua.createForInStatement(block, tmps, [luaIterator]); } else { - // Single variable is not allowed - throw UnsupportedNonDestructuringLuaIterator(statement.initializer); + context.diagnostics.push(luaIteratorForbiddenUsage(statement.initializer)); } } } else { @@ -179,23 +170,25 @@ function transformForOfLuaIteratorStatement( ) { // Single variable declared in for loop // for ${initializer} in ${iterator} do - return lua.createForInStatement( - block, - [transformIdentifier(context, statement.initializer.declarations[0].name)], - [luaIterator] - ); + identifiers.push(transformIdentifier(context, statement.initializer.declarations[0].name)); } else { // Destructuring or variable NOT declared in for loop // for ____value in ${iterator} do - // local ${initializer} = unpack(____value) + // local ${initializer} = ____value const valueVariable = lua.createIdentifier("____value"); const initializer = transformForOfInitializer(context, statement.initializer, valueVariable); if (initializer) { - block.statements.splice(0, 0, initializer); + identifiers.push(valueVariable); + block.statements.unshift(initializer); } - return lua.createForInStatement(block, [valueVariable], [luaIterator]); } } + + if (identifiers.length === 0) { + identifiers.push(lua.createAnonymousIdentifier()); + } + + return lua.createForInStatement(block, identifiers, [luaIterator]); } function transformForOfArrayStatement( diff --git a/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap b/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap new file mode 100644 index 000000000..00f10a7e4 --- /dev/null +++ b/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`forof lua iterator tuple-return single existing variable: code 1`] = ` +"local x +for ____ in luaIter(_G) do +end" +`; + +exports[`forof lua iterator tuple-return single existing variable: diagnostics 1`] = `"main.ts(9,14): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."`; + +exports[`forof lua iterator tuple-return single variable: code 1`] = ` +"for ____ in luaIter(_G) do +end" +`; + +exports[`forof lua iterator tuple-return single variable: diagnostics 1`] = `"main.ts(8,18): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."`; diff --git a/test/unit/decorators/luaIterator.spec.ts b/test/unit/decorators/luaIterator.spec.ts index 122c6e7fb..3804bf6bb 100644 --- a/test/unit/decorators/luaIterator.spec.ts +++ b/test/unit/decorators/luaIterator.spec.ts @@ -1,6 +1,3 @@ -import * as ts from "typescript"; -import * as tstl from "../../../src"; -import { UnsupportedNonDestructuringLuaIterator } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; test("forof lua iterator", () => { @@ -16,12 +13,7 @@ test("forof lua iterator", () => { for (let e of luaIter()) { result += e; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("abc"); }); @@ -38,12 +30,7 @@ test("forof array lua iterator", () => { for (let e of luaIter()) { result += e; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("abc"); }); @@ -61,12 +48,7 @@ test("forof lua iterator with existing variable", () => { for (e of luaIter()) { result += e; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("abc"); }); @@ -83,12 +65,7 @@ test("forof lua iterator destructuring", () => { for (let [a, b] of luaIter()) { result += a + b; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("0a1b2c"); }); @@ -107,12 +84,7 @@ test("forof lua iterator destructuring with existing variables", () => { for ([a, b] of luaIter()) { result += a + b; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("0a1b2c"); }); @@ -134,12 +106,7 @@ test("forof lua iterator tuple-return", () => { for (let [a, b] of luaIter()) { result += a + b; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("0a1b2c"); }); @@ -163,17 +130,12 @@ test("forof lua iterator tuple-return with existing variables", () => { for ([a, b] of luaIter()) { result += a + b; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("0a1b2c"); }); test("forof lua iterator tuple-return single variable", () => { - const code = ` + util.testModule` /** * @luaIterator * @tupleReturn @@ -181,19 +143,11 @@ test("forof lua iterator tuple-return single variable", () => { interface Iter extends Iterable<[string, string]> {} declare function luaIter(): Iter; for (let x of luaIter()) {} - `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - expect(() => util.transpileString(code, compilerOptions)).toThrowExactError( - UnsupportedNonDestructuringLuaIterator(util.nodeStub) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("forof lua iterator tuple-return single existing variable", () => { - const code = ` + util.testModule` /** * @luaIterator * @tupleReturn @@ -202,15 +156,7 @@ test("forof lua iterator tuple-return single existing variable", () => { declare function luaIter(): Iter; let x: [string, string]; for (x of luaIter()) {} - `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - expect(() => util.transpileString(code, compilerOptions)).toThrowExactError( - UnsupportedNonDestructuringLuaIterator(util.nodeStub) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("forof forwarded lua iterator", () => { @@ -231,12 +177,7 @@ test("forof forwarded lua iterator", () => { for (let a of forward()) { result += a; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("abc"); }); @@ -262,11 +203,6 @@ test("forof forwarded lua iterator with tupleReturn", () => { for (let [a, b] of forward()) { result += a + b; } return result; `; - const compilerOptions = { - luaLibImport: tstl.LuaLibImportKind.Require, - luaTarget: tstl.LuaTarget.Lua53, - target: ts.ScriptTarget.ES2015, - }; - const result = util.transpileAndExecute(code, compilerOptions); + const result = util.transpileAndExecute(code); expect(result).toBe("0a1b2c"); }); From 0306f280bb3a9ed5088e96a46c30b3d6a0343e9a Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Dec 2019 16:34:48 +0000 Subject: [PATCH 10/42] Make function assignment errors diagnostics --- src/transformation/builtins/function.ts | 5 +- .../utils/assignment-validation.ts | 14 +- src/transformation/utils/diagnostics.ts | 24 + src/transformation/utils/errors.ts | 27 - .../invalidFunctionAssignments.spec.ts.snap | 1723 +++++++++++++++++ .../validation/functionPermutations.ts | 42 +- .../invalidFunctionAssignments.spec.ts | 209 +- .../validFunctionAssignments.spec.ts | 35 +- test/util.ts | 6 +- 9 files changed, 1866 insertions(+), 219 deletions(-) create mode 100644 test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap diff --git a/src/transformation/builtins/function.ts b/src/transformation/builtins/function.ts index 2eefae340..e2f2c7e29 100644 --- a/src/transformation/builtins/function.ts +++ b/src/transformation/builtins/function.ts @@ -1,6 +1,7 @@ import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { UnsupportedProperty, UnsupportedSelfFunctionConversion } from "../utils/errors"; +import { unsupportedSelfFunctionConversion } from "../utils/diagnostics"; +import { UnsupportedProperty } from "../utils/errors"; import { ContextType, getFunctionContextType } from "../utils/function-context"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; @@ -12,7 +13,7 @@ export function transformFunctionPrototypeCall( const expression = node.expression; const callerType = context.checker.getTypeAtLocation(expression.expression); if (getFunctionContextType(context, callerType) === ContextType.Void) { - throw UnsupportedSelfFunctionConversion(node); + context.diagnostics.push(unsupportedSelfFunctionConversion(node)); } const signature = context.checker.getResolvedSignature(node); diff --git a/src/transformation/utils/assignment-validation.ts b/src/transformation/utils/assignment-validation.ts index d67b984bd..05cfea467 100644 --- a/src/transformation/utils/assignment-validation.ts +++ b/src/transformation/utils/assignment-validation.ts @@ -2,10 +2,10 @@ import * as ts from "typescript"; import { getOrUpdate } from "../../utils"; import { TransformationContext } from "../context"; import { - UnsupportedNoSelfFunctionConversion, - UnsupportedOverloadAssignment, - UnsupportedSelfFunctionConversion, -} from "./errors"; + unsupportedNoSelfFunctionConversion, + unsupportedOverloadAssignment, + unsupportedSelfFunctionConversion, +} from "./diagnostics"; import { ContextType, getFunctionContextType } from "./function-context"; // TODO: Clear if types are reused between compilations @@ -97,12 +97,12 @@ function validateFunctionAssignment( const toContext = getFunctionContextType(context, toType); if (fromContext === ContextType.Mixed || toContext === ContextType.Mixed) { - throw UnsupportedOverloadAssignment(node, toName); + context.diagnostics.push(unsupportedOverloadAssignment(node, toName)); } else if (fromContext !== toContext && fromContext !== ContextType.None && toContext !== ContextType.None) { if (toContext === ContextType.Void) { - throw UnsupportedNoSelfFunctionConversion(node, toName); + context.diagnostics.push(unsupportedNoSelfFunctionConversion(node, toName)); } else { - throw UnsupportedSelfFunctionConversion(node, toName); + context.diagnostics.push(unsupportedSelfFunctionConversion(node, toName)); } } } diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index 595ca7e10..9aebcbd98 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -16,6 +16,30 @@ const createDiagnosticFactory = ( export const forbiddenForIn = createDiagnosticFactory(`Iterating over arrays with 'for ... in' is not allowed.`); +export const unsupportedNoSelfFunctionConversion = createDiagnosticFactory((name?: string) => { + const nameReference = name ? ` '${name}'` : ""; + return ( + `Unable to convert function with a 'this' parameter to function${nameReference} with no 'this'. ` + + `To fix, wrap in an arrow function, or declare with 'this: void'.` + ); +}); + +export const unsupportedSelfFunctionConversion = createDiagnosticFactory((name?: string) => { + const nameReference = name ? ` '${name}'` : ""; + return ( + `Unable to convert function with no 'this' parameter to function${nameReference} with 'this'. ` + + `To fix, wrap in an arrow function, or declare with 'this: any'.` + ); +}); + +export const unsupportedOverloadAssignment = createDiagnosticFactory((name?: string) => { + const nameReference = name ? ` to '${name}'` : ""; + return ( + `Unsupported assignment of function with different overloaded types for 'this'${nameReference}. ` + + "Overloads should all have the same type for 'this'." + ); +}); + export const annotationInvalidArgumentCount = createDiagnosticFactory( (kind: AnnotationKind, got: number, expected: number) => `'@${kind}' expects ${expected} arguments, but got ${got}.` ); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index 2d83b43ff..0447a5a74 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -30,33 +30,6 @@ export const UnsupportedProperty = (parentName: string, property: string, node: export const UnsupportedForTarget = (functionality: string, version: LuaTarget, node: ts.Node) => new TranspileError(`${functionality} is/are not supported for target ${getLuaTargetName(version)}.`, node); -export const UnsupportedNoSelfFunctionConversion = (node: ts.Node, name?: string) => { - const nameReference = name ? ` '${name}'` : ""; - return new TranspileError( - `Unable to convert function with a 'this' parameter to function${nameReference} with no 'this'. ` + - `To fix, wrap in an arrow function, or declare with 'this: void'.`, - node - ); -}; - -export const UnsupportedSelfFunctionConversion = (node: ts.Node, name?: string) => { - const nameReference = name ? ` '${name}'` : ""; - return new TranspileError( - `Unable to convert function with no 'this' parameter to function${nameReference} with 'this'. ` + - `To fix, wrap in an arrow function or declare with 'this: any'.`, - node - ); -}; - -export const UnsupportedOverloadAssignment = (node: ts.Node, name?: string) => { - const nameReference = name ? ` to '${name}'` : ""; - return new TranspileError( - `Unsupported assignment of function with different overloaded types for 'this'${nameReference}. ` + - "Overloads should all have the same type for 'this'.", - node - ); -}; - export const UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => new TranspileError(`${reason}. TypeScript path: ${path}.`, node); diff --git a/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap b/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap new file mode 100644 index 000000000..06ab4a8b4 --- /dev/null +++ b/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap @@ -0,0 +1,1723 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { + method() { return function(s: string) { return s; } } + } + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { + export class MethodClass { + method(s: string): string { return s; } + } + } + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { + export interface MethodInterface { + method(s: string): string; + } + } + const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { + method: function(s: string): string { return s; } + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { + method() { return function(s: string) { return s; } } + } + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { + export function noSelfInFileNsFunc(s: string) { return s; } + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { + export let noSelfInFileNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } + /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class AnonStaticFuncPropClass { + static anonStaticFuncProp: (s: string) => string = s => s; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class StaticFuncPropClass { + static staticFuncProp: (this: any, s: string) => string = s => s; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class StaticMethodClass { + static staticMethod(this: any, s: string): string { return s; } + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } + const anonMethodInterface: AnonMethodInterface = { + anonMethod: function(this: any, s: string): string { return s; } + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "interface MethodInterface { method(this: any, s: string): string; } + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "namespace FuncNestedNs { + export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "namespace LambdaNestedNs { + export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "namespace LambdaNs { + export let nsLambda: (s: string) => string = s => s; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function argument with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = ` +"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function argument with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 2`] = ` +"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function argument with cast ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = ` +"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function argument with cast ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 2`] = ` +"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function argument with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = ` +"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function argument with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = ` +"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function argument with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 3`] = ` +"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function argument with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 4`] = ` +"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { + method() { return function(s: string) { return s; } } + } + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { + export class MethodClass { + method(s: string): string { return s; } + } + } + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { + export interface MethodInterface { + method(s: string): string; + } + } + const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { + method: function(s: string): string { return s; } + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { + method() { return function(s: string) { return s; } } + } + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { + export function noSelfInFileNsFunc(s: string) { return s; } + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { + export let noSelfInFileNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } + /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class AnonStaticFuncPropClass { + static anonStaticFuncProp: (s: string) => string = s => s; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class StaticFuncPropClass { + static staticFuncProp: (this: any, s: string) => string = s => s; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class StaticMethodClass { + static staticMethod(this: any, s: string): string { return s; } + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } + const anonMethodInterface: AnonMethodInterface = { + anonMethod: function(this: any, s: string): string { return s; } + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "interface MethodInterface { method(this: any, s: string): string; } + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "namespace FuncNestedNs { + export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "namespace LambdaNestedNs { + export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "namespace LambdaNs { + export let nsLambda: (s: string) => string = s => s; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function assignment ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function assignment with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = ` +"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function assignment with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 2`] = ` +"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function assignment with cast ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = ` +"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function assignment with cast ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 2`] = ` +"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function assignment with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = ` +"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function assignment with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = ` +"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function assignment with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 3`] = ` +"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function assignment with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 4`] = ` +"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { + method() { return function(s: string) { return s; } } + } + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { + export class MethodClass { + method(s: string): string { return s; } + } + } + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { + export interface MethodInterface { + method(s: string): string; + } + } + const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { + method: function(s: string): string { return s; } + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { + method() { return function(s: string) { return s; } } + } + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { + export function noSelfInFileNsFunc(s: string) { return s; } + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { + export let noSelfInFileNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } + /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class AnonStaticFuncPropClass { + static anonStaticFuncProp: (s: string) => string = s => s; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class StaticFuncPropClass { + static staticFuncProp: (this: any, s: string) => string = s => s; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class StaticMethodClass { + static staticMethod(this: any, s: string): string { return s; } + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } + const anonMethodInterface: AnonMethodInterface = { + anonMethod: function(this: any, s: string): string { return s; } + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "interface MethodInterface { method(this: any, s: string): string; } + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "namespace FuncNestedNs { + export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "namespace LambdaNestedNs { + export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "namespace LambdaNs { + export let nsLambda: (s: string) => string = s => s; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function generic argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function generic argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function overload assignment ("(this: void, s: string) => string"): diagnostics 1`] = `"main.ts(7,52): error TSTL: Unsupported assignment of function with different overloaded types for 'this'. Overloads should all have the same type for 'this'."`; + +exports[`Invalid function overload assignment ("(this: void, s1: string, s2: string) => string"): diagnostics 1`] = `"main.ts(7,65): error TSTL: Unsupported assignment of function with different overloaded types for 'this'. Overloads should all have the same type for 'this'."`; + +exports[`Invalid function overload assignment ("{(this: any, s1: string, s2: string): string}"): diagnostics 1`] = `"main.ts(7,64): error TSTL: Unsupported assignment of function with different overloaded types for 'this'. Overloads should all have the same type for 'this'."`; + +exports[`Invalid function overload assignment ("{(this: void, s: string): string}"): diagnostics 1`] = `"main.ts(7,52): error TSTL: Unsupported assignment of function with different overloaded types for 'this'. Overloads should all have the same type for 'this'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { + method() { return function(s: string) { return s; } } + } + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { + export class MethodClass { + method(s: string): string { return s; } + } + } + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { + export interface MethodInterface { + method(s: string): string; + } + } + const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { + method: function(s: string): string { return s; } + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { + method() { return function(s: string) { return s; } } + } + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { + export function noSelfInFileNsFunc(s: string) { return s; } + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { + export let noSelfInFileNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } + /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class AnonStaticFuncPropClass { + static anonStaticFuncProp: (s: string) => string = s => s; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class StaticFuncPropClass { + static staticFuncProp: (this: any, s: string) => string = s => s; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class StaticMethodClass { + static staticMethod(this: any, s: string): string { return s; } + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } + const anonMethodInterface: AnonMethodInterface = { + anonMethod: function(this: any, s: string): string { return s; } + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "interface MethodInterface { method(this: any, s: string): string; } + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "namespace FuncNestedNs { + export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "namespace LambdaNestedNs { + export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "namespace LambdaNs { + export let nsLambda: (s: string) => string = s => s; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function return ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function return with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = ` +"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function return with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 2`] = ` +"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function return with cast ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = ` +"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'. +main.ts(4,20): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'." +`; + +exports[`Invalid function return with cast ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 2`] = ` +"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'. +main.ts(4,20): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'." +`; + +exports[`Invalid function return with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = ` +"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function return with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = ` +"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function return with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 3`] = ` +"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function return with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 4`] = ` +"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +`; + +exports[`Invalid function tuple assignment: diagnostics 1`] = ` +"main.ts(5,13): error TS2322: Type '[number, Meth]' is not assignable to type '[number, Func]'. + Type 'Meth' is not assignable to type 'Func'. + The 'this' types of each signature are incompatible. + Type 'void' is not assignable to type '{}'. +main.ts(5,38): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'." +`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { + method() { return function(s: string) { return s; } } + } + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(6,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(5,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } + namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(4,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(4,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(4,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(4,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(5,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { + static noSelfStaticFuncProp: (s: string) => string = s => s; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(5,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { + static noSelfStaticMethod(s: string): string { return s; } + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(6,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { + noSelfMethod(s: string): string { return s; } + } + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(6,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(6,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } + const noSelfFuncPropInterface: NoSelfFuncPropInterface = { + noSelfFuncProp: (s: string): string => s + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(6,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(6,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } + const noSelfMethodInterface: NoSelfMethodInterface = { + noSelfMethod: function(s: string): string { return s; } + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(6,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(9,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { + export class AnonFunctionNestedInClass { + method() { return function(s: string) { return s; } } + } + } + const anonFunctionNestedInClassInNoSelfNs = + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(9,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { + export class MethodClass { + method(s: string): string { return s; } + } + } + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(8,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { + export interface MethodInterface { + method(s: string): string; + } + } + const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { + method: function(s: string): string { return s; } + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(10,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(5,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { + export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(3,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(3,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(5,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { + export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(5,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { + export let noSelfNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { + method() { return function(s: string) { return s; } } + } + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(6,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(3,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(3,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { + export function noSelfInFileNsFunc(s: string) { return s; } + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { + export let noSelfInFileNsLambda: (s: string) => string = s => s; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } + /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(5,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class AnonStaticFuncPropClass { + static anonStaticFuncProp: (s: string) => string = s => s; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(5,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(3,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(4,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(4,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class StaticFuncPropClass { + static staticFuncProp: (this: any, s: string) => string = s => s; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(5,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class StaticMethodClass { + static staticMethod(this: any, s: string): string { return s; } + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(5,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(5,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class StaticVoidFuncPropClass { + static staticVoidFuncProp: (this: void, s: string) => string = s => s; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(5,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class StaticVoidMethodClass { + static staticVoidMethod(this: void, s: string): string { return s; } + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(5,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(6,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class VoidFuncPropClass { + voidFuncProp: (this: void, s: string) => string = s => s; + } + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(6,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(6,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "class VoidMethodClass { + voidMethod(this: void, s: string): string { return s; } + } + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(6,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } + const anonMethodInterface: AnonMethodInterface = { + anonMethod: function(this: any, s: string): string { return s; } + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(6,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "interface MethodInterface { method(this: any, s: string): string; } + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(8,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "interface VoidFuncPropInterface { + voidFuncProp: (this: void, s: string) => string; + } + const voidFuncPropInterface: VoidFuncPropInterface = { + voidFuncProp: function(this: void, s: string): string { return s; } + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(8,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(8,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "interface VoidMethodInterface { + voidMethod(this: void, s: string): string; + } + const voidMethodInterface: VoidMethodInterface = { + voidMethod(this: void, s: string): string { return s; } + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(8,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(3,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(3,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(3,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(3,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(3,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(3,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(3,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(3,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "namespace FuncNestedNs { + export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(5,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(3,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "namespace LambdaNestedNs { + export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(5,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "namespace LambdaNs { + export let nsLambda: (s: string) => string = s => s; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(5,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(4,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(4,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(4,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(3,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(3,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(3,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(3,59): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid function variable declaration ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(3,47): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid function variable declaration ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(3,58): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid interface method assignment: diagnostics 1`] = `"main.ts(5,22): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + +exports[`Invalid lua lib function argument: diagnostics 1`] = `"main.ts(4,19): error TSTL: Unable to convert function with no 'this' parameter to function 'callbackfn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + +exports[`Invalid method tuple assignment: diagnostics 1`] = `"main.ts(5,38): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; diff --git a/test/unit/functions/validation/functionPermutations.ts b/test/unit/functions/validation/functionPermutations.ts index 2602e2ba7..b5e233d7c 100644 --- a/test/unit/functions/validation/functionPermutations.ts +++ b/test/unit/functions/validation/functionPermutations.ts @@ -348,11 +348,7 @@ export const anonTestFunctionType = "(s: string) => string"; export const selfTestFunctionType = "(this: any, s: string) => string"; export const noSelfTestFunctionType = "(this: void, s: string) => string"; -type TestFunctionCast = [ - /*testFunction: */ TestFunction, - /*castedFunction: */ string, - /*isSelfConversion?: */ boolean? -]; +type TestFunctionCast = [TestFunction, string]; export const validTestFunctionCasts: TestFunctionCast[] = [ [selfTestFunctions[0], `<${anonTestFunctionType}>(${selfTestFunctions[0].value})`], [selfTestFunctions[0], `(${selfTestFunctions[0].value}) as (${anonTestFunctionType})`], @@ -366,21 +362,17 @@ export const validTestFunctionCasts: TestFunctionCast[] = [ [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${noSelfTestFunctionType})`], ]; export const invalidTestFunctionCasts: TestFunctionCast[] = [ - [noSelfTestFunctions[0], `<${anonTestFunctionType}>(${noSelfTestFunctions[0].value})`, false], - [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${anonTestFunctionType})`, false], - [noSelfTestFunctions[0], `<${selfTestFunctionType}>(${noSelfTestFunctions[0].value})`, false], - [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${selfTestFunctionType})`, false], - [noSelfInFileTestFunctions[0], `<${selfTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`, false], - [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${selfTestFunctionType})`, false], - [selfTestFunctions[0], `<${noSelfTestFunctionType}>(${selfTestFunctions[0].value})`, true], - [selfTestFunctions[0], `(${selfTestFunctions[0].value}) as (${noSelfTestFunctionType})`, true], + [noSelfTestFunctions[0], `<${anonTestFunctionType}>(${noSelfTestFunctions[0].value})`], + [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${anonTestFunctionType})`], + [noSelfTestFunctions[0], `<${selfTestFunctionType}>(${noSelfTestFunctions[0].value})`], + [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${selfTestFunctionType})`], + [noSelfInFileTestFunctions[0], `<${selfTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`], + [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${selfTestFunctionType})`], + [selfTestFunctions[0], `<${noSelfTestFunctionType}>(${selfTestFunctions[0].value})`], + [selfTestFunctions[0], `(${selfTestFunctions[0].value}) as (${noSelfTestFunctionType})`], ]; -export type TestFunctionAssignment = [ - /*testFunction: */ TestFunction, - /*functionType: */ string, - /*isSelfConversion?: */ boolean? -]; +export type TestFunctionAssignment = [TestFunction, string]; export const validTestFunctionAssignments: TestFunctionAssignment[] = [ ...selfTestFunctions.map((f): TestFunctionAssignment => [f, anonTestFunctionType]), ...selfTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), @@ -395,11 +387,11 @@ export const validTestFunctionAssignments: TestFunctionAssignment[] = [ ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), ]; export const invalidTestFunctionAssignments: TestFunctionAssignment[] = [ - ...selfTestFunctions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType, false]), - ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, anonTestFunctionType, true]), - ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), - ...noSelfInFileTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), - ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType, false]), - ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, anonTestFunctionType, true]), - ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), + ...selfTestFunctions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), + ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, anonTestFunctionType]), + ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), + ...noSelfInFileTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), + ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), + ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, anonTestFunctionType]), + ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), ]; diff --git a/test/unit/functions/validation/invalidFunctionAssignments.spec.ts b/test/unit/functions/validation/invalidFunctionAssignments.spec.ts index 4f2e385be..b08b5a66d 100644 --- a/test/unit/functions/validation/invalidFunctionAssignments.spec.ts +++ b/test/unit/functions/validation/invalidFunctionAssignments.spec.ts @@ -1,191 +1,107 @@ -import { - UnsupportedNoSelfFunctionConversion, - UnsupportedOverloadAssignment, - UnsupportedSelfFunctionConversion, -} from "../../../../src/transformation/utils/errors"; import * as util from "../../../util"; import { invalidTestFunctionAssignments, invalidTestFunctionCasts } from "./functionPermutations"; test.each(invalidTestFunctionAssignments)( "Invalid function variable declaration (%p)", - (testFunction, functionType, isSelfConversion) => { - const code = ` + (testFunction, functionType) => { + util.testModule` ${testFunction.definition || ""} const fn: ${functionType} = ${testFunction.value}; - `; - const err = isSelfConversion - ? UnsupportedSelfFunctionConversion(util.nodeStub) - : UnsupportedNoSelfFunctionConversion(util.nodeStub); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); + `.expectDiagnosticsToMatchSnapshot(true); } ); -test.each(invalidTestFunctionAssignments)( - "Invalid function assignment (%p)", - (testFunction, functionType, isSelfConversion) => { - const code = ` - ${testFunction.definition || ""} - let fn: ${functionType}; - fn = ${testFunction.value}; - `; - const err = isSelfConversion - ? UnsupportedSelfFunctionConversion(util.nodeStub) - : UnsupportedNoSelfFunctionConversion(util.nodeStub); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - } -); +test.each(invalidTestFunctionAssignments)("Invalid function assignment (%p)", (testFunction, functionType) => { + util.testModule` + ${testFunction.definition || ""} + let fn: ${functionType}; + fn = ${testFunction.value}; + `.expectDiagnosticsToMatchSnapshot(true); +}); -test.each(invalidTestFunctionCasts)( - "Invalid function assignment with cast (%p)", - (testFunction, castedFunction, isSelfConversion) => { - const code = ` - ${testFunction.definition || ""} - let fn: typeof ${testFunction.value}; - fn = ${castedFunction}; - `; - const err = isSelfConversion - ? UnsupportedSelfFunctionConversion(util.nodeStub) - : UnsupportedNoSelfFunctionConversion(util.nodeStub); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - } -); +test.each(invalidTestFunctionCasts)("Invalid function assignment with cast (%p)", (testFunction, castedFunction) => { + util.testModule` + ${testFunction.definition || ""} + let fn: typeof ${testFunction.value}; + fn = ${castedFunction}; + `.expectDiagnosticsToMatchSnapshot(true); +}); -test.each(invalidTestFunctionAssignments)( - "Invalid function argument (%p)", - (testFunction, functionType, isSelfConversion) => { - const code = ` - ${testFunction.definition || ""} - declare function takesFunction(fn: ${functionType}); - takesFunction(${testFunction.value}); - `; - const err = isSelfConversion - ? UnsupportedSelfFunctionConversion(util.nodeStub, "fn") - : UnsupportedNoSelfFunctionConversion(util.nodeStub, "fn"); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - } -); +test.each(invalidTestFunctionAssignments)("Invalid function argument (%p)", (testFunction, functionType) => { + util.testModule` + ${testFunction.definition || ""} + declare function takesFunction(fn: ${functionType}); + takesFunction(${testFunction.value}); + `.expectDiagnosticsToMatchSnapshot(true); +}); test("Invalid lua lib function argument", () => { - const code = ` + util.testModule` declare function foo(this: void, value: string): void; declare const a: string[]; a.forEach(foo); - `; - const err = UnsupportedSelfFunctionConversion(util.nodeStub, "callbackfn"); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); + `.expectDiagnosticsToMatchSnapshot(true); }); -test.each(invalidTestFunctionCasts)( - "Invalid function argument with cast (%p)", - (testFunction, castedFunction, isSelfConversion) => { - const code = ` - ${testFunction.definition || ""} - declare function takesFunction(fn: typeof ${testFunction.value}); - takesFunction(${castedFunction}); - `; - // TODO: Changed in #705 because of order change in `transformArguments`. - // After #412 both errors should be reported. - const err = isSelfConversion - ? UnsupportedNoSelfFunctionConversion(util.nodeStub) - : UnsupportedSelfFunctionConversion(util.nodeStub); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - } -); - -test.each(invalidTestFunctionAssignments)( - "Invalid function generic argument (%p)", - (testFunction, functionType, isSelfConversion) => { - const code = ` - ${testFunction.definition || ""} - declare function takesFunction(fn: T); - takesFunction(${testFunction.value}); - `; - const err = isSelfConversion - ? UnsupportedSelfFunctionConversion(util.nodeStub, "fn") - : UnsupportedNoSelfFunctionConversion(util.nodeStub, "fn"); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - } -); - -test.each(invalidTestFunctionAssignments)( - "Invalid function return (%p)", - (testFunction, functionType, isSelfConversion) => { - const code = ` - ${testFunction.definition || ""} - function returnsFunction(): ${functionType} { - return ${testFunction.value}; - } - `; - const err = isSelfConversion - ? UnsupportedSelfFunctionConversion(util.nodeStub) - : UnsupportedNoSelfFunctionConversion(util.nodeStub); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - } -); +test.each(invalidTestFunctionCasts)("Invalid function argument with cast (%p)", (testFunction, castedFunction) => { + util.testModule` + ${testFunction.definition || ""} + declare function takesFunction(fn: typeof ${testFunction.value}); + takesFunction(${castedFunction}); + `.expectDiagnosticsToMatchSnapshot(true); +}); -test.each(invalidTestFunctionCasts)( - "Invalid function return with cast (%p)", - (testFunction, castedFunction, isSelfConversion) => { - const code = ` - ${testFunction.definition || ""} - function returnsFunction(): typeof ${testFunction.value} { - return ${castedFunction}; - } - `; - const err = isSelfConversion - ? UnsupportedSelfFunctionConversion(util.nodeStub) - : UnsupportedNoSelfFunctionConversion(util.nodeStub); - expect(() => util.transpileString(code, undefined, false)).toThrowExactError(err); - } -); +test.each(invalidTestFunctionAssignments)("Invalid function generic argument (%p)", (testFunction, functionType) => { + util.testModule` + ${testFunction.definition || ""} + declare function takesFunction(fn: T); + takesFunction(${testFunction.value}); + `.expectDiagnosticsToMatchSnapshot(true); +}); -test("Interface method assignment", () => { - const code = ` - class Foo { - method(s: string): string { return s + "+method"; } - lambdaProp: (s: string) => string = s => s + "+lambdaProp"; +test.each(invalidTestFunctionAssignments)("Invalid function return (%p)", (testFunction, functionType) => { + util.testModule` + ${testFunction.definition || ""} + function returnsFunction(): ${functionType} { + return ${testFunction.value}; } - interface IFoo { - method: (s: string) => string; - lambdaProp(s: string): string; + `.expectDiagnosticsToMatchSnapshot(true); +}); + +test.each(invalidTestFunctionCasts)("Invalid function return with cast (%p)", (testFunction, castedFunction) => { + util.testModule` + ${testFunction.definition || ""} + function returnsFunction(): typeof ${testFunction.value} { + return ${castedFunction}; } - const foo: IFoo = new Foo(); - return foo.method("foo") + "|" + foo.lambdaProp("bar"); - `; - const result = util.transpileAndExecute(code); - expect(result).toBe("foo+method|bar+lambdaProp"); + `.expectDiagnosticsToMatchSnapshot(true); }); test("Invalid function tuple assignment", () => { - const code = ` + util.testModule` interface Func { (this: void, s: string): string; } interface Meth { (this: {}, s: string): string; } declare function getTuple(): [number, Meth]; let [i, f]: [number, Func] = getTuple(); - `; - expect(() => util.transpileString(code)).toThrowExactError(UnsupportedNoSelfFunctionConversion(util.nodeStub)); + `.expectDiagnosticsToMatchSnapshot(true); }); test("Invalid method tuple assignment", () => { - const code = ` + util.testModule` interface Func { (this: void, s: string): string; } interface Meth { (this: {}, s: string): string; } declare function getTuple(): [number, Func]; let [i, f]: [number, Meth] = getTuple(); - `; - expect(() => util.transpileString(code)).toThrowExactError(UnsupportedSelfFunctionConversion(util.nodeStub)); + `.expectDiagnosticsToMatchSnapshot(true); }); test("Invalid interface method assignment", () => { - const code = ` + util.testModule` interface A { fn(s: string): string; } interface B { fn(this: void, s: string): string; } declare const a: A; const b: B = a; - `; - expect(() => util.transpileString(code)).toThrowExactError( - UnsupportedNoSelfFunctionConversion(util.nodeStub, "fn") - ); + `.expectDiagnosticsToMatchSnapshot(true); }); test.each([ @@ -194,13 +110,12 @@ test.each([ "{(this: void, s: string): string}", "{(this: any, s1: string, s2: string): string}", ])("Invalid function overload assignment (%p)", assignType => { - const code = ` + util.testModule` interface O { (this: any, s1: string, s2: string): string; (this: void, s: string): string; } declare const o: O; let f: ${assignType} = o; - `; - expect(() => util.transpileString(code)).toThrowExactError(UnsupportedOverloadAssignment(util.nodeStub)); + `.expectDiagnosticsToMatchSnapshot(true); }); diff --git a/test/unit/functions/validation/validFunctionAssignments.spec.ts b/test/unit/functions/validation/validFunctionAssignments.spec.ts index be1130ba6..4b4721d63 100644 --- a/test/unit/functions/validation/validFunctionAssignments.spec.ts +++ b/test/unit/functions/validation/validFunctionAssignments.spec.ts @@ -144,16 +144,21 @@ test("Valid function tuple assignment", () => { expect(result).toBe("foo"); }); -test("Valid method tuple assignment", () => { - const code = `interface Foo { method(s: string): string; } - interface Meth { (this: Foo, s: string): string; } - let meth: Meth = s => s; - function getTuple(): [number, Meth] { return [1, meth]; } - let [i, f]: [number, Meth] = getTuple(); - let foo: Foo = {method: f}; - return foo.method("foo");`; +test("Interface method assignment", () => { + const code = ` + class Foo { + method(s: string): string { return s + "+method"; } + lambdaProp: (s: string) => string = s => s + "+lambdaProp"; + } + interface IFoo { + method: (s: string) => string; + lambdaProp(s: string): string; + } + const foo: IFoo = new Foo(); + return foo.method("foo") + "|" + foo.lambdaProp("bar"); + `; const result = util.transpileAndExecute(code); - expect(result).toBe("foo"); + expect(result).toBe("foo+method|bar+lambdaProp"); }); test("Valid interface method assignment", () => { @@ -166,6 +171,18 @@ test("Valid interface method assignment", () => { expect(result).toBe("foo"); }); +test("Valid method tuple assignment", () => { + const code = `interface Foo { method(s: string): string; } + interface Meth { (this: Foo, s: string): string; } + let meth: Meth = s => s; + function getTuple(): [number, Meth] { return [1, meth]; } + let [i, f]: [number, Meth] = getTuple(); + let foo: Foo = {method: f}; + return foo.method("foo");`; + const result = util.transpileAndExecute(code); + expect(result).toBe("foo"); +}); + test.each([ { assignType: "(this: any, s: string) => string", args: ["foo"], expectResult: "foobar" }, { assignType: "{(this: any, s: string): string}", args: ["foo"], expectResult: "foobar" }, diff --git a/test/util.ts b/test/util.ts index 4eb4ef092..4977f1469 100644 --- a/test/util.ts +++ b/test/util.ts @@ -365,7 +365,7 @@ export abstract class TestBuilder { return this; } - public expectDiagnosticsToMatchSnapshot(): this { + public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this { this.expectToHaveDiagnostics(); const diagnosticMessages = ts.formatDiagnostics( @@ -373,8 +373,10 @@ export abstract class TestBuilder { { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } ); - expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); expect(diagnosticMessages.trim()).toMatchSnapshot("diagnostics"); + if (!diagnosticsOnly) { + expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); + } return this; } From 8d9a91b4e70a83c7ade83306dce9853e73f77ba9 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Dec 2019 22:21:53 +0000 Subject: [PATCH 11/42] Replace UnsupportedKind errors with diagnostics or better types --- src/transformation/context/context.ts | 2 +- src/transformation/utils/diagnostics.ts | 16 ++ src/transformation/utils/errors.ts | 3 - src/transformation/visitors/access.ts | 4 +- .../visitors/binary-expression/bit.ts | 67 ++++--- .../visitors/binary-expression/compound.ts | 37 ++-- .../destructuring-assignments.ts | 18 +- .../visitors/binary-expression/index.ts | 187 +++++++----------- src/transformation/visitors/call.ts | 3 +- src/transformation/visitors/literal.ts | 9 +- src/transformation/visitors/lua-table.ts | 105 ++++------ src/transformation/visitors/typeof.ts | 58 +++--- .../visitors/unary-expression.ts | 6 +- .../visitors/variable-declaration.ts | 17 +- .../__snapshots__/expressions.spec.ts.snap | 19 ++ .../__snapshots__/luaTable.spec.ts.snap | 24 +++ test/unit/decorators/luaTable.spec.ts | 6 +- test/unit/expressions.spec.ts | 11 +- 18 files changed, 307 insertions(+), 285 deletions(-) diff --git a/src/transformation/context/context.ts b/src/transformation/context/context.ts index 69aa542bb..b756ac9df 100644 --- a/src/transformation/context/context.ts +++ b/src/transformation/context/context.ts @@ -47,7 +47,7 @@ export class TransformationContext { const nodeVisitors = this.visitorMap.get(node.kind); if (!nodeVisitors || nodeVisitors.length === 0) { - throw new Error(`${ts.SyntaxKind[node.kind]} is not supported`); + throw new Error(`Unsupported node kind: ${ts.SyntaxKind[node.kind]}.`); } const previousNodeVisitors = this.currentNodeVisitors; diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index 9aebcbd98..ccf3634ae 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -82,6 +82,8 @@ export const luaTableInvalidInstanceOf = createDiagnosticFactory( "The instanceof operator cannot be used with a '@luaTable' class." ); +export const luaTableCannotBeAccessedDynamically = createDiagnosticFactory("@luaTable cannot be accessed dynamically."); + export const luaTableForbiddenUsage = createDiagnosticFactory( (description: string) => `Invalid @luaTable usage: ${description}.` ); @@ -91,3 +93,17 @@ export const luaIteratorForbiddenUsage = createDiagnosticFactory( "You must use a destructuring statement to catch results from a lua iterator with " + "the '@tupleReturn' annotation." ); + +export const unsupportedSyntaxKind = createDiagnosticFactory( + (description: string, kind: ts.SyntaxKind) => `Unsupported ${description} kind: ${ts.SyntaxKind[kind]}` +); + +export const unsupportedNullishCoalescing = createDiagnosticFactory("Nullish coalescing is not supported."); + +export const unsupportedAccessorInObjectLiteral = createDiagnosticFactory( + "Accessors in object literal are not supported." +); + +export const unsupportedRightShiftOperator = createDiagnosticFactory( + "Right shift operator is not supported. Use `>>>` instead." +); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index 0447a5a74..c9f21a38e 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -21,9 +21,6 @@ export const UnsupportedForInVariable = (node: ts.Node) => export const UndefinedScope = () => new Error("Expected to pop a scope, but found undefined."); -export const UnsupportedKind = (description: string, kind: ts.SyntaxKind, node: ts.Node) => - new TranspileError(`Unsupported ${description} kind: ${ts.SyntaxKind[kind]}`, node); - export const UnsupportedProperty = (parentName: string, property: string, node: ts.Node) => new TranspileError(`Unsupported property on ${parentName}: ${property}`, node); diff --git a/src/transformation/visitors/access.ts b/src/transformation/visitors/access.ts index 747ba0455..31f34ff64 100644 --- a/src/transformation/visitors/access.ts +++ b/src/transformation/visitors/access.ts @@ -6,7 +6,7 @@ import { AnnotationKind, getTypeAnnotations } from "../utils/annotations"; import { createExpressionPlusOne } from "../utils/lua-ast"; import { isArrayType, isNumberType, isStringType } from "../utils/typescript"; import { tryGetConstEnumValue } from "./enum"; -import { transformLuaTableElementAccessExpression, transformLuaTablePropertyAccessExpression } from "./lua-table"; +import { transformLuaTablePropertyAccessExpression, validateLuaTableElementAccessExpression } from "./lua-table"; export function transformElementAccessArgument( context: TransformationContext, @@ -24,7 +24,7 @@ export function transformElementAccessArgument( } export const transformElementAccessExpression: FunctionVisitor = (expression, context) => { - transformLuaTableElementAccessExpression(context, expression); + validateLuaTableElementAccessExpression(context, expression); const constEnumValue = tryGetConstEnumValue(context, expression); if (constEnumValue) { diff --git a/src/transformation/visitors/binary-expression/bit.ts b/src/transformation/visitors/binary-expression/bit.ts index e8369e91d..55ff0f681 100644 --- a/src/transformation/visitors/binary-expression/bit.ts +++ b/src/transformation/visitors/binary-expression/bit.ts @@ -1,11 +1,24 @@ import * as ts from "typescript"; import { LuaTarget } from "../../../CompilerOptions"; import * as lua from "../../../LuaAST"; +import { assertNever } from "../../../utils"; import { TransformationContext } from "../../context"; -import { UnsupportedForTarget, UnsupportedKind } from "../../utils/errors"; -import { transformBinaryOperator } from "../binary-expression"; +import { unsupportedRightShiftOperator } from "../../utils/diagnostics"; +import { UnsupportedForTarget } from "../../utils/errors"; + +export type BitOperator = ts.ShiftOperator | ts.BitwiseOperator; +export const isBitOperator = (operator: ts.BinaryOperator): operator is BitOperator => + operator in bitOperatorToLibOperation; + +const bitOperatorToLibOperation: Record = { + [ts.SyntaxKind.AmpersandToken]: "band", + [ts.SyntaxKind.BarToken]: "bor", + [ts.SyntaxKind.CaretToken]: "bxor", + [ts.SyntaxKind.LessThanLessThanToken]: "lshift", + [ts.SyntaxKind.GreaterThanGreaterThanToken]: "arshift", + [ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken]: "rshift", +}; -type BitOperator = ts.ShiftOperator | ts.BitwiseOperator; function transformBinaryBitLibOperation( node: ts.Node, left: lua.Expression, @@ -13,35 +26,33 @@ function transformBinaryBitLibOperation( operator: BitOperator, lib: string ): lua.Expression { - let bitFunction: string; + const functionName = bitOperatorToLibOperation[operator]; + return lua.createCallExpression( + lua.createTableIndexExpression(lua.createIdentifier(lib), lua.createStringLiteral(functionName)), + [left, right], + node + ); +} + +function transformBitOperatorToLuaOperator( + context: TransformationContext, + node: ts.Node, + operator: BitOperator +): lua.BinaryOperator { switch (operator) { - case ts.SyntaxKind.AmpersandToken: - bitFunction = "band"; - break; case ts.SyntaxKind.BarToken: - bitFunction = "bor"; - break; + return lua.SyntaxKind.BitwiseOrOperator; case ts.SyntaxKind.CaretToken: - bitFunction = "bxor"; - break; + return lua.SyntaxKind.BitwiseExclusiveOrOperator; + case ts.SyntaxKind.AmpersandToken: + return lua.SyntaxKind.BitwiseAndOperator; case ts.SyntaxKind.LessThanLessThanToken: - bitFunction = "lshift"; - break; - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - bitFunction = "rshift"; - break; + return lua.SyntaxKind.BitwiseLeftShiftOperator; case ts.SyntaxKind.GreaterThanGreaterThanToken: - bitFunction = "arshift"; - break; - default: - throw UnsupportedKind("binary bitwise operator", operator, node); + context.diagnostics.push(unsupportedRightShiftOperator(node)); + case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + return lua.SyntaxKind.BitwiseRightShiftOperator; } - - return lua.createCallExpression( - lua.createTableIndexExpression(lua.createIdentifier(lib), lua.createStringLiteral(bitFunction)), - [left, right], - node - ); } export function transformBinaryBitOperation( @@ -62,7 +73,7 @@ export function transformBinaryBitOperation( return transformBinaryBitLibOperation(node, left, right, operator, "bit"); default: - const luaOperator = transformBinaryOperator(context, node, operator); + const luaOperator = transformBitOperatorToLuaOperator(context, node, operator); return lua.createBinaryExpression(left, right, luaOperator, node); } } @@ -79,7 +90,7 @@ function transformUnaryBitLibOperation( bitFunction = "bnot"; break; default: - throw UnsupportedKind("unary bitwise operator", operator, node); + assertNever(operator); } return lua.createCallExpression( diff --git a/src/transformation/visitors/binary-expression/compound.ts b/src/transformation/visitors/binary-expression/compound.ts index 70340fbeb..50d9d6c49 100644 --- a/src/transformation/visitors/binary-expression/compound.ts +++ b/src/transformation/visitors/binary-expression/compound.ts @@ -33,7 +33,22 @@ export function parseAccessExpressionWithEvaluationEffects( return []; } -const compoundToAssignmentTokens: Record = { +// TODO: `as const` doesn't work on enum members +type CompoundAssignmentToken = + | ts.SyntaxKind.BarToken + | ts.SyntaxKind.PlusToken + | ts.SyntaxKind.CaretToken + | ts.SyntaxKind.MinusToken + | ts.SyntaxKind.SlashToken + | ts.SyntaxKind.PercentToken + | ts.SyntaxKind.AsteriskToken + | ts.SyntaxKind.AmpersandToken + | ts.SyntaxKind.AsteriskAsteriskToken + | ts.SyntaxKind.LessThanLessThanToken + | ts.SyntaxKind.GreaterThanGreaterThanToken + | ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + +const compoundToAssignmentTokens: Record = { [ts.SyntaxKind.BarEqualsToken]: ts.SyntaxKind.BarToken, [ts.SyntaxKind.PlusEqualsToken]: ts.SyntaxKind.PlusToken, [ts.SyntaxKind.CaretEqualsToken]: ts.SyntaxKind.CaretToken, @@ -51,7 +66,7 @@ const compoundToAssignmentTokens: Record token in compoundToAssignmentTokens; -export const unwrapCompoundAssignmentToken = (token: ts.CompoundAssignmentOperator) => +export const unwrapCompoundAssignmentToken = (token: ts.CompoundAssignmentOperator): CompoundAssignmentToken => compoundToAssignmentTokens[token]; export function transformCompoundAssignmentExpression( @@ -60,7 +75,7 @@ export function transformCompoundAssignmentExpression( // TODO: Change type to ts.LeftHandSideExpression? lhs: ts.Expression, rhs: ts.Expression, - replacementOperator: ts.BinaryOperator, + operator: CompoundAssignmentToken, isPostfix: boolean ): lua.CallExpression { const left = cast(context.transformExpression(lhs), lua.isAssignmentLeftHandSideExpression); @@ -86,7 +101,7 @@ export function transformCompoundAssignmentExpression( // local ____tmp = ____obj[____index]; // ____obj[____index] = ____tmp ${replacementOperator} ${right}; tmpDeclaration = lua.createVariableDeclarationStatement(tmp, accessExpression); - const operatorExpression = transformBinaryOperation(context, tmp, right, replacementOperator, expression); + const operatorExpression = transformBinaryOperation(context, tmp, right, operator, expression); assignStatement = lua.createAssignmentStatement(accessExpression, operatorExpression); } else { // local ____tmp = ____obj[____index] ${replacementOperator} ${right}; @@ -95,7 +110,7 @@ export function transformCompoundAssignmentExpression( context, accessExpression, right, - replacementOperator, + operator, expression ); tmpDeclaration = lua.createVariableDeclarationStatement(tmp, operatorExpression); @@ -118,7 +133,7 @@ export function transformCompoundAssignmentExpression( context, tmpIdentifier, right, - replacementOperator, + operator, expression ); const assignStatement = transformAssignment(context, lhs, operatorExpression); @@ -129,14 +144,14 @@ export function transformCompoundAssignmentExpression( // ${left} = ____tmp; // return ____tmp const tmpIdentifier = lua.createIdentifier("____tmp"); - const operatorExpression = transformBinaryOperation(context, left, right, replacementOperator, expression); + const operatorExpression = transformBinaryOperation(context, left, right, operator, expression); const tmpDeclaration = lua.createVariableDeclarationStatement(tmpIdentifier, operatorExpression); const assignStatement = transformAssignment(context, lhs, tmpIdentifier); return createImmediatelyInvokedFunctionExpression([tmpDeclaration, assignStatement], tmpIdentifier, expression); } else { // Simple expressions // ${left} = ${right}; return ${right} - const operatorExpression = transformBinaryOperation(context, left, right, replacementOperator, expression); + const operatorExpression = transformBinaryOperation(context, left, right, operator, expression); const assignStatement = transformAssignment(context, lhs, operatorExpression); return createImmediatelyInvokedFunctionExpression([assignStatement], left, expression); } @@ -147,7 +162,7 @@ export function transformCompoundAssignmentStatement( node: ts.Node, lhs: ts.Expression, rhs: ts.Expression, - replacementOperator: ts.BinaryOperator + operator: CompoundAssignmentToken ): lua.Statement { const left = cast(context.transformExpression(lhs), lua.isAssignmentLeftHandSideExpression); const right = context.transformExpression(rhs); @@ -168,7 +183,7 @@ export function transformCompoundAssignmentStatement( context, accessExpression, lua.createParenthesizedExpression(right), - replacementOperator, + operator, node ); const assignStatement = lua.createAssignmentStatement(accessExpression, operatorExpression); @@ -176,7 +191,7 @@ export function transformCompoundAssignmentStatement( } else { // Simple statements // ${left} = ${left} ${replacementOperator} ${right} - const operatorExpression = transformBinaryOperation(context, left, right, replacementOperator, node); + const operatorExpression = transformBinaryOperation(context, left, right, operator, node); return transformAssignment(context, lhs, operatorExpression); } } diff --git a/src/transformation/visitors/binary-expression/destructuring-assignments.ts b/src/transformation/visitors/binary-expression/destructuring-assignments.ts index cb89a3673..0b9b2666e 100644 --- a/src/transformation/visitors/binary-expression/destructuring-assignments.ts +++ b/src/transformation/visitors/binary-expression/destructuring-assignments.ts @@ -1,8 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; -import { flatMap } from "../../../utils"; +import { assertNever, flatMap } from "../../../utils"; import { TransformationContext } from "../../context"; -import { UnsupportedKind } from "../../utils/errors"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; import { isArrayType, isAssignmentPattern } from "../../utils/typescript"; import { transformIdentifier } from "../identifier"; @@ -111,7 +110,10 @@ function transformArrayLiteralAssignmentPattern( case ts.SyntaxKind.ElementAccessExpression: return transformAssignment(context, element, indexedRoot); case ts.SyntaxKind.SpreadElement: - if (index !== node.elements.length - 1) return []; + if (index !== node.elements.length - 1) { + // TypeScript error + return []; + } const restElements = transformLuaLibFunction( context, @@ -125,7 +127,8 @@ function transformArrayLiteralAssignmentPattern( case ts.SyntaxKind.OmittedExpression: return []; default: - throw UnsupportedKind("Array Destructure Assignment Element", element.kind, element); + // TypeScript error + return []; } }); } @@ -156,8 +159,13 @@ function transformObjectLiteralAssignmentPattern( case ts.SyntaxKind.SpreadAssignment: result.push(...transformSpreadAssignment(context, property, root, node.properties)); break; + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.GetAccessor: + case ts.SyntaxKind.SetAccessor: + // TypeScript error + break; default: - throw UnsupportedKind("Object Destructure Property", property.kind, property); + assertNever(property); } } diff --git a/src/transformation/visitors/binary-expression/index.ts b/src/transformation/visitors/binary-expression/index.ts index 9715746a6..d0cfa2aed 100644 --- a/src/transformation/visitors/binary-expression/index.ts +++ b/src/transformation/visitors/binary-expression/index.ts @@ -1,15 +1,19 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; +import { assertNever } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations"; -import { extensionInvalidInstanceOf, luaTableInvalidInstanceOf } from "../../utils/diagnostics"; -import { UnsupportedKind } from "../../utils/errors"; +import { + extensionInvalidInstanceOf, + luaTableInvalidInstanceOf, + unsupportedNullishCoalescing, +} from "../../utils/diagnostics"; import { createImmediatelyInvokedFunctionExpression, wrapInToStringForConcat } from "../../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; import { isStandardLibraryType, isStringType } from "../../utils/typescript"; import { transformTypeOfBinaryExpression } from "../typeof"; import { transformAssignmentExpression, transformAssignmentStatement } from "./assignments"; -import { transformBinaryBitOperation } from "./bit"; +import { BitOperator, isBitOperator, transformBinaryBitOperation } from "./bit"; import { isCompoundAssignmentToken, transformCompoundAssignmentExpression, @@ -17,105 +21,70 @@ import { unwrapCompoundAssignmentToken, } from "./compound"; -export function transformBinaryOperator( - context: TransformationContext, - node: ts.Node, - operator: ts.BinaryOperator -): lua.BinaryOperator { - switch (operator) { - // Bitwise operators - case ts.SyntaxKind.BarToken: - return lua.SyntaxKind.BitwiseOrOperator; - case ts.SyntaxKind.CaretToken: - return lua.SyntaxKind.BitwiseExclusiveOrOperator; - case ts.SyntaxKind.AmpersandToken: - return lua.SyntaxKind.BitwiseAndOperator; - case ts.SyntaxKind.LessThanLessThanToken: - return lua.SyntaxKind.BitwiseLeftShiftOperator; - case ts.SyntaxKind.GreaterThanGreaterThanToken: - throw UnsupportedKind("right shift operator (use >>> instead)", operator, node); - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - return lua.SyntaxKind.BitwiseRightShiftOperator; - // Regular operators - case ts.SyntaxKind.AmpersandAmpersandToken: - return lua.SyntaxKind.AndOperator; - case ts.SyntaxKind.BarBarToken: - return lua.SyntaxKind.OrOperator; - case ts.SyntaxKind.MinusToken: - return lua.SyntaxKind.SubtractionOperator; - case ts.SyntaxKind.PlusToken: - if (ts.isBinaryExpression(node)) { - // Check is we need to use string concat operator - const typeLeft = context.checker.getTypeAtLocation(node.left); - const typeRight = context.checker.getTypeAtLocation(node.right); - if (isStringType(context, typeLeft) || isStringType(context, typeRight)) { - return lua.SyntaxKind.ConcatOperator; - } - } - - return lua.SyntaxKind.AdditionOperator; - case ts.SyntaxKind.AsteriskToken: - return lua.SyntaxKind.MultiplicationOperator; - case ts.SyntaxKind.AsteriskAsteriskToken: - return lua.SyntaxKind.PowerOperator; - case ts.SyntaxKind.SlashToken: - return lua.SyntaxKind.DivisionOperator; - case ts.SyntaxKind.PercentToken: - return lua.SyntaxKind.ModuloOperator; - case ts.SyntaxKind.GreaterThanToken: - return lua.SyntaxKind.GreaterThanOperator; - case ts.SyntaxKind.GreaterThanEqualsToken: - return lua.SyntaxKind.GreaterEqualOperator; - case ts.SyntaxKind.LessThanToken: - return lua.SyntaxKind.LessThanOperator; - case ts.SyntaxKind.LessThanEqualsToken: - return lua.SyntaxKind.LessEqualOperator; - case ts.SyntaxKind.EqualsEqualsToken: - case ts.SyntaxKind.EqualsEqualsEqualsToken: - return lua.SyntaxKind.EqualityOperator; - case ts.SyntaxKind.ExclamationEqualsToken: - case ts.SyntaxKind.ExclamationEqualsEqualsToken: - return lua.SyntaxKind.InequalityOperator; - default: - throw UnsupportedKind("binary operator", operator, node); - } -} +type SimpleOperator = keyof typeof simpleOperatorsToLua; +const isSimpleOperator = (operator: ts.BinaryOperator): operator is SimpleOperator => operator in simpleOperatorsToLua; + +const simpleOperatorsToLua = { + [ts.SyntaxKind.AmpersandAmpersandToken]: lua.SyntaxKind.AndOperator, + [ts.SyntaxKind.BarBarToken]: lua.SyntaxKind.OrOperator, + [ts.SyntaxKind.MinusToken]: lua.SyntaxKind.SubtractionOperator, + [ts.SyntaxKind.AsteriskToken]: lua.SyntaxKind.MultiplicationOperator, + [ts.SyntaxKind.AsteriskAsteriskToken]: lua.SyntaxKind.PowerOperator, + [ts.SyntaxKind.SlashToken]: lua.SyntaxKind.DivisionOperator, + [ts.SyntaxKind.PercentToken]: lua.SyntaxKind.ModuloOperator, + [ts.SyntaxKind.GreaterThanToken]: lua.SyntaxKind.GreaterThanOperator, + [ts.SyntaxKind.GreaterThanEqualsToken]: lua.SyntaxKind.GreaterEqualOperator, + [ts.SyntaxKind.LessThanToken]: lua.SyntaxKind.LessThanOperator, + [ts.SyntaxKind.LessThanEqualsToken]: lua.SyntaxKind.LessEqualOperator, + [ts.SyntaxKind.EqualsEqualsToken]: lua.SyntaxKind.EqualityOperator, + [ts.SyntaxKind.EqualsEqualsEqualsToken]: lua.SyntaxKind.EqualityOperator, + [ts.SyntaxKind.ExclamationEqualsToken]: lua.SyntaxKind.InequalityOperator, + [ts.SyntaxKind.ExclamationEqualsEqualsToken]: lua.SyntaxKind.InequalityOperator, +}; export function transformBinaryOperation( context: TransformationContext, left: lua.Expression, right: lua.Expression, - operator: ts.BinaryOperator, - tsOriginal: ts.Node + operator: BitOperator | SimpleOperator | ts.SyntaxKind.PlusToken, + node: ts.Node ): lua.Expression { - switch (operator) { - case ts.SyntaxKind.AmpersandToken: - case ts.SyntaxKind.BarToken: - case ts.SyntaxKind.CaretToken: - case ts.SyntaxKind.LessThanLessThanToken: - case ts.SyntaxKind.GreaterThanGreaterThanToken: - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - return transformBinaryBitOperation(context, tsOriginal, left, right, operator); - default: - const luaOperator = transformBinaryOperator(context, tsOriginal, operator); - if (luaOperator === lua.SyntaxKind.ConcatOperator) { + if (isBitOperator(operator)) { + return transformBinaryBitOperation(context, node, left, right, operator); + } + + if (isSimpleOperator(operator)) { + const luaOperator = simpleOperatorsToLua[operator] as lua.BinaryOperator; + return lua.createBinaryExpression(left, right, luaOperator, node); + } + + if (operator === ts.SyntaxKind.PlusToken) { + let luaOperator = lua.SyntaxKind.AdditionOperator; + if (ts.isBinaryExpression(node)) { + // Check is we need to use string concat operator + const typeLeft = context.checker.getTypeAtLocation(node.left); + const typeRight = context.checker.getTypeAtLocation(node.right); + if (isStringType(context, typeLeft) || isStringType(context, typeRight)) { + luaOperator = lua.SyntaxKind.ConcatOperator; left = wrapInToStringForConcat(left); right = wrapInToStringForConcat(right); } + } - return lua.createBinaryExpression(left, right, luaOperator, tsOriginal); + return lua.createBinaryExpression(left, right, luaOperator, node); } + + assertNever(operator); } export const transformBinaryExpression: FunctionVisitor = (node, context) => { + const operator = node.operatorToken.kind; + const typeOfResult = transformTypeOfBinaryExpression(context, node); if (typeOfResult) { return typeOfResult; } - const operator = node.operatorToken.kind; - - // Check if this is an assignment token, then handle accordingly if (isCompoundAssignmentToken(operator)) { return transformCompoundAssignmentExpression( context, @@ -129,37 +98,6 @@ export const transformBinaryExpression: FunctionVisitor = ( // Transpile operators switch (operator) { - case ts.SyntaxKind.AmpersandToken: - case ts.SyntaxKind.BarToken: - case ts.SyntaxKind.CaretToken: - case ts.SyntaxKind.LessThanLessThanToken: - case ts.SyntaxKind.GreaterThanGreaterThanToken: - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.AmpersandAmpersandToken: - case ts.SyntaxKind.BarBarToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.AsteriskToken: - case ts.SyntaxKind.AsteriskAsteriskToken: - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.PercentToken: - - case ts.SyntaxKind.GreaterThanToken: - case ts.SyntaxKind.GreaterThanEqualsToken: - case ts.SyntaxKind.LessThanToken: - case ts.SyntaxKind.LessThanEqualsToken: - case ts.SyntaxKind.EqualsEqualsToken: - case ts.SyntaxKind.EqualsEqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsToken: - case ts.SyntaxKind.ExclamationEqualsEqualsToken: - return transformBinaryOperation( - context, - context.transformExpression(node.left), - context.transformExpression(node.right), - operator, - node - ); - case ts.SyntaxKind.EqualsToken: return transformAssignmentExpression(context, node as ts.AssignmentExpression); @@ -197,16 +135,31 @@ export const transformBinaryExpression: FunctionVisitor = ( } case ts.SyntaxKind.CommaToken: { - const rhs = context.transformExpression(node.right); return createImmediatelyInvokedFunctionExpression( context.transformStatements(ts.createExpressionStatement(node.left)), - rhs, + context.transformExpression(node.right), + node + ); + } + + case ts.SyntaxKind.QuestionQuestionToken: { + context.diagnostics.push(unsupportedNullishCoalescing(node.operatorToken)); + return lua.createBinaryExpression( + context.transformExpression(node.left), + context.transformExpression(node.right), + lua.SyntaxKind.OrOperator, node ); } default: - throw UnsupportedKind("binary operator", operator, node); + return transformBinaryOperation( + context, + context.transformExpression(node.left), + context.transformExpression(node.right), + operator, + node + ); } }; diff --git a/src/transformation/visitors/call.ts b/src/transformation/visitors/call.ts index 6511347c6..315dd0422 100644 --- a/src/transformation/visitors/call.ts +++ b/src/transformation/visitors/call.ts @@ -4,7 +4,6 @@ import { transformBuiltinCallExpression } from "../builtins"; import { FunctionVisitor, TransformationContext } from "../context"; import { isInTupleReturnFunction, isTupleReturnCall, isVarArgType } from "../utils/annotations"; import { validateAssignment } from "../utils/assignment-validation"; -import { UnsupportedKind } from "../utils/errors"; import { ContextType, getDeclarationContextType } from "../utils/function-context"; import { createImmediatelyInvokedFunctionExpression, createUnpackCall, wrapInTable } from "../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; @@ -90,7 +89,7 @@ export function transformContextualCallExpression( const expression = context.transformExpression(left); return lua.createCallExpression(expression, transformedArguments, node); } else { - throw UnsupportedKind("Left Hand Side Call Expression", left.kind, left); + throw new Error(`Unsupported LeftHandSideExpression kind: ${ts.SyntaxKind[left.kind]}`); } } diff --git a/src/transformation/visitors/literal.ts b/src/transformation/visitors/literal.ts index 281f70ec6..6a3804baa 100644 --- a/src/transformation/visitors/literal.ts +++ b/src/transformation/visitors/literal.ts @@ -1,7 +1,9 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; +import { assertNever } from "../../utils"; import { FunctionVisitor, TransformationContext, Visitors } from "../context"; -import { InvalidAmbientIdentifierName, UnsupportedKind } from "../utils/errors"; +import { unsupportedAccessorInObjectLiteral } from "../utils/diagnostics"; +import { InvalidAmbientIdentifierName } from "../utils/errors"; import { createExportedIdentifier, getSymbolExportScope } from "../utils/export"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; import { @@ -104,9 +106,10 @@ const transformObjectLiteralExpression: FunctionVisitor + [context.transformExpression(node.expression), node.name.text] as const; function validateLuaTableCall( context: TransformationContext, @@ -48,10 +40,18 @@ function validateLuaTableCall( } } -function transformLuaTableExpressionAsExpressionStatement( +export function transformLuaTableExpressionStatement( context: TransformationContext, - expression: ts.CallExpression -): lua.Statement { + node: ts.ExpressionStatement +): lua.Statement | undefined { + const expression = ts.isExpressionStatement(node) ? node.expression : node; + + if (!ts.isCallExpression(expression) || !ts.isPropertyAccessExpression(expression.expression)) return; + + const ownerType = context.checker.getTypeAtLocation(expression.expression.expression); + const annotations = getTypeAnnotations(context, ownerType); + if (!annotations.has(AnnotationKind.LuaTable)) return; + const [luaTable, methodName] = parseLuaTableExpression(context, expression.expression); validateLuaTableCall(context, expression, methodName, expression.arguments); const signature = context.checker.getResolvedSignature(expression); @@ -75,42 +75,26 @@ function transformLuaTableExpressionAsExpressionStatement( } } -export function transformLuaTableExpressionStatement( - context: TransformationContext, - node: ts.ExpressionStatement -): lua.Statement | undefined { - const expression = ts.isExpressionStatement(node) ? node.expression : node; - - if (ts.isCallExpression(expression) && ts.isPropertyAccessExpression(expression.expression)) { - const ownerType = context.checker.getTypeAtLocation(expression.expression.expression); - const annotations = getTypeAnnotations(context, ownerType); - if (annotations.has(AnnotationKind.LuaTable)) { - return transformLuaTableExpressionAsExpressionStatement(context, expression); - } - } -} - export function transformLuaTableCallExpression( context: TransformationContext, node: ts.CallExpression ): lua.Expression | undefined { - if (ts.isPropertyAccessExpression(node.expression) || ts.isElementAccessExpression(node.expression)) { - const ownerType = context.checker.getTypeAtLocation(node.expression.expression); - const annotations = getTypeAnnotations(context, ownerType); - - if (annotations.has(AnnotationKind.LuaTable)) { - const [luaTable, methodName] = parseLuaTableExpression(context, node.expression); - validateLuaTableCall(context, node, methodName, node.arguments); - const signature = context.checker.getResolvedSignature(node); - const params = transformArguments(context, node.arguments, signature); - - switch (methodName) { - case "get": - return lua.createTableIndexExpression(luaTable, params[0] ?? lua.createNilLiteral(), node); - default: - throw UnsupportedProperty("LuaTable", methodName, node); - } - } + if (!ts.isPropertyAccessExpression(node.expression)) return; + + const ownerType = context.checker.getTypeAtLocation(node.expression.expression); + const annotations = getTypeAnnotations(context, ownerType); + if (!annotations.has(AnnotationKind.LuaTable)) return; + + const [luaTable, methodName] = parseLuaTableExpression(context, node.expression); + validateLuaTableCall(context, node, methodName, node.arguments); + const signature = context.checker.getResolvedSignature(node); + const params = transformArguments(context, node.arguments, signature); + + switch (methodName) { + case "get": + return lua.createTableIndexExpression(luaTable, params[0] ?? lua.createNilLiteral(), node); + default: + throw UnsupportedProperty("LuaTable", methodName, node); } } @@ -118,8 +102,7 @@ export function transformLuaTablePropertyAccessExpression( context: TransformationContext, node: ts.PropertyAccessExpression ): lua.Expression | undefined { - const type = context.checker.getTypeAtLocation(node.expression); - const annotations = getTypeAnnotations(context, type); + const annotations = getTypeAnnotations(context, context.checker.getTypeAtLocation(node.expression)); if (!annotations.has(AnnotationKind.LuaTable)) return; const [luaTable, propertyName] = parseLuaTableExpression(context, node); @@ -136,8 +119,7 @@ export function transformLuaTablePropertyAccessInAssignment( ): lua.AssignmentLeftHandSideExpression | undefined { if (!ts.isPropertyAccessExpression(node)) return; - const type = context.checker.getTypeAtLocation(node.expression); - const annotations = getTypeAnnotations(context, type); + const annotations = getTypeAnnotations(context, context.checker.getTypeAtLocation(node.expression)); if (!annotations.has(AnnotationKind.LuaTable)) return; const [luaTable, propertyName] = parseLuaTableExpression(context, node); @@ -149,13 +131,13 @@ export function transformLuaTablePropertyAccessInAssignment( return lua.createTableIndexExpression(luaTable, lua.createStringLiteral(propertyName), node); } -export function transformLuaTableElementAccessExpression( +export function validateLuaTableElementAccessExpression( context: TransformationContext, node: ts.ElementAccessExpression ): void { const annotations = getTypeAnnotations(context, context.checker.getTypeAtLocation(node.expression)); if (annotations.has(AnnotationKind.LuaTable)) { - throw UnsupportedKind("LuaTable access expression", node.kind, node); + context.diagnostics.push(luaTableCannotBeAccessedDynamically(node)); } } @@ -163,15 +145,14 @@ export function transformLuaTableNewExpression( context: TransformationContext, node: ts.NewExpression ): lua.Expression | undefined { - const type = context.checker.getTypeAtLocation(node); - const annotations = getTypeAnnotations(context, type); - if (annotations.has(AnnotationKind.LuaTable)) { - if (node.arguments && node.arguments.length > 0) { - context.diagnostics.push( - luaTableForbiddenUsage(node, "No parameters are allowed when constructing a LuaTable object") - ); - } + const annotations = getTypeAnnotations(context, context.checker.getTypeAtLocation(node)); + if (!annotations.has(AnnotationKind.LuaTable)) return; - return lua.createTableExpression(); + if (node.arguments && node.arguments.length > 0) { + context.diagnostics.push( + luaTableForbiddenUsage(node, "No parameters are allowed when constructing a LuaTable object") + ); } + + return lua.createTableExpression(); } diff --git a/src/transformation/visitors/typeof.ts b/src/transformation/visitors/typeof.ts index 585746ca4..60eef310c 100644 --- a/src/transformation/visitors/typeof.ts +++ b/src/transformation/visitors/typeof.ts @@ -15,37 +15,37 @@ export function transformTypeOfBinaryExpression( node: ts.BinaryExpression ): lua.Expression | undefined { const operator = node.operatorToken.kind; - function transformTypeOfLiteralComparison( - typeOfExpression: ts.TypeOfExpression, - comparedExpression: lua.StringLiteral - ): lua.Expression { - if (comparedExpression.value === "object") { - comparedExpression.value = "table"; - } else if (comparedExpression.value === "undefined") { - comparedExpression.value = "nil"; - } + if ( + operator !== ts.SyntaxKind.EqualsEqualsToken && + operator !== ts.SyntaxKind.EqualsEqualsEqualsToken && + operator !== ts.SyntaxKind.ExclamationEqualsToken && + operator !== ts.SyntaxKind.ExclamationEqualsEqualsToken + ) { + return; + } - const innerExpression = context.transformExpression(typeOfExpression.expression); - const typeCall = lua.createCallExpression(lua.createIdentifier("type"), [innerExpression], typeOfExpression); - return transformBinaryOperation(context, typeCall, comparedExpression, operator, node); + let literalExpression: ts.Expression; + let typeOfExpression: ts.TypeOfExpression; + if (ts.isTypeOfExpression(node.left)) { + typeOfExpression = node.left; + literalExpression = node.right; + } else if (ts.isTypeOfExpression(node.right)) { + typeOfExpression = node.right; + literalExpression = node.left; + } else { + return; } - if ( - operator === ts.SyntaxKind.EqualsEqualsToken || - operator === ts.SyntaxKind.EqualsEqualsEqualsToken || - operator === ts.SyntaxKind.ExclamationEqualsToken || - operator === ts.SyntaxKind.ExclamationEqualsEqualsToken - ) { - if (ts.isTypeOfExpression(node.left)) { - const right = context.transformExpression(node.right); - if (lua.isStringLiteral(right)) { - return transformTypeOfLiteralComparison(node.left, right); - } - } else if (ts.isTypeOfExpression(node.right)) { - const left = context.transformExpression(node.left); - if (lua.isStringLiteral(left)) { - return transformTypeOfLiteralComparison(node.right, left); - } - } + const comparedExpression = context.transformExpression(literalExpression); + if (!lua.isStringLiteral(comparedExpression)) return; + + if (comparedExpression.value === "object") { + comparedExpression.value = "table"; + } else if (comparedExpression.value === "undefined") { + comparedExpression.value = "nil"; } + + const innerExpression = context.transformExpression(typeOfExpression.expression); + const typeCall = lua.createCallExpression(lua.createIdentifier("type"), [innerExpression], typeOfExpression); + return transformBinaryOperation(context, typeCall, comparedExpression, operator, node); } diff --git a/src/transformation/visitors/unary-expression.ts b/src/transformation/visitors/unary-expression.ts index e4c8dfad2..935fc8487 100644 --- a/src/transformation/visitors/unary-expression.ts +++ b/src/transformation/visitors/unary-expression.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; +import { assertNever } from "../../utils"; import { FunctionVisitor, TransformationContext } from "../context"; -import { UnsupportedKind } from "../utils/errors"; import { transformUnaryBitOperation } from "./binary-expression/bit"; import { transformCompoundAssignmentExpression, @@ -66,7 +66,7 @@ export const transformPostfixUnaryExpression: FunctionVisitor; diff --git a/test/unit/__snapshots__/expressions.spec.ts.snap b/test/unit/__snapshots__/expressions.spec.ts.snap index db8863e35..4ac94f696 100644 --- a/test/unit/__snapshots__/expressions.spec.ts.snap +++ b/test/unit/__snapshots__/expressions.spec.ts.snap @@ -402,3 +402,22 @@ function ____exports.__main(self) end return ____exports" `; + +exports[`Unsupported bitop 5.3 ("a>>=b"): code 1`] = ` +"local ____exports = {} +____exports.__result = (function() + a = a >> b + return a +end)() +return ____exports" +`; + +exports[`Unsupported bitop 5.3 ("a>>=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Right shift operator is not supported. Use \`>>>\` instead."`; + +exports[`Unsupported bitop 5.3 ("a>>b"): code 1`] = ` +"local ____exports = {} +____exports.__result = a >> b +return ____exports" +`; + +exports[`Unsupported bitop 5.3 ("a>>b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Right shift operator is not supported. Use \`>>>\` instead."`; diff --git a/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap b/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap index 704721806..6a5c7ea50 100644 --- a/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap @@ -33,6 +33,30 @@ exports[`Cannot set LuaTable length: diagnostics 1`] = `"main.ts(11,1): error TS exports[`Cannot set LuaTable length: diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: A LuaTable object's length cannot be re-assigned."`; +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"field\\")"): code 1`] = `"tbl.get(tbl, \\"field\\")"`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"field\\")"): code 2`] = `"tbl.get(tbl, \\"field\\")"`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"field\\")"): diagnostics 1`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"field\\")"): diagnostics 2`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): code 1`] = `"local ____ = tbl.length"`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): code 2`] = `"local ____ = tbl.length"`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): diagnostics 1`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): diagnostics 2`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"field\\")"): code 1`] = `"tbl.set(tbl, \\"field\\")"`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"field\\")"): code 2`] = `"tbl.set(tbl, \\"field\\")"`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"field\\")"): diagnostics 1`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; + +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"field\\")"): diagnostics 2`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; + exports[`Cannot use instanceof on a LuaTable class ("tbl instanceof Table"): code 1`] = ` "require(\\"lualib_bundle\\"); __TS__InstanceOf(tbl, Table)" diff --git a/test/unit/decorators/luaTable.spec.ts b/test/unit/decorators/luaTable.spec.ts index 3e41ceefb..89ea22331 100644 --- a/test/unit/decorators/luaTable.spec.ts +++ b/test/unit/decorators/luaTable.spec.ts @@ -1,5 +1,5 @@ import * as ts from "typescript"; -import { UnsupportedKind, UnsupportedProperty } from "../../../src/transformation/utils/errors"; +import { UnsupportedProperty } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; const tableLibClass = ` @@ -108,9 +108,7 @@ test.each([tableLibClass, tableLibInterface])("Cannot use ElementAccessExpressio test.each([`tbl["get"]("field")`, `tbl["set"]("field")`, `tbl["length"]`])( "Cannot use ElementAccessExpression on a LuaTable (%p)", code => { - expect(() => util.transpileString(tableLib + code)).toThrowExactError( - UnsupportedKind("LuaTable access expression", ts.SyntaxKind.ElementAccessExpression, util.nodeStub) - ); + util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot(); } ); }); diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index c65c1ebbc..9d41b1695 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -1,6 +1,5 @@ -import * as ts from "typescript"; import * as tstl from "../../src"; -import { UnsupportedForTarget, UnsupportedKind } from "../../src/transformation/utils/errors"; +import { UnsupportedForTarget } from "../../src/transformation/utils/errors"; import * as util from "../util"; // TODO: @@ -95,13 +94,7 @@ test.each(unsupportedIn53)("Unsupported bitop 5.3 (%p)", input => { util.testExpression(input) .setOptions({ luaTarget: tstl.LuaTarget.Lua53, luaLibImport: tstl.LuaLibImportKind.None }) .disableSemanticCheck() - .expectToHaveDiagnosticOfError( - UnsupportedKind( - "right shift operator (use >>> instead)", - ts.SyntaxKind.GreaterThanGreaterThanToken, - util.nodeStub - ) - ); + .expectDiagnosticsToMatchSnapshot(); }); test.each(["1+1", "-1+1", "1*30+4", "1*(3+4)", "1*(3+4*2)", "10-(4+5)"])( From 8aff305275ace737bbe5b3ead202ee2d71e4ac2f Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Dec 2019 23:02:27 +0000 Subject: [PATCH 12/42] Make `UnsupportedForTarget` error a diagnostic --- src/transformation/utils/diagnostics.ts | 7 + src/transformation/utils/errors.ts | 6 - .../visitors/binary-expression/bit.ts | 18 ++- src/transformation/visitors/break-continue.ts | 5 +- src/transformation/visitors/switch.ts | 4 +- .../__snapshots__/conditionals.spec.ts.snap | 13 ++ .../__snapshots__/expressions.spec.ts.snap | 122 ++++++++++++++++++ test/unit/__snapshots__/loops.spec.ts.snap | 59 +++++++++ test/unit/conditionals.spec.ts | 3 +- test/unit/expressions.spec.ts | 3 +- test/unit/loops.spec.ts | 38 +++--- test/util.ts | 8 +- 12 files changed, 239 insertions(+), 47 deletions(-) create mode 100644 test/unit/__snapshots__/conditionals.spec.ts.snap diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index ccf3634ae..9cda3ea57 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -1,4 +1,5 @@ import * as ts from "typescript"; +import { LuaTarget } from "../../CompilerOptions"; import { AnnotationKind } from "./annotations"; const createDiagnosticFactory = ( @@ -107,3 +108,9 @@ export const unsupportedAccessorInObjectLiteral = createDiagnosticFactory( export const unsupportedRightShiftOperator = createDiagnosticFactory( "Right shift operator is not supported. Use `>>>` instead." ); + +const getLuaTargetName = (version: LuaTarget) => (version === LuaTarget.LuaJIT ? "LuaJIT" : `Lua ${version}`); +export const unsupportedForTarget = createDiagnosticFactory( + (functionality: string, version: LuaTarget) => + `${functionality} is/are not supported for target ${getLuaTargetName(version)}.` +); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index c9f21a38e..d6491c0a9 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -1,5 +1,4 @@ import * as ts from "typescript"; -import { LuaTarget } from "../../CompilerOptions"; export class TranspileError extends Error { public name = "TranspileError"; @@ -8,8 +7,6 @@ export class TranspileError extends Error { } } -const getLuaTargetName = (version: LuaTarget) => (version === LuaTarget.LuaJIT ? "LuaJIT" : `Lua ${version}`); - export const InvalidDecoratorContext = (node: ts.Node) => new TranspileError(`Decorator function cannot have 'this: void'.`, node); @@ -24,9 +21,6 @@ export const UndefinedScope = () => new Error("Expected to pop a scope, but foun export const UnsupportedProperty = (parentName: string, property: string, node: ts.Node) => new TranspileError(`Unsupported property on ${parentName}: ${property}`, node); -export const UnsupportedForTarget = (functionality: string, version: LuaTarget, node: ts.Node) => - new TranspileError(`${functionality} is/are not supported for target ${getLuaTargetName(version)}.`, node); - export const UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => new TranspileError(`${reason}. TypeScript path: ${path}.`, node); diff --git a/src/transformation/visitors/binary-expression/bit.ts b/src/transformation/visitors/binary-expression/bit.ts index 55ff0f681..ffdf410ec 100644 --- a/src/transformation/visitors/binary-expression/bit.ts +++ b/src/transformation/visitors/binary-expression/bit.ts @@ -3,8 +3,7 @@ import { LuaTarget } from "../../../CompilerOptions"; import * as lua from "../../../LuaAST"; import { assertNever } from "../../../utils"; import { TransformationContext } from "../../context"; -import { unsupportedRightShiftOperator } from "../../utils/diagnostics"; -import { UnsupportedForTarget } from "../../utils/errors"; +import { unsupportedForTarget, unsupportedRightShiftOperator } from "../../utils/diagnostics"; export type BitOperator = ts.ShiftOperator | ts.BitwiseOperator; export const isBitOperator = (operator: ts.BinaryOperator): operator is BitOperator => @@ -64,14 +63,13 @@ export function transformBinaryBitOperation( ): lua.Expression { switch (context.luaTarget) { case LuaTarget.Lua51: - throw UnsupportedForTarget("Bitwise operations", LuaTarget.Lua51, node); - - case LuaTarget.Lua52: - return transformBinaryBitLibOperation(node, left, right, operator, "bit32"); + context.diagnostics.push(unsupportedForTarget(node, "Bitwise operations", LuaTarget.Lua51)); case LuaTarget.LuaJIT: return transformBinaryBitLibOperation(node, left, right, operator, "bit"); + case LuaTarget.Lua52: + return transformBinaryBitLibOperation(node, left, right, operator, "bit32"); default: const luaOperator = transformBitOperatorToLuaOperator(context, node, operator); return lua.createBinaryExpression(left, right, luaOperator, node); @@ -108,14 +106,14 @@ export function transformUnaryBitOperation( ): lua.Expression { switch (context.luaTarget) { case LuaTarget.Lua51: - throw UnsupportedForTarget("Bitwise operations", LuaTarget.Lua51, node); - - case LuaTarget.Lua52: - return transformUnaryBitLibOperation(node, expression, operator, "bit32"); + context.diagnostics.push(unsupportedForTarget(node, "Bitwise operations", LuaTarget.Lua51)); case LuaTarget.LuaJIT: return transformUnaryBitLibOperation(node, expression, operator, "bit"); + case LuaTarget.Lua52: + return transformUnaryBitLibOperation(node, expression, operator, "bit32"); + default: return lua.createUnaryExpression(expression, operator, node); } diff --git a/src/transformation/visitors/break-continue.ts b/src/transformation/visitors/break-continue.ts index 49ead1ff6..5449930a7 100644 --- a/src/transformation/visitors/break-continue.ts +++ b/src/transformation/visitors/break-continue.ts @@ -2,7 +2,8 @@ import * as ts from "typescript"; import { LuaTarget } from "../../CompilerOptions"; import * as lua from "../../LuaAST"; import { FunctionVisitor } from "../context"; -import { UndefinedScope, UnsupportedForTarget } from "../utils/errors"; +import { unsupportedForTarget } from "../utils/diagnostics"; +import { UndefinedScope } from "../utils/errors"; import { findScope, ScopeType } from "../utils/scope"; export const transformBreakStatement: FunctionVisitor = (breakStatement, context) => { @@ -20,7 +21,7 @@ export const transformBreakStatement: FunctionVisitor = (brea export const transformContinueStatement: FunctionVisitor = (statement, context) => { if (context.luaTarget === LuaTarget.Lua51) { - throw UnsupportedForTarget("Continue statement", LuaTarget.Lua51, statement); + context.diagnostics.push(unsupportedForTarget(statement, "Continue statement", LuaTarget.Lua51)); } const scope = findScope(context, ScopeType.Loop); diff --git a/src/transformation/visitors/switch.ts b/src/transformation/visitors/switch.ts index 0c6ece043..1767aec58 100644 --- a/src/transformation/visitors/switch.ts +++ b/src/transformation/visitors/switch.ts @@ -2,12 +2,12 @@ import * as ts from "typescript"; import { LuaTarget } from "../../CompilerOptions"; import * as lua from "../../LuaAST"; import { FunctionVisitor } from "../context"; -import { UnsupportedForTarget } from "../utils/errors"; +import { unsupportedForTarget } from "../utils/diagnostics"; import { peekScope, performHoisting, popScope, pushScope, ScopeType } from "../utils/scope"; export const transformSwitchStatement: FunctionVisitor = (statement, context) => { if (context.luaTarget === LuaTarget.Lua51) { - throw UnsupportedForTarget("Switch statements", LuaTarget.Lua51, statement); + context.diagnostics.push(unsupportedForTarget(statement, "Switch statements", LuaTarget.Lua51)); } pushScope(context, ScopeType.Switch); diff --git a/test/unit/__snapshots__/conditionals.spec.ts.snap b/test/unit/__snapshots__/conditionals.spec.ts.snap new file mode 100644 index 000000000..25d9b1397 --- /dev/null +++ b/test/unit/__snapshots__/conditionals.spec.ts.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`switch not allowed in 5.1: code 1`] = ` +"local ____exports = {} +function ____exports.__main(self) + local ____switch3 = \\"abc\\" + goto ____switch3_end + ::____switch3_end:: +end +return ____exports" +`; + +exports[`switch not allowed in 5.1: diagnostics 1`] = `"main.ts(2,9): error TSTL: Switch statements is/are not supported for target Lua 5.1."`; diff --git a/test/unit/__snapshots__/expressions.spec.ts.snap b/test/unit/__snapshots__/expressions.spec.ts.snap index 4ac94f696..412cdd329 100644 --- a/test/unit/__snapshots__/expressions.spec.ts.snap +++ b/test/unit/__snapshots__/expressions.spec.ts.snap @@ -36,6 +36,128 @@ ____exports.__result = 10 - (4 + 5) return ____exports" `; +exports[`Bitop [5.1] ("~a"): code 1`] = ` +"local ____exports = {} +____exports.__result = bit.bnot(a) +return ____exports" +`; + +exports[`Bitop [5.1] ("~a"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a&=b"): code 1`] = ` +"local ____exports = {} +____exports.__result = (function() + a = bit.band(a, b) + return a +end)() +return ____exports" +`; + +exports[`Bitop [5.1] ("a&=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a&b"): code 1`] = ` +"local ____exports = {} +____exports.__result = bit.band(a, b) +return ____exports" +`; + +exports[`Bitop [5.1] ("a&b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a<<=b"): code 1`] = ` +"local ____exports = {} +____exports.__result = (function() + a = bit.lshift(a, b) + return a +end)() +return ____exports" +`; + +exports[`Bitop [5.1] ("a<<=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a<>=b"): code 1`] = ` +"local ____exports = {} +____exports.__result = (function() + a = bit.arshift(a, b) + return a +end)() +return ____exports" +`; + +exports[`Bitop [5.1] ("a>>=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a>>>=b"): code 1`] = ` +"local ____exports = {} +____exports.__result = (function() + a = bit.rshift(a, b) + return a +end)() +return ____exports" +`; + +exports[`Bitop [5.1] ("a>>>=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a>>>b"): code 1`] = ` +"local ____exports = {} +____exports.__result = bit.rshift(a, b) +return ____exports" +`; + +exports[`Bitop [5.1] ("a>>>b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a>>b"): code 1`] = ` +"local ____exports = {} +____exports.__result = bit.arshift(a, b) +return ____exports" +`; + +exports[`Bitop [5.1] ("a>>b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a^=b"): code 1`] = ` +"local ____exports = {} +____exports.__result = (function() + a = bit.bxor(a, b) + return a +end)() +return ____exports" +`; + +exports[`Bitop [5.1] ("a^=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a^b"): code 1`] = ` +"local ____exports = {} +____exports.__result = bit.bxor(a, b) +return ____exports" +`; + +exports[`Bitop [5.1] ("a^b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a|=b"): code 1`] = ` +"local ____exports = {} +____exports.__result = (function() + a = bit.bor(a, b) + return a +end)() +return ____exports" +`; + +exports[`Bitop [5.1] ("a|=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + +exports[`Bitop [5.1] ("a|b"): code 1`] = ` +"local ____exports = {} +____exports.__result = bit.bor(a, b) +return ____exports" +`; + +exports[`Bitop [5.1] ("a|b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Bitwise operations is/are not supported for target Lua 5.1."`; + exports[`Bitop [5.2] ("~a") 1`] = ` "local ____exports = {} ____exports.__result = bit32.bnot(a) diff --git a/test/unit/__snapshots__/loops.spec.ts.snap b/test/unit/__snapshots__/loops.spec.ts.snap index 29b609730..f1daffe65 100644 --- a/test/unit/__snapshots__/loops.spec.ts.snap +++ b/test/unit/__snapshots__/loops.spec.ts.snap @@ -11,3 +11,62 @@ return ____exports" `; exports[`forin[Array]: diagnostics 1`] = `"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`; + +exports[`loop continue (do { continue; } while (false)) [5.1]: code 1`] = ` +"repeat + do + do + goto __continue2 + end + ::__continue2:: + end +until not false" +`; + +exports[`loop continue (do { continue; } while (false)) [5.1]: diagnostics 1`] = `"main.ts(1,6): error TSTL: Continue statement is/are not supported for target Lua 5.1."`; + +exports[`loop continue (for (;;) { continue; }) [5.1]: code 1`] = ` +"do + while true do + do + goto __continue2 + end + ::__continue2:: + end +end" +`; + +exports[`loop continue (for (;;) { continue; }) [5.1]: diagnostics 1`] = `"main.ts(1,12): error TSTL: Continue statement is/are not supported for target Lua 5.1."`; + +exports[`loop continue (for (const a in {}) { continue; }) [5.1]: code 1`] = ` +"for a in pairs({}) do + do + goto __continue2 + end + ::__continue2:: +end" +`; + +exports[`loop continue (for (const a in {}) { continue; }) [5.1]: diagnostics 1`] = `"main.ts(1,23): error TSTL: Continue statement is/are not supported for target Lua 5.1."`; + +exports[`loop continue (for (const a of []) { continue; }) [5.1]: code 1`] = ` +"for ____, a in ipairs({}) do + do + goto __continue2 + end + ::__continue2:: +end" +`; + +exports[`loop continue (for (const a of []) { continue; }) [5.1]: diagnostics 1`] = `"main.ts(1,23): error TSTL: Continue statement is/are not supported for target Lua 5.1."`; + +exports[`loop continue (while (false) { continue; }) [5.1]: code 1`] = ` +"while false do + do + goto __continue2 + end + ::__continue2:: +end" +`; + +exports[`loop continue (while (false) { continue; }) [5.1]: diagnostics 1`] = `"main.ts(1,17): error TSTL: Continue statement is/are not supported for target Lua 5.1."`; diff --git a/test/unit/conditionals.spec.ts b/test/unit/conditionals.spec.ts index d33d39fdd..a9296ee91 100644 --- a/test/unit/conditionals.spec.ts +++ b/test/unit/conditionals.spec.ts @@ -1,5 +1,4 @@ import * as tstl from "../../src"; -import { UnsupportedForTarget } from "../../src/transformation/utils/errors"; import * as util from "../util"; test.each([0, 1])("if (%p)", inp => { @@ -278,7 +277,7 @@ test("switch not allowed in 5.1", () => { switch ("abc") {} ` .setOptions({ luaTarget: tstl.LuaTarget.Lua51 }) - .expectToHaveDiagnosticOfError(UnsupportedForTarget("Switch statements", tstl.LuaTarget.Lua51, util.nodeStub)); + .expectDiagnosticsToMatchSnapshot(); }); test.each([ diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index 9d41b1695..9db033b8d 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -1,5 +1,4 @@ import * as tstl from "../../src"; -import { UnsupportedForTarget } from "../../src/transformation/utils/errors"; import * as util from "../util"; // TODO: @@ -66,7 +65,7 @@ test.each(allBinaryOperators)("Bitop [5.1] (%p)", input => { util.testExpression(input) .setOptions({ luaTarget: tstl.LuaTarget.Lua51, luaLibImport: tstl.LuaLibImportKind.None }) .disableSemanticCheck() - .expectToHaveDiagnosticOfError(UnsupportedForTarget("Bitwise operations", tstl.LuaTarget.Lua51, util.nodeStub)); + .expectDiagnosticsToMatchSnapshot(); }); test.each(allBinaryOperators)("Bitop [JIT] (%p)", input => { diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index 5c40003b9..fad1020e2 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -1,6 +1,6 @@ import * as ts from "typescript"; import * as tstl from "../../src"; -import { UnsupportedForTarget, UnsupportedObjectDestructuringInForOf } from "../../src/transformation/utils/errors"; +import { UnsupportedObjectDestructuringInForOf } from "../../src/transformation/utils/errors"; import * as util from "../util"; test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("while (%p)", ({ inp, expected }) => { @@ -588,25 +588,23 @@ describe("for...of empty destructuring", () => { describe("assignment", () => declareTests("")); }); -test.each([ - "while (a < b) { i++; continue; }", - "do { i++; continue; } while (a < b)", - "for (let i = 0; i < 3; i++) { continue; }", - "for (let a in b) { continue; }", - "for (let a of b) { continue; }", -])("loop continue in different lua versions (%p)", loop => { - const lua51 = { luaTarget: tstl.LuaTarget.Lua51 }; - const lua52 = { luaTarget: tstl.LuaTarget.Lua52 }; - const lua53 = { luaTarget: tstl.LuaTarget.Lua53 }; - const luajit = { luaTarget: tstl.LuaTarget.LuaJIT }; - - expect(() => util.transpileString(loop, lua51)).toThrowExactError( - UnsupportedForTarget("Continue statement", tstl.LuaTarget.Lua51, ts.createContinue()) - ); - expect(util.transpileString(loop, lua52).indexOf("::__continue2::") !== -1).toBe(true); - expect(util.transpileString(loop, lua53).indexOf("::__continue2::") !== -1).toBe(true); - expect(util.transpileString(loop, luajit).indexOf("::__continue2::") !== -1).toBe(true); -}); +for (const testCase of [ + "while (false) { continue; }", + "do { continue; } while (false)", + "for (;;) { continue; }", + "for (const a in {}) { continue; }", + "for (const a of []) { continue; }", +]) { + const expectContinueGotoLabel: util.TapCallback = builder => + expect(builder.getMainLuaCodeChunk()).toMatch("::__continue2::"); + + util.testEachVersion(`loop continue (${testCase})`, () => util.testModule(testCase), { + [tstl.LuaTarget.Lua51]: builder => builder.expectDiagnosticsToMatchSnapshot(), + [tstl.LuaTarget.Lua52]: expectContinueGotoLabel, + [tstl.LuaTarget.Lua53]: expectContinueGotoLabel, + [tstl.LuaTarget.LuaJIT]: expectContinueGotoLabel, + }); +} test("do...while", () => { const code = ` diff --git a/test/util.ts b/test/util.ts index 4977f1469..6359e95c1 100644 --- a/test/util.ts +++ b/test/util.ts @@ -50,17 +50,19 @@ export const formatCode = (...values: unknown[]) => values.map(e => stringify(e) export function testEachVersion( name: string | undefined, common: () => T, - special: Record T) | false> + special?: Record void) | boolean> ): void { for (const version of Object.values(tstl.LuaTarget) as tstl.LuaTarget[]) { - const specialBuilder = special[version]; + const specialBuilder = special?.[version]; if (specialBuilder === false) return; const testName = name === undefined ? version : `${name} [${version}]`; test(testName, () => { const builder = common(); builder.setOptions({ luaTarget: version }); - specialBuilder(builder); + if (typeof specialBuilder === 'function') { + specialBuilder(builder); + } }); } } From 2b9c2a6b91e75a3f4bc122a321aa5e3e959a8032 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Dec 2019 23:31:27 +0000 Subject: [PATCH 13/42] Make `UnsupportedProperty` error a diagnostic --- src/transformation/builtins/array.ts | 4 +- src/transformation/builtins/console.ts | 6 +-- src/transformation/builtins/function.ts | 7 ++- src/transformation/builtins/index.ts | 26 +++++----- src/transformation/builtins/math.ts | 16 ++++-- src/transformation/builtins/number.ts | 10 ++-- src/transformation/builtins/object.ts | 6 +-- src/transformation/builtins/string.ts | 14 ++--- src/transformation/builtins/symbol.ts | 7 ++- src/transformation/utils/diagnostics.ts | 4 ++ src/transformation/utils/errors.ts | 3 -- src/transformation/visitors/lua-table.ts | 21 ++++---- .../__snapshots__/loading.spec.ts.snap | 17 ++++++ test/unit/builtins/loading.spec.ts | 9 +--- test/unit/builtins/string.spec.ts | 7 --- .../__snapshots__/luaTable.spec.ts.snap | 52 +++++++++++++++++++ test/unit/decorators/luaTable.spec.ts | 18 ++----- 17 files changed, 138 insertions(+), 89 deletions(-) create mode 100644 test/unit/builtins/__snapshots__/loading.spec.ts.snap diff --git a/src/transformation/builtins/array.ts b/src/transformation/builtins/array.ts index cf4bef707..e9a18db54 100644 --- a/src/transformation/builtins/array.ts +++ b/src/transformation/builtins/array.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { UnsupportedProperty } from "../utils/errors"; +import { unsupportedProperty } from "../utils/diagnostics"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; import { isExplicitArrayType } from "../utils/typescript"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; @@ -80,7 +80,7 @@ export function transformArrayPrototypeCall( return transformLuaLibFunction(context, LuaLibFeature.ArrayFlatMap, node, caller, ...params); default: if (isExplicitArrayType(context, ownerType)) { - throw UnsupportedProperty("array", expressionName, node); + context.diagnostics.push(unsupportedProperty(node, "array", expressionName)); } } } diff --git a/src/transformation/builtins/console.ts b/src/transformation/builtins/console.ts index 988aba1b3..e1e12e06a 100644 --- a/src/transformation/builtins/console.ts +++ b/src/transformation/builtins/console.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { UnsupportedProperty } from "../utils/errors"; +import { unsupportedProperty } from "../utils/diagnostics"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; const isStringFormatTemplate = (node: ts.Expression) => ts.isStringLiteral(node) && node.text.includes("%"); @@ -9,7 +9,7 @@ const isStringFormatTemplate = (node: ts.Expression) => ts.isStringLiteral(node) export function transformConsoleCall( context: TransformationContext, expression: PropertyCallExpression -): lua.Expression { +): lua.Expression | undefined { const method = expression.expression; const methodName = method.name.text; const signature = context.checker.getResolvedSignature(expression); @@ -61,6 +61,6 @@ export function transformConsoleCall( ); return lua.createCallExpression(lua.createIdentifier("print"), [debugTracebackCall]); default: - throw UnsupportedProperty("console", methodName, expression); + context.diagnostics.push(unsupportedProperty(expression, "console", methodName)); } } diff --git a/src/transformation/builtins/function.ts b/src/transformation/builtins/function.ts index e2f2c7e29..2572bac71 100644 --- a/src/transformation/builtins/function.ts +++ b/src/transformation/builtins/function.ts @@ -1,7 +1,6 @@ import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { unsupportedSelfFunctionConversion } from "../utils/diagnostics"; -import { UnsupportedProperty } from "../utils/errors"; +import { unsupportedProperty, unsupportedSelfFunctionConversion } from "../utils/diagnostics"; import { ContextType, getFunctionContextType } from "../utils/function-context"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; @@ -9,7 +8,7 @@ import { PropertyCallExpression, transformArguments } from "../visitors/call"; export function transformFunctionPrototypeCall( context: TransformationContext, node: PropertyCallExpression -): lua.CallExpression { +): lua.CallExpression | undefined { const expression = node.expression; const callerType = context.checker.getTypeAtLocation(expression.expression); if (getFunctionContextType(context, callerType) === ContextType.Void) { @@ -28,6 +27,6 @@ export function transformFunctionPrototypeCall( case "call": return transformLuaLibFunction(context, LuaLibFeature.FunctionCall, node, caller, ...params); default: - throw UnsupportedProperty("function", expressionName, node); + context.diagnostics.push(unsupportedProperty(node, "function", expressionName)); } } diff --git a/src/transformation/builtins/index.ts b/src/transformation/builtins/index.ts index 22ff84fa3..e870eddf9 100644 --- a/src/transformation/builtins/index.ts +++ b/src/transformation/builtins/index.ts @@ -21,24 +21,22 @@ export function transformBuiltinPropertyAccessExpression( context: TransformationContext, node: ts.PropertyAccessExpression ): lua.Expression | undefined { - const type = context.checker.getTypeAtLocation(node.expression); - if (isStringType(context, type)) { + const ownerType = context.checker.getTypeAtLocation(node.expression); + + if (isStringType(context, ownerType)) { return transformStringProperty(context, node); - } else if (isArrayType(context, type)) { - const arrayPropertyAccess = transformArrayProperty(context, node); - if (arrayPropertyAccess) { - return arrayPropertyAccess; - } } - if (ts.isIdentifier(node.expression)) { - const ownerType = context.checker.getTypeAtLocation(node.expression); + if (isArrayType(context, ownerType)) { + return transformArrayProperty(context, node); + } - if (isStandardLibraryType(context, ownerType, "Math")) { - return transformMathProperty(node); - } else if (isStandardLibraryType(context, ownerType, "Symbol")) { - // Pull in Symbol lib - importLuaLibFeature(context, LuaLibFeature.Symbol); + if (ts.isIdentifier(node.expression) && isStandardLibraryType(context, ownerType, undefined)) { + switch (node.expression.text) { + case "Math": + return transformMathProperty(context, node); + case "Symbol": + importLuaLibFeature(context, LuaLibFeature.Symbol); } } } diff --git a/src/transformation/builtins/math.ts b/src/transformation/builtins/math.ts index 5daf2d24a..f8405deab 100644 --- a/src/transformation/builtins/math.ts +++ b/src/transformation/builtins/math.ts @@ -1,10 +1,13 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { UnsupportedProperty } from "../utils/errors"; +import { unsupportedProperty } from "../utils/diagnostics"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; -export function transformMathProperty(node: ts.PropertyAccessExpression): lua.Expression { +export function transformMathProperty( + context: TransformationContext, + node: ts.PropertyAccessExpression +): lua.Expression | undefined { const name = node.name.text; switch (name) { case "PI": @@ -22,11 +25,14 @@ export function transformMathProperty(node: ts.PropertyAccessExpression): lua.Ex return lua.createNumericLiteral(Math[name], node); default: - throw UnsupportedProperty("Math", name, node); + context.diagnostics.push(unsupportedProperty(node, "Math", name)); } } -export function transformMathCall(context: TransformationContext, node: PropertyCallExpression): lua.Expression { +export function transformMathCall( + context: TransformationContext, + node: PropertyCallExpression +): lua.Expression | undefined { const expression = node.expression; const signature = context.checker.getResolvedSignature(node); const params = transformArguments(context, node.arguments, signature); @@ -92,6 +98,6 @@ export function transformMathCall(context: TransformationContext, node: Property } default: - throw UnsupportedProperty("Math", expressionName, expression); + context.diagnostics.push(unsupportedProperty(expression, "Math", expressionName)); } } diff --git a/src/transformation/builtins/number.ts b/src/transformation/builtins/number.ts index 9200be74a..d3ee0ab40 100644 --- a/src/transformation/builtins/number.ts +++ b/src/transformation/builtins/number.ts @@ -1,13 +1,13 @@ import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { UnsupportedProperty } from "../utils/errors"; +import { unsupportedProperty } from "../utils/diagnostics"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; export function transformNumberPrototypeCall( context: TransformationContext, node: PropertyCallExpression -): lua.Expression { +): lua.Expression | undefined { const expression = node.expression; const signature = context.checker.getResolvedSignature(node); const params = transformArguments(context, node.arguments, signature); @@ -20,14 +20,14 @@ export function transformNumberPrototypeCall( ? lua.createCallExpression(lua.createIdentifier("tostring"), [caller], node) : transformLuaLibFunction(context, LuaLibFeature.NumberToString, node, caller, ...params); default: - throw UnsupportedProperty("number", expressionName, node); + context.diagnostics.push(unsupportedProperty(node, "number", expressionName)); } } export function transformNumberConstructorCall( context: TransformationContext, expression: PropertyCallExpression -): lua.CallExpression { +): lua.CallExpression | undefined { const method = expression.expression; const parameters = transformArguments(context, expression.arguments); const methodName = method.name.text; @@ -37,6 +37,6 @@ export function transformNumberConstructorCall( case "isFinite": return transformLuaLibFunction(context, LuaLibFeature.NumberIsFinite, expression, ...parameters); default: - throw UnsupportedProperty("Number", methodName, expression); + context.diagnostics.push(unsupportedProperty(expression, "Number", methodName)); } } diff --git a/src/transformation/builtins/object.ts b/src/transformation/builtins/object.ts index 9f30840ba..94b48c1d0 100644 --- a/src/transformation/builtins/object.ts +++ b/src/transformation/builtins/object.ts @@ -1,13 +1,13 @@ import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { UnsupportedProperty } from "../utils/errors"; +import { unsupportedProperty } from "../utils/diagnostics"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; export function transformObjectConstructorCall( context: TransformationContext, expression: PropertyCallExpression -): lua.Expression { +): lua.Expression | undefined { const method = expression.expression; const parameters = transformArguments(context, expression.arguments); const methodName = method.name.text; @@ -24,7 +24,7 @@ export function transformObjectConstructorCall( case "values": return transformLuaLibFunction(context, LuaLibFeature.ObjectValues, expression, ...parameters); default: - throw UnsupportedProperty("Object", methodName, expression); + context.diagnostics.push(unsupportedProperty(expression, "Object", methodName)); } } diff --git a/src/transformation/builtins/string.ts b/src/transformation/builtins/string.ts index e1f32a886..da7e6546f 100644 --- a/src/transformation/builtins/string.ts +++ b/src/transformation/builtins/string.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { UnsupportedProperty } from "../utils/errors"; +import { unsupportedProperty } from "../utils/diagnostics"; import { createExpressionPlusOne } from "../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; @@ -19,7 +19,7 @@ function createStringCall(methodName: string, tsOriginal: ts.Node, ...params: lu export function transformStringPrototypeCall( context: TransformationContext, node: PropertyCallExpression -): lua.Expression { +): lua.Expression | undefined { const expression = node.expression; const signature = context.checker.getResolvedSignature(node); const params = transformArguments(context, node.arguments, signature); @@ -148,14 +148,14 @@ export function transformStringPrototypeCall( node ); default: - throw UnsupportedProperty("string", expressionName, node); + context.diagnostics.push(unsupportedProperty(node, "string", expressionName)); } } export function transformStringConstructorCall( context: TransformationContext, node: PropertyCallExpression -): lua.Expression { +): lua.Expression | undefined { const expression = node.expression; const signature = context.checker.getResolvedSignature(node); const params = transformArguments(context, node.arguments, signature); @@ -170,14 +170,14 @@ export function transformStringConstructorCall( ); default: - throw UnsupportedProperty("String", expressionName, node); + context.diagnostics.push(unsupportedProperty(node, "String", expressionName)); } } export function transformStringProperty( context: TransformationContext, node: ts.PropertyAccessExpression -): lua.UnaryExpression { +): lua.UnaryExpression | undefined { switch (node.name.text) { case "length": let expression = context.transformExpression(node.expression); @@ -186,6 +186,6 @@ export function transformStringProperty( } return lua.createUnaryExpression(expression, lua.SyntaxKind.LengthOperator, node); default: - throw UnsupportedProperty("string", node.name.text, node); + context.diagnostics.push(unsupportedProperty(node, "string", node.name.text)); } } diff --git a/src/transformation/builtins/symbol.ts b/src/transformation/builtins/symbol.ts index 4a6e5e43f..85cea3314 100644 --- a/src/transformation/builtins/symbol.ts +++ b/src/transformation/builtins/symbol.ts @@ -1,14 +1,13 @@ import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; -import { UnsupportedProperty } from "../utils/errors"; +import { unsupportedProperty } from "../utils/diagnostics"; import { importLuaLibFeature, LuaLibFeature } from "../utils/lualib"; import { PropertyCallExpression, transformArguments } from "../visitors/call"; -// Transpile a Symbol._ property export function transformSymbolConstructorCall( context: TransformationContext, expression: PropertyCallExpression -): lua.CallExpression { +): lua.CallExpression | undefined { const method = expression.expression; const signature = context.checker.getResolvedSignature(expression); const parameters = transformArguments(context, expression.arguments, signature); @@ -21,6 +20,6 @@ export function transformSymbolConstructorCall( const functionIdentifier = lua.createIdentifier(`__TS__SymbolRegistry${upperMethodName}`); return lua.createCallExpression(functionIdentifier, parameters, expression); default: - throw UnsupportedProperty("Symbol", methodName, expression); + context.diagnostics.push(unsupportedProperty(expression, "Symbol", methodName)); } } diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index 9cda3ea57..fb47be68a 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -114,3 +114,7 @@ export const unsupportedForTarget = createDiagnosticFactory( (functionality: string, version: LuaTarget) => `${functionality} is/are not supported for target ${getLuaTargetName(version)}.` ); + +export const unsupportedProperty = createDiagnosticFactory( + (parentName: string, property: string) => `${parentName}.${property} is unsupported.` +); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index d6491c0a9..aae243538 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -18,9 +18,6 @@ export const UnsupportedForInVariable = (node: ts.Node) => export const UndefinedScope = () => new Error("Expected to pop a scope, but found undefined."); -export const UnsupportedProperty = (parentName: string, property: string, node: ts.Node) => - new TranspileError(`Unsupported property on ${parentName}: ${property}`, node); - export const UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => new TranspileError(`${reason}. TypeScript path: ${path}.`, node); diff --git a/src/transformation/visitors/lua-table.ts b/src/transformation/visitors/lua-table.ts index 24cb5b24c..124fec931 100644 --- a/src/transformation/visitors/lua-table.ts +++ b/src/transformation/visitors/lua-table.ts @@ -2,8 +2,7 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; import { AnnotationKind, getTypeAnnotations } from "../utils/annotations"; -import { luaTableCannotBeAccessedDynamically, luaTableForbiddenUsage } from "../utils/diagnostics"; -import { UnsupportedProperty } from "../utils/errors"; +import { luaTableCannotBeAccessedDynamically, luaTableForbiddenUsage, unsupportedProperty } from "../utils/diagnostics"; import { transformArguments } from "./call"; const parseLuaTableExpression = (context: TransformationContext, node: ts.PropertyAccessExpression) => @@ -71,7 +70,7 @@ export function transformLuaTableExpressionStatement( expression ); default: - throw UnsupportedProperty("LuaTable", methodName, expression); + context.diagnostics.push(unsupportedProperty(expression, "LuaTable", methodName)); } } @@ -94,7 +93,7 @@ export function transformLuaTableCallExpression( case "get": return lua.createTableIndexExpression(luaTable, params[0] ?? lua.createNilLiteral(), node); default: - throw UnsupportedProperty("LuaTable", methodName, node); + context.diagnostics.push(unsupportedProperty(node, "LuaTable", methodName)); } } @@ -106,11 +105,11 @@ export function transformLuaTablePropertyAccessExpression( if (!annotations.has(AnnotationKind.LuaTable)) return; const [luaTable, propertyName] = parseLuaTableExpression(context, node); - if (propertyName !== "length") { - throw UnsupportedProperty("LuaTable", propertyName, node); + if (propertyName === "length") { + return lua.createUnaryExpression(luaTable, lua.SyntaxKind.LengthOperator, node); } - return lua.createUnaryExpression(luaTable, lua.SyntaxKind.LengthOperator, node); + context.diagnostics.push(unsupportedProperty(node, "LuaTable", propertyName)); } export function transformLuaTablePropertyAccessInAssignment( @@ -123,12 +122,12 @@ export function transformLuaTablePropertyAccessInAssignment( if (!annotations.has(AnnotationKind.LuaTable)) return; const [luaTable, propertyName] = parseLuaTableExpression(context, node); - if (propertyName !== "length") { - throw UnsupportedProperty("LuaTable", propertyName, node); + if (propertyName === "length") { + context.diagnostics.push(luaTableForbiddenUsage(node, `A LuaTable object's length cannot be re-assigned`)); + return lua.createTableIndexExpression(luaTable, lua.createStringLiteral(propertyName), node); } - context.diagnostics.push(luaTableForbiddenUsage(node, `A LuaTable object's length cannot be re-assigned`)); - return lua.createTableIndexExpression(luaTable, lua.createStringLiteral(propertyName), node); + context.diagnostics.push(unsupportedProperty(node, "LuaTable", propertyName)); } export function validateLuaTableElementAccessExpression( diff --git a/test/unit/builtins/__snapshots__/loading.spec.ts.snap b/test/unit/builtins/__snapshots__/loading.spec.ts.snap new file mode 100644 index 000000000..5c30da22e --- /dev/null +++ b/test/unit/builtins/__snapshots__/loading.spec.ts.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Unknown builtin property access: code 1`] = ` +"local ____exports = {} +____exports.__result = Math.unknownProperty +return ____exports" +`; + +exports[`Unknown builtin property access: diagnostics 1`] = `"main.ts(1,25): error TSTL: Math.unknownProperty is unsupported."`; + +exports[`Unknown builtin property function call: code 1`] = ` +"local ____exports = {} +____exports.__result = ({}):unknownFunction() +return ____exports" +`; + +exports[`Unknown builtin property function call: diagnostics 1`] = `"main.ts(1,25): error TSTL: array.unknownFunction is unsupported."`; diff --git a/test/unit/builtins/loading.spec.ts b/test/unit/builtins/loading.spec.ts index d43797e43..b90012bda 100644 --- a/test/unit/builtins/loading.spec.ts +++ b/test/unit/builtins/loading.spec.ts @@ -1,5 +1,4 @@ import * as tstl from "../../../src"; -import { UnsupportedProperty } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; describe("luaLibImport", () => { @@ -40,14 +39,10 @@ test("lualib should not include tstl header", () => { describe("Unknown builtin property", () => { test("access", () => { - util.testExpression`Math.unknownProperty` - .disableSemanticCheck() - .expectToHaveDiagnosticOfError(UnsupportedProperty("Math", "unknownProperty", util.nodeStub)); + util.testExpression`Math.unknownProperty`.disableSemanticCheck().expectDiagnosticsToMatchSnapshot(); }); test("function call", () => { - util.testExpression`[].unknownFunction()` - .disableSemanticCheck() - .expectToHaveDiagnosticOfError(UnsupportedProperty("array", "unknownFunction", util.nodeStub)); + util.testExpression`[].unknownFunction()`.disableSemanticCheck().expectDiagnosticsToMatchSnapshot(); }); }); diff --git a/test/unit/builtins/string.spec.ts b/test/unit/builtins/string.spec.ts index 7ecf860c7..21d4d02af 100644 --- a/test/unit/builtins/string.spec.ts +++ b/test/unit/builtins/string.spec.ts @@ -1,12 +1,5 @@ -import { UnsupportedProperty } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; -test("Unsupported string function", () => { - util.testExpression`"test".testThisIsNoMember()` - .disableSemanticCheck() - .expectToHaveDiagnosticOfError(UnsupportedProperty("string", "testThisIsNoMember", util.nodeStub)); -}); - test("Supported lua string function", () => { const tsHeader = ` declare global { diff --git a/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap b/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap index 6a5c7ea50..8bf940d89 100644 --- a/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/luaTable.spec.ts.snap @@ -25,6 +25,34 @@ end)()" exports[`Cannot extend LuaTable class ("const c = class Ext extends Table {}"): diagnostics 1`] = `"main.ts(11,29): error TSTL: Cannot extend classes with the '@luaTable' annotation."`; +exports[`Cannot isolate LuaTable method ("get"): code 1`] = ` +"local property +property = tbl.get" +`; + +exports[`Cannot isolate LuaTable method ("get"): code 2`] = ` +"local property +property = tbl.get" +`; + +exports[`Cannot isolate LuaTable method ("get"): diagnostics 1`] = `"main.ts(11,17): error TSTL: LuaTable.get is unsupported."`; + +exports[`Cannot isolate LuaTable method ("get"): diagnostics 2`] = `"main.ts(11,17): error TSTL: LuaTable.get is unsupported."`; + +exports[`Cannot isolate LuaTable method ("set"): code 1`] = ` +"local property +property = tbl.set" +`; + +exports[`Cannot isolate LuaTable method ("set"): code 2`] = ` +"local property +property = tbl.set" +`; + +exports[`Cannot isolate LuaTable method ("set"): diagnostics 1`] = `"main.ts(11,17): error TSTL: LuaTable.set is unsupported."`; + +exports[`Cannot isolate LuaTable method ("set"): diagnostics 2`] = `"main.ts(11,17): error TSTL: LuaTable.set is unsupported."`; + exports[`Cannot set LuaTable length: code 1`] = `"tbl.length = 2"`; exports[`Cannot set LuaTable length: code 2`] = `"tbl.length = 2"`; @@ -168,6 +196,30 @@ return ____exports" exports[`LuaTable classes must be ambient ("/** @luaTable */ export class Table {}"): diagnostics 1`] = `"main.ts(1,18): error TSTL: Classes with the '@luaTable' annotation must be ambient."`; +exports[`LuaTable set() cannot be used in a LuaTable call expression: code 1`] = `"local exp = tbl:set(\\"value\\", 5)"`; + +exports[`LuaTable set() cannot be used in a LuaTable call expression: code 2`] = `"local exp = tbl:set(\\"value\\", 5)"`; + +exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 1`] = `"main.ts(11,13): error TSTL: LuaTable.set is unsupported."`; + +exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 2`] = `"main.ts(11,13): error TSTL: LuaTable.set is unsupported."`; + exports[`LuaTables cannot be constructed with arguments: code 1`] = `"local ____table = {}"`; exports[`LuaTables cannot be constructed with arguments: diagnostics 1`] = `"main.ts(11,15): error TSTL: Invalid @luaTable usage: No parameters are allowed when constructing a LuaTable object."`; + +exports[`LuaTables cannot have other members: code 1`] = `"tbl:other()"`; + +exports[`LuaTables cannot have other members: code 2`] = `"tbl:other()"`; + +exports[`LuaTables cannot have other members: code 3`] = `"local x = tbl:other()"`; + +exports[`LuaTables cannot have other members: code 4`] = `"local x = tbl:other()"`; + +exports[`LuaTables cannot have other members: diagnostics 1`] = `"main.ts(11,1): error TSTL: LuaTable.other is unsupported."`; + +exports[`LuaTables cannot have other members: diagnostics 2`] = `"main.ts(11,1): error TSTL: LuaTable.other is unsupported."`; + +exports[`LuaTables cannot have other members: diagnostics 3`] = `"main.ts(11,9): error TSTL: LuaTable.other is unsupported."`; + +exports[`LuaTables cannot have other members: diagnostics 4`] = `"main.ts(11,9): error TSTL: LuaTable.other is unsupported."`; diff --git a/test/unit/decorators/luaTable.spec.ts b/test/unit/decorators/luaTable.spec.ts index 89ea22331..8f5b4d6ca 100644 --- a/test/unit/decorators/luaTable.spec.ts +++ b/test/unit/decorators/luaTable.spec.ts @@ -1,5 +1,3 @@ -import * as ts from "typescript"; -import { UnsupportedProperty } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; const tableLibClass = ` @@ -34,22 +32,16 @@ test.each([tableLibClass])("LuaTables cannot be constructed with arguments", tab test.each([tableLibClass, tableLibInterface])( "LuaTable set() cannot be used in a LuaTable call expression", tableLib => { - expect(() => util.transpileString(tableLib + `const exp = tbl.set("value", 5)`)).toThrowExactError( - UnsupportedProperty("LuaTable", "set", util.nodeStub) - ); + util.testModule(tableLib + `const exp = tbl.set("value", 5)`).expectDiagnosticsToMatchSnapshot(); } ); test.each([tableLibClass, tableLibInterface])("LuaTables cannot have other members", tableLib => { - expect(() => util.transpileString(tableLib + `tbl.other()`)).toThrowExactError( - UnsupportedProperty("LuaTable", "other", util.nodeStub) - ); + util.testModule(tableLib + `tbl.other()`).expectDiagnosticsToMatchSnapshot(); }); test.each([tableLibClass, tableLibInterface])("LuaTables cannot have other members", tableLib => { - expect(() => util.transpileString(tableLib + `let x = tbl.other()`)).toThrowExactError( - UnsupportedProperty("LuaTable", "other", util.nodeStub) - ); + util.testModule(tableLib + `let x = tbl.other()`).expectDiagnosticsToMatchSnapshot(); }); test.each([tableLibClass])("LuaTable new", tableLib => { @@ -115,9 +107,7 @@ test.each([tableLibClass, tableLibInterface])("Cannot use ElementAccessExpressio test.each([tableLibClass, tableLibInterface])("Cannot isolate LuaTable methods", tableLib => { test.each([`set`, `get`])("Cannot isolate LuaTable method (%p)", propertyName => { - expect(() => util.transpileString(`${tableLib} let property = tbl.${propertyName}`)).toThrowExactError( - UnsupportedProperty("LuaTable", propertyName, util.nodeStub) - ); + util.testModule(`${tableLib} let property = tbl.${propertyName}`).expectDiagnosticsToMatchSnapshot(); }); }); From 85df23ffa715a0dc2ead6fc5a3029b6a406a05fd Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Dec 2019 23:55:38 +0000 Subject: [PATCH 14/42] Make loop errors diagnostics --- src/transformation/utils/diagnostics.ts | 4 +++ src/transformation/utils/errors.ts | 9 ------- src/transformation/visitors/loops/for-in.ts | 5 ++-- src/transformation/visitors/loops/for-of.ts | 30 +++++++++++---------- test/unit/loops.spec.ts | 10 +++---- 5 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index fb47be68a..b2c631cdd 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -118,3 +118,7 @@ export const unsupportedForTarget = createDiagnosticFactory( export const unsupportedProperty = createDiagnosticFactory( (parentName: string, property: string) => `${parentName}.${property} is unsupported.` ); + +export const forOfUnsupportedObjectDestructuring = createDiagnosticFactory( + `Unsupported object destructuring in for...of statement.` +); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index aae243538..ebbab0919 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -10,12 +10,6 @@ export class TranspileError extends Error { export const InvalidDecoratorContext = (node: ts.Node) => new TranspileError(`Decorator function cannot have 'this: void'.`, node); -export const MissingForOfVariables = (node: ts.Node) => - new TranspileError("Transpiled ForOf variable declaration list contains no declarations.", node); - -export const UnsupportedForInVariable = (node: ts.Node) => - new TranspileError(`Unsupported for-in variable kind.`, node); - export const UndefinedScope = () => new Error("Expected to pop a scope, but found undefined."); export const UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => @@ -28,9 +22,6 @@ export const ReferencedBeforeDeclaration = (node: ts.Identifier) => node ); -export const UnsupportedObjectDestructuringInForOf = (node: ts.Node) => - new TranspileError(`Unsupported object destructuring in for...of statement.`, node); - export const InvalidAmbientIdentifierName = (node: ts.Identifier) => new TranspileError( `Invalid ambient identifier name "${node.text}". Ambient identifiers must be valid lua identifiers.`, diff --git a/src/transformation/visitors/loops/for-in.ts b/src/transformation/visitors/loops/for-in.ts index e2111ff2a..d96b02289 100644 --- a/src/transformation/visitors/loops/for-in.ts +++ b/src/transformation/visitors/loops/for-in.ts @@ -2,7 +2,6 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; import { FunctionVisitor } from "../../context"; import { forbiddenForIn } from "../../utils/diagnostics"; -import { UnsupportedForInVariable } from "../../utils/errors"; import { isArrayType } from "../../utils/typescript"; import { transformIdentifier } from "../identifier"; import { transformLoopBody } from "./body"; @@ -38,8 +37,8 @@ export const transformForInStatement: FunctionVisitor = (stat ); body.statements.unshift(initializer); } else { - // This should never occur - throw UnsupportedForInVariable(statement.initializer); + // TODO: + throw new Error(`Unsupported for...in variable kind: ${ts.SyntaxKind[statement.initializer.kind]}.`); } return lua.createForInStatement(body, [iterationVariable], [pairsCall], statement); diff --git a/src/transformation/visitors/loops/for-of.ts b/src/transformation/visitors/loops/for-of.ts index cbdd29767..2bc2cc959 100644 --- a/src/transformation/visitors/loops/for-of.ts +++ b/src/transformation/visitors/loops/for-of.ts @@ -3,8 +3,11 @@ import * as lua from "../../../LuaAST"; import { assert, cast, castEach } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations, isForRangeType, isLuaIteratorType } from "../../utils/annotations"; -import { invalidForRangeCall, luaIteratorForbiddenUsage } from "../../utils/diagnostics"; -import { MissingForOfVariables, UnsupportedObjectDestructuringInForOf } from "../../utils/errors"; +import { + forOfUnsupportedObjectDestructuring, + invalidForRangeCall, + luaIteratorForbiddenUsage, +} from "../../utils/diagnostics"; import { createUnpackCall } from "../../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; import { isArrayType, isNumberType } from "../../utils/typescript"; @@ -28,19 +31,17 @@ function transformForOfInitializer( expression = createUnpackCall(context, expression, initializer); } else if (ts.isObjectBindingPattern(initializer.declarations[0].name)) { - throw UnsupportedObjectDestructuringInForOf(initializer); + context.diagnostics.push(forOfUnsupportedObjectDestructuring(initializer)); + return; } - const variableStatements = transformVariableDeclaration(context, initializer.declarations[0]); - if (variableStatements[0]) { - // we can safely assume that for vars are not exported and therefore declarationstatenents - return lua.createVariableDeclarationStatement( - (variableStatements[0] as lua.VariableDeclarationStatement).left, - expression - ); - } else { - throw MissingForOfVariables(initializer); - } + // we can safely assume that for vars are not exported and therefore VariableDeclarationStatement's + const assignmentStatement = cast( + transformVariableDeclaration(context, initializer.declarations[0])[0], + lua.isVariableDeclarationStatement + ); + + return lua.createVariableDeclarationStatement(assignmentStatement.left, expression); } else { // Assignment to existing variable let variables: lua.AssignmentLeftHandSideExpression | lua.AssignmentLeftHandSideExpression[]; @@ -56,7 +57,8 @@ function transformForOfInitializer( return undefined; } } else if (ts.isObjectLiteralExpression(initializer)) { - throw UnsupportedObjectDestructuringInForOf(initializer); + context.diagnostics.push(forOfUnsupportedObjectDestructuring(initializer)); + return; } else { variables = cast(context.transformExpression(initializer), lua.isAssignmentLeftHandSideExpression); } diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index fad1020e2..c3c74f591 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -1,6 +1,5 @@ import * as ts from "typescript"; import * as tstl from "../../src"; -import { UnsupportedObjectDestructuringInForOf } from "../../src/transformation/utils/errors"; import * as util from "../util"; test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("while (%p)", ({ inp, expected }) => { @@ -487,14 +486,11 @@ test.each([ { initializer: "{a, b}", vars: "let a: string, b: string;" }, { initializer: "{a: c, b: d}", vars: "let c: string, d: string;" }, ])("forof object destructuring (%p)", ({ initializer, vars }) => { - const code = ` + util.testModule` declare const arr: {a: string, b: string}[]; ${vars} - for (${initializer} of arr) {}`; - - expect(() => util.transpileString(code)).toThrow( - UnsupportedObjectDestructuringInForOf(ts.createEmptyStatement()).message - ); + for (${initializer} of arr) {} + `.expectDiagnosticsToMatchSnapshot(); }); test("forof with array typed as iterable", () => { From 65562cb135490d195078dcb01d2ab885a6b95966 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 00:36:01 +0000 Subject: [PATCH 15/42] Simplift `isValidLuaIdentifier` usage --- src/LuaPrinter.ts | 14 +++---------- src/transformation/utils/safe-names.ts | 28 ++++++++++---------------- src/transformation/visitors/call.ts | 8 ++------ src/transformation/visitors/literal.ts | 3 +-- 4 files changed, 17 insertions(+), 36 deletions(-) diff --git a/src/LuaPrinter.ts b/src/LuaPrinter.ts index fda6e89ff..75f3b722e 100644 --- a/src/LuaPrinter.ts +++ b/src/LuaPrinter.ts @@ -4,7 +4,7 @@ import * as ts from "typescript"; import { CompilerOptions, LuaLibImportKind } from "./CompilerOptions"; import * as lua from "./LuaAST"; import { loadLuaLibFeatures, LuaLibFeature } from "./LuaLib"; -import { isValidLuaIdentifier, luaKeywords } from "./transformation/utils/safe-names"; +import { isValidLuaIdentifier } from "./transformation/utils/safe-names"; import { EmitHost } from "./transpilation"; import { trimExtension } from "./utils"; @@ -660,11 +660,7 @@ export class LuaPrinter { const value = this.printExpression(expression.value); if (expression.key) { - if ( - lua.isStringLiteral(expression.key) && - isValidLuaIdentifier(expression.key.value) && - !luaKeywords.has(expression.key.value) - ) { + if (lua.isStringLiteral(expression.key) && isValidLuaIdentifier(expression.key.value)) { chunks.push(expression.key.value, " = ", value); } else { chunks.push("[", this.printExpression(expression.key), "] = ", value); @@ -764,11 +760,7 @@ export class LuaPrinter { const chunks: SourceChunk[] = []; chunks.push(this.printExpression(expression.table)); - if ( - lua.isStringLiteral(expression.index) && - isValidLuaIdentifier(expression.index.value) && - !luaKeywords.has(expression.index.value) - ) { + if (lua.isStringLiteral(expression.index) && isValidLuaIdentifier(expression.index.value)) { chunks.push(".", this.createSourceNode(expression.index, expression.index.value)); } else { chunks.push("[", this.printExpression(expression.index), "]"); diff --git a/src/transformation/utils/safe-names.ts b/src/transformation/utils/safe-names.ts index 9969bd561..96815806b 100644 --- a/src/transformation/utils/safe-names.ts +++ b/src/transformation/utils/safe-names.ts @@ -4,6 +4,7 @@ import { InvalidAmbientIdentifierName } from "./errors"; import { isAmbientNode } from "./typescript"; import { isSymbolExported } from "./export"; +export const isValidLuaIdentifier = (name: string) => !luaKeywords.has(name) && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name); export const luaKeywords: ReadonlySet = new Set([ "and", "break", @@ -28,7 +29,7 @@ export const luaKeywords: ReadonlySet = new Set([ "while", ]); -export const luaBuiltins: ReadonlySet = new Set([ +const luaBuiltins: ReadonlySet = new Set([ "_G", "assert", "coroutine", @@ -51,38 +52,31 @@ export const luaBuiltins: ReadonlySet = new Set([ "unpack", ]); -export const isValidLuaIdentifier = (str: string) => /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(str); - -export const isUnsafeName = (name: string) => - luaKeywords.has(name) || luaBuiltins.has(name) || !isValidLuaIdentifier(name); +export const isUnsafeName = (name: string) => !isValidLuaIdentifier(name) || luaBuiltins.has(name); export function hasUnsafeSymbolName( context: TransformationContext, symbol: ts.Symbol, tsOriginal: ts.Identifier ): boolean { - const isLuaKeyword = luaKeywords.has(symbol.name); - const isInvalidIdentifier = !isValidLuaIdentifier(symbol.name); const isAmbient = symbol.declarations && symbol.declarations.some(d => isAmbientNode(d)); - if ((isLuaKeyword || isInvalidIdentifier) && isAmbient) { + + if (!isValidLuaIdentifier(symbol.name) && isAmbient) { // Catch ambient declarations of identifiers with bad names throw InvalidAmbientIdentifierName(tsOriginal); } - if (isUnsafeName(symbol.name)) { - // only unsafe when non-ambient and not exported - return !isAmbient && !isSymbolExported(context, symbol); - } - - return false; + // only unsafe when non-ambient and not exported + return isUnsafeName(symbol.name) && !isAmbient && !isSymbolExported(context, symbol); } export function hasUnsafeIdentifierName(context: TransformationContext, identifier: ts.Identifier): boolean { const symbol = context.checker.getSymbolAtLocation(identifier); - - if (symbol !== undefined) { + if (symbol) { return hasUnsafeSymbolName(context, symbol, identifier); - } else if (luaKeywords.has(identifier.text) || !isValidLuaIdentifier(identifier.text)) { + } + + if (!isValidLuaIdentifier(identifier.text)) { throw InvalidAmbientIdentifierName(identifier); } diff --git a/src/transformation/visitors/call.ts b/src/transformation/visitors/call.ts index 315dd0422..ae69c5252 100644 --- a/src/transformation/visitors/call.ts +++ b/src/transformation/visitors/call.ts @@ -7,7 +7,7 @@ import { validateAssignment } from "../utils/assignment-validation"; import { ContextType, getDeclarationContextType } from "../utils/function-context"; import { createImmediatelyInvokedFunctionExpression, createUnpackCall, wrapInTable } from "../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; -import { isValidLuaIdentifier, luaKeywords } from "../utils/safe-names"; +import { isValidLuaIdentifier } from "../utils/safe-names"; import { isArrayType, isExpressionWithEvaluationEffect, isInDestructingAssignment } from "../utils/typescript"; import { transformElementAccessArgument } from "./access"; import { transformIdentifier } from "./identifier"; @@ -46,11 +46,7 @@ export function transformContextualCallExpression( transformedArguments: lua.Expression[] ): lua.Expression { const left = ts.isCallExpression(node) ? node.expression : node.tag; - if ( - ts.isPropertyAccessExpression(left) && - !luaKeywords.has(left.name.text) && - isValidLuaIdentifier(left.name.text) - ) { + if (ts.isPropertyAccessExpression(left) && isValidLuaIdentifier(left.name.text)) { // table:name() let table = context.transformExpression(left.expression); if (lua.isTableExpression(table)) { diff --git a/src/transformation/visitors/literal.ts b/src/transformation/visitors/literal.ts index 6a3804baa..130bc1770 100644 --- a/src/transformation/visitors/literal.ts +++ b/src/transformation/visitors/literal.ts @@ -11,7 +11,6 @@ import { hasUnsafeIdentifierName, hasUnsafeSymbolName, isValidLuaIdentifier, - luaKeywords, } from "../utils/safe-names"; import { getSymbolIdOfSymbol, trackSymbolReference } from "../utils/symbols"; import { isArrayType } from "../utils/typescript"; @@ -40,7 +39,7 @@ export function createShorthandIdentifier( : valueSymbol.name; } else { const propertyName = propertyIdentifier.text; - if (luaKeywords.has(propertyName) || !isValidLuaIdentifier(propertyName)) { + if (!isValidLuaIdentifier(propertyName)) { // Catch ambient declarations of identifiers with bad names throw InvalidAmbientIdentifierName(propertyIdentifier); } From 1cfec8e11d4908bf9bc83783ebdedee1de6f1867 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 01:30:54 +0000 Subject: [PATCH 16/42] Make `InvalidAmbientIdentifierName` error a diagnostic --- src/transformation/utils/diagnostics.ts | 4 + src/transformation/utils/errors.ts | 6 - src/transformation/utils/safe-names.ts | 26 +- src/transformation/visitors/literal.ts | 27 +- .../__snapshots__/identifiers.spec.ts.snap | 241 ++++++++++++++++++ test/unit/identifiers.spec.ts | 12 +- 6 files changed, 274 insertions(+), 42 deletions(-) create mode 100644 test/unit/__snapshots__/identifiers.spec.ts.snap diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index b2c631cdd..4bfb3cd61 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -122,3 +122,7 @@ export const unsupportedProperty = createDiagnosticFactory( export const forOfUnsupportedObjectDestructuring = createDiagnosticFactory( `Unsupported object destructuring in for...of statement.` ); + +export const invalidAmbientIdentifierName = createDiagnosticFactory( + (text: string) => `Invalid ambient identifier name '${text}'. Ambient identifiers must be valid lua identifiers.` +); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index ebbab0919..1f76097a2 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -21,9 +21,3 @@ export const ReferencedBeforeDeclaration = (node: ts.Identifier) => "must be moved before the identifier's use, or hoisting must be enabled.", node ); - -export const InvalidAmbientIdentifierName = (node: ts.Identifier) => - new TranspileError( - `Invalid ambient identifier name "${node.text}". Ambient identifiers must be valid lua identifiers.`, - node - ); diff --git a/src/transformation/utils/safe-names.ts b/src/transformation/utils/safe-names.ts index 96815806b..3e20f4d44 100644 --- a/src/transformation/utils/safe-names.ts +++ b/src/transformation/utils/safe-names.ts @@ -1,8 +1,8 @@ import * as ts from "typescript"; import { TransformationContext } from "../context"; -import { InvalidAmbientIdentifierName } from "./errors"; -import { isAmbientNode } from "./typescript"; +import { invalidAmbientIdentifierName } from "./diagnostics"; import { isSymbolExported } from "./export"; +import { isAmbientNode } from "./typescript"; export const isValidLuaIdentifier = (name: string) => !luaKeywords.has(name) && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name); export const luaKeywords: ReadonlySet = new Set([ @@ -61,23 +61,31 @@ export function hasUnsafeSymbolName( ): boolean { const isAmbient = symbol.declarations && symbol.declarations.some(d => isAmbientNode(d)); + // Catch ambient declarations of identifiers with bad names if (!isValidLuaIdentifier(symbol.name) && isAmbient) { - // Catch ambient declarations of identifiers with bad names - throw InvalidAmbientIdentifierName(tsOriginal); + context.diagnostics.push(invalidAmbientIdentifierName(tsOriginal, symbol.name)); + return true; } // only unsafe when non-ambient and not exported return isUnsafeName(symbol.name) && !isAmbient && !isSymbolExported(context, symbol); } -export function hasUnsafeIdentifierName(context: TransformationContext, identifier: ts.Identifier): boolean { - const symbol = context.checker.getSymbolAtLocation(identifier); - if (symbol) { - return hasUnsafeSymbolName(context, symbol, identifier); +export function hasUnsafeIdentifierName( + context: TransformationContext, + identifier: ts.Identifier, + checkSymbol = true +): boolean { + if (checkSymbol) { + const symbol = context.checker.getSymbolAtLocation(identifier); + if (symbol) { + return hasUnsafeSymbolName(context, symbol, identifier); + } } if (!isValidLuaIdentifier(identifier.text)) { - throw InvalidAmbientIdentifierName(identifier); + context.diagnostics.push(invalidAmbientIdentifierName(identifier, identifier.text)); + return true; } return false; diff --git a/src/transformation/visitors/literal.ts b/src/transformation/visitors/literal.ts index 130bc1770..2498176b0 100644 --- a/src/transformation/visitors/literal.ts +++ b/src/transformation/visitors/literal.ts @@ -3,15 +3,9 @@ import * as lua from "../../LuaAST"; import { assertNever } from "../../utils"; import { FunctionVisitor, TransformationContext, Visitors } from "../context"; import { unsupportedAccessorInObjectLiteral } from "../utils/diagnostics"; -import { InvalidAmbientIdentifierName } from "../utils/errors"; import { createExportedIdentifier, getSymbolExportScope } from "../utils/export"; import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib"; -import { - createSafeName, - hasUnsafeIdentifierName, - hasUnsafeSymbolName, - isValidLuaIdentifier, -} from "../utils/safe-names"; +import { createSafeName, hasUnsafeIdentifierName, hasUnsafeSymbolName } from "../utils/safe-names"; import { getSymbolIdOfSymbol, trackSymbolReference } from "../utils/symbols"; import { isArrayType } from "../utils/typescript"; import { transformFunctionLikeDeclaration } from "./function"; @@ -32,20 +26,13 @@ export function createShorthandIdentifier( valueSymbol: ts.Symbol | undefined, propertyIdentifier: ts.Identifier ): lua.Expression { - let name: string; - if (valueSymbol !== undefined) { - name = hasUnsafeSymbolName(context, valueSymbol, propertyIdentifier) - ? createSafeName(valueSymbol.name) - : valueSymbol.name; - } else { - const propertyName = propertyIdentifier.text; - if (!isValidLuaIdentifier(propertyName)) { - // Catch ambient declarations of identifiers with bad names - throw InvalidAmbientIdentifierName(propertyIdentifier); - } + const propertyName = propertyIdentifier.text; - name = hasUnsafeIdentifierName(context, propertyIdentifier) ? createSafeName(propertyName) : propertyName; - } + const isUnsafeName = valueSymbol + ? hasUnsafeSymbolName(context, valueSymbol, propertyIdentifier) + : hasUnsafeIdentifierName(context, propertyIdentifier, false); + + const name = isUnsafeName ? createSafeName(propertyName) : propertyName; let identifier = context.transformExpression(ts.createIdentifier(name)); lua.setNodeOriginal(identifier, propertyIdentifier); diff --git a/test/unit/__snapshots__/identifiers.spec.ts.snap b/test/unit/__snapshots__/identifiers.spec.ts.snap new file mode 100644 index 000000000..24399a875 --- /dev/null +++ b/test/unit/__snapshots__/identifiers.spec.ts.snap @@ -0,0 +1,241 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ambient identifier cannot be a lua keyword ("class local {}"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("class local {}"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier cannot be a lua keyword ("const foo: any, bar: any, local: any;"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("const foo: any, bar: any, local: any;"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier cannot be a lua keyword ("const local: any;"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("const local: any;"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier cannot be a lua keyword ("enum local {}"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("enum local {}"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier cannot be a lua keyword ("function local() {}"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("function local() {}"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier cannot be a lua keyword ("let local: any;"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("let local: any;"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier cannot be a lua keyword ("module local { export const bar: any; }"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("module local { export const bar: any; }"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier cannot be a lua keyword ("namespace local { export const bar: any; }"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("namespace local { export const bar: any; }"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier cannot be a lua keyword ("var local: any;"): code 1`] = `"local ____ = ____local"`; + +exports[`ambient identifier cannot be a lua keyword ("var local: any;"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("class $$ {}"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("class $$ {}"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("const $$: any;"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("const $$: any;"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("const foo: any, bar: any, $$: any;"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("const foo: any, bar: any, $$: any;"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("enum $$ {}"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("enum $$ {}"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("function $$();"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("function $$();"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("let $$: any;"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("let $$: any;"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("module $$ { export const bar: any; }"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("module $$ { export const bar: any; }"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("namespace $$ { export const bar: any; }"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("namespace $$ { export const bar: any; }"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier ("var $$: any;"): code 1`] = `"local ____ = _____24_24_24"`; + +exports[`ambient identifier must be a valid lua identifier ("var $$: any;"): diagnostics 1`] = `"main.ts(3,9): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("$$"): code 1`] = `"local foo = {[\\"$$$\\"] = _____24_24_24}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("$$"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("_̀ः٠‿"): code 1`] = `"local foo = {[\\"_̀ः٠‿\\"] = ______300_903_660_203F}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("_̀ः٠‿"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name '_̀ः٠‿'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("and"): code 1`] = `"local foo = {[\\"and\\"] = ____and}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("and"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'and'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("elseif"): code 1`] = `"local foo = {[\\"elseif\\"] = ____elseif}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("elseif"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'elseif'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("end"): code 1`] = `"local foo = {[\\"end\\"] = ____end}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("end"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'end'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("goto"): code 1`] = `"local foo = {[\\"goto\\"] = ____goto}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("goto"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'goto'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("local"): code 1`] = `"local foo = {[\\"local\\"] = ____local}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("local"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("nil"): code 1`] = `"local foo = {[\\"nil\\"] = ____nil}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("nil"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'nil'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("not"): code 1`] = `"local foo = {[\\"not\\"] = ____not}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("not"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'not'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("or"): code 1`] = `"local foo = {[\\"or\\"] = ____or}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("or"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'or'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("repeat"): code 1`] = `"local foo = {[\\"repeat\\"] = ____repeat}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("repeat"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'repeat'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("then"): code 1`] = `"local foo = {[\\"then\\"] = ____then}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("then"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'then'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("until"): code 1`] = `"local foo = {[\\"until\\"] = ____until}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("until"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'until'. Ambient identifiers must be valid lua identifiers."`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("ɥɣɎɌͼƛಠ"): code 1`] = `"local foo = {[\\"ɥɣɎɌͼƛಠ\\"] = _____265_263_24E_24C_37C_19B_CA0}"`; + +exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("ɥɣɎɌͼƛಠ"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'ɥɣɎɌͼƛಠ'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("$$"): code 1`] = `"local foo = _____24_24_24"`; + +exports[`undeclared identifier must be a valid lua identifier ("$$"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("_̀ः٠‿"): code 1`] = `"local foo = ______300_903_660_203F"`; + +exports[`undeclared identifier must be a valid lua identifier ("_̀ः٠‿"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name '_̀ः٠‿'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("and"): code 1`] = `"local foo = ____and"`; + +exports[`undeclared identifier must be a valid lua identifier ("and"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'and'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("elseif"): code 1`] = `"local foo = ____elseif"`; + +exports[`undeclared identifier must be a valid lua identifier ("elseif"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'elseif'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("end"): code 1`] = `"local foo = ____end"`; + +exports[`undeclared identifier must be a valid lua identifier ("end"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'end'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("goto"): code 1`] = `"local foo = ____goto"`; + +exports[`undeclared identifier must be a valid lua identifier ("goto"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'goto'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("local"): code 1`] = `"local foo = ____local"`; + +exports[`undeclared identifier must be a valid lua identifier ("local"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("nil"): code 1`] = `"local foo = ____nil"`; + +exports[`undeclared identifier must be a valid lua identifier ("nil"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'nil'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("not"): code 1`] = `"local foo = ____not"`; + +exports[`undeclared identifier must be a valid lua identifier ("not"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'not'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("or"): code 1`] = `"local foo = ____or"`; + +exports[`undeclared identifier must be a valid lua identifier ("or"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'or'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("repeat"): code 1`] = `"local foo = ____repeat"`; + +exports[`undeclared identifier must be a valid lua identifier ("repeat"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'repeat'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("then"): code 1`] = `"local foo = ____then"`; + +exports[`undeclared identifier must be a valid lua identifier ("then"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'then'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("until"): code 1`] = `"local foo = ____until"`; + +exports[`undeclared identifier must be a valid lua identifier ("until"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'until'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier ("ɥɣɎɌͼƛಠ"): code 1`] = `"local foo = _____265_263_24E_24C_37C_19B_CA0"`; + +exports[`undeclared identifier must be a valid lua identifier ("ɥɣɎɌͼƛಠ"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name 'ɥɣɎɌͼƛಠ'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("$$"): code 1`] = `"local foo = {[\\"$$$\\"] = _____24_24_24}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("$$"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("_̀ः٠‿"): code 1`] = `"local foo = {[\\"_̀ः٠‿\\"] = ______300_903_660_203F}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("_̀ः٠‿"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name '_̀ः٠‿'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("and"): code 1`] = `"local foo = {[\\"and\\"] = ____and}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("and"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'and'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("elseif"): code 1`] = `"local foo = {[\\"elseif\\"] = ____elseif}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("elseif"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'elseif'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("end"): code 1`] = `"local foo = {[\\"end\\"] = ____end}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("end"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'end'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("goto"): code 1`] = `"local foo = {[\\"goto\\"] = ____goto}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("goto"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'goto'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("local"): code 1`] = `"local foo = {[\\"local\\"] = ____local}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("local"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'local'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("nil"): code 1`] = `"local foo = {[\\"nil\\"] = ____nil}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("nil"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'nil'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("not"): code 1`] = `"local foo = {[\\"not\\"] = ____not}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("not"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'not'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("or"): code 1`] = `"local foo = {[\\"or\\"] = ____or}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("or"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'or'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("repeat"): code 1`] = `"local foo = {[\\"repeat\\"] = ____repeat}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("repeat"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'repeat'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("then"): code 1`] = `"local foo = {[\\"then\\"] = ____then}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("then"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'then'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("until"): code 1`] = `"local foo = {[\\"until\\"] = ____until}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("until"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'until'. Ambient identifiers must be valid lua identifiers."`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("ɥɣɎɌͼƛಠ"): code 1`] = `"local foo = {[\\"ɥɣɎɌͼƛಠ\\"] = _____265_263_24E_24C_37C_19B_CA0}"`; + +exports[`undeclared identifier must be a valid lua identifier (object literal shorthand) ("ɥɣɎɌͼƛಠ"): diagnostics 1`] = `"main.ts(2,27): error TSTL: Invalid ambient identifier name 'ɥɣɎɌͼƛಠ'. Ambient identifiers must be valid lua identifiers."`; diff --git a/test/unit/identifiers.spec.ts b/test/unit/identifiers.spec.ts index 88c5cc23b..1cc87ecfc 100644 --- a/test/unit/identifiers.spec.ts +++ b/test/unit/identifiers.spec.ts @@ -1,5 +1,3 @@ -import * as ts from "typescript"; -import { InvalidAmbientIdentifierName } from "../../src/transformation/utils/errors"; import { luaKeywords } from "../../src/transformation/utils/safe-names"; import * as util from "../util"; @@ -83,7 +81,7 @@ test.each([ local; ` .disableSemanticCheck() - .expectToHaveDiagnosticOfError(InvalidAmbientIdentifierName(ts.createIdentifier("local"))); + .expectDiagnosticsToMatchSnapshot(); }); test.each([ @@ -100,7 +98,7 @@ test.each([ util.testModule` declare ${statement} $$$; - `.expectToHaveDiagnosticOfError(InvalidAmbientIdentifierName(ts.createIdentifier("$$$"))); + `.expectDiagnosticsToMatchSnapshot(); }); test.each(validTsInvalidLuaNames)( @@ -109,7 +107,7 @@ test.each(validTsInvalidLuaNames)( util.testModule` declare var ${name}: any; const foo = { ${name} }; - `.expectToHaveDiagnosticOfError(InvalidAmbientIdentifierName(ts.createIdentifier(name))); + `.expectDiagnosticsToMatchSnapshot(); } ); @@ -118,7 +116,7 @@ test.each(validTsInvalidLuaNames)("undeclared identifier must be a valid lua ide const foo = ${name}; ` .disableSemanticCheck() - .expectToHaveDiagnosticOfError(InvalidAmbientIdentifierName(ts.createIdentifier(name))); + .expectDiagnosticsToMatchSnapshot(); }); test.each(validTsInvalidLuaNames)( @@ -128,7 +126,7 @@ test.each(validTsInvalidLuaNames)( const foo = { ${name} }; ` .disableSemanticCheck() - .expectToHaveDiagnosticOfError(InvalidAmbientIdentifierName(ts.createIdentifier(name))); + .expectDiagnosticsToMatchSnapshot(); } ); From afb40a56fbf4c6e98a45006eab858b65c93fd873 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 02:24:40 +0000 Subject: [PATCH 17/42] Remove `UndefinedScope` --- src/transformation/utils/errors.ts | 2 -- src/transformation/utils/lua-ast.ts | 13 +++++-------- src/transformation/utils/scope.ts | 9 ++------- src/transformation/visitors/break-continue.ts | 15 +++++---------- 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index 1f76097a2..37d882966 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -10,8 +10,6 @@ export class TranspileError extends Error { export const InvalidDecoratorContext = (node: ts.Node) => new TranspileError(`Decorator function cannot have 'this: void'.`, node); -export const UndefinedScope = () => new Error("Expected to pop a scope, but found undefined."); - export const UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => new TranspileError(`${reason}. TypeScript path: ${path}.`, node); diff --git a/src/transformation/utils/lua-ast.ts b/src/transformation/utils/lua-ast.ts index 6043a4c07..e2a637ab8 100644 --- a/src/transformation/utils/lua-ast.ts +++ b/src/transformation/utils/lua-ast.ts @@ -3,7 +3,6 @@ import { LuaTarget } from "../../CompilerOptions"; import * as lua from "../../LuaAST"; import { TransformationContext } from "../context"; import { getCurrentNamespace } from "../visitors/namespace"; -import { UndefinedScope } from "./errors"; import { createExportedIdentifier, getIdentifierExportScope } from "./export"; import { findScope, peekScope, ScopeType } from "./scope"; import { isFirstDeclaration, isFunctionType } from "./typescript"; @@ -193,15 +192,13 @@ export function createLocalOrExportedOrGlobalDeclaration( ? peekScope(context) : findScope(context, ScopeType.Function | ScopeType.File); - if (scope === undefined) { - throw UndefinedScope(); - } + if (scope) { + if (!scope.variableDeclarations) { + scope.variableDeclarations = []; + } - if (!scope.variableDeclarations) { - scope.variableDeclarations = []; + scope.variableDeclarations.push(declaration); } - - scope.variableDeclarations.push(declaration); } } else if (rhs) { // global diff --git a/src/transformation/utils/scope.ts b/src/transformation/utils/scope.ts index 6f354b01c..c98b3f627 100644 --- a/src/transformation/utils/scope.ts +++ b/src/transformation/utils/scope.ts @@ -2,7 +2,6 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { assert, getOrUpdate, isNonNull } from "../../utils"; import { TransformationContext } from "../context"; -import { UndefinedScope } from "./errors"; import { replaceStatementInParent } from "./lua-ast"; import { getSymbolInfo } from "./symbols"; import { getFirstDeclarationInFile } from "./typescript"; @@ -65,9 +64,7 @@ export function markSymbolAsReferencedInCurrentScopes( export function peekScope(context: TransformationContext): Scope { const scopeStack = getScopeStack(context); const scope = scopeStack[scopeStack.length - 1]; - if (!scope) { - throw UndefinedScope(); - } + assert(scope); return scope; } @@ -88,9 +85,7 @@ export function pushScope(context: TransformationContext, scopeType: ScopeType): export function popScope(context: TransformationContext): Scope { const scopeStack = getScopeStack(context); const scope = scopeStack.pop(); - if (!scope) { - throw UndefinedScope(); - } + assert(scope); return scope; } diff --git a/src/transformation/visitors/break-continue.ts b/src/transformation/visitors/break-continue.ts index 5449930a7..bde4ddd52 100644 --- a/src/transformation/visitors/break-continue.ts +++ b/src/transformation/visitors/break-continue.ts @@ -3,16 +3,11 @@ import { LuaTarget } from "../../CompilerOptions"; import * as lua from "../../LuaAST"; import { FunctionVisitor } from "../context"; import { unsupportedForTarget } from "../utils/diagnostics"; -import { UndefinedScope } from "../utils/errors"; import { findScope, ScopeType } from "../utils/scope"; export const transformBreakStatement: FunctionVisitor = (breakStatement, context) => { const breakableScope = findScope(context, ScopeType.Loop | ScopeType.Switch); - if (breakableScope === undefined) { - throw UndefinedScope(); - } - - if (breakableScope.type === ScopeType.Switch) { + if (breakableScope?.type === ScopeType.Switch) { return lua.createGotoStatement(`____switch${breakableScope.id}_end`); } else { return lua.createBreakStatement(breakStatement); @@ -25,10 +20,10 @@ export const transformContinueStatement: FunctionVisitor = } const scope = findScope(context, ScopeType.Loop); - if (scope === undefined) { - throw UndefinedScope(); + + if (scope) { + scope.loopContinued = true; } - scope.loopContinued = true; - return lua.createGotoStatement(`__continue${scope.id}`, statement); + return lua.createGotoStatement(`__continue${scope?.id ?? ""}`, statement); }; From 2b8303e11f9f178523137ffbd5ed137f69da3b3f Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 11:28:11 +0000 Subject: [PATCH 18/42] Make class transform safer, fixes #771 --- src/transformation/visitors/class/index.ts | 36 +++++++++---------- .../__snapshots__/classes.spec.ts.snap | 9 +++++ test/unit/classes/classes.spec.ts | 20 +++++++++++ 3 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 test/unit/classes/__snapshots__/classes.spec.ts.snap diff --git a/src/transformation/visitors/class/index.ts b/src/transformation/visitors/class/index.ts index 82f16e1fb..758a1406a 100644 --- a/src/transformation/visitors/class/index.ts +++ b/src/transformation/visitors/class/index.ts @@ -1,6 +1,6 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; -import { assert, getOrUpdate, isNonNull } from "../../../utils"; +import { getOrUpdate, isNonNull } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations"; import { @@ -59,16 +59,17 @@ export function transformClassAsExpression( return createImmediatelyInvokedFunctionExpression(classDeclaration, className, expression); } -const classStacks = new WeakMap(); +const classSuperInfos = new WeakMap(); +interface ClassSuperInfo { + className: lua.Identifier; + extendsTypeNode?: ts.ExpressionWithTypeArguments; +} export function transformClassDeclaration( classDeclaration: ts.ClassLikeDeclaration, context: TransformationContext, nameOverride?: lua.Identifier ): OneToManyVisitorResult { - const classStack = getOrUpdate(classStacks, context, () => []); - classStack.push(classDeclaration); - let className: lua.Identifier; let classNameText: string; if (nameOverride !== undefined) { @@ -108,6 +109,9 @@ export function transformClassDeclaration( const extendsTypeNode = getExtendedTypeNode(context, classDeclaration); const extendsType = getExtendedType(context, classDeclaration); + const superInfo = getOrUpdate(classSuperInfos, context, () => []); + superInfo.push({ className, extendsTypeNode }); + if (extendsType) { checkForLuaLibType(context, extendsType); } @@ -308,17 +312,19 @@ export function transformClassDeclaration( result.push(decorationStatement); } - classStack.pop(); + superInfo.pop(); return result; } export const transformSuperExpression: FunctionVisitor = (expression, context) => { - const classStack = getOrUpdate(classStacks, context, () => []); - const classDeclaration = classStack[classStack.length - 1]; - const typeNode = getExtendedTypeNode(context, classDeclaration); - // `undefined` is a TypeScript error - const extendsExpression = typeNode?.expression; + const superInfos = getOrUpdate(classSuperInfos, context, () => []); + const superInfo = superInfos[superInfos.length - 1]; + if (!superInfo) return lua.createAnonymousIdentifier(expression); + const { className, extendsTypeNode } = superInfo; + + // Using `super` without extended type node is a TypeScript error + const extendsExpression = extendsTypeNode?.expression; let baseClassName: lua.AssignmentLeftHandSideExpression | undefined; if (extendsExpression && ts.isIdentifier(extendsExpression)) { @@ -330,14 +336,8 @@ export const transformSuperExpression: FunctionVisitor = (ex } if (!baseClassName) { - assert(classDeclaration.name); - // Use "className.____super" if the base is not a simple identifier - baseClassName = lua.createTableIndexExpression( - transformIdentifier(context, classDeclaration.name), - lua.createStringLiteral("____super"), - expression - ); + baseClassName = lua.createTableIndexExpression(className, lua.createStringLiteral("____super"), expression); } return lua.createTableIndexExpression(baseClassName, lua.createStringLiteral("prototype")); diff --git a/test/unit/classes/__snapshots__/classes.spec.ts.snap b/test/unit/classes/__snapshots__/classes.spec.ts.snap new file mode 100644 index 000000000..f6d370e0c --- /dev/null +++ b/test/unit/classes/__snapshots__/classes.spec.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`super without class: code 1`] = ` +"local ____exports = {} +____exports.__result = ____.____constructor(self) +return ____exports" +`; + +exports[`super without class: diagnostics 1`] = `"main.ts(1,25): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors."`; diff --git a/test/unit/classes/classes.spec.ts b/test/unit/classes/classes.spec.ts index 12751fd40..e0291c31d 100644 --- a/test/unit/classes/classes.spec.ts +++ b/test/unit/classes/classes.spec.ts @@ -236,6 +236,26 @@ test("Subclass constructor across merged namespace", () => { expect(util.transpileAndExecute("return (new NS.Sub()).prop", undefined, undefined, tsHeader)).toBe("foo"); }); +test("super without class", () => { + util.testExpression`super()`.expectDiagnosticsToMatchSnapshot(); +}); + +test("super in unnamed class", () => { + util.testFunction` + class Foo { + public x = true; + } + + const Bar = (class extends (Foo) { + constructor() { + super(); + } + }); + + return new Bar().x; + `.expectToMatchJsResult(); +}); + test("classSuper", () => { const result = util.transpileAndExecute( `class a { From dc45631220045d2b20636e4d203075f4bd545909 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 11:45:20 +0000 Subject: [PATCH 19/42] Make all other errors diagnostics --- src/transformation/utils/diagnostics.ts | 12 ++ src/transformation/utils/errors.ts | 13 -- src/transformation/utils/symbols.ts | 4 +- .../visitors/class/decorators.ts | 4 +- src/transformation/visitors/modules/import.ts | 20 +-- test/unit/__snapshots__/hoisting.spec.ts.snap | 146 ++++++++++++++++++ .../__snapshots__/decorators.spec.ts.snap | 18 +++ test/unit/classes/decorators.spec.ts | 7 +- test/unit/hoisting.spec.ts | 41 +++-- 9 files changed, 208 insertions(+), 57 deletions(-) create mode 100644 test/unit/__snapshots__/hoisting.spec.ts.snap create mode 100644 test/unit/classes/__snapshots__/decorators.spec.ts.snap diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index 4bfb3cd61..8cd1d46e7 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -41,6 +41,8 @@ export const unsupportedOverloadAssignment = createDiagnosticFactory((name?: str ); }); +export const decoratorInvalidContext = createDiagnosticFactory(`Decorator function cannot have 'this: void'.`); + export const annotationInvalidArgumentCount = createDiagnosticFactory( (kind: AnnotationKind, got: number, expected: number) => `'@${kind}' expects ${expected} arguments, but got ${got}.` ); @@ -126,3 +128,13 @@ export const forOfUnsupportedObjectDestructuring = createDiagnosticFactory( export const invalidAmbientIdentifierName = createDiagnosticFactory( (text: string) => `Invalid ambient identifier name '${text}'. Ambient identifiers must be valid lua identifiers.` ); + +export const referencedBeforeDeclaration = createDiagnosticFactory( + (text: string) => + `Identifier '${text}' was referenced before it was declared. The declaration ` + + "must be moved before the identifier's use, or hoisting must be enabled." +); + +export const unresolvableRequirePath = createDiagnosticFactory( + (path: string) => `Cannot create require path. Module '${path}' does not exist within --rootDir.` +); diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts index 37d882966..baeded940 100644 --- a/src/transformation/utils/errors.ts +++ b/src/transformation/utils/errors.ts @@ -6,16 +6,3 @@ export class TranspileError extends Error { super(message); } } - -export const InvalidDecoratorContext = (node: ts.Node) => - new TranspileError(`Decorator function cannot have 'this: void'.`, node); - -export const UnresolvableRequirePath = (node: ts.Node, reason: string, path?: string) => - new TranspileError(`${reason}. TypeScript path: ${path}.`, node); - -export const ReferencedBeforeDeclaration = (node: ts.Identifier) => - new TranspileError( - `Identifier "${node.text}" was referenced before it was declared. The declaration ` + - "must be moved before the identifier's use, or hoisting must be enabled.", - node - ); diff --git a/src/transformation/utils/symbols.ts b/src/transformation/utils/symbols.ts index a08197c72..09e40d24f 100644 --- a/src/transformation/utils/symbols.ts +++ b/src/transformation/utils/symbols.ts @@ -2,7 +2,7 @@ import * as ts from "typescript"; import * as lua from "../../LuaAST"; import { getOrUpdate } from "../../utils"; import { TransformationContext } from "../context"; -import { ReferencedBeforeDeclaration } from "./errors"; +import { referencedBeforeDeclaration } from "./diagnostics"; import { markSymbolAsReferencedInCurrentScopes } from "./scope"; import { getFirstDeclarationInFile } from "./typescript"; @@ -50,7 +50,7 @@ export function trackSymbolReference( // Check for reference-before-declaration const declaration = getFirstDeclarationInFile(symbol, context.sourceFile); if (declaration && identifier.pos < declaration.pos) { - throw ReferencedBeforeDeclaration(identifier); + context.diagnostics.push(referencedBeforeDeclaration(identifier, identifier.text)); } } diff --git a/src/transformation/visitors/class/decorators.ts b/src/transformation/visitors/class/decorators.ts index 5c8406209..5cae0cf17 100644 --- a/src/transformation/visitors/class/decorators.ts +++ b/src/transformation/visitors/class/decorators.ts @@ -1,7 +1,7 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; import { TransformationContext } from "../../context"; -import { InvalidDecoratorContext } from "../../utils/errors"; +import { decoratorInvalidContext } from "../../utils/diagnostics"; import { addExportToIdentifier } from "../../utils/export"; import { ContextType, getFunctionContextType } from "../../utils/function-context"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; @@ -26,7 +26,7 @@ export function createConstructorDecorationStatement( const type = context.checker.getTypeAtLocation(expression); const callContext = getFunctionContextType(context, type); if (callContext === ContextType.Void) { - throw InvalidDecoratorContext(decorator); + context.diagnostics.push(decoratorInvalidContext(decorator)); } return context.transformExpression(expression); diff --git a/src/transformation/visitors/modules/import.ts b/src/transformation/visitors/modules/import.ts index 2dd390b6f..7e9b1a2f4 100644 --- a/src/transformation/visitors/modules/import.ts +++ b/src/transformation/visitors/modules/import.ts @@ -4,20 +4,22 @@ import * as lua from "../../../LuaAST"; import { formatPathToLuaPath } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getSymbolAnnotations, getTypeAnnotations } from "../../utils/annotations"; -import { UnresolvableRequirePath } from "../../utils/errors"; import { createDefaultExportStringLiteral } from "../../utils/export"; import { createHoistableVariableDeclarationStatement } from "../../utils/lua-ast"; import { createSafeName } from "../../utils/safe-names"; import { peekScope } from "../../utils/scope"; import { transformIdentifier } from "../identifier"; import { transformPropertyName } from "../literal"; +import { unresolvableRequirePath } from "../../utils/diagnostics"; const getAbsoluteImportPath = (relativePath: string, directoryPath: string, options: ts.CompilerOptions): string => relativePath[0] !== "." && options.baseUrl ? path.resolve(options.baseUrl, relativePath) : path.resolve(directoryPath, relativePath); -function getImportPath(fileName: string, relativePath: string, node: ts.Node, options: ts.CompilerOptions): string { +function getImportPath(context: TransformationContext, relativePath: string, node: ts.Node): string { + const fileName = context.sourceFile.fileName; + const options = context.options; const rootDir = options.rootDir ? path.resolve(options.rootDir) : path.resolve("."); const absoluteImportPath = path.format( @@ -27,11 +29,8 @@ function getImportPath(fileName: string, relativePath: string, node: ts.Node, op if (absoluteImportPath.includes(absoluteRootDirPath)) { return formatPathToLuaPath(absoluteImportPath.replace(absoluteRootDirPath, "").slice(1)); } else { - throw UnresolvableRequirePath( - node, - `Cannot create require path. Module does not exist within --rootDir`, - relativePath - ); + context.diagnostics.push(unresolvableRequirePath(node, relativePath)); + return relativePath; } } @@ -51,12 +50,7 @@ export function createModuleRequire( const params: lua.Expression[] = []; if (ts.isStringLiteral(moduleSpecifier)) { const modulePath = shouldResolveModulePath(context, moduleSpecifier) - ? getImportPath( - context.sourceFile.fileName, - moduleSpecifier.text.replace(/"/g, ""), - moduleSpecifier, - context.options - ) + ? getImportPath(context, moduleSpecifier.text.replace(/"/g, ""), moduleSpecifier) : moduleSpecifier.text; params.push(lua.createStringLiteral(modulePath)); diff --git a/test/unit/__snapshots__/hoisting.spec.ts.snap b/test/unit/__snapshots__/hoisting.spec.ts.snap new file mode 100644 index 000000000..f4a803a0d --- /dev/null +++ b/test/unit/__snapshots__/hoisting.spec.ts.snap @@ -0,0 +1,146 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`No Hoisting ("const foo = bar(); export function bar() { return \\"bar\\"; }"): code 1`] = ` +"local ____exports = {} +local foo = ____exports.bar(nil) +function ____exports.bar(self) + return \\"bar\\" +end +return ____exports" +`; + +exports[`No Hoisting ("const foo = bar(); export function bar() { return \\"bar\\"; }"): diagnostics 1`] = `"main.ts(1,13): error TSTL: Identifier 'bar' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("const foo = bar(); function bar() { return \\"bar\\"; }"): code 1`] = ` +"local foo = bar(_G) +function bar(self) + return \\"bar\\" +end" +`; + +exports[`No Hoisting ("const foo = bar(); function bar() { return \\"bar\\"; }"): diagnostics 1`] = `"main.ts(1,13): error TSTL: Identifier 'bar' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("export const foo = bar(); function bar() { return \\"bar\\"; }"): code 1`] = ` +"local ____exports = {} +____exports.foo = bar(nil) +local function bar(self) + return \\"bar\\" +end +return ____exports" +`; + +exports[`No Hoisting ("export const foo = bar(); function bar() { return \\"bar\\"; }"): diagnostics 1`] = `"main.ts(1,20): error TSTL: Identifier 'bar' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("export namespace O { export function f() { return I.foo; } namespace I { export let foo = \\"foo\\"; } }"): code 1`] = ` +"local ____exports = {} +____exports.O = {} +local O = ____exports.O +do + function O.f(self) + return I.foo + end + local I = {} + do + I.foo = \\"foo\\" + end +end +return ____exports" +`; + +exports[`No Hoisting ("export namespace O { export function f() { return I.foo; } namespace I { export let foo = \\"foo\\"; } }"): diagnostics 1`] = `"main.ts(1,51): error TSTL: Identifier 'I' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("foo = \\"foo\\"; export var foo;"): code 1`] = ` +"local ____exports = {} +____exports.foo = \\"foo\\" +return ____exports" +`; + +exports[`No Hoisting ("foo = \\"foo\\"; export var foo;"): diagnostics 1`] = `"main.ts(1,1): error TSTL: Identifier 'foo' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("foo = \\"foo\\"; var foo;"): code 1`] = `"foo = \\"foo\\""`; + +exports[`No Hoisting ("foo = \\"foo\\"; var foo;"): diagnostics 1`] = `"main.ts(1,1): error TSTL: Identifier 'foo' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("function bar() { return E.A; } enum E { A = \\"foo\\" }"): code 1`] = ` +"function bar(self) + return E.A +end +E = {} +E.A = \\"foo\\"" +`; + +exports[`No Hoisting ("function bar() { return E.A; } enum E { A = \\"foo\\" }"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Identifier 'E' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("function bar() { return NS.foo; } namespace NS { export let foo = \\"foo\\"; }"): code 1`] = ` +"function bar(self) + return NS.foo +end +NS = NS or {} +do + NS.foo = \\"foo\\" +end" +`; + +exports[`No Hoisting ("function bar() { return NS.foo; } namespace NS { export let foo = \\"foo\\"; }"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Identifier 'NS' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("function makeFoo() { return new Foo(); } class Foo {}"): code 1`] = ` +"require(\\"lualib_bundle\\"); +function makeFoo(self) + return __TS__New(Foo) +end +Foo = __TS__Class() +Foo.name = \\"Foo\\" +function Foo.prototype.____constructor(self) +end" +`; + +exports[`No Hoisting ("function makeFoo() { return new Foo(); } class Foo {}"): diagnostics 1`] = `"main.ts(1,33): error TSTL: Identifier 'Foo' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("function setBar() { const bar = { foo }; } let foo = \\"foo\\";"): code 1`] = ` +"function setBar(self) + local bar = {foo = foo} +end +local foo = \\"foo\\"" +`; + +exports[`No Hoisting ("function setBar() { const bar = { foo }; } let foo = \\"foo\\";"): diagnostics 1`] = `"main.ts(1,35): error TSTL: Identifier 'foo' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("function setBar() { const bar = foo; } const foo = \\"foo\\";"): code 1`] = ` +"function setBar(self) + local bar = foo +end +local foo = \\"foo\\"" +`; + +exports[`No Hoisting ("function setBar() { const bar = foo; } const foo = \\"foo\\";"): diagnostics 1`] = `"main.ts(1,33): error TSTL: Identifier 'foo' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("function setBar() { const bar = foo; } export const foo = \\"foo\\";"): code 1`] = ` +"local ____exports = {} +local function setBar(self) + local bar = ____exports.foo +end +____exports.foo = \\"foo\\" +return ____exports" +`; + +exports[`No Hoisting ("function setBar() { const bar = foo; } export const foo = \\"foo\\";"): diagnostics 1`] = `"main.ts(1,33): error TSTL: Identifier 'foo' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("function setBar() { const bar = foo; } export let foo = \\"foo\\";"): code 1`] = ` +"local ____exports = {} +local function setBar(self) + local bar = ____exports.foo +end +____exports.foo = \\"foo\\" +return ____exports" +`; + +exports[`No Hoisting ("function setBar() { const bar = foo; } export let foo = \\"foo\\";"): diagnostics 1`] = `"main.ts(1,33): error TSTL: Identifier 'foo' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; + +exports[`No Hoisting ("function setBar() { const bar = foo; } let foo = \\"foo\\";"): code 1`] = ` +"function setBar(self) + local bar = foo +end +local foo = \\"foo\\"" +`; + +exports[`No Hoisting ("function setBar() { const bar = foo; } let foo = \\"foo\\";"): diagnostics 1`] = `"main.ts(1,33): error TSTL: Identifier 'foo' was referenced before it was declared. The declaration must be moved before the identifier's use, or hoisting must be enabled."`; diff --git a/test/unit/classes/__snapshots__/decorators.spec.ts.snap b/test/unit/classes/__snapshots__/decorators.spec.ts.snap new file mode 100644 index 000000000..cbc983bd5 --- /dev/null +++ b/test/unit/classes/__snapshots__/decorators.spec.ts.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Throws error if decorator function has void context: code 1`] = ` +"require(\\"lualib_bundle\\"); +local ____exports = {} +function ____exports.__main(self) + local function decorator(constructor) + end + local TestClass = __TS__Class() + TestClass.name = \\"TestClass\\" + function TestClass.prototype.____constructor(self) + end + TestClass = __TS__Decorate({decorator}, TestClass) +end +return ____exports" +`; + +exports[`Throws error if decorator function has void context: diagnostics 1`] = `"main.ts(4,9): error TSTL: Decorator function cannot have 'this: void'."`; diff --git a/test/unit/classes/decorators.spec.ts b/test/unit/classes/decorators.spec.ts index 7d4223ecd..e64bec99d 100644 --- a/test/unit/classes/decorators.spec.ts +++ b/test/unit/classes/decorators.spec.ts @@ -1,4 +1,3 @@ -import { InvalidDecoratorContext } from "../../../src/transformation/utils/errors"; import * as util from "../../util"; test("Class decorator with no parameters", () => { @@ -105,11 +104,11 @@ test("Class decorators are applied in order and executed in reverse order", () = test("Throws error if decorator function has void context", () => { util.testFunction` - function SetBool(this: void, constructor: new (...args: any[]) => {}) {} + function decorator(this: void, constructor: new (...args: any[]) => {}) {} - @SetBool + @decorator class TestClass {} - `.expectToHaveDiagnosticOfError(InvalidDecoratorContext(util.nodeStub)); + `.expectDiagnosticsToMatchSnapshot(); }); test("Exported class decorator", () => { diff --git a/test/unit/hoisting.spec.ts b/test/unit/hoisting.spec.ts index e8ee28947..4a96f2b8b 100644 --- a/test/unit/hoisting.spec.ts +++ b/test/unit/hoisting.spec.ts @@ -1,5 +1,3 @@ -import * as ts from "typescript"; -import { ReferencedBeforeDeclaration } from "../../src/transformation/utils/errors"; import * as util from "../util"; test("Var Hoisting", () => { @@ -219,27 +217,24 @@ test("Enum Hoisting", () => { }); test.each([ - { code: `foo = "foo"; var foo;`, identifier: "foo" }, - { code: `foo = "foo"; export var foo;`, identifier: "foo" }, - { code: `function setBar() { const bar = foo; } let foo = "foo";`, identifier: "foo" }, - { code: `function setBar() { const bar = foo; } const foo = "foo";`, identifier: "foo" }, - { code: `function setBar() { const bar = foo; } export let foo = "foo";`, identifier: "foo" }, - { code: `function setBar() { const bar = foo; } export const foo = "foo";`, identifier: "foo" }, - { code: `const foo = bar(); function bar() { return "bar"; }`, identifier: "bar" }, - { code: `export const foo = bar(); function bar() { return "bar"; }`, identifier: "bar" }, - { code: `const foo = bar(); export function bar() { return "bar"; }`, identifier: "bar" }, - { code: `function bar() { return NS.foo; } namespace NS { export let foo = "foo"; }`, identifier: "NS" }, - { - code: `export namespace O { export function f() { return I.foo; } namespace I { export let foo = "foo"; } }`, - identifier: "I", - }, - { code: `function makeFoo() { return new Foo(); } class Foo {}`, identifier: "Foo" }, - { code: `function bar() { return E.A; } enum E { A = "foo" }`, identifier: "E" }, - { code: `function setBar() { const bar = { foo }; } let foo = "foo";`, identifier: "foo" }, -])("No Hoisting (%p)", ({ code, identifier }) => { - expect(() => util.transpileString(code, { noHoisting: true })).toThrowExactError( - ReferencedBeforeDeclaration(ts.createIdentifier(identifier)) - ); + `foo = "foo"; var foo;`, + `foo = "foo"; export var foo;`, + `function setBar() { const bar = foo; } let foo = "foo";`, + `function setBar() { const bar = foo; } const foo = "foo";`, + `function setBar() { const bar = foo; } export let foo = "foo";`, + `function setBar() { const bar = foo; } export const foo = "foo";`, + `const foo = bar(); function bar() { return "bar"; }`, + `export const foo = bar(); function bar() { return "bar"; }`, + `const foo = bar(); export function bar() { return "bar"; }`, + `function bar() { return NS.foo; } namespace NS { export let foo = "foo"; }`, + `export namespace O { export function f() { return I.foo; } namespace I { export let foo = "foo"; } }`, + `function makeFoo() { return new Foo(); } class Foo {}`, + `function bar() { return E.A; } enum E { A = "foo" }`, + `function setBar() { const bar = { foo }; } let foo = "foo";`, +])("No Hoisting (%p)", (code) => { + util.testModule(code) + .setOptions({ noHoisting: true }) + .expectDiagnosticsToMatchSnapshot(); }); test("Import hoisting (named)", () => { From 11c3ee4e95a0e6adb1cc6a8ca1f7dd4f501ae436 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 17:09:16 +0000 Subject: [PATCH 20/42] Make `bundle` tests check diagnostic snapshots --- test/unit/__snapshots__/bundle.spec.ts.snap | 7 +++ test/unit/bundle.spec.ts | 52 +++++++-------------- 2 files changed, 23 insertions(+), 36 deletions(-) create mode 100644 test/unit/__snapshots__/bundle.spec.ts.snap diff --git a/test/unit/__snapshots__/bundle.spec.ts.snap b/test/unit/__snapshots__/bundle.spec.ts.snap new file mode 100644 index 000000000..516991b33 --- /dev/null +++ b/test/unit/__snapshots__/bundle.spec.ts.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LuaLibImportKind.Inline generates a warning: diagnostics 1`] = `"warning TSTL: Using 'luaBundle' with 'luaLibImport: \\"inline\\"' might generate duplicate code. It is recommended to use 'luaLibImport: \\"require\\"'"`; + +exports[`luaEntry doesn't exist: diagnostics 1`] = `"error TSTL: Could not find bundle entry point 'entry.ts'. It should be a file in the project."`; + +exports[`no entry point: diagnostics 1`] = `"error TSTL: 'luaBundleEntry' is required when 'luaBundle' is enabled."`; diff --git a/test/unit/bundle.spec.ts b/test/unit/bundle.spec.ts index 582b79177..ca58b778d 100644 --- a/test/unit/bundle.spec.ts +++ b/test/unit/bundle.spec.ts @@ -1,20 +1,8 @@ import * as path from "path"; import * as ts from "typescript"; -import { DiagnosticCategory } from "typescript"; import { LuaLibImportKind } from "../../src"; -import { couldNotFindBundleEntryPoint } from "../../src/transpilation/diagnostics"; import * as util from "../util"; -test("no entry point", () => { - util.testBundle`` - .setOptions({ luaBundleEntry: undefined }) - .expectToHaveDiagnostic( - d => - d.messageText === `'luaBundleEntry' is required when 'luaBundle' is enabled.` && - d.category === DiagnosticCategory.Error - ); -}); - test("import module -> main", () => { util.testBundle` export { value } from "./module"; @@ -24,14 +12,14 @@ test("import module -> main", () => { }); test("bundle file name", () => { - const { diagnostics, transpiledFiles } = util.testModule` + const { transpiledFiles } = util.testModule` export { value } from "./module"; ` .addExtraFile("module.ts", "export const value = true") .setOptions({ luaBundle: "mybundle.lua", luaBundleEntry: "main.ts" }) + .expectToHaveNoDiagnostics() .getLuaResult(); - expect(diagnostics.length).toBe(0); expect(transpiledFiles.length).toBe(1); expect(transpiledFiles[0].fileName).toBe( path.join(ts.sys.getCurrentDirectory(), "mybundle.lua").replace(/\\/g, "/") @@ -87,35 +75,23 @@ test("entry point in directory", () => { .expectToEqual({ value: true }); }); -test.each([LuaLibImportKind.Inline, LuaLibImportKind.Require])("LuaLib %p", lualibOption => { - const testBundle = util.testBundle` +test("LuaLibImportKind.Require", () => { + util.testBundle` export const result = [1, 2]; result.push(3); - `.setOptions({ luaLibImport: lualibOption }); - - if (lualibOption === LuaLibImportKind.Inline) { - testBundle.expectToHaveDiagnostic(d => d.category === DiagnosticCategory.Warning); - } else { - expect(testBundle.getLuaResult().diagnostics).toEqual([]); - } - expect(testBundle.getLuaExecutionResult()).toEqual({ result: [1, 2, 3] }); + ` + .setOptions({ luaLibImport: LuaLibImportKind.Require }) + .expectToEqual({ result: [1, 2, 3] }); }); -test("LuaBundle and LuaLibImport.Inline generate warning", () => { - const testBundle = util.testBundle` +test("LuaLibImportKind.Inline generates a warning", () => { + util.testBundle` export const result = [1, 2]; result.push(3); ` .setOptions({ luaLibImport: LuaLibImportKind.Inline }) - .expectToHaveDiagnostic( - d => - d.category === DiagnosticCategory.Warning && - d.messageText === - `Using 'luaBundle' with 'luaLibImport: "inline"' might generate duplicate code. ` + - `It is recommended to use 'luaLibImport: "require"'` - ); - - expect(testBundle.getLuaExecutionResult()).toEqual({ result: [1, 2, 3] }); // Result should still be the same + .expectDiagnosticsToMatchSnapshot(true) + .expectToEqual({ result: [1, 2, 3] }); }); test("cyclic imports", () => { @@ -136,6 +112,10 @@ test("cyclic imports", () => { .expectToEqual(new util.ExecutionError("stack overflow")); }); +test("no entry point", () => { + util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot(true); +}); + test("luaEntry doesn't exist", () => { - util.testBundle``.setEntryPoint("entry.ts").expectToHaveExactDiagnostic(couldNotFindBundleEntryPoint("entry.ts")); + util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot(true); }); From d70666f4a861a040a14ca77dd760a09f68360384 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 17:10:57 +0000 Subject: [PATCH 21/42] Remove remaining TranspileError handling code --- src/index.ts | 1 - src/transformation/index.ts | 39 +++----------------- src/transformation/utils/errors.ts | 8 ---- test/setup.ts | 21 ----------- test/util.ts | 59 +++++++++++------------------- 5 files changed, 27 insertions(+), 101 deletions(-) delete mode 100644 src/transformation/utils/errors.ts diff --git a/src/index.ts b/src/index.ts index 8b0159a9c..c828369df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,5 +6,4 @@ export * from "./LuaAST"; export { LuaLibFeature } from "./LuaLib"; export * from "./LuaPrinter"; export * from "./transformation/context"; -export { TranspileError } from "./transformation/utils/errors"; export * from "./transpilation"; diff --git a/src/transformation/index.ts b/src/transformation/index.ts index ae62ed8d9..69b098811 100644 --- a/src/transformation/index.ts +++ b/src/transformation/index.ts @@ -3,20 +3,9 @@ import * as lua from "../LuaAST"; import { LuaLibFeature } from "../LuaLib"; import { getOrUpdate } from "../utils"; import { ObjectVisitor, TransformationContext, VisitorMap, Visitors } from "./context"; -import { TranspileError } from "./utils/errors"; import { getUsedLuaLibFeatures } from "./utils/lualib"; import { standardVisitors } from "./visitors"; -const transpileErrorDiagnostic = (error: TranspileError): ts.Diagnostic => ({ - file: error.node.getSourceFile(), - start: error.node.getStart(), - length: error.node.getWidth(), - category: ts.DiagnosticCategory.Error, - code: 0, - source: "typescript-to-lua", - messageText: error.message, -}); - export function createVisitorMap(customVisitors: Visitors[]): VisitorMap { const visitorMap: VisitorMap = new Map(); for (const visitors of [standardVisitors, ...customVisitors]) { @@ -52,27 +41,11 @@ export function transformSourceFile( visitorMap: VisitorMap ): TransformSourceFileResult { const context = new TransformationContext(program, sourceFile, visitorMap); + const [luaAst] = context.transformNode(sourceFile) as [lua.Block]; - // TODO: Remove once we'll get rid of all `TranspileError`s - try { - const [luaAst] = context.transformNode(sourceFile) as [lua.Block]; - - return { - luaAst, - luaLibFeatures: getUsedLuaLibFeatures(context), - diagnostics: context.diagnostics, - }; - } catch (error) { - if (!(error instanceof TranspileError)) throw error; - - return { - luaAst: lua.createBlock([ - lua.createExpressionStatement( - lua.createCallExpression(lua.createIdentifier("error"), [lua.createStringLiteral(error.message)]) - ), - ]), - luaLibFeatures: new Set(), - diagnostics: [transpileErrorDiagnostic(error)], - }; - } + return { + luaAst, + luaLibFeatures: getUsedLuaLibFeatures(context), + diagnostics: context.diagnostics, + }; } diff --git a/src/transformation/utils/errors.ts b/src/transformation/utils/errors.ts deleted file mode 100644 index baeded940..000000000 --- a/src/transformation/utils/errors.ts +++ /dev/null @@ -1,8 +0,0 @@ -import * as ts from "typescript"; - -export class TranspileError extends Error { - public name = "TranspileError"; - constructor(message: string, public node: ts.Node) { - super(message); - } -} diff --git a/test/setup.ts b/test/setup.ts index b43c9287a..97ddade65 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,36 +1,15 @@ import * as ts from "typescript"; import * as tstl from "../src"; -import * as util from "./util"; declare global { namespace jest { interface Matchers { - toThrowExactError(error: Error): R; toHaveDiagnostics(): R; } } } expect.extend({ - toThrowExactError(callback: () => void, error: Error): jest.CustomMatcherResult { - if (this.isNot) { - return { pass: true, message: () => "Inverted toThrowExactError is not implemented" }; - } - - let executionError: Error | undefined; - try { - callback(); - } catch (err) { - executionError = err; - } - - // TODO: - if (util.expectToBeDefined(executionError)) { - expect(executionError.message).toContain(error.message); - } - - return { pass: true, message: () => "" }; - }, toHaveDiagnostics(diagnostics: ts.Diagnostic[]): jest.CustomMatcherResult { expect(diagnostics).toBeInstanceOf(Array); // @ts-ignore diff --git a/test/util.ts b/test/util.ts index 6359e95c1..a56de6086 100644 --- a/test/util.ts +++ b/test/util.ts @@ -60,7 +60,7 @@ export function testEachVersion( test(testName, () => { const builder = common(); builder.setOptions({ luaTarget: version }); - if (typeof specialBuilder === 'function') { + if (typeof specialBuilder === "function") { specialBuilder(builder); } }); @@ -151,7 +151,6 @@ export class ExecutionError extends Error { export type ExecutableTranspiledFile = tstl.TranspiledFile & { lua: string; sourceMap: string }; export type TapCallback = (builder: TestBuilder) => void; -export type DiagnosticMatcher = (diagnostic: ts.Diagnostic) => boolean; export abstract class TestBuilder { constructor(protected _tsCode: string) {} @@ -339,47 +338,21 @@ export abstract class TestBuilder { return this; } - public expectToHaveDiagnostic(matcher: DiagnosticMatcher): this { - expect(this.getLuaDiagnostics().find(matcher)).toBeDefined(); - return this; - } - - public expectToHaveExactDiagnostic(diagnostic: ts.Diagnostic): this { - expect(this.getLuaDiagnostics()).toContainEqual(diagnostic); - return this; - } + private diagnosticsChecked = false; public expectToHaveDiagnostics(): this { - expect(this.getLuaDiagnostics()).toHaveDiagnostics(); - return this; - } + if (this.diagnosticsChecked) return this; + this.diagnosticsChecked = true; - public expectToHaveDiagnosticOfError(error: Error): this { - this.expectToHaveDiagnostics(); - expect(this.getLuaDiagnostics()).toHaveLength(1); - const firstDiagnostic = this.getLuaDiagnostics()[0]; - expect(firstDiagnostic).toMatchObject({ messageText: error.message }); + expect(this.getLuaDiagnostics()).toHaveDiagnostics(); return this; } public expectToHaveNoDiagnostics(): this { - expect(this.getLuaDiagnostics()).not.toHaveDiagnostics(); - return this; - } - - public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this { - this.expectToHaveDiagnostics(); - - const diagnosticMessages = ts.formatDiagnostics( - this.getLuaDiagnostics().map(tstl.prepareDiagnosticForFormatting), - { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } - ); - - expect(diagnosticMessages.trim()).toMatchSnapshot("diagnostics"); - if (!diagnosticsOnly) { - expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); - } + if (this.diagnosticsChecked) return this; + this.diagnosticsChecked = true; + expect(this.getLuaDiagnostics()).not.toHaveDiagnostics(); return this; } @@ -416,9 +389,19 @@ export abstract class TestBuilder { return this; } - public expectResultToMatchSnapshot(): this { - this.expectToHaveNoDiagnostics(); - expect(this.getLuaExecutionResult()).toMatchSnapshot(); + public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this { + this.expectToHaveDiagnostics(); + + const diagnosticMessages = ts.formatDiagnostics( + this.getLuaDiagnostics().map(tstl.prepareDiagnosticForFormatting), + { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } + ); + + expect(diagnosticMessages.trim()).toMatchSnapshot("diagnostics"); + if (!diagnosticsOnly) { + expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); + } + return this; } From 9c3a235e23c792c76ebadac28138e1f5d2a39f63 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 17:33:22 +0000 Subject: [PATCH 22/42] Fix formatting --- .../visitors/binary-expression/compound.ts | 16 ++-------------- test/unit/hoisting.spec.ts | 2 +- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/transformation/visitors/binary-expression/compound.ts b/src/transformation/visitors/binary-expression/compound.ts index 50d9d6c49..449b31f28 100644 --- a/src/transformation/visitors/binary-expression/compound.ts +++ b/src/transformation/visitors/binary-expression/compound.ts @@ -106,13 +106,7 @@ export function transformCompoundAssignmentExpression( } else { // local ____tmp = ____obj[____index] ${replacementOperator} ${right}; // ____obj[____index] = ____tmp; - const operatorExpression = transformBinaryOperation( - context, - accessExpression, - right, - operator, - expression - ); + const operatorExpression = transformBinaryOperation(context, accessExpression, right, operator, expression); tmpDeclaration = lua.createVariableDeclarationStatement(tmp, operatorExpression); assignStatement = lua.createAssignmentStatement(accessExpression, tmp); } @@ -129,13 +123,7 @@ export function transformCompoundAssignmentExpression( // return ____tmp const tmpIdentifier = lua.createIdentifier("____tmp"); const tmpDeclaration = lua.createVariableDeclarationStatement(tmpIdentifier, left); - const operatorExpression = transformBinaryOperation( - context, - tmpIdentifier, - right, - operator, - expression - ); + const operatorExpression = transformBinaryOperation(context, tmpIdentifier, right, operator, expression); const assignStatement = transformAssignment(context, lhs, operatorExpression); return createImmediatelyInvokedFunctionExpression([tmpDeclaration, assignStatement], tmpIdentifier, expression); } else if (ts.isPropertyAccessExpression(lhs) || ts.isElementAccessExpression(lhs)) { diff --git a/test/unit/hoisting.spec.ts b/test/unit/hoisting.spec.ts index 4a96f2b8b..2e04ad342 100644 --- a/test/unit/hoisting.spec.ts +++ b/test/unit/hoisting.spec.ts @@ -231,7 +231,7 @@ test.each([ `function makeFoo() { return new Foo(); } class Foo {}`, `function bar() { return E.A; } enum E { A = "foo" }`, `function setBar() { const bar = { foo }; } let foo = "foo";`, -])("No Hoisting (%p)", (code) => { +])("No Hoisting (%p)", code => { util.testModule(code) .setOptions({ noHoisting: true }) .expectDiagnosticsToMatchSnapshot(); From 42f2dcaa4f896e54390dbc0593252e851a598f55 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 19:45:04 +0000 Subject: [PATCH 23/42] Update `loops.spec.ts.snap` --- test/unit/__snapshots__/loops.spec.ts.snap | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/unit/__snapshots__/loops.spec.ts.snap b/test/unit/__snapshots__/loops.spec.ts.snap index f1daffe65..5eac11ed2 100644 --- a/test/unit/__snapshots__/loops.spec.ts.snap +++ b/test/unit/__snapshots__/loops.spec.ts.snap @@ -12,6 +12,38 @@ return ____exports" exports[`forin[Array]: diagnostics 1`] = `"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`; +exports[`forof object destructuring ({"initializer": "{a, b}", "vars": "let a: string, b: string;"}): code 1`] = ` +"local a +local b +for ____, ____value in ipairs(arr) do +end" +`; + +exports[`forof object destructuring ({"initializer": "{a, b}", "vars": "let a: string, b: string;"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unsupported object destructuring in for...of statement."`; + +exports[`forof object destructuring ({"initializer": "{a: c, b: d}", "vars": "let c: string, d: string;"}): code 1`] = ` +"local c +local d +for ____, ____value in ipairs(arr) do +end" +`; + +exports[`forof object destructuring ({"initializer": "{a: c, b: d}", "vars": "let c: string, d: string;"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unsupported object destructuring in for...of statement."`; + +exports[`forof object destructuring ({"initializer": "const {a, b}", "vars": ""}): code 1`] = ` +"for ____, ____values in ipairs(arr) do +end" +`; + +exports[`forof object destructuring ({"initializer": "const {a, b}", "vars": ""}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unsupported object destructuring in for...of statement."`; + +exports[`forof object destructuring ({"initializer": "const {a: x, b: y}", "vars": ""}): code 1`] = ` +"for ____, ____values in ipairs(arr) do +end" +`; + +exports[`forof object destructuring ({"initializer": "const {a: x, b: y}", "vars": ""}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unsupported object destructuring in for...of statement."`; + exports[`loop continue (do { continue; } while (false)) [5.1]: code 1`] = ` "repeat do From ef22253db1a1d935dd6eec4ce10fdf2c4314500f Mon Sep 17 00:00:00 2001 From: ark120202 Date: Thu, 12 Dec 2019 19:45:49 +0000 Subject: [PATCH 24/42] Temporary loosen `for...of` initializer variable declaration check --- src/transformation/visitors/loops/for-of.ts | 16 +++++++++++----- test/unit/builtins/map.spec.ts | 16 ++++++++-------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/transformation/visitors/loops/for-of.ts b/src/transformation/visitors/loops/for-of.ts index 2bc2cc959..ca7d7acae 100644 --- a/src/transformation/visitors/loops/for-of.ts +++ b/src/transformation/visitors/loops/for-of.ts @@ -35,11 +35,17 @@ function transformForOfInitializer( return; } - // we can safely assume that for vars are not exported and therefore VariableDeclarationStatement's - const assignmentStatement = cast( - transformVariableDeclaration(context, initializer.declarations[0])[0], - lua.isVariableDeclarationStatement - ); + // TODO: It's not correct without https://github.com/TypeScriptToLua/TypeScriptToLua/pull/762 + // // we can safely assume that for vars are not exported and therefore VariableDeclarationStatement's + // const assignmentStatement = cast( + // transformVariableDeclaration(context, initializer.declarations[0])[0], + // lua.isVariableDeclarationStatement + // ); + + const assignmentStatement = transformVariableDeclaration(context, initializer.declarations[0])[0] as + | lua.VariableDeclarationStatement + | undefined; + assert(assignmentStatement); return lua.createVariableDeclarationStatement(assignmentStatement.left, expression); } else { diff --git a/test/unit/builtins/map.spec.ts b/test/unit/builtins/map.spec.ts index cc5d1eb9c..5c839ca41 100644 --- a/test/unit/builtins/map.spec.ts +++ b/test/unit/builtins/map.spec.ts @@ -160,14 +160,14 @@ describe.each(iterationMethods)("map.%s() preserves insertion order", iterationM test("basic", () => { util.testFunction` const mymap = new Map(); - + mymap.set("x", 1); mymap.set("a", 2); mymap.set(4, 3); mymap.set("b", 6); mymap.set(1, 4); mymap.set("a", 5); - + mymap.delete("b"); return [...mymap.${iterationMethod}()]; @@ -177,11 +177,11 @@ describe.each(iterationMethods)("map.%s() preserves insertion order", iterationM test("after removing last", () => { util.testFunction` const mymap = new Map(); - + mymap.set("x", 1); mymap.set("a", 2); mymap.set(4, 3); - + mymap.delete(4); return [...mymap.${iterationMethod}()]; @@ -191,11 +191,11 @@ describe.each(iterationMethods)("map.%s() preserves insertion order", iterationM test("after removing first", () => { util.testFunction` const mymap = new Map(); - + mymap.set("x", 1); mymap.set("a", 2); mymap.set(4, 3); - + mymap.delete("x"); return [...mymap.${iterationMethod}()]; @@ -205,10 +205,10 @@ describe.each(iterationMethods)("map.%s() preserves insertion order", iterationM test("after removing all", () => { util.testFunction` const mymap = new Map(); - + mymap.set("x", 1); mymap.set("a", 2); - + mymap.delete("a"); mymap.delete("x"); From 3434bcef77a72abfbdc516afad407a22a89176b3 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Sun, 15 Dec 2019 21:29:03 +0000 Subject: [PATCH 25/42] Refactor SimpleOperator handling --- .../visitors/binary-expression/index.ts | 83 +++++++++---------- 1 file changed, 38 insertions(+), 45 deletions(-) diff --git a/src/transformation/visitors/binary-expression/index.ts b/src/transformation/visitors/binary-expression/index.ts index d0cfa2aed..ab240def1 100644 --- a/src/transformation/visitors/binary-expression/index.ts +++ b/src/transformation/visitors/binary-expression/index.ts @@ -1,6 +1,5 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; -import { assertNever } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations } from "../../utils/annotations"; import { @@ -21,12 +20,16 @@ import { unwrapCompoundAssignmentToken, } from "./compound"; -type SimpleOperator = keyof typeof simpleOperatorsToLua; -const isSimpleOperator = (operator: ts.BinaryOperator): operator is SimpleOperator => operator in simpleOperatorsToLua; +type SimpleOperator = + | ts.AdditiveOperatorOrHigher + | Exclude + | ts.EqualityOperator + | ts.LogicalOperator; -const simpleOperatorsToLua = { +const simpleOperatorsToLua: Record = { [ts.SyntaxKind.AmpersandAmpersandToken]: lua.SyntaxKind.AndOperator, [ts.SyntaxKind.BarBarToken]: lua.SyntaxKind.OrOperator, + [ts.SyntaxKind.PlusToken]: lua.SyntaxKind.AdditionOperator, [ts.SyntaxKind.MinusToken]: lua.SyntaxKind.SubtractionOperator, [ts.SyntaxKind.AsteriskToken]: lua.SyntaxKind.MultiplicationOperator, [ts.SyntaxKind.AsteriskAsteriskToken]: lua.SyntaxKind.PowerOperator, @@ -46,35 +49,27 @@ export function transformBinaryOperation( context: TransformationContext, left: lua.Expression, right: lua.Expression, - operator: BitOperator | SimpleOperator | ts.SyntaxKind.PlusToken, + operator: BitOperator | SimpleOperator, node: ts.Node ): lua.Expression { if (isBitOperator(operator)) { return transformBinaryBitOperation(context, node, left, right, operator); } - if (isSimpleOperator(operator)) { - const luaOperator = simpleOperatorsToLua[operator] as lua.BinaryOperator; - return lua.createBinaryExpression(left, right, luaOperator, node); - } + let luaOperator = simpleOperatorsToLua[operator]; - if (operator === ts.SyntaxKind.PlusToken) { - let luaOperator = lua.SyntaxKind.AdditionOperator; - if (ts.isBinaryExpression(node)) { - // Check is we need to use string concat operator - const typeLeft = context.checker.getTypeAtLocation(node.left); - const typeRight = context.checker.getTypeAtLocation(node.right); - if (isStringType(context, typeLeft) || isStringType(context, typeRight)) { - luaOperator = lua.SyntaxKind.ConcatOperator; - left = wrapInToStringForConcat(left); - right = wrapInToStringForConcat(right); - } + // Check is we need to use string concat operator + if (operator === ts.SyntaxKind.PlusToken && ts.isBinaryExpression(node)) { + const typeLeft = context.checker.getTypeAtLocation(node.left); + const typeRight = context.checker.getTypeAtLocation(node.right); + if (isStringType(context, typeLeft) || isStringType(context, typeRight)) { + left = wrapInToStringForConcat(left); + right = wrapInToStringForConcat(right); + luaOperator = lua.SyntaxKind.ConcatOperator; } - - return lua.createBinaryExpression(left, right, luaOperator, node); } - assertNever(operator); + return lua.createBinaryExpression(left, right, luaOperator, node); } export const transformBinaryExpression: FunctionVisitor = (node, context) => { @@ -96,7 +91,6 @@ export const transformBinaryExpression: FunctionVisitor = ( ); } - // Transpile operators switch (operator) { case ts.SyntaxKind.EqualsToken: return transformAssignmentExpression(context, node as ts.AssignmentExpression); @@ -168,27 +162,26 @@ export function transformBinaryExpressionStatement( node: ts.ExpressionStatement ): lua.Statement[] | lua.Statement | undefined { const { expression } = node; - if (ts.isBinaryExpression(expression)) { - const operator = expression.operatorToken.kind; + if (!ts.isBinaryExpression(expression)) return; + const operator = expression.operatorToken.kind; - if (isCompoundAssignmentToken(operator)) { - // +=, -=, etc... - return transformCompoundAssignmentStatement( - context, - expression, - expression.left, - expression.right, - unwrapCompoundAssignmentToken(operator) - ); - } else if (operator === ts.SyntaxKind.EqualsToken) { - return transformAssignmentStatement(context, expression as ts.AssignmentExpression); - } else if (operator === ts.SyntaxKind.CommaToken) { - const statements = [ - ...context.transformStatements(ts.createExpressionStatement(expression.left)), - ...context.transformStatements(ts.createExpressionStatement(expression.right)), - ]; - - return lua.createDoStatement(statements, expression); - } + if (isCompoundAssignmentToken(operator)) { + // +=, -=, etc... + return transformCompoundAssignmentStatement( + context, + expression, + expression.left, + expression.right, + unwrapCompoundAssignmentToken(operator) + ); + } else if (operator === ts.SyntaxKind.EqualsToken) { + return transformAssignmentStatement(context, expression as ts.AssignmentExpression); + } else if (operator === ts.SyntaxKind.CommaToken) { + const statements = [ + ...context.transformStatements(ts.createExpressionStatement(expression.left)), + ...context.transformStatements(ts.createExpressionStatement(expression.right)), + ]; + + return lua.createDoStatement(statements, expression); } } From 03e9aa3adbcd9f8b4cc5c89d4777940b8af04dea Mon Sep 17 00:00:00 2001 From: ark120202 Date: Sun, 15 Dec 2019 21:52:04 +0000 Subject: [PATCH 26/42] Fix typo --- src/transformation/visitors/binary-expression/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transformation/visitors/binary-expression/index.ts b/src/transformation/visitors/binary-expression/index.ts index ab240def1..fa8e71d7f 100644 --- a/src/transformation/visitors/binary-expression/index.ts +++ b/src/transformation/visitors/binary-expression/index.ts @@ -58,7 +58,7 @@ export function transformBinaryOperation( let luaOperator = simpleOperatorsToLua[operator]; - // Check is we need to use string concat operator + // Check if we need to use string concat operator if (operator === ts.SyntaxKind.PlusToken && ts.isBinaryExpression(node)) { const typeLeft = context.checker.getTypeAtLocation(node.left); const typeRight = context.checker.getTypeAtLocation(node.right); From f2feeb448aa1b6bc25d727486b5a546ff1736944 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 1 Jan 2020 23:13:23 +0000 Subject: [PATCH 27/42] Remove unused missing import --- src/transformation/visitors/binary-expression/assignments.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transformation/visitors/binary-expression/assignments.ts b/src/transformation/visitors/binary-expression/assignments.ts index ce8428537..bd09fc321 100644 --- a/src/transformation/visitors/binary-expression/assignments.ts +++ b/src/transformation/visitors/binary-expression/assignments.ts @@ -3,7 +3,7 @@ import * as lua from "../../../LuaAST"; import { cast } from "../../../utils"; import { TransformationContext } from "../../context"; import { isTupleReturnCall } from "../../utils/annotations"; -import { validateAssignment, validatePropertyAssignment } from "../../utils/assignment-validation"; +import { validateAssignment } from "../../utils/assignment-validation"; import { createExportedIdentifier, getDependenciesOfSymbol, isSymbolExported } from "../../utils/export"; import { createImmediatelyInvokedFunctionExpression, createUnpackCall, wrapInTable } from "../../utils/lua-ast"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; From 54aa5c27e7b9791dd051f3982ccd256d80f8db75 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 1 Jan 2020 23:20:16 +0000 Subject: [PATCH 28/42] Remove `test.only` from `conditionals.spec.ts` --- test/unit/conditionals.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/conditionals.spec.ts b/test/unit/conditionals.spec.ts index 3fdb649c6..33d65cf01 100644 --- a/test/unit/conditionals.spec.ts +++ b/test/unit/conditionals.spec.ts @@ -183,7 +183,7 @@ test("variable in nested scope does not interfere with case scope", () => { `.expectToMatchJsResult(); }); -test.only("switch using variable re-declared in cases", () => { +test("switch using variable re-declared in cases", () => { util.testFunction` let foo: number = 0; switch (foo) { From 9312a0c9eea2e38cf3931d3c873d244c678380c4 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 6 Jan 2020 17:41:44 +0000 Subject: [PATCH 29/42] Use inline snapshots for simple tests --- .../__snapshots__/conditionals.spec.ts.snap | 2 -- test/unit/__snapshots__/loops.spec.ts.snap | 2 -- .../__snapshots__/loading.spec.ts.snap | 4 --- test/unit/builtins/loading.spec.ts | 12 ++++++-- test/unit/bundle.spec.ts | 25 +++++++++++++++-- .../__snapshots__/classes.spec.ts.snap | 2 -- .../__snapshots__/decorators.spec.ts.snap | 2 -- test/unit/classes/classes.spec.ts | 6 +++- test/unit/classes/decorators.spec.ts | 4 ++- test/unit/conditionals.spec.ts | 6 +++- .../customConstructor.spec.ts.snap | 2 -- .../__snapshots__/forRange.spec.ts.snap | 10 ------- .../__snapshots__/luaIterator.spec.ts.snap | 4 --- .../__snapshots__/metaExtension.spec.ts.snap | 4 --- .../unit/decorators/customConstructor.spec.ts | 4 ++- test/unit/decorators/forRange.spec.ts | 28 +++++++++++++++---- test/unit/decorators/luaIterator.spec.ts | 12 ++++++-- test/unit/decorators/metaExtension.spec.ts | 12 ++++++-- test/unit/loops.spec.ts | 4 ++- test/util.ts | 20 +++++++++++-- 20 files changed, 112 insertions(+), 53 deletions(-) diff --git a/test/unit/__snapshots__/conditionals.spec.ts.snap b/test/unit/__snapshots__/conditionals.spec.ts.snap index 25d9b1397..5bca9f002 100644 --- a/test/unit/__snapshots__/conditionals.spec.ts.snap +++ b/test/unit/__snapshots__/conditionals.spec.ts.snap @@ -9,5 +9,3 @@ function ____exports.__main(self) end return ____exports" `; - -exports[`switch not allowed in 5.1: diagnostics 1`] = `"main.ts(2,9): error TSTL: Switch statements is/are not supported for target Lua 5.1."`; diff --git a/test/unit/__snapshots__/loops.spec.ts.snap b/test/unit/__snapshots__/loops.spec.ts.snap index 5eac11ed2..6e55ab1c1 100644 --- a/test/unit/__snapshots__/loops.spec.ts.snap +++ b/test/unit/__snapshots__/loops.spec.ts.snap @@ -10,8 +10,6 @@ end return ____exports" `; -exports[`forin[Array]: diagnostics 1`] = `"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`; - exports[`forof object destructuring ({"initializer": "{a, b}", "vars": "let a: string, b: string;"}): code 1`] = ` "local a local b diff --git a/test/unit/builtins/__snapshots__/loading.spec.ts.snap b/test/unit/builtins/__snapshots__/loading.spec.ts.snap index 5c30da22e..750b8afb5 100644 --- a/test/unit/builtins/__snapshots__/loading.spec.ts.snap +++ b/test/unit/builtins/__snapshots__/loading.spec.ts.snap @@ -6,12 +6,8 @@ ____exports.__result = Math.unknownProperty return ____exports" `; -exports[`Unknown builtin property access: diagnostics 1`] = `"main.ts(1,25): error TSTL: Math.unknownProperty is unsupported."`; - exports[`Unknown builtin property function call: code 1`] = ` "local ____exports = {} ____exports.__result = ({}):unknownFunction() return ____exports" `; - -exports[`Unknown builtin property function call: diagnostics 1`] = `"main.ts(1,25): error TSTL: array.unknownFunction is unsupported."`; diff --git a/test/unit/builtins/loading.spec.ts b/test/unit/builtins/loading.spec.ts index b90012bda..4acce3e46 100644 --- a/test/unit/builtins/loading.spec.ts +++ b/test/unit/builtins/loading.spec.ts @@ -39,10 +39,18 @@ test("lualib should not include tstl header", () => { describe("Unknown builtin property", () => { test("access", () => { - util.testExpression`Math.unknownProperty`.disableSemanticCheck().expectDiagnosticsToMatchSnapshot(); + util.testExpression`Math.unknownProperty` + .disableSemanticCheck() + .expectDiagnostics(m => + m.toMatchInlineSnapshot(`"main.ts(1,25): error TSTL: Math.unknownProperty is unsupported."`) + ); }); test("function call", () => { - util.testExpression`[].unknownFunction()`.disableSemanticCheck().expectDiagnosticsToMatchSnapshot(); + util.testExpression`[].unknownFunction()` + .disableSemanticCheck() + .expectDiagnostics(m => + m.toMatchInlineSnapshot(`"main.ts(1,25): error TSTL: array.unknownFunction is unsupported."`) + ); }); }); diff --git a/test/unit/bundle.spec.ts b/test/unit/bundle.spec.ts index ca58b778d..5943c8778 100644 --- a/test/unit/bundle.spec.ts +++ b/test/unit/bundle.spec.ts @@ -90,7 +90,13 @@ test("LuaLibImportKind.Inline generates a warning", () => { result.push(3); ` .setOptions({ luaLibImport: LuaLibImportKind.Inline }) - .expectDiagnosticsToMatchSnapshot(true) + .expectDiagnostics( + m => + m.toMatchInlineSnapshot( + `"warning TSTL: Using 'luaBundle' with 'luaLibImport: \\"inline\\"' might generate duplicate code. It is recommended to use 'luaLibImport: \\"require\\"'"` + ), + true + ) .expectToEqual({ result: [1, 2, 3] }); }); @@ -113,9 +119,22 @@ test("cyclic imports", () => { }); test("no entry point", () => { - util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot(true); + util.testBundle`` + .setOptions({ luaBundleEntry: undefined }) + .expectDiagnostics( + m => m.toMatchInlineSnapshot(`"error TSTL: 'luaBundleEntry' is required when 'luaBundle' is enabled."`), + true + ); }); test("luaEntry doesn't exist", () => { - util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot(true); + util.testBundle`` + .setEntryPoint("entry.ts") + .expectDiagnostics( + m => + m.toMatchInlineSnapshot( + `"error TSTL: Could not find bundle entry point 'entry.ts'. It should be a file in the project."` + ), + true + ); }); diff --git a/test/unit/classes/__snapshots__/classes.spec.ts.snap b/test/unit/classes/__snapshots__/classes.spec.ts.snap index f6d370e0c..8aa5c089e 100644 --- a/test/unit/classes/__snapshots__/classes.spec.ts.snap +++ b/test/unit/classes/__snapshots__/classes.spec.ts.snap @@ -5,5 +5,3 @@ exports[`super without class: code 1`] = ` ____exports.__result = ____.____constructor(self) return ____exports" `; - -exports[`super without class: diagnostics 1`] = `"main.ts(1,25): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors."`; diff --git a/test/unit/classes/__snapshots__/decorators.spec.ts.snap b/test/unit/classes/__snapshots__/decorators.spec.ts.snap index cbc983bd5..0c19de2bc 100644 --- a/test/unit/classes/__snapshots__/decorators.spec.ts.snap +++ b/test/unit/classes/__snapshots__/decorators.spec.ts.snap @@ -14,5 +14,3 @@ function ____exports.__main(self) end return ____exports" `; - -exports[`Throws error if decorator function has void context: diagnostics 1`] = `"main.ts(4,9): error TSTL: Decorator function cannot have 'this: void'."`; diff --git a/test/unit/classes/classes.spec.ts b/test/unit/classes/classes.spec.ts index e0291c31d..477050c49 100644 --- a/test/unit/classes/classes.spec.ts +++ b/test/unit/classes/classes.spec.ts @@ -237,7 +237,11 @@ test("Subclass constructor across merged namespace", () => { }); test("super without class", () => { - util.testExpression`super()`.expectDiagnosticsToMatchSnapshot(); + util.testExpression`super()`.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(1,25): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors."` + ) + ); }); test("super in unnamed class", () => { diff --git a/test/unit/classes/decorators.spec.ts b/test/unit/classes/decorators.spec.ts index e64bec99d..9c0cde8db 100644 --- a/test/unit/classes/decorators.spec.ts +++ b/test/unit/classes/decorators.spec.ts @@ -108,7 +108,9 @@ test("Throws error if decorator function has void context", () => { @decorator class TestClass {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot(`"main.ts(4,9): error TSTL: Decorator function cannot have 'this: void'."`) + ); }); test("Exported class decorator", () => { diff --git a/test/unit/conditionals.spec.ts b/test/unit/conditionals.spec.ts index 33d65cf01..716bc1a26 100644 --- a/test/unit/conditionals.spec.ts +++ b/test/unit/conditionals.spec.ts @@ -315,7 +315,11 @@ test("switch not allowed in 5.1", () => { switch ("abc") {} ` .setOptions({ luaTarget: tstl.LuaTarget.Lua51 }) - .expectDiagnosticsToMatchSnapshot(); + .expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(2,9): error TSTL: Switch statements is/are not supported for target Lua 5.1."` + ) + ); }); test.each([ diff --git a/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap b/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap index c283485bf..bd1e87f44 100644 --- a/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap @@ -12,5 +12,3 @@ function ____exports.__main(self) end return ____exports" `; - -exports[`IncorrectUsage: diagnostics 1`] = `"main.ts(5,9): error TSTL: '@customConstructor' expects 1 arguments, but got 0."`; diff --git a/test/unit/decorators/__snapshots__/forRange.spec.ts.snap b/test/unit/decorators/__snapshots__/forRange.spec.ts.snap index 568ad7476..63f97852d 100644 --- a/test/unit/decorators/__snapshots__/forRange.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/forRange.spec.ts.snap @@ -26,23 +26,17 @@ exports[`invalid usage argument types: code 1`] = ` end" `; -exports[`invalid usage argument types: diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: arguments must be numbers."`; - exports[`invalid usage non-ambient declaration: code 1`] = ` "function luaRange(self) end" `; -exports[`invalid usage non-ambient declaration: diagnostics 1`] = `"main.ts(3,22): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."`; - exports[`invalid usage non-declared loop variable: code 1`] = ` "local i for ____ = 1, 10, 2 do end" `; -exports[`invalid usage non-declared loop variable: diagnostics 1`] = `"main.ts(7,18): error TSTL: Invalid @forRange call: loop must declare it's own control variable."`; - exports[`invalid usage reference ("const call = undefined as any; call(luaRange);"): code 1`] = ` "local call = nil call(_G, luaRange)" @@ -83,11 +77,7 @@ exports[`invalid usage return type: code 1`] = ` end" `; -exports[`invalid usage return type: diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: function must return Iterable."`; - exports[`invalid usage variable destructuring: code 1`] = ` "for ____ = 1, 10, 2 do end" `; - -exports[`invalid usage variable destructuring: diagnostics 1`] = `"main.ts(6,18): error TSTL: Invalid @forRange call: destructuring cannot be used."`; diff --git a/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap b/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap index 00f10a7e4..373a5cad3 100644 --- a/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap @@ -6,11 +6,7 @@ for ____ in luaIter(_G) do end" `; -exports[`forof lua iterator tuple-return single existing variable: diagnostics 1`] = `"main.ts(9,14): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."`; - exports[`forof lua iterator tuple-return single variable: code 1`] = ` "for ____ in luaIter(_G) do end" `; - -exports[`forof lua iterator tuple-return single variable: diagnostics 1`] = `"main.ts(8,18): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."`; diff --git a/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap b/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap index 2c9611bd0..22e23ed78 100644 --- a/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap @@ -6,12 +6,8 @@ local __meta___LOADED = debug.getregistry()._LOADED local e = __TS__New(Ext)" `; -exports[`DontAllowInstantiation: diagnostics 1`] = `"main.ts(5,19): error TSTL: Cannot construct classes with '@extension' or '@metaExtension' annotation."`; - exports[`IncorrectUsage: code 1`] = ` "function LoadedExt.test(self) return 5 end" `; - -exports[`IncorrectUsage: diagnostics 1`] = `"main.ts(3,9): error TSTL: '@metaExtension' annotation requires the extension of the metatable class."`; diff --git a/test/unit/decorators/customConstructor.spec.ts b/test/unit/decorators/customConstructor.spec.ts index 035ec56fc..c22e5e608 100644 --- a/test/unit/decorators/customConstructor.spec.ts +++ b/test/unit/decorators/customConstructor.spec.ts @@ -29,5 +29,7 @@ test("IncorrectUsage", () => { class Point2D {} new Point2D(); - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot(`"main.ts(5,9): error TSTL: '@customConstructor' expects 1 arguments, but got 0."`) + ); }); diff --git a/test/unit/decorators/forRange.spec.ts b/test/unit/decorators/forRange.spec.ts index 1d6dd4198..4d383b027 100644 --- a/test/unit/decorators/forRange.spec.ts +++ b/test/unit/decorators/forRange.spec.ts @@ -28,7 +28,11 @@ describe("invalid usage", () => { util.testModule` /** @forRange */ function luaRange() {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(3,22): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."` + ) + ); }); test.each<[number[]]>([[[]], [[1]], [[1, 2, 3, 4]]])("argument count (%p)", args => { @@ -43,28 +47,42 @@ describe("invalid usage", () => { ${createForRangeDeclaration()} let i: number; for (i of luaRange(1, 10, 2)) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(7,18): error TSTL: Invalid @forRange call: loop must declare it's own control variable."` + ) + ); }); test("argument types", () => { util.testModule` ${createForRangeDeclaration("i: string, j: number")} for (const i of luaRange("foo", 2)) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot(`"main.ts(6,29): error TSTL: Invalid @forRange call: arguments must be numbers."`) + ); }); test("variable destructuring", () => { util.testModule` ${createForRangeDeclaration(undefined, "number[][]")} for (const [i] of luaRange(1, 10, 2)) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(6,18): error TSTL: Invalid @forRange call: destructuring cannot be used."` + ) + ); }); test("return type", () => { util.testModule` ${createForRangeDeclaration(undefined, "string[]")} for (const i of luaRange(1, 10)) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(6,29): error TSTL: Invalid @forRange call: function must return Iterable."` + ) + ); }); test.each([ diff --git a/test/unit/decorators/luaIterator.spec.ts b/test/unit/decorators/luaIterator.spec.ts index 3804bf6bb..fd1a4bcab 100644 --- a/test/unit/decorators/luaIterator.spec.ts +++ b/test/unit/decorators/luaIterator.spec.ts @@ -143,7 +143,11 @@ test("forof lua iterator tuple-return single variable", () => { interface Iter extends Iterable<[string, string]> {} declare function luaIter(): Iter; for (let x of luaIter()) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(8,18): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."` + ) + ); }); test("forof lua iterator tuple-return single existing variable", () => { @@ -156,7 +160,11 @@ test("forof lua iterator tuple-return single existing variable", () => { declare function luaIter(): Iter; let x: [string, string]; for (x of luaIter()) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(9,14): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."` + ) + ); }); test("forof forwarded lua iterator", () => { diff --git a/test/unit/decorators/metaExtension.spec.ts b/test/unit/decorators/metaExtension.spec.ts index c2a83b6fe..f0343ea14 100644 --- a/test/unit/decorators/metaExtension.spec.ts +++ b/test/unit/decorators/metaExtension.spec.ts @@ -32,7 +32,11 @@ test("IncorrectUsage", () => { return 5; } } - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(3,9): error TSTL: '@metaExtension' annotation requires the extension of the metatable class."` + ) + ); }); test("DontAllowInstantiation", () => { @@ -41,5 +45,9 @@ test("DontAllowInstantiation", () => { /** @metaExtension */ class Ext extends _LOADED {} const e = new Ext(); - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot( + `"main.ts(5,19): error TSTL: Cannot construct classes with '@extension' or '@metaExtension' annotation."` + ) + ); }); diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index c3c74f591..f82e611de 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -234,7 +234,9 @@ test("forin[Array]", () => { util.testFunction` const array = []; for (const key in array) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnostics(m => + m.toMatchInlineSnapshot(`"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`) + ); }); test.each([{ inp: { a: 0, b: 1, c: 2, d: 3, e: 4 }, expected: { a: 0, b: 0, c: 2, d: 0, e: 4 } }])( diff --git a/test/util.ts b/test/util.ts index a56de6086..3e0e0a3c3 100644 --- a/test/util.ts +++ b/test/util.ts @@ -389,7 +389,7 @@ export abstract class TestBuilder { return this; } - public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this { + private getDiagnosticsSnapshot(): string { this.expectToHaveDiagnostics(); const diagnosticMessages = ts.formatDiagnostics( @@ -397,7 +397,23 @@ export abstract class TestBuilder { { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } ); - expect(diagnosticMessages.trim()).toMatchSnapshot("diagnostics"); + return diagnosticMessages.trim(); + } + + public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this { + expect(this.getDiagnosticsSnapshot()).toMatchSnapshot("diagnostics"); + if (!diagnosticsOnly) { + expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); + } + + return this; + } + + public expectDiagnostics( + callback: (matchers: Pick, "toMatchInlineSnapshot">) => void, + diagnosticsOnly = false + ): this { + callback(expect(this.getDiagnosticsSnapshot())); if (!diagnosticsOnly) { expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); } From e6883bfcc6dcf237994397b534db624c0a94161c Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 6 Jan 2020 20:23:07 +0000 Subject: [PATCH 30/42] Revert "Use inline snapshots for simple tests" This reverts commit 9312a0c9eea2e38cf3931d3c873d244c678380c4. --- .../__snapshots__/conditionals.spec.ts.snap | 2 ++ test/unit/__snapshots__/loops.spec.ts.snap | 2 ++ .../__snapshots__/loading.spec.ts.snap | 4 +++ test/unit/builtins/loading.spec.ts | 12 ++------ test/unit/bundle.spec.ts | 25 ++--------------- .../__snapshots__/classes.spec.ts.snap | 2 ++ .../__snapshots__/decorators.spec.ts.snap | 2 ++ test/unit/classes/classes.spec.ts | 6 +--- test/unit/classes/decorators.spec.ts | 4 +-- test/unit/conditionals.spec.ts | 6 +--- .../customConstructor.spec.ts.snap | 2 ++ .../__snapshots__/forRange.spec.ts.snap | 10 +++++++ .../__snapshots__/luaIterator.spec.ts.snap | 4 +++ .../__snapshots__/metaExtension.spec.ts.snap | 4 +++ .../unit/decorators/customConstructor.spec.ts | 4 +-- test/unit/decorators/forRange.spec.ts | 28 ++++--------------- test/unit/decorators/luaIterator.spec.ts | 12 ++------ test/unit/decorators/metaExtension.spec.ts | 12 ++------ test/unit/loops.spec.ts | 4 +-- test/util.ts | 20 ++----------- 20 files changed, 53 insertions(+), 112 deletions(-) diff --git a/test/unit/__snapshots__/conditionals.spec.ts.snap b/test/unit/__snapshots__/conditionals.spec.ts.snap index 5bca9f002..25d9b1397 100644 --- a/test/unit/__snapshots__/conditionals.spec.ts.snap +++ b/test/unit/__snapshots__/conditionals.spec.ts.snap @@ -9,3 +9,5 @@ function ____exports.__main(self) end return ____exports" `; + +exports[`switch not allowed in 5.1: diagnostics 1`] = `"main.ts(2,9): error TSTL: Switch statements is/are not supported for target Lua 5.1."`; diff --git a/test/unit/__snapshots__/loops.spec.ts.snap b/test/unit/__snapshots__/loops.spec.ts.snap index 6e55ab1c1..5eac11ed2 100644 --- a/test/unit/__snapshots__/loops.spec.ts.snap +++ b/test/unit/__snapshots__/loops.spec.ts.snap @@ -10,6 +10,8 @@ end return ____exports" `; +exports[`forin[Array]: diagnostics 1`] = `"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`; + exports[`forof object destructuring ({"initializer": "{a, b}", "vars": "let a: string, b: string;"}): code 1`] = ` "local a local b diff --git a/test/unit/builtins/__snapshots__/loading.spec.ts.snap b/test/unit/builtins/__snapshots__/loading.spec.ts.snap index 750b8afb5..5c30da22e 100644 --- a/test/unit/builtins/__snapshots__/loading.spec.ts.snap +++ b/test/unit/builtins/__snapshots__/loading.spec.ts.snap @@ -6,8 +6,12 @@ ____exports.__result = Math.unknownProperty return ____exports" `; +exports[`Unknown builtin property access: diagnostics 1`] = `"main.ts(1,25): error TSTL: Math.unknownProperty is unsupported."`; + exports[`Unknown builtin property function call: code 1`] = ` "local ____exports = {} ____exports.__result = ({}):unknownFunction() return ____exports" `; + +exports[`Unknown builtin property function call: diagnostics 1`] = `"main.ts(1,25): error TSTL: array.unknownFunction is unsupported."`; diff --git a/test/unit/builtins/loading.spec.ts b/test/unit/builtins/loading.spec.ts index 4acce3e46..b90012bda 100644 --- a/test/unit/builtins/loading.spec.ts +++ b/test/unit/builtins/loading.spec.ts @@ -39,18 +39,10 @@ test("lualib should not include tstl header", () => { describe("Unknown builtin property", () => { test("access", () => { - util.testExpression`Math.unknownProperty` - .disableSemanticCheck() - .expectDiagnostics(m => - m.toMatchInlineSnapshot(`"main.ts(1,25): error TSTL: Math.unknownProperty is unsupported."`) - ); + util.testExpression`Math.unknownProperty`.disableSemanticCheck().expectDiagnosticsToMatchSnapshot(); }); test("function call", () => { - util.testExpression`[].unknownFunction()` - .disableSemanticCheck() - .expectDiagnostics(m => - m.toMatchInlineSnapshot(`"main.ts(1,25): error TSTL: array.unknownFunction is unsupported."`) - ); + util.testExpression`[].unknownFunction()`.disableSemanticCheck().expectDiagnosticsToMatchSnapshot(); }); }); diff --git a/test/unit/bundle.spec.ts b/test/unit/bundle.spec.ts index 5943c8778..ca58b778d 100644 --- a/test/unit/bundle.spec.ts +++ b/test/unit/bundle.spec.ts @@ -90,13 +90,7 @@ test("LuaLibImportKind.Inline generates a warning", () => { result.push(3); ` .setOptions({ luaLibImport: LuaLibImportKind.Inline }) - .expectDiagnostics( - m => - m.toMatchInlineSnapshot( - `"warning TSTL: Using 'luaBundle' with 'luaLibImport: \\"inline\\"' might generate duplicate code. It is recommended to use 'luaLibImport: \\"require\\"'"` - ), - true - ) + .expectDiagnosticsToMatchSnapshot(true) .expectToEqual({ result: [1, 2, 3] }); }); @@ -119,22 +113,9 @@ test("cyclic imports", () => { }); test("no entry point", () => { - util.testBundle`` - .setOptions({ luaBundleEntry: undefined }) - .expectDiagnostics( - m => m.toMatchInlineSnapshot(`"error TSTL: 'luaBundleEntry' is required when 'luaBundle' is enabled."`), - true - ); + util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot(true); }); test("luaEntry doesn't exist", () => { - util.testBundle`` - .setEntryPoint("entry.ts") - .expectDiagnostics( - m => - m.toMatchInlineSnapshot( - `"error TSTL: Could not find bundle entry point 'entry.ts'. It should be a file in the project."` - ), - true - ); + util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot(true); }); diff --git a/test/unit/classes/__snapshots__/classes.spec.ts.snap b/test/unit/classes/__snapshots__/classes.spec.ts.snap index 8aa5c089e..f6d370e0c 100644 --- a/test/unit/classes/__snapshots__/classes.spec.ts.snap +++ b/test/unit/classes/__snapshots__/classes.spec.ts.snap @@ -5,3 +5,5 @@ exports[`super without class: code 1`] = ` ____exports.__result = ____.____constructor(self) return ____exports" `; + +exports[`super without class: diagnostics 1`] = `"main.ts(1,25): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors."`; diff --git a/test/unit/classes/__snapshots__/decorators.spec.ts.snap b/test/unit/classes/__snapshots__/decorators.spec.ts.snap index 0c19de2bc..cbc983bd5 100644 --- a/test/unit/classes/__snapshots__/decorators.spec.ts.snap +++ b/test/unit/classes/__snapshots__/decorators.spec.ts.snap @@ -14,3 +14,5 @@ function ____exports.__main(self) end return ____exports" `; + +exports[`Throws error if decorator function has void context: diagnostics 1`] = `"main.ts(4,9): error TSTL: Decorator function cannot have 'this: void'."`; diff --git a/test/unit/classes/classes.spec.ts b/test/unit/classes/classes.spec.ts index 477050c49..e0291c31d 100644 --- a/test/unit/classes/classes.spec.ts +++ b/test/unit/classes/classes.spec.ts @@ -237,11 +237,7 @@ test("Subclass constructor across merged namespace", () => { }); test("super without class", () => { - util.testExpression`super()`.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(1,25): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors."` - ) - ); + util.testExpression`super()`.expectDiagnosticsToMatchSnapshot(); }); test("super in unnamed class", () => { diff --git a/test/unit/classes/decorators.spec.ts b/test/unit/classes/decorators.spec.ts index 9c0cde8db..e64bec99d 100644 --- a/test/unit/classes/decorators.spec.ts +++ b/test/unit/classes/decorators.spec.ts @@ -108,9 +108,7 @@ test("Throws error if decorator function has void context", () => { @decorator class TestClass {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot(`"main.ts(4,9): error TSTL: Decorator function cannot have 'this: void'."`) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("Exported class decorator", () => { diff --git a/test/unit/conditionals.spec.ts b/test/unit/conditionals.spec.ts index 716bc1a26..33d65cf01 100644 --- a/test/unit/conditionals.spec.ts +++ b/test/unit/conditionals.spec.ts @@ -315,11 +315,7 @@ test("switch not allowed in 5.1", () => { switch ("abc") {} ` .setOptions({ luaTarget: tstl.LuaTarget.Lua51 }) - .expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(2,9): error TSTL: Switch statements is/are not supported for target Lua 5.1."` - ) - ); + .expectDiagnosticsToMatchSnapshot(); }); test.each([ diff --git a/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap b/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap index bd1e87f44..c283485bf 100644 --- a/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/customConstructor.spec.ts.snap @@ -12,3 +12,5 @@ function ____exports.__main(self) end return ____exports" `; + +exports[`IncorrectUsage: diagnostics 1`] = `"main.ts(5,9): error TSTL: '@customConstructor' expects 1 arguments, but got 0."`; diff --git a/test/unit/decorators/__snapshots__/forRange.spec.ts.snap b/test/unit/decorators/__snapshots__/forRange.spec.ts.snap index 63f97852d..568ad7476 100644 --- a/test/unit/decorators/__snapshots__/forRange.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/forRange.spec.ts.snap @@ -26,17 +26,23 @@ exports[`invalid usage argument types: code 1`] = ` end" `; +exports[`invalid usage argument types: diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: arguments must be numbers."`; + exports[`invalid usage non-ambient declaration: code 1`] = ` "function luaRange(self) end" `; +exports[`invalid usage non-ambient declaration: diagnostics 1`] = `"main.ts(3,22): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."`; + exports[`invalid usage non-declared loop variable: code 1`] = ` "local i for ____ = 1, 10, 2 do end" `; +exports[`invalid usage non-declared loop variable: diagnostics 1`] = `"main.ts(7,18): error TSTL: Invalid @forRange call: loop must declare it's own control variable."`; + exports[`invalid usage reference ("const call = undefined as any; call(luaRange);"): code 1`] = ` "local call = nil call(_G, luaRange)" @@ -77,7 +83,11 @@ exports[`invalid usage return type: code 1`] = ` end" `; +exports[`invalid usage return type: diagnostics 1`] = `"main.ts(6,29): error TSTL: Invalid @forRange call: function must return Iterable."`; + exports[`invalid usage variable destructuring: code 1`] = ` "for ____ = 1, 10, 2 do end" `; + +exports[`invalid usage variable destructuring: diagnostics 1`] = `"main.ts(6,18): error TSTL: Invalid @forRange call: destructuring cannot be used."`; diff --git a/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap b/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap index 373a5cad3..00f10a7e4 100644 --- a/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/luaIterator.spec.ts.snap @@ -6,7 +6,11 @@ for ____ in luaIter(_G) do end" `; +exports[`forof lua iterator tuple-return single existing variable: diagnostics 1`] = `"main.ts(9,14): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."`; + exports[`forof lua iterator tuple-return single variable: code 1`] = ` "for ____ in luaIter(_G) do end" `; + +exports[`forof lua iterator tuple-return single variable: diagnostics 1`] = `"main.ts(8,18): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."`; diff --git a/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap b/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap index 22e23ed78..2c9611bd0 100644 --- a/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap +++ b/test/unit/decorators/__snapshots__/metaExtension.spec.ts.snap @@ -6,8 +6,12 @@ local __meta___LOADED = debug.getregistry()._LOADED local e = __TS__New(Ext)" `; +exports[`DontAllowInstantiation: diagnostics 1`] = `"main.ts(5,19): error TSTL: Cannot construct classes with '@extension' or '@metaExtension' annotation."`; + exports[`IncorrectUsage: code 1`] = ` "function LoadedExt.test(self) return 5 end" `; + +exports[`IncorrectUsage: diagnostics 1`] = `"main.ts(3,9): error TSTL: '@metaExtension' annotation requires the extension of the metatable class."`; diff --git a/test/unit/decorators/customConstructor.spec.ts b/test/unit/decorators/customConstructor.spec.ts index c22e5e608..035ec56fc 100644 --- a/test/unit/decorators/customConstructor.spec.ts +++ b/test/unit/decorators/customConstructor.spec.ts @@ -29,7 +29,5 @@ test("IncorrectUsage", () => { class Point2D {} new Point2D(); - `.expectDiagnostics(m => - m.toMatchInlineSnapshot(`"main.ts(5,9): error TSTL: '@customConstructor' expects 1 arguments, but got 0."`) - ); + `.expectDiagnosticsToMatchSnapshot(); }); diff --git a/test/unit/decorators/forRange.spec.ts b/test/unit/decorators/forRange.spec.ts index 4d383b027..1d6dd4198 100644 --- a/test/unit/decorators/forRange.spec.ts +++ b/test/unit/decorators/forRange.spec.ts @@ -28,11 +28,7 @@ describe("invalid usage", () => { util.testModule` /** @forRange */ function luaRange() {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(3,22): error TSTL: Invalid @forRange call: can be used only as an iterable in a for...of loop."` - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test.each<[number[]]>([[[]], [[1]], [[1, 2, 3, 4]]])("argument count (%p)", args => { @@ -47,42 +43,28 @@ describe("invalid usage", () => { ${createForRangeDeclaration()} let i: number; for (i of luaRange(1, 10, 2)) {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(7,18): error TSTL: Invalid @forRange call: loop must declare it's own control variable."` - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("argument types", () => { util.testModule` ${createForRangeDeclaration("i: string, j: number")} for (const i of luaRange("foo", 2)) {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot(`"main.ts(6,29): error TSTL: Invalid @forRange call: arguments must be numbers."`) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("variable destructuring", () => { util.testModule` ${createForRangeDeclaration(undefined, "number[][]")} for (const [i] of luaRange(1, 10, 2)) {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(6,18): error TSTL: Invalid @forRange call: destructuring cannot be used."` - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("return type", () => { util.testModule` ${createForRangeDeclaration(undefined, "string[]")} for (const i of luaRange(1, 10)) {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(6,29): error TSTL: Invalid @forRange call: function must return Iterable."` - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test.each([ diff --git a/test/unit/decorators/luaIterator.spec.ts b/test/unit/decorators/luaIterator.spec.ts index fd1a4bcab..3804bf6bb 100644 --- a/test/unit/decorators/luaIterator.spec.ts +++ b/test/unit/decorators/luaIterator.spec.ts @@ -143,11 +143,7 @@ test("forof lua iterator tuple-return single variable", () => { interface Iter extends Iterable<[string, string]> {} declare function luaIter(): Iter; for (let x of luaIter()) {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(8,18): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."` - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("forof lua iterator tuple-return single existing variable", () => { @@ -160,11 +156,7 @@ test("forof lua iterator tuple-return single existing variable", () => { declare function luaIter(): Iter; let x: [string, string]; for (x of luaIter()) {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(9,14): error TSTL: Unsupported use of lua iterator with '@tupleReturn' annotation in for...of statement. You must use a destructuring statement to catch results from a lua iterator with the '@tupleReturn' annotation."` - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("forof forwarded lua iterator", () => { diff --git a/test/unit/decorators/metaExtension.spec.ts b/test/unit/decorators/metaExtension.spec.ts index f0343ea14..c2a83b6fe 100644 --- a/test/unit/decorators/metaExtension.spec.ts +++ b/test/unit/decorators/metaExtension.spec.ts @@ -32,11 +32,7 @@ test("IncorrectUsage", () => { return 5; } } - `.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(3,9): error TSTL: '@metaExtension' annotation requires the extension of the metatable class."` - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test("DontAllowInstantiation", () => { @@ -45,9 +41,5 @@ test("DontAllowInstantiation", () => { /** @metaExtension */ class Ext extends _LOADED {} const e = new Ext(); - `.expectDiagnostics(m => - m.toMatchInlineSnapshot( - `"main.ts(5,19): error TSTL: Cannot construct classes with '@extension' or '@metaExtension' annotation."` - ) - ); + `.expectDiagnosticsToMatchSnapshot(); }); diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index f82e611de..c3c74f591 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -234,9 +234,7 @@ test("forin[Array]", () => { util.testFunction` const array = []; for (const key in array) {} - `.expectDiagnostics(m => - m.toMatchInlineSnapshot(`"main.ts(3,9): error TSTL: Iterating over arrays with 'for ... in' is not allowed."`) - ); + `.expectDiagnosticsToMatchSnapshot(); }); test.each([{ inp: { a: 0, b: 1, c: 2, d: 3, e: 4 }, expected: { a: 0, b: 0, c: 2, d: 0, e: 4 } }])( diff --git a/test/util.ts b/test/util.ts index 3e0e0a3c3..a56de6086 100644 --- a/test/util.ts +++ b/test/util.ts @@ -389,7 +389,7 @@ export abstract class TestBuilder { return this; } - private getDiagnosticsSnapshot(): string { + public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this { this.expectToHaveDiagnostics(); const diagnosticMessages = ts.formatDiagnostics( @@ -397,23 +397,7 @@ export abstract class TestBuilder { { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } ); - return diagnosticMessages.trim(); - } - - public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this { - expect(this.getDiagnosticsSnapshot()).toMatchSnapshot("diagnostics"); - if (!diagnosticsOnly) { - expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); - } - - return this; - } - - public expectDiagnostics( - callback: (matchers: Pick, "toMatchInlineSnapshot">) => void, - diagnosticsOnly = false - ): this { - callback(expect(this.getDiagnosticsSnapshot())); + expect(diagnosticMessages.trim()).toMatchSnapshot("diagnostics"); if (!diagnosticsOnly) { expect(this.getMainLuaCodeChunk()).toMatchSnapshot("code"); } From e23b1d62ec9d43076141acdb486efae175c9b801 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Mar 2020 14:45:03 +0000 Subject: [PATCH 31/42] Factorize transpilation diagnostics --- src/transformation/utils/diagnostics.ts | 4 -- src/transpilation/diagnostics.ts | 60 +++++++++---------------- 2 files changed, 22 insertions(+), 42 deletions(-) diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index c3d29a0ff..63017acc6 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -97,10 +97,6 @@ export const luaIteratorForbiddenUsage = createDiagnosticFactory( "the '@tupleReturn' annotation." ); -export const unsupportedSyntaxKind = createDiagnosticFactory( - (description: string, kind: ts.SyntaxKind) => `Unsupported ${description} kind: ${ts.SyntaxKind[kind]}` -); - export const unsupportedNullishCoalescing = createDiagnosticFactory("Nullish coalescing is not supported."); export const unsupportedAccessorInObjectLiteral = createDiagnosticFactory( diff --git a/src/transpilation/diagnostics.ts b/src/transpilation/diagnostics.ts index 3383c3cfd..25425a135 100644 --- a/src/transpilation/diagnostics.ts +++ b/src/transpilation/diagnostics.ts @@ -1,51 +1,35 @@ import * as ts from "typescript"; -export const toLoadTransformerItShouldBeTranspiled = (transform: string): ts.Diagnostic => ({ +const createDiagnosticFactory = (getMessage: (...args: TArgs) => string) => ( + ...args: TArgs +): ts.Diagnostic => ({ file: undefined, start: undefined, length: undefined, category: ts.DiagnosticCategory.Error, code: 0, source: "typescript-to-lua", - messageText: `To load "${transform}" transformer it should be transpiled or "ts-node" should be installed`, + messageText: getMessage(...args), }); -export const couldNotResolveTransformerFrom = (transform: string, base: string): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, - category: ts.DiagnosticCategory.Error, - code: 0, - source: "typescript-to-lua", - messageText: `Could not resolve "${transform}" transformer from "${base}".`, -}); +export const toLoadTransformerItShouldBeTranspiled = createDiagnosticFactory( + (transform: string) => + `To load "${transform}" transformer it should be transpiled or "ts-node" should be installed.` +); -export const transformerShouldHaveAExport = (transform: string, importName: string): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, - category: ts.DiagnosticCategory.Error, - code: 0, - source: "typescript-to-lua", - messageText: `"${transform}" transformer should have a "${importName}" export`, -}); +export const couldNotResolveTransformerFrom = createDiagnosticFactory( + (transform: string, base: string) => `Could not resolve "${transform}" transformer from "${base}".` +); -export const transformerShouldBeATsTransformerFactory = (transform: string): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, - category: ts.DiagnosticCategory.Error, - code: 0, - source: "typescript-to-lua", - messageText: `"${transform}" transformer should be a ts.TransformerFactory or an object with ts.TransformerFactory values`, -}); +export const transformerShouldHaveAExport = createDiagnosticFactory( + (transform: string, importName: string) => `"${transform}" transformer should have a "${importName}" export.` +); -export const couldNotFindBundleEntryPoint = (entryPoint: string): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, - category: ts.DiagnosticCategory.Error, - code: 0, - source: "typescript-to-lua", - messageText: `Could not find bundle entry point '${entryPoint}'. It should be a file in the project.`, -}); +export const transformerShouldBeATsTransformerFactory = createDiagnosticFactory( + (transform: string) => + `"${transform}" transformer should be a ts.TransformerFactory or an object with ts.TransformerFactory values.` +); + +export const couldNotFindBundleEntryPoint = createDiagnosticFactory( + (entryPoint: string) => `Could not find bundle entry point '${entryPoint}'. It should be a file in the project.` +); From e533ed7d8a91d616d7655ed8111d6f450fa9cf85 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Mar 2020 15:59:19 +0000 Subject: [PATCH 32/42] Improve some diagnostic code spans --- src/transformation/builtins/array.ts | 2 +- src/transformation/builtins/console.ts | 2 +- src/transformation/builtins/function.ts | 2 +- src/transformation/builtins/math.ts | 4 +- src/transformation/builtins/number.ts | 4 +- src/transformation/builtins/object.ts | 2 +- src/transformation/builtins/string.ts | 6 +-- src/transformation/builtins/symbol.ts | 2 +- src/transformation/utils/diagnostics.ts | 8 +--- src/transformation/utils/safe-names.ts | 23 +++++---- src/transformation/visitors/lua-table.ts | 8 ++-- .../visitors/variable-declaration.ts | 4 +- .../__snapshots__/assignments.spec.ts.snap | 47 +++++++++++++++++++ .../__snapshots__/identifiers.spec.ts.snap | 8 ++++ test/unit/assignments.spec.ts | 8 ++-- .../__snapshots__/classes.spec.ts.snap | 10 ++++ test/unit/classes/classes.spec.ts | 6 +++ .../__snapshots__/functions.spec.ts.snap | 8 ++++ test/unit/functions/functions.spec.ts | 6 +++ test/unit/identifiers.spec.ts | 4 ++ 20 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 test/unit/__snapshots__/assignments.spec.ts.snap create mode 100644 test/unit/functions/__snapshots__/functions.spec.ts.snap diff --git a/src/transformation/builtins/array.ts b/src/transformation/builtins/array.ts index 392658c5f..41859e57c 100644 --- a/src/transformation/builtins/array.ts +++ b/src/transformation/builtins/array.ts @@ -79,7 +79,7 @@ export function transformArrayPrototypeCall( case "flatMap": return transformLuaLibFunction(context, LuaLibFeature.ArrayFlatMap, node, caller, ...params); default: - context.diagnostics.push(unsupportedProperty(node, "array", expressionName)); + context.diagnostics.push(unsupportedProperty(expression.name, "array", expressionName)); } } diff --git a/src/transformation/builtins/console.ts b/src/transformation/builtins/console.ts index e1e12e06a..af7ceb87e 100644 --- a/src/transformation/builtins/console.ts +++ b/src/transformation/builtins/console.ts @@ -61,6 +61,6 @@ export function transformConsoleCall( ); return lua.createCallExpression(lua.createIdentifier("print"), [debugTracebackCall]); default: - context.diagnostics.push(unsupportedProperty(expression, "console", methodName)); + context.diagnostics.push(unsupportedProperty(method.name, "console", methodName)); } } diff --git a/src/transformation/builtins/function.ts b/src/transformation/builtins/function.ts index 2572bac71..3ba8c2aaa 100644 --- a/src/transformation/builtins/function.ts +++ b/src/transformation/builtins/function.ts @@ -27,6 +27,6 @@ export function transformFunctionPrototypeCall( case "call": return transformLuaLibFunction(context, LuaLibFeature.FunctionCall, node, caller, ...params); default: - context.diagnostics.push(unsupportedProperty(node, "function", expressionName)); + context.diagnostics.push(unsupportedProperty(expression.name, "function", expressionName)); } } diff --git a/src/transformation/builtins/math.ts b/src/transformation/builtins/math.ts index da5eec589..6ceae16bd 100644 --- a/src/transformation/builtins/math.ts +++ b/src/transformation/builtins/math.ts @@ -26,7 +26,7 @@ export function transformMathProperty( return lua.createNumericLiteral(Math[name], node); default: - context.diagnostics.push(unsupportedProperty(node, "Math", name)); + context.diagnostics.push(unsupportedProperty(node.name, "Math", name)); } } @@ -99,6 +99,6 @@ export function transformMathCall( } default: - context.diagnostics.push(unsupportedProperty(expression, "Math", expressionName)); + context.diagnostics.push(unsupportedProperty(expression.name, "Math", expressionName)); } } diff --git a/src/transformation/builtins/number.ts b/src/transformation/builtins/number.ts index d3ee0ab40..227d82b23 100644 --- a/src/transformation/builtins/number.ts +++ b/src/transformation/builtins/number.ts @@ -20,7 +20,7 @@ export function transformNumberPrototypeCall( ? lua.createCallExpression(lua.createIdentifier("tostring"), [caller], node) : transformLuaLibFunction(context, LuaLibFeature.NumberToString, node, caller, ...params); default: - context.diagnostics.push(unsupportedProperty(node, "number", expressionName)); + context.diagnostics.push(unsupportedProperty(expression.name, "number", expressionName)); } } @@ -37,6 +37,6 @@ export function transformNumberConstructorCall( case "isFinite": return transformLuaLibFunction(context, LuaLibFeature.NumberIsFinite, expression, ...parameters); default: - context.diagnostics.push(unsupportedProperty(expression, "Number", methodName)); + context.diagnostics.push(unsupportedProperty(method.name, "Number", methodName)); } } diff --git a/src/transformation/builtins/object.ts b/src/transformation/builtins/object.ts index d652aafc5..358bebbf5 100644 --- a/src/transformation/builtins/object.ts +++ b/src/transformation/builtins/object.ts @@ -24,7 +24,7 @@ export function transformObjectConstructorCall( case "values": return transformLuaLibFunction(context, LuaLibFeature.ObjectValues, expression, ...parameters); default: - context.diagnostics.push(unsupportedProperty(expression, "Object", methodName)); + context.diagnostics.push(unsupportedProperty(method.name, "Object", methodName)); } } diff --git a/src/transformation/builtins/string.ts b/src/transformation/builtins/string.ts index f86ba4254..ac2005929 100644 --- a/src/transformation/builtins/string.ts +++ b/src/transformation/builtins/string.ts @@ -110,7 +110,7 @@ export function transformStringPrototypeCall( case "padEnd": return transformLuaLibFunction(context, LuaLibFeature.StringPadEnd, node, caller, ...params); default: - context.diagnostics.push(unsupportedProperty(node, "string", expressionName)); + context.diagnostics.push(unsupportedProperty(expression.name, "string", expressionName)); } } @@ -132,7 +132,7 @@ export function transformStringConstructorCall( ); default: - context.diagnostics.push(unsupportedProperty(node, "String", expressionName)); + context.diagnostics.push(unsupportedProperty(expression.name, "String", expressionName)); } } @@ -145,6 +145,6 @@ export function transformStringProperty( const expression = context.transformExpression(node.expression); return lua.createUnaryExpression(expression, lua.SyntaxKind.LengthOperator, node); default: - context.diagnostics.push(unsupportedProperty(node, "string", node.name.text)); + context.diagnostics.push(unsupportedProperty(node.name, "string", node.name.text)); } } diff --git a/src/transformation/builtins/symbol.ts b/src/transformation/builtins/symbol.ts index 85cea3314..04329e059 100644 --- a/src/transformation/builtins/symbol.ts +++ b/src/transformation/builtins/symbol.ts @@ -20,6 +20,6 @@ export function transformSymbolConstructorCall( const functionIdentifier = lua.createIdentifier(`__TS__SymbolRegistry${upperMethodName}`); return lua.createCallExpression(functionIdentifier, parameters, expression); default: - context.diagnostics.push(unsupportedProperty(expression, "Symbol", methodName)); + context.diagnostics.push(unsupportedProperty(method.name, "Symbol", methodName)); } } diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index 63017acc6..f783205f2 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -97,12 +97,12 @@ export const luaIteratorForbiddenUsage = createDiagnosticFactory( "the '@tupleReturn' annotation." ); -export const unsupportedNullishCoalescing = createDiagnosticFactory("Nullish coalescing is not supported."); - export const unsupportedAccessorInObjectLiteral = createDiagnosticFactory( "Accessors in object literal are not supported." ); +export const unsupportedNullishCoalescing = createDiagnosticFactory("Nullish coalescing is not supported."); + export const unsupportedRightShiftOperator = createDiagnosticFactory( "Right shift operator is not supported. Use `>>>` instead." ); @@ -117,10 +117,6 @@ export const unsupportedProperty = createDiagnosticFactory( (parentName: string, property: string) => `${parentName}.${property} is unsupported.` ); -export const forOfUnsupportedObjectDestructuring = createDiagnosticFactory( - `Unsupported object destructuring in for...of statement.` -); - export const invalidAmbientIdentifierName = createDiagnosticFactory( (text: string) => `Invalid ambient identifier name '${text}'. Ambient identifiers must be valid lua identifiers.` ); diff --git a/src/transformation/utils/safe-names.ts b/src/transformation/utils/safe-names.ts index 2b5e45845..166dd4888 100644 --- a/src/transformation/utils/safe-names.ts +++ b/src/transformation/utils/safe-names.ts @@ -55,6 +55,19 @@ const luaBuiltins: ReadonlySet = new Set([ export const isUnsafeName = (name: string) => !isValidLuaIdentifier(name) || luaBuiltins.has(name); +function checkName(context: TransformationContext, name: string, node: ts.Node): boolean { + const isInvalid = !isValidLuaIdentifier(name); + + if (isInvalid) { + // Empty identifier is a TypeScript error + if (name !== "") { + context.diagnostics.push(invalidAmbientIdentifierName(node, name)); + } + } + + return isInvalid; +} + export function hasUnsafeSymbolName( context: TransformationContext, symbol: ts.Symbol, @@ -63,8 +76,7 @@ export function hasUnsafeSymbolName( const isAmbient = symbol.declarations && symbol.declarations.some(d => isAmbientNode(d)); // Catch ambient declarations of identifiers with bad names - if (!isValidLuaIdentifier(symbol.name) && isAmbient) { - context.diagnostics.push(invalidAmbientIdentifierName(tsOriginal, symbol.name)); + if (isAmbient && checkName(context, symbol.name, tsOriginal)) { return true; } @@ -84,12 +96,7 @@ export function hasUnsafeIdentifierName( } } - if (!isValidLuaIdentifier(identifier.text)) { - context.diagnostics.push(invalidAmbientIdentifierName(identifier, identifier.text)); - return true; - } - - return false; + return checkName(context, identifier.text, identifier); } const fixInvalidLuaIdentifier = (name: string) => diff --git a/src/transformation/visitors/lua-table.ts b/src/transformation/visitors/lua-table.ts index c91e8c5ed..c4f7e14ed 100644 --- a/src/transformation/visitors/lua-table.ts +++ b/src/transformation/visitors/lua-table.ts @@ -70,7 +70,7 @@ export function transformLuaTableExpressionStatement( expression ); default: - context.diagnostics.push(unsupportedProperty(expression, "LuaTable", methodName)); + context.diagnostics.push(unsupportedProperty(expression.expression.name, "LuaTable", methodName)); } } @@ -93,7 +93,7 @@ export function transformLuaTableCallExpression( case "get": return lua.createTableIndexExpression(luaTable, params[0] ?? lua.createNilLiteral(), node); default: - context.diagnostics.push(unsupportedProperty(node, "LuaTable", methodName)); + context.diagnostics.push(unsupportedProperty(node.expression.name, "LuaTable", methodName)); } } @@ -109,7 +109,7 @@ export function transformLuaTablePropertyAccessExpression( return lua.createUnaryExpression(luaTable, lua.SyntaxKind.LengthOperator, node); } - context.diagnostics.push(unsupportedProperty(node, "LuaTable", propertyName)); + context.diagnostics.push(unsupportedProperty(node.name, "LuaTable", propertyName)); } export function transformLuaTablePropertyAccessInAssignment( @@ -127,7 +127,7 @@ export function transformLuaTablePropertyAccessInAssignment( return lua.createTableIndexExpression(luaTable, lua.createStringLiteral(propertyName), node); } - context.diagnostics.push(unsupportedProperty(node, "LuaTable", propertyName)); + context.diagnostics.push(unsupportedProperty(node.name, "LuaTable", propertyName)); } export function validateLuaTableElementAccessExpression( diff --git a/src/transformation/visitors/variable-declaration.ts b/src/transformation/visitors/variable-declaration.ts index 7594b6b1b..f165711e3 100644 --- a/src/transformation/visitors/variable-declaration.ts +++ b/src/transformation/visitors/variable-declaration.ts @@ -237,7 +237,9 @@ export function transformVariableDeclaration( export function checkVariableDeclarationList(context: TransformationContext, node: ts.VariableDeclarationList): void { if ((node.flags & (ts.NodeFlags.Let | ts.NodeFlags.Const)) === 0) { - context.diagnostics.push(unsupportedVarDeclaration(node)); + const token = node.getFirstToken(); + assert(token); + context.diagnostics.push(unsupportedVarDeclaration(token)); } } diff --git a/test/unit/__snapshots__/assignments.spec.ts.snap b/test/unit/__snapshots__/assignments.spec.ts.snap new file mode 100644 index 000000000..6f9f553ff --- /dev/null +++ b/test/unit/__snapshots__/assignments.spec.ts.snap @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`var declaration in for loop is disallowed: code 1`] = ` +"local ____exports = {} +function ____exports.__main(self) + do + local foo = 0 + while true do + end + end +end +return ____exports" +`; + +exports[`var declaration in for loop is disallowed: diagnostics 1`] = `"main.ts(2,14): error TSTL: \`var\` declarations are not supported. Use \`let\` or \`const\` instead."`; + +exports[`var declaration in for...in loop is disallowed: code 1`] = ` +"local ____exports = {} +function ____exports.__main(self) + for foo in pairs({}) do + end +end +return ____exports" +`; + +exports[`var declaration in for...in loop is disallowed: diagnostics 1`] = `"main.ts(2,14): error TSTL: \`var\` declarations are not supported. Use \`let\` or \`const\` instead."`; + +exports[`var declaration in for...of loop is disallowed: code 1`] = ` +"local ____exports = {} +function ____exports.__main(self) + for ____, foo in ipairs({}) do + end +end +return ____exports" +`; + +exports[`var declaration in for...of loop is disallowed: diagnostics 1`] = `"main.ts(2,14): error TSTL: \`var\` declarations are not supported. Use \`let\` or \`const\` instead."`; + +exports[`var declaration is disallowed: code 1`] = ` +"local ____exports = {} +function ____exports.__main(self) + local foo = true +end +return ____exports" +`; + +exports[`var declaration is disallowed: diagnostics 1`] = `"main.ts(2,9): error TSTL: \`var\` declarations are not supported. Use \`let\` or \`const\` instead."`; diff --git a/test/unit/__snapshots__/identifiers.spec.ts.snap b/test/unit/__snapshots__/identifiers.spec.ts.snap index 6ab8a4433..5108c0198 100644 --- a/test/unit/__snapshots__/identifiers.spec.ts.snap +++ b/test/unit/__snapshots__/identifiers.spec.ts.snap @@ -128,6 +128,14 @@ exports[`ambient identifier must be a valid lua identifier (object literal short exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("ɥɣɎɌͼƛಠ"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'ɥɣɎɌͼƛಠ'. Ambient identifiers must be valid lua identifiers."`; +exports[`missing expression ("({})[]"): code 1`] = `"local ____ = ({})[____]"`; + +exports[`missing expression ("({})[]"): diagnostics 1`] = `"main.ts(1,6): error TS1011: An element access expression should take an argument."`; + +exports[`missing expression ("const x = ;"): code 1`] = `"x = ____"`; + +exports[`missing expression ("const x = ;"): diagnostics 1`] = `"main.ts(1,11): error TS1109: Expression expected."`; + exports[`undeclared identifier must be a valid lua identifier ("$$"): code 1`] = `"foo = _____24_24_24"`; exports[`undeclared identifier must be a valid lua identifier ("$$"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; diff --git a/test/unit/assignments.spec.ts b/test/unit/assignments.spec.ts index ce7abd622..0d396fd66 100644 --- a/test/unit/assignments.spec.ts +++ b/test/unit/assignments.spec.ts @@ -21,25 +21,25 @@ test.each(["const", "let"])("%s declaration top-level is global", declarationKin test("var declaration is disallowed", () => { util.testFunction` var foo = true; - `.expectToHaveDiagnostics(); + `.expectDiagnosticsToMatchSnapshot(); }); test("var declaration in for loop is disallowed", () => { util.testFunction` for (var foo = 0;;) {} - `.expectToHaveDiagnostics(); + `.expectDiagnosticsToMatchSnapshot(); }); test("var declaration in for...in loop is disallowed", () => { util.testFunction` for (var foo in {}) {} - `.expectToHaveDiagnostics(); + `.expectDiagnosticsToMatchSnapshot(); }); test("var declaration in for...of loop is disallowed", () => { util.testFunction` for (var foo of []) {} - `.expectToHaveDiagnostics(); + `.expectDiagnosticsToMatchSnapshot(); }); test.each(["let myvar;", "const myvar = null;", "const myvar = undefined;"])("Null assignments (%p)", declaration => { diff --git a/test/unit/classes/__snapshots__/classes.spec.ts.snap b/test/unit/classes/__snapshots__/classes.spec.ts.snap index f6d370e0c..0acca51b6 100644 --- a/test/unit/classes/__snapshots__/classes.spec.ts.snap +++ b/test/unit/classes/__snapshots__/classes.spec.ts.snap @@ -1,5 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`missing declaration name: code 1`] = ` +"require(\\"lualib_bundle\\"); +____ = __TS__Class() +____.name = \\"____\\" +function ____.prototype.____constructor(self) +end" +`; + +exports[`missing declaration name: diagnostics 1`] = `"main.ts(2,9): error TS1211: A class declaration without the 'default' modifier must have a name."`; + exports[`super without class: code 1`] = ` "local ____exports = {} ____exports.__result = ____.____constructor(self) diff --git a/test/unit/classes/classes.spec.ts b/test/unit/classes/classes.spec.ts index e0291c31d..3430e20c2 100644 --- a/test/unit/classes/classes.spec.ts +++ b/test/unit/classes/classes.spec.ts @@ -849,3 +849,9 @@ test("Class field override in subclass with constructors", () => { return (new Foo()).field + (new Bar()).field;`; expect(util.transpileAndExecute(code)).toBe("foobar"); }); + +test("missing declaration name", () => { + util.testModule` + class {} + `.expectDiagnosticsToMatchSnapshot(); +}); diff --git a/test/unit/functions/__snapshots__/functions.spec.ts.snap b/test/unit/functions/__snapshots__/functions.spec.ts.snap new file mode 100644 index 000000000..e1e5b49d2 --- /dev/null +++ b/test/unit/functions/__snapshots__/functions.spec.ts.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`missing declaration name: code 1`] = ` +"function ____(self) +end" +`; + +exports[`missing declaration name: diagnostics 1`] = `"main.ts(2,18): error TS1003: Identifier expected."`; diff --git a/test/unit/functions/functions.spec.ts b/test/unit/functions/functions.spec.ts index aab7b151a..c8a996739 100644 --- a/test/unit/functions/functions.spec.ts +++ b/test/unit/functions/functions.spec.ts @@ -496,3 +496,9 @@ test("named function expression reference", () => { return y(); `.expectToMatchJsResult(); }); + +test("missing declaration name", () => { + util.testModule` + function () {} + `.expectDiagnosticsToMatchSnapshot(); +}); diff --git a/test/unit/identifiers.spec.ts b/test/unit/identifiers.spec.ts index 25c346ddf..551ed6bae 100644 --- a/test/unit/identifiers.spec.ts +++ b/test/unit/identifiers.spec.ts @@ -101,6 +101,10 @@ test.each([ `.expectDiagnosticsToMatchSnapshot(); }); +test.each(["const x = ;", "({})[]"])("missing expression (%p)", statement => { + util.testModule(statement).expectDiagnosticsToMatchSnapshot(); +}); + test.each(validTsInvalidLuaNames)( "ambient identifier must be a valid lua identifier (object literal shorthand) (%p)", name => { From 0473f457b584e964de829ac119aa25484c2405b4 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Mon, 9 Mar 2020 18:31:57 +0000 Subject: [PATCH 33/42] Allow to specify expected diagnostic codes in matchers --- src/transformation/utils/diagnostics.ts | 27 ++++++++++++------- test/setup.ts | 26 ++++++++++++------ test/unit/bundle.spec.ts | 6 ++--- .../invalidFunctionAssignments.spec.ts | 26 +++++++++--------- .../__snapshots__/resolution.spec.ts.snap | 10 +++++++ test/unit/modules/resolution.spec.ts | 2 +- test/util.ts | 10 +++---- 7 files changed, 67 insertions(+), 40 deletions(-) create mode 100644 test/unit/modules/__snapshots__/resolution.spec.ts.snap diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index f783205f2..9705cf760 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -2,18 +2,25 @@ import * as ts from "typescript"; import { LuaTarget } from "../../CompilerOptions"; import { AnnotationKind } from "./annotations"; -const createDiagnosticFactory = ( +let diagnosticCodeCounter = 100000; +const createDiagnosticFactory = ( message: string | ((...args: TArgs) => string), category = ts.DiagnosticCategory.Error -) => (node: ts.Node, ...args: TArgs): ts.Diagnostic => ({ - file: node.getSourceFile(), - start: node.getStart(), - length: node.getWidth(), - category, - code: 0, - source: "typescript-to-lua", - messageText: typeof message === "string" ? message : message(...args), -}); +) => { + const code = diagnosticCodeCounter++; + return Object.assign( + (node: ts.Node, ...args: TArgs): ts.Diagnostic => ({ + file: node.getSourceFile(), + start: node.getStart(), + length: node.getWidth(), + category, + code, + source: "typescript-to-lua", + messageText: typeof message === "string" ? message : message(...args), + }), + { code } + ); +}; export const forbiddenForIn = createDiagnosticFactory(`Iterating over arrays with 'for ... in' is not allowed.`); diff --git a/test/setup.ts b/test/setup.ts index 97ddade65..bc3123703 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -4,13 +4,13 @@ import * as tstl from "../src"; declare global { namespace jest { interface Matchers { - toHaveDiagnostics(): R; + toHaveDiagnostics(expected?: number[]): R; } } } expect.extend({ - toHaveDiagnostics(diagnostics: ts.Diagnostic[]): jest.CustomMatcherResult { + toHaveDiagnostics(diagnostics: ts.Diagnostic[], expected?: number[]): jest.CustomMatcherResult { expect(diagnostics).toBeInstanceOf(Array); // @ts-ignore const matcherHint = this.utils.matcherHint("toHaveDiagnostics", undefined, "", this); @@ -20,14 +20,24 @@ expect.extend({ { getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" } ); + if (this.isNot && expected !== undefined) { + throw new Error(`expect(actual).not.toHaveDiagnostics(expected) is not supported`); + } + return { - pass: diagnostics.length > 0, + pass: expected + ? diagnostics.length === expected.length && + diagnostics.every((diag, index) => diag.code === expected[index]) + : diagnostics.length > 0, + message: () => { - return ( - matcherHint + - "\n\n" + - (this.isNot ? diagnosticMessages : `Received: ${this.utils.printReceived(diagnostics)}\n`) - ); + const message = this.isNot + ? diagnosticMessages + : expected + ? `Expected:\n${expected.join("\n")}\nReceived:\n${diagnosticMessages}\n` + : `Received: ${this.utils.printReceived([])}\n`; + + return matcherHint + "\n\n" + message; }, }; }, diff --git a/test/unit/bundle.spec.ts b/test/unit/bundle.spec.ts index ca58b778d..b6abf4ae1 100644 --- a/test/unit/bundle.spec.ts +++ b/test/unit/bundle.spec.ts @@ -90,7 +90,7 @@ test("LuaLibImportKind.Inline generates a warning", () => { result.push(3); ` .setOptions({ luaLibImport: LuaLibImportKind.Inline }) - .expectDiagnosticsToMatchSnapshot(true) + .expectDiagnosticsToMatchSnapshot(undefined, true) .expectToEqual({ result: [1, 2, 3] }); }); @@ -113,9 +113,9 @@ test("cyclic imports", () => { }); test("no entry point", () => { - util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot(true); + util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot(undefined, true); }); test("luaEntry doesn't exist", () => { - util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot(true); + util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot(undefined, true); }); diff --git a/test/unit/functions/validation/invalidFunctionAssignments.spec.ts b/test/unit/functions/validation/invalidFunctionAssignments.spec.ts index b08b5a66d..cf20aaefd 100644 --- a/test/unit/functions/validation/invalidFunctionAssignments.spec.ts +++ b/test/unit/functions/validation/invalidFunctionAssignments.spec.ts @@ -7,7 +7,7 @@ test.each(invalidTestFunctionAssignments)( util.testModule` ${testFunction.definition || ""} const fn: ${functionType} = ${testFunction.value}; - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); } ); @@ -16,7 +16,7 @@ test.each(invalidTestFunctionAssignments)("Invalid function assignment (%p)", (t ${testFunction.definition || ""} let fn: ${functionType}; fn = ${testFunction.value}; - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test.each(invalidTestFunctionCasts)("Invalid function assignment with cast (%p)", (testFunction, castedFunction) => { @@ -24,7 +24,7 @@ test.each(invalidTestFunctionCasts)("Invalid function assignment with cast (%p)" ${testFunction.definition || ""} let fn: typeof ${testFunction.value}; fn = ${castedFunction}; - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test.each(invalidTestFunctionAssignments)("Invalid function argument (%p)", (testFunction, functionType) => { @@ -32,7 +32,7 @@ test.each(invalidTestFunctionAssignments)("Invalid function argument (%p)", (tes ${testFunction.definition || ""} declare function takesFunction(fn: ${functionType}); takesFunction(${testFunction.value}); - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test("Invalid lua lib function argument", () => { @@ -40,7 +40,7 @@ test("Invalid lua lib function argument", () => { declare function foo(this: void, value: string): void; declare const a: string[]; a.forEach(foo); - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test.each(invalidTestFunctionCasts)("Invalid function argument with cast (%p)", (testFunction, castedFunction) => { @@ -48,7 +48,7 @@ test.each(invalidTestFunctionCasts)("Invalid function argument with cast (%p)", ${testFunction.definition || ""} declare function takesFunction(fn: typeof ${testFunction.value}); takesFunction(${castedFunction}); - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test.each(invalidTestFunctionAssignments)("Invalid function generic argument (%p)", (testFunction, functionType) => { @@ -56,7 +56,7 @@ test.each(invalidTestFunctionAssignments)("Invalid function generic argument (%p ${testFunction.definition || ""} declare function takesFunction(fn: T); takesFunction(${testFunction.value}); - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test.each(invalidTestFunctionAssignments)("Invalid function return (%p)", (testFunction, functionType) => { @@ -65,7 +65,7 @@ test.each(invalidTestFunctionAssignments)("Invalid function return (%p)", (testF function returnsFunction(): ${functionType} { return ${testFunction.value}; } - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test.each(invalidTestFunctionCasts)("Invalid function return with cast (%p)", (testFunction, castedFunction) => { @@ -74,7 +74,7 @@ test.each(invalidTestFunctionCasts)("Invalid function return with cast (%p)", (t function returnsFunction(): typeof ${testFunction.value} { return ${castedFunction}; } - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test("Invalid function tuple assignment", () => { @@ -83,7 +83,7 @@ test("Invalid function tuple assignment", () => { interface Meth { (this: {}, s: string): string; } declare function getTuple(): [number, Meth]; let [i, f]: [number, Func] = getTuple(); - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test("Invalid method tuple assignment", () => { @@ -92,7 +92,7 @@ test("Invalid method tuple assignment", () => { interface Meth { (this: {}, s: string): string; } declare function getTuple(): [number, Func]; let [i, f]: [number, Meth] = getTuple(); - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test("Invalid interface method assignment", () => { @@ -101,7 +101,7 @@ test("Invalid interface method assignment", () => { interface B { fn(this: void, s: string): string; } declare const a: A; const b: B = a; - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); test.each([ @@ -117,5 +117,5 @@ test.each([ } declare const o: O; let f: ${assignType} = o; - `.expectDiagnosticsToMatchSnapshot(true); + `.expectDiagnosticsToMatchSnapshot(undefined, true); }); diff --git a/test/unit/modules/__snapshots__/resolution.spec.ts.snap b/test/unit/modules/__snapshots__/resolution.spec.ts.snap new file mode 100644 index 000000000..d4228141d --- /dev/null +++ b/test/unit/modules/__snapshots__/resolution.spec.ts.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`doesn't resolve paths out of root dir: code 1`] = ` +"local ____exports = {} +local module = require(\\"../module\\") +local ____ = module +return ____exports" +`; + +exports[`doesn't resolve paths out of root dir: diagnostics 1`] = `"src/main.ts(2,33): error TSTL: Cannot create require path. Module '../module' does not exist within --rootDir."`; diff --git a/test/unit/modules/resolution.spec.ts b/test/unit/modules/resolution.spec.ts index 6c1dbe105..cdbf239fe 100644 --- a/test/unit/modules/resolution.spec.ts +++ b/test/unit/modules/resolution.spec.ts @@ -82,7 +82,7 @@ test("doesn't resolve paths out of root dir", () => { .setMainFileName("src/main.ts") .setOptions({ rootDir: "./src" }) .disableSemanticCheck() - .expectToHaveDiagnostics(); + .expectDiagnosticsToMatchSnapshot(); }); test.each([ diff --git a/test/util.ts b/test/util.ts index f9108070e..6a8909e18 100644 --- a/test/util.ts +++ b/test/util.ts @@ -9,7 +9,7 @@ import * as tstl from "../src"; export * from "./legacy-utils"; -export const nodeStub = ts.createNode(ts.SyntaxKind.Unknown); +export const nodeStub = ts.createNode(ts.SyntaxKind.Unknown, 0, 0); export function parseTypeScript( typescript: string, @@ -362,11 +362,11 @@ export abstract class TestBuilder { private diagnosticsChecked = false; - public expectToHaveDiagnostics(): this { + public expectToHaveDiagnostics(expected?: number[]): this { if (this.diagnosticsChecked) return this; this.diagnosticsChecked = true; - expect(this.getLuaDiagnostics()).toHaveDiagnostics(); + expect(this.getLuaDiagnostics()).toHaveDiagnostics(expected); return this; } @@ -411,8 +411,8 @@ export abstract class TestBuilder { return this; } - public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this { - this.expectToHaveDiagnostics(); + public expectDiagnosticsToMatchSnapshot(expected?: number[], diagnosticsOnly = false): this { + this.expectToHaveDiagnostics(expected); const diagnosticMessages = ts.formatDiagnostics( this.getLuaDiagnostics().map(tstl.prepareDiagnosticForFormatting), From 5ef5ff20108548559508e64c67e28135c2b259df Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Mar 2020 10:05:43 +0000 Subject: [PATCH 34/42] Add expected diagnostics to snapshot assertions --- src/transformation/utils/diagnostics.ts | 2 +- src/transformation/visitors/lua-table.ts | 1 + .../__snapshots__/expressions.spec.ts.snap | 4 +- .../__snapshots__/identifiers.spec.ts.snap | 8 - .../__snapshots__/luaTable.spec.ts.snap | 40 +- .../annotations/customConstructor.spec.ts | 3 +- test/unit/annotations/extension.spec.ts | 11 +- test/unit/annotations/forRange.spec.ts | 15 +- test/unit/annotations/luaIterator.spec.ts | 5 +- test/unit/annotations/luaTable.spec.ts | 50 +- test/unit/annotations/metaExtension.spec.ts | 5 +- test/unit/assignments.spec.ts | 9 +- .../__snapshots__/loading.spec.ts.snap | 2 +- test/unit/builtins/loading.spec.ts | 5 +- test/unit/classes/classes.spec.ts | 4 +- test/unit/classes/decorators.spec.ts | 3 +- test/unit/conditionals.spec.ts | 3 +- test/unit/expressions.spec.ts | 5 +- test/unit/functions/functions.spec.ts | 2 +- .../invalidFunctionAssignments.spec.ts.snap | 664 +++++++++--------- .../validation/functionPermutations.ts | 42 +- .../invalidFunctionAssignments.spec.ts | 104 ++- test/unit/identifiers.spec.ts | 15 +- test/unit/loops.spec.ts | 5 +- test/unit/modules/resolution.spec.ts | 3 +- 25 files changed, 531 insertions(+), 479 deletions(-) diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index 9705cf760..331d2cb11 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -111,7 +111,7 @@ export const unsupportedAccessorInObjectLiteral = createDiagnosticFactory( export const unsupportedNullishCoalescing = createDiagnosticFactory("Nullish coalescing is not supported."); export const unsupportedRightShiftOperator = createDiagnosticFactory( - "Right shift operator is not supported. Use `>>>` instead." + "Right shift operator is not supported for target Lua 5.3. Use `>>>` instead." ); const getLuaTargetName = (version: LuaTarget) => (version === LuaTarget.LuaJIT ? "LuaJIT" : `Lua ${version}`); diff --git a/src/transformation/visitors/lua-table.ts b/src/transformation/visitors/lua-table.ts index c4f7e14ed..7647921c3 100644 --- a/src/transformation/visitors/lua-table.ts +++ b/src/transformation/visitors/lua-table.ts @@ -17,6 +17,7 @@ function validateLuaTableCall( for (const argument of callArguments) { if (ts.isSpreadElement(argument)) { context.diagnostics.push(luaTableForbiddenUsage(argument, "Arguments cannot be spread")); + return; } } diff --git a/test/unit/__snapshots__/expressions.spec.ts.snap b/test/unit/__snapshots__/expressions.spec.ts.snap index fe61f9e53..fd53ab8ac 100644 --- a/test/unit/__snapshots__/expressions.spec.ts.snap +++ b/test/unit/__snapshots__/expressions.spec.ts.snap @@ -534,7 +534,7 @@ end)() return ____exports" `; -exports[`Unsupported bitop 5.3 ("a>>=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Right shift operator is not supported. Use \`>>>\` instead."`; +exports[`Unsupported bitop 5.3 ("a>>=b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Right shift operator is not supported for target Lua 5.3. Use \`>>>\` instead."`; exports[`Unsupported bitop 5.3 ("a>>b"): code 1`] = ` "local ____exports = {} @@ -542,4 +542,4 @@ ____exports.__result = a >> b return ____exports" `; -exports[`Unsupported bitop 5.3 ("a>>b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Right shift operator is not supported. Use \`>>>\` instead."`; +exports[`Unsupported bitop 5.3 ("a>>b"): diagnostics 1`] = `"main.ts(1,25): error TSTL: Right shift operator is not supported for target Lua 5.3. Use \`>>>\` instead."`; diff --git a/test/unit/__snapshots__/identifiers.spec.ts.snap b/test/unit/__snapshots__/identifiers.spec.ts.snap index 5108c0198..6ab8a4433 100644 --- a/test/unit/__snapshots__/identifiers.spec.ts.snap +++ b/test/unit/__snapshots__/identifiers.spec.ts.snap @@ -128,14 +128,6 @@ exports[`ambient identifier must be a valid lua identifier (object literal short exports[`ambient identifier must be a valid lua identifier (object literal shorthand) ("ɥɣɎɌͼƛಠ"): diagnostics 1`] = `"main.ts(3,27): error TSTL: Invalid ambient identifier name 'ɥɣɎɌͼƛಠ'. Ambient identifiers must be valid lua identifiers."`; -exports[`missing expression ("({})[]"): code 1`] = `"local ____ = ({})[____]"`; - -exports[`missing expression ("({})[]"): diagnostics 1`] = `"main.ts(1,6): error TS1011: An element access expression should take an argument."`; - -exports[`missing expression ("const x = ;"): code 1`] = `"x = ____"`; - -exports[`missing expression ("const x = ;"): diagnostics 1`] = `"main.ts(1,11): error TS1109: Expression expected."`; - exports[`undeclared identifier must be a valid lua identifier ("$$"): code 1`] = `"foo = _____24_24_24"`; exports[`undeclared identifier must be a valid lua identifier ("$$"): diagnostics 1`] = `"main.ts(2,21): error TSTL: Invalid ambient identifier name '$$$'. Ambient identifiers must be valid lua identifiers."`; diff --git a/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap b/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap index aa7da24e1..5b7332187 100644 --- a/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap +++ b/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap @@ -29,17 +29,17 @@ exports[`Cannot isolate LuaTable method ("get"): code 1`] = `"property = tbl.get exports[`Cannot isolate LuaTable method ("get"): code 2`] = `"property = tbl.get"`; -exports[`Cannot isolate LuaTable method ("get"): diagnostics 1`] = `"main.ts(11,17): error TSTL: LuaTable.get is unsupported."`; +exports[`Cannot isolate LuaTable method ("get"): diagnostics 1`] = `"main.ts(11,21): error TSTL: LuaTable.get is unsupported."`; -exports[`Cannot isolate LuaTable method ("get"): diagnostics 2`] = `"main.ts(11,17): error TSTL: LuaTable.get is unsupported."`; +exports[`Cannot isolate LuaTable method ("get"): diagnostics 2`] = `"main.ts(11,21): error TSTL: LuaTable.get is unsupported."`; exports[`Cannot isolate LuaTable method ("set"): code 1`] = `"property = tbl.set"`; exports[`Cannot isolate LuaTable method ("set"): code 2`] = `"property = tbl.set"`; -exports[`Cannot isolate LuaTable method ("set"): diagnostics 1`] = `"main.ts(11,17): error TSTL: LuaTable.set is unsupported."`; +exports[`Cannot isolate LuaTable method ("set"): diagnostics 1`] = `"main.ts(11,21): error TSTL: LuaTable.set is unsupported."`; -exports[`Cannot isolate LuaTable method ("set"): diagnostics 2`] = `"main.ts(11,17): error TSTL: LuaTable.set is unsupported."`; +exports[`Cannot isolate LuaTable method ("set"): diagnostics 2`] = `"main.ts(11,21): error TSTL: LuaTable.set is unsupported."`; exports[`Cannot set LuaTable length: code 1`] = `"tbl.length = 2"`; @@ -108,15 +108,9 @@ exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): cod exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): code 2`] = `"tbl[table.unpack({\\"field\\", 0})] = nil"`; -exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 1`] = ` -"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1. -main.ts(11,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread." -`; +exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 1`] = `"main.ts(11,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; -exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 2`] = ` -"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1. -main.ts(11,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread." -`; +exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 2`] = `"main.ts(11,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): code 1`] = `"tbl.field = nil"`; @@ -138,15 +132,9 @@ exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): code 1`] = `"tbl exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): code 2`] = `"tbl.field = 0"`; -exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 1`] = ` -"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3. -main.ts(11,21): error TS2554: Expected 0-2 arguments, but got 3." -`; +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3."`; -exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 2`] = ` -"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3. -main.ts(11,21): error TS2554: Expected 0-2 arguments, but got 3." -`; +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3."`; exports[`LuaTable classes must be ambient ("/** @luaTable */ class Table {}"): code 1`] = ` "require(\\"lualib_bundle\\"); @@ -188,9 +176,9 @@ exports[`LuaTable set() cannot be used in a LuaTable call expression: code 1`] = exports[`LuaTable set() cannot be used in a LuaTable call expression: code 2`] = `"exp = tbl:set(\\"value\\", 5)"`; -exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 1`] = `"main.ts(11,13): error TSTL: LuaTable.set is unsupported."`; +exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 1`] = `"main.ts(11,17): error TSTL: LuaTable.set is unsupported."`; -exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 2`] = `"main.ts(11,13): error TSTL: LuaTable.set is unsupported."`; +exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 2`] = `"main.ts(11,17): error TSTL: LuaTable.set is unsupported."`; exports[`LuaTables cannot be constructed with arguments: code 1`] = `"____table = {}"`; @@ -204,10 +192,10 @@ exports[`LuaTables cannot have other members: code 3`] = `"x = tbl:other()"`; exports[`LuaTables cannot have other members: code 4`] = `"x = tbl:other()"`; -exports[`LuaTables cannot have other members: diagnostics 1`] = `"main.ts(11,1): error TSTL: LuaTable.other is unsupported."`; +exports[`LuaTables cannot have other members: diagnostics 1`] = `"main.ts(11,5): error TSTL: LuaTable.other is unsupported."`; -exports[`LuaTables cannot have other members: diagnostics 2`] = `"main.ts(11,1): error TSTL: LuaTable.other is unsupported."`; +exports[`LuaTables cannot have other members: diagnostics 2`] = `"main.ts(11,5): error TSTL: LuaTable.other is unsupported."`; -exports[`LuaTables cannot have other members: diagnostics 3`] = `"main.ts(11,9): error TSTL: LuaTable.other is unsupported."`; +exports[`LuaTables cannot have other members: diagnostics 3`] = `"main.ts(11,13): error TSTL: LuaTable.other is unsupported."`; -exports[`LuaTables cannot have other members: diagnostics 4`] = `"main.ts(11,9): error TSTL: LuaTable.other is unsupported."`; +exports[`LuaTables cannot have other members: diagnostics 4`] = `"main.ts(11,13): error TSTL: LuaTable.other is unsupported."`; diff --git a/test/unit/annotations/customConstructor.spec.ts b/test/unit/annotations/customConstructor.spec.ts index 035ec56fc..cd77bcca6 100644 --- a/test/unit/annotations/customConstructor.spec.ts +++ b/test/unit/annotations/customConstructor.spec.ts @@ -1,3 +1,4 @@ +import { annotationInvalidArgumentCount } from "../../../src/transformation/utils/diagnostics"; import * as util from "../../util"; test("CustomCreate", () => { @@ -29,5 +30,5 @@ test("IncorrectUsage", () => { class Point2D {} new Point2D(); - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([annotationInvalidArgumentCount.code]); }); diff --git a/test/unit/annotations/extension.spec.ts b/test/unit/annotations/extension.spec.ts index aa297f744..c8da1b81b 100644 --- a/test/unit/annotations/extension.spec.ts +++ b/test/unit/annotations/extension.spec.ts @@ -1,3 +1,8 @@ +import { + extensionCannotConstruct, + extensionCannotExtend, + extensionInvalidInstanceOf, +} from "../../../src/transformation/utils/diagnostics"; import * as util from "../../util"; test.each(["extension", "metaExtension"])("Class extends extension (%p)", extensionType => { @@ -6,7 +11,7 @@ test.each(["extension", "metaExtension"])("Class extends extension (%p)", extens /** @${extensionType} **/ class B extends A {} class C extends B {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([extensionCannotExtend.code]); }); test.each(["extension", "metaExtension"])("Class construct extension (%p)", extensionType => { @@ -15,7 +20,7 @@ test.each(["extension", "metaExtension"])("Class construct extension (%p)", exte /** @${extensionType} **/ class B extends A {} const b = new B(); - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([extensionCannotConstruct.code]); }); test.each(["extension", "metaExtension"])("instanceof extension (%p)", extensionType => { @@ -25,5 +30,5 @@ test.each(["extension", "metaExtension"])("instanceof extension (%p)", extension class B extends A {} declare const foo: any; const result = foo instanceof B; - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([extensionInvalidInstanceOf.code]); }); diff --git a/test/unit/annotations/forRange.spec.ts b/test/unit/annotations/forRange.spec.ts index 1d6dd4198..661c45253 100644 --- a/test/unit/annotations/forRange.spec.ts +++ b/test/unit/annotations/forRange.spec.ts @@ -1,3 +1,4 @@ +import { invalidForRangeCall } from "../../../src/transformation/utils/diagnostics"; import * as util from "../../util"; const createForRangeDeclaration = (args = "i: number, j: number, k?: number", returns = "number[]") => ` @@ -28,14 +29,14 @@ describe("invalid usage", () => { util.testModule` /** @forRange */ function luaRange() {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidForRangeCall.code]); }); test.each<[number[]]>([[[]], [[1]], [[1, 2, 3, 4]]])("argument count (%p)", args => { util.testModule` ${createForRangeDeclaration("...args: number[]")} for (const i of luaRange(${args})) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidForRangeCall.code]); }); test("non-declared loop variable", () => { @@ -43,28 +44,28 @@ describe("invalid usage", () => { ${createForRangeDeclaration()} let i: number; for (i of luaRange(1, 10, 2)) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidForRangeCall.code]); }); test("argument types", () => { util.testModule` ${createForRangeDeclaration("i: string, j: number")} for (const i of luaRange("foo", 2)) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidForRangeCall.code]); }); test("variable destructuring", () => { util.testModule` ${createForRangeDeclaration(undefined, "number[][]")} for (const [i] of luaRange(1, 10, 2)) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidForRangeCall.code]); }); test("return type", () => { util.testModule` ${createForRangeDeclaration(undefined, "string[]")} for (const i of luaRange(1, 10)) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidForRangeCall.code]); }); test.each([ @@ -77,6 +78,6 @@ describe("invalid usage", () => { util.testModule` ${createForRangeDeclaration()} ${statement} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidForRangeCall.code]); }); }); diff --git a/test/unit/annotations/luaIterator.spec.ts b/test/unit/annotations/luaIterator.spec.ts index 3804bf6bb..46e324bc5 100644 --- a/test/unit/annotations/luaIterator.spec.ts +++ b/test/unit/annotations/luaIterator.spec.ts @@ -1,4 +1,5 @@ import * as util from "../../util"; +import { luaIteratorForbiddenUsage } from "../../../src/transformation/utils/diagnostics"; test("forof lua iterator", () => { const code = ` @@ -143,7 +144,7 @@ test("forof lua iterator tuple-return single variable", () => { interface Iter extends Iterable<[string, string]> {} declare function luaIter(): Iter; for (let x of luaIter()) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([luaIteratorForbiddenUsage.code]); }); test("forof lua iterator tuple-return single existing variable", () => { @@ -156,7 +157,7 @@ test("forof lua iterator tuple-return single existing variable", () => { declare function luaIter(): Iter; let x: [string, string]; for (x of luaIter()) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([luaIteratorForbiddenUsage.code]); }); test("forof forwarded lua iterator", () => { diff --git a/test/unit/annotations/luaTable.spec.ts b/test/unit/annotations/luaTable.spec.ts index 8f5b4d6ca..78b23d78d 100644 --- a/test/unit/annotations/luaTable.spec.ts +++ b/test/unit/annotations/luaTable.spec.ts @@ -1,12 +1,20 @@ +import { + luaTableCannotBeAccessedDynamically, + luaTableCannotBeExtended, + luaTableForbiddenUsage, + luaTableMustBeAmbient, + unsupportedProperty, + luaTableInvalidInstanceOf, +} from "../../../src/transformation/utils/diagnostics"; import * as util from "../../util"; const tableLibClass = ` /** @luaTable */ declare class Table { length: number; - constructor(notAllowed?: boolean); - set(key?: K, value?: V): void; - get(key?: K, notAllowed?: K): V; + constructor(notAllowed?: any); + set(key?: K, value?: V, notAllowed?: any): void; + get(key?: K, notAllowed?: any): V; other(): void; } declare let tbl: Table; @@ -17,31 +25,35 @@ const tableLibInterface = ` /** @luaTable */ declare interface Table { length: number; - constructor(notAllowed?: boolean); - set(key?: K, value?: V): void; - get(key?: K, notAllowed?: K): V; + constructor(notAllowed?: any); + set(key?: K, value?: V, notAllowed?: any): void; + get(key?: K, notAllowed?: any): V; other(): void; } declare let tbl: Table; `; test.each([tableLibClass])("LuaTables cannot be constructed with arguments", tableLib => { - util.testModule(tableLib + `const table = new Table(true);`).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + `const table = new Table(true);`).expectDiagnosticsToMatchSnapshot([ + luaTableForbiddenUsage.code, + ]); }); test.each([tableLibClass, tableLibInterface])( "LuaTable set() cannot be used in a LuaTable call expression", tableLib => { - util.testModule(tableLib + `const exp = tbl.set("value", 5)`).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + `const exp = tbl.set("value", 5)`).expectDiagnosticsToMatchSnapshot([ + unsupportedProperty.code, + ]); } ); test.each([tableLibClass, tableLibInterface])("LuaTables cannot have other members", tableLib => { - util.testModule(tableLib + `tbl.other()`).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + `tbl.other()`).expectDiagnosticsToMatchSnapshot([unsupportedProperty.code]); }); test.each([tableLibClass, tableLibInterface])("LuaTables cannot have other members", tableLib => { - util.testModule(tableLib + `let x = tbl.other()`).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + `let x = tbl.other()`).expectDiagnosticsToMatchSnapshot([unsupportedProperty.code]); }); test.each([tableLibClass])("LuaTable new", tableLib => { @@ -56,7 +68,7 @@ test.each([tableLibClass])("LuaTable length", tableLib => { }); test.each([tableLibClass, tableLibInterface])("Cannot set LuaTable length", tableLib => { - util.testModule(tableLib + `tbl.length = 2;`).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + `tbl.length = 2;`).expectDiagnosticsToMatchSnapshot([luaTableForbiddenUsage.code]); }); test.each([tableLibClass, tableLibInterface])("Forbidden LuaTable use", tableLib => { @@ -69,7 +81,7 @@ test.each([tableLibClass, tableLibInterface])("Forbidden LuaTable use", tableLib 'tbl.set(...(["field", 0] as const))', 'tbl.set("field", ...([0] as const))', ])("Forbidden LuaTable use (%p)", invalidCode => { - util.testModule(tableLib + invalidCode).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + invalidCode).expectDiagnosticsToMatchSnapshot([luaTableForbiddenUsage.code]); }); }); @@ -77,7 +89,7 @@ test.each([tableLibClass])("Cannot extend LuaTable class", tableLib => { test.each([`class Ext extends Table {}`, `const c = class Ext extends Table {}`])( "Cannot extend LuaTable class (%p)", code => { - util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot([luaTableCannotBeExtended.code]); } ); }); @@ -87,12 +99,12 @@ test.each([ `/** @luaTable */ export class Table {}`, `/** @luaTable */ const c = class Table {}`, ])("LuaTable classes must be ambient (%p)", code => { - util.testModule(code).expectDiagnosticsToMatchSnapshot(); + util.testModule(code).expectDiagnosticsToMatchSnapshot([luaTableMustBeAmbient.code]); }); test.each([tableLibClass])("Cannot extend LuaTable class", tableLib => { test.each([`tbl instanceof Table`])("Cannot use instanceof on a LuaTable class (%p)", code => { - util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot([luaTableInvalidInstanceOf.code]); }); }); @@ -100,14 +112,18 @@ test.each([tableLibClass, tableLibInterface])("Cannot use ElementAccessExpressio test.each([`tbl["get"]("field")`, `tbl["set"]("field")`, `tbl["length"]`])( "Cannot use ElementAccessExpression on a LuaTable (%p)", code => { - util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot(); + util.testModule(tableLib + code).expectDiagnosticsToMatchSnapshot([ + luaTableCannotBeAccessedDynamically.code, + ]); } ); }); test.each([tableLibClass, tableLibInterface])("Cannot isolate LuaTable methods", tableLib => { test.each([`set`, `get`])("Cannot isolate LuaTable method (%p)", propertyName => { - util.testModule(`${tableLib} let property = tbl.${propertyName}`).expectDiagnosticsToMatchSnapshot(); + util.testModule(`${tableLib} let property = tbl.${propertyName}`).expectDiagnosticsToMatchSnapshot([ + unsupportedProperty.code, + ]); }); }); diff --git a/test/unit/annotations/metaExtension.spec.ts b/test/unit/annotations/metaExtension.spec.ts index c2a83b6fe..da0f1992a 100644 --- a/test/unit/annotations/metaExtension.spec.ts +++ b/test/unit/annotations/metaExtension.spec.ts @@ -1,3 +1,4 @@ +import { extensionCannotConstruct, metaExtensionMissingExtends } from "../../../src/transformation/utils/diagnostics"; import * as util from "../../util"; test("MetaExtension", () => { @@ -32,7 +33,7 @@ test("IncorrectUsage", () => { return 5; } } - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([metaExtensionMissingExtends.code]); }); test("DontAllowInstantiation", () => { @@ -41,5 +42,5 @@ test("DontAllowInstantiation", () => { /** @metaExtension */ class Ext extends _LOADED {} const e = new Ext(); - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([extensionCannotConstruct.code]); }); diff --git a/test/unit/assignments.spec.ts b/test/unit/assignments.spec.ts index 0d396fd66..1a8665464 100644 --- a/test/unit/assignments.spec.ts +++ b/test/unit/assignments.spec.ts @@ -1,3 +1,4 @@ +import { unsupportedVarDeclaration } from "../../src/transformation/utils/diagnostics"; import * as util from "../util"; test.each(["const", "let"])("%s declaration not top-level is not global", declarationKind => { @@ -21,25 +22,25 @@ test.each(["const", "let"])("%s declaration top-level is global", declarationKin test("var declaration is disallowed", () => { util.testFunction` var foo = true; - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([unsupportedVarDeclaration.code]); }); test("var declaration in for loop is disallowed", () => { util.testFunction` for (var foo = 0;;) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([unsupportedVarDeclaration.code]); }); test("var declaration in for...in loop is disallowed", () => { util.testFunction` for (var foo in {}) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([unsupportedVarDeclaration.code]); }); test("var declaration in for...of loop is disallowed", () => { util.testFunction` for (var foo of []) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([unsupportedVarDeclaration.code]); }); test.each(["let myvar;", "const myvar = null;", "const myvar = undefined;"])("Null assignments (%p)", declaration => { diff --git a/test/unit/builtins/__snapshots__/loading.spec.ts.snap b/test/unit/builtins/__snapshots__/loading.spec.ts.snap index 5f05babec..de7fb50b4 100644 --- a/test/unit/builtins/__snapshots__/loading.spec.ts.snap +++ b/test/unit/builtins/__snapshots__/loading.spec.ts.snap @@ -6,4 +6,4 @@ ____exports.__result = Math.unknownProperty return ____exports" `; -exports[`Unknown builtin property access: diagnostics 1`] = `"main.ts(1,25): error TSTL: Math.unknownProperty is unsupported."`; +exports[`Unknown builtin property access: diagnostics 1`] = `"main.ts(1,30): error TSTL: Math.unknownProperty is unsupported."`; diff --git a/test/unit/builtins/loading.spec.ts b/test/unit/builtins/loading.spec.ts index be63e98af..9284363be 100644 --- a/test/unit/builtins/loading.spec.ts +++ b/test/unit/builtins/loading.spec.ts @@ -1,4 +1,5 @@ import * as tstl from "../../../src"; +import { unsupportedProperty } from "../../../src/transformation/utils/diagnostics"; import * as util from "../../util"; describe("luaLibImport", () => { @@ -39,6 +40,8 @@ test("lualib should not include tstl header", () => { describe("Unknown builtin property", () => { test("access", () => { - util.testExpression`Math.unknownProperty`.disableSemanticCheck().expectDiagnosticsToMatchSnapshot(); + util.testExpression`Math.unknownProperty` + .disableSemanticCheck() + .expectDiagnosticsToMatchSnapshot([unsupportedProperty.code]); }); }); diff --git a/test/unit/classes/classes.spec.ts b/test/unit/classes/classes.spec.ts index 3430e20c2..0e6761fbc 100644 --- a/test/unit/classes/classes.spec.ts +++ b/test/unit/classes/classes.spec.ts @@ -237,7 +237,7 @@ test("Subclass constructor across merged namespace", () => { }); test("super without class", () => { - util.testExpression`super()`.expectDiagnosticsToMatchSnapshot(); + util.testExpression`super()`.expectDiagnosticsToMatchSnapshot([2337]); }); test("super in unnamed class", () => { @@ -853,5 +853,5 @@ test("Class field override in subclass with constructors", () => { test("missing declaration name", () => { util.testModule` class {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([1211]); }); diff --git a/test/unit/classes/decorators.spec.ts b/test/unit/classes/decorators.spec.ts index e64bec99d..ad77a3a11 100644 --- a/test/unit/classes/decorators.spec.ts +++ b/test/unit/classes/decorators.spec.ts @@ -1,3 +1,4 @@ +import { decoratorInvalidContext } from "../../../src/transformation/utils/diagnostics"; import * as util from "../../util"; test("Class decorator with no parameters", () => { @@ -108,7 +109,7 @@ test("Throws error if decorator function has void context", () => { @decorator class TestClass {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([decoratorInvalidContext.code]); }); test("Exported class decorator", () => { diff --git a/test/unit/conditionals.spec.ts b/test/unit/conditionals.spec.ts index 5af98ce95..890c6dc71 100644 --- a/test/unit/conditionals.spec.ts +++ b/test/unit/conditionals.spec.ts @@ -1,4 +1,5 @@ import * as tstl from "../../src"; +import { unsupportedForTarget } from "../../src/transformation/utils/diagnostics"; import * as util from "../util"; test.each([0, 1])("if (%p)", inp => { @@ -344,7 +345,7 @@ test("switch not allowed in 5.1", () => { switch ("abc") {} ` .setOptions({ luaTarget: tstl.LuaTarget.Lua51 }) - .expectDiagnosticsToMatchSnapshot(); + .expectDiagnosticsToMatchSnapshot([unsupportedForTarget.code]); }); test.each([ diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index 559d74d3d..90211b78c 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -1,4 +1,5 @@ import * as tstl from "../../src"; +import { unsupportedForTarget, unsupportedRightShiftOperator } from "../../src/transformation/utils/diagnostics"; import * as util from "../util"; // TODO: @@ -65,7 +66,7 @@ test.each(allBinaryOperators)("Bitop [5.1] (%p)", input => { util.testExpression(input) .setOptions({ luaTarget: tstl.LuaTarget.Lua51, luaLibImport: tstl.LuaLibImportKind.None }) .disableSemanticCheck() - .expectDiagnosticsToMatchSnapshot(); + .expectDiagnosticsToMatchSnapshot([unsupportedForTarget.code]); }); test.each(allBinaryOperators)("Bitop [JIT] (%p)", input => { @@ -93,7 +94,7 @@ test.each(unsupportedIn53)("Unsupported bitop 5.3 (%p)", input => { util.testExpression(input) .setOptions({ luaTarget: tstl.LuaTarget.Lua53, luaLibImport: tstl.LuaLibImportKind.None }) .disableSemanticCheck() - .expectDiagnosticsToMatchSnapshot(); + .expectDiagnosticsToMatchSnapshot([unsupportedRightShiftOperator.code]); }); test.each(["1+1", "-1+1", "1*30+4", "1*(3+4)", "1*(3+4*2)", "10-(4+5)"])( diff --git a/test/unit/functions/functions.spec.ts b/test/unit/functions/functions.spec.ts index c8a996739..d664ab061 100644 --- a/test/unit/functions/functions.spec.ts +++ b/test/unit/functions/functions.spec.ts @@ -500,5 +500,5 @@ test("named function expression reference", () => { test("missing declaration name", () => { util.testModule` function () {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([1003]); }); diff --git a/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap b/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap index 06ab4a8b4..5147e6055 100644 --- a/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap +++ b/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap @@ -1,78 +1,78 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Invalid function argument ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } - namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { method() { return function(s: string) { return s; } } } - const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } - const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } - const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } - const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } - const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { static noSelfStaticFuncProp: (s: string) => string = s => s; - }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { static noSelfStaticFuncProp: (s: string) => string = s => s; - }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { static noSelfStaticMethod(s: string): string { return s; } - }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { static noSelfStaticMethod(s: string): string { return s; } - }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } const noSelfFuncPropInterface: NoSelfFuncPropInterface = { noSelfFuncProp: (s: string): string => s - };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } const noSelfFuncPropInterface: NoSelfFuncPropInterface = { noSelfFuncProp: (s: string): string => s - };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } const noSelfMethodInterface: NoSelfMethodInterface = { noSelfMethod: function(s: string): string { return s; } - };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } const noSelfMethodInterface: NoSelfMethodInterface = { noSelfMethod: function(s: string): string { return s; } - };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { export class AnonFunctionNestedInClass { @@ -80,7 +80,7 @@ exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace Ano } } const anonFunctionNestedInClassInNoSelfNs = - (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { export class AnonFunctionNestedInClass { @@ -88,14 +88,14 @@ exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace Ano } } const anonFunctionNestedInClassInNoSelfNs = - (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { export class MethodClass { method(s: string): string { return s; } } } - const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { export interface MethodInterface { @@ -104,217 +104,217 @@ exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace Ano } const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { method: function(s: string): string { return s; } - };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } - }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } - }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } - }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } - }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { export let noSelfNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { export let noSelfNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { method() { return function(s: string) { return s; } } } - const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { export function noSelfInFileNsFunc(s: string) { return s; } - }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { export let noSelfInFileNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } - const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } - const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } - const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "class AnonStaticFuncPropClass { static anonStaticFuncProp: (s: string) => string = s => s; - }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function argument ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } - const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } - const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class StaticFuncPropClass { static staticFuncProp: (this: any, s: string) => string = s => s; - }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "class StaticMethodClass { static staticMethod(this: any, s: string): string { return s; } - }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "class StaticVoidFuncPropClass { static staticVoidFuncProp: (this: void, s: string) => string = s => s; - }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class StaticVoidFuncPropClass { static staticVoidFuncProp: (this: void, s: string) => string = s => s; - }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class StaticVoidMethodClass { static staticVoidMethod(this: void, s: string): string { return s; } - }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class StaticVoidMethodClass { static staticVoidMethod(this: void, s: string): string { return s; } - }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class VoidFuncPropClass { voidFuncProp: (this: void, s: string) => string = s => s; } - const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class VoidFuncPropClass { voidFuncProp: (this: void, s: string) => string = s => s; } - const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class VoidMethodClass { voidMethod(this: void, s: string): string { return s; } } - const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "class VoidMethodClass { voidMethod(this: void, s: string): string { return s; } } - const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } - const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } const anonMethodInterface: AnonMethodInterface = { anonMethod: function(this: any, s: string): string { return s; } - };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } - const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "interface MethodInterface { method(this: any, s: string): string; } - const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "interface VoidFuncPropInterface { voidFuncProp: (this: void, s: string) => string; } const voidFuncPropInterface: VoidFuncPropInterface = { voidFuncProp: function(this: void, s: string): string { return s; } - };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "interface VoidFuncPropInterface { voidFuncProp: (this: void, s: string) => string; } const voidFuncPropInterface: VoidFuncPropInterface = { voidFuncProp: function(this: void, s: string): string { return s; } - };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "interface VoidMethodInterface { voidMethod(this: void, s: string): string; } const voidMethodInterface: VoidMethodInterface = { voidMethod(this: void, s: string): string { return s; } - };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "interface VoidMethodInterface { voidMethod(this: void, s: string): string; } const voidMethodInterface: VoidMethodInterface = { voidMethod(this: void, s: string): string { return s; } - };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function argument ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function argument ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function argument ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function argument ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "namespace FuncNestedNs { export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } - }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function argument ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "namespace LambdaNestedNs { export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } - }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "namespace LambdaNs { export let nsLambda: (s: string) => string = s => s; - }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function argument ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function argument ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function argument ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function argument with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = ` "main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. @@ -357,78 +357,78 @@ main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter t `; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } - namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { method() { return function(s: string) { return s; } } } - const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } - const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } - const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } - const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } - const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { static noSelfStaticFuncProp: (s: string) => string = s => s; - }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { static noSelfStaticFuncProp: (s: string) => string = s => s; - }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { static noSelfStaticMethod(s: string): string { return s; } - }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { static noSelfStaticMethod(s: string): string { return s; } - }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } const noSelfFuncPropInterface: NoSelfFuncPropInterface = { noSelfFuncProp: (s: string): string => s - };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } const noSelfFuncPropInterface: NoSelfFuncPropInterface = { noSelfFuncProp: (s: string): string => s - };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } const noSelfMethodInterface: NoSelfMethodInterface = { noSelfMethod: function(s: string): string { return s; } - };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } const noSelfMethodInterface: NoSelfMethodInterface = { noSelfMethod: function(s: string): string { return s; } - };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { export class AnonFunctionNestedInClass { @@ -436,7 +436,7 @@ exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace A } } const anonFunctionNestedInClassInNoSelfNs = - (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { export class AnonFunctionNestedInClass { @@ -444,14 +444,14 @@ exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace A } } const anonFunctionNestedInClassInNoSelfNs = - (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { export class MethodClass { method(s: string): string { return s; } } } - const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { export interface MethodInterface { @@ -460,217 +460,217 @@ exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace A } const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { method: function(s: string): string { return s; } - };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } - }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } - }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } - }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } - }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { export let noSelfNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { export let noSelfNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { method() { return function(s: string) { return s; } } } - const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { export function noSelfInFileNsFunc(s: string) { return s; } - }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { export let noSelfInFileNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } - const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } - const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } - const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "class AnonStaticFuncPropClass { static anonStaticFuncProp: (s: string) => string = s => s; - }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function assignment ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } - const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } - const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class StaticFuncPropClass { static staticFuncProp: (this: any, s: string) => string = s => s; - }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "class StaticMethodClass { static staticMethod(this: any, s: string): string { return s; } - }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "class StaticVoidFuncPropClass { static staticVoidFuncProp: (this: void, s: string) => string = s => s; - }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class StaticVoidFuncPropClass { static staticVoidFuncProp: (this: void, s: string) => string = s => s; - }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class StaticVoidMethodClass { static staticVoidMethod(this: void, s: string): string { return s; } - }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class StaticVoidMethodClass { static staticVoidMethod(this: void, s: string): string { return s; } - }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class VoidFuncPropClass { voidFuncProp: (this: void, s: string) => string = s => s; } - const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class VoidFuncPropClass { voidFuncProp: (this: void, s: string) => string = s => s; } - const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class VoidMethodClass { voidMethod(this: void, s: string): string { return s; } } - const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "class VoidMethodClass { voidMethod(this: void, s: string): string { return s; } } - const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } - const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } const anonMethodInterface: AnonMethodInterface = { anonMethod: function(this: any, s: string): string { return s; } - };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } - const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "interface MethodInterface { method(this: any, s: string): string; } - const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "interface VoidFuncPropInterface { voidFuncProp: (this: void, s: string) => string; } const voidFuncPropInterface: VoidFuncPropInterface = { voidFuncProp: function(this: void, s: string): string { return s; } - };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "interface VoidFuncPropInterface { voidFuncProp: (this: void, s: string) => string; } const voidFuncPropInterface: VoidFuncPropInterface = { voidFuncProp: function(this: void, s: string): string { return s; } - };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "interface VoidMethodInterface { voidMethod(this: void, s: string): string; } const voidMethodInterface: VoidMethodInterface = { voidMethod(this: void, s: string): string { return s; } - };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "interface VoidMethodInterface { voidMethod(this: void, s: string): string; } const voidMethodInterface: VoidMethodInterface = { voidMethod(this: void, s: string): string { return s; } - };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function assignment ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function assignment ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function assignment ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function assignment ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "namespace FuncNestedNs { export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } - }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function assignment ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "namespace LambdaNestedNs { export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } - }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "namespace LambdaNs { export let nsLambda: (s: string) => string = s => s; - }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function assignment ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function assignment ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function assignment ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function assignment ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function assignment ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function assignment ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,18): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function assignment with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = ` "main.ts(4,14): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. @@ -713,78 +713,78 @@ main.ts(4,14): error TSTL: Unable to convert function with no 'this' parameter t `; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } - namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { method() { return function(s: string) { return s; } } } - const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } - const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } - const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } - const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } - const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { static noSelfStaticFuncProp: (s: string) => string = s => s; - }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { static noSelfStaticFuncProp: (s: string) => string = s => s; - }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { static noSelfStaticMethod(s: string): string { return s; } - }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { static noSelfStaticMethod(s: string): string { return s; } - }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } const noSelfFuncPropInterface: NoSelfFuncPropInterface = { noSelfFuncProp: (s: string): string => s - };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } const noSelfFuncPropInterface: NoSelfFuncPropInterface = { noSelfFuncProp: (s: string): string => s - };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } const noSelfMethodInterface: NoSelfMethodInterface = { noSelfMethod: function(s: string): string { return s; } - };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } const noSelfMethodInterface: NoSelfMethodInterface = { noSelfMethod: function(s: string): string { return s; } - };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { export class AnonFunctionNestedInClass { @@ -792,7 +792,7 @@ exports[`Invalid function generic argument ({"definition": "/** @noSelf */ names } } const anonFunctionNestedInClassInNoSelfNs = - (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { export class AnonFunctionNestedInClass { @@ -800,14 +800,14 @@ exports[`Invalid function generic argument ({"definition": "/** @noSelf */ names } } const anonFunctionNestedInClassInNoSelfNs = - (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { export class MethodClass { method(s: string): string { return s; } } } - const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { export interface MethodInterface { @@ -816,217 +816,217 @@ exports[`Invalid function generic argument ({"definition": "/** @noSelf */ names } const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { method: function(s: string): string { return s; } - };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } - }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } - }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } - }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } - }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { export let noSelfNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { export let noSelfNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { method() { return function(s: string) { return s; } } } - const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { export function noSelfInFileNsFunc(s: string) { return s; } - }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { export let noSelfInFileNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } - const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } - const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } - const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "class AnonStaticFuncPropClass { static anonStaticFuncProp: (s: string) => string = s => s; - }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function generic argument ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } - const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } - const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class StaticFuncPropClass { static staticFuncProp: (this: any, s: string) => string = s => s; - }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "class StaticMethodClass { static staticMethod(this: any, s: string): string { return s; } - }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "class StaticVoidFuncPropClass { static staticVoidFuncProp: (this: void, s: string) => string = s => s; - }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class StaticVoidFuncPropClass { static staticVoidFuncProp: (this: void, s: string) => string = s => s; - }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class StaticVoidMethodClass { static staticVoidMethod(this: void, s: string): string { return s; } - }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class StaticVoidMethodClass { static staticVoidMethod(this: void, s: string): string { return s; } - }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class VoidFuncPropClass { voidFuncProp: (this: void, s: string) => string = s => s; } - const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class VoidFuncPropClass { voidFuncProp: (this: void, s: string) => string = s => s; } - const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class VoidMethodClass { voidMethod(this: void, s: string): string { return s; } } - const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "class VoidMethodClass { voidMethod(this: void, s: string): string { return s; } } - const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } - const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } const anonMethodInterface: AnonMethodInterface = { anonMethod: function(this: any, s: string): string { return s; } - };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } - const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "interface MethodInterface { method(this: any, s: string): string; } - const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "interface VoidFuncPropInterface { voidFuncProp: (this: void, s: string) => string; } const voidFuncPropInterface: VoidFuncPropInterface = { voidFuncProp: function(this: void, s: string): string { return s; } - };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "interface VoidFuncPropInterface { voidFuncProp: (this: void, s: string) => string; } const voidFuncPropInterface: VoidFuncPropInterface = { voidFuncProp: function(this: void, s: string): string { return s; } - };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "interface VoidMethodInterface { voidMethod(this: void, s: string): string; } const voidMethodInterface: VoidMethodInterface = { voidMethod(this: void, s: string): string { return s; } - };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "interface VoidMethodInterface { voidMethod(this: void, s: string): string; } const voidMethodInterface: VoidMethodInterface = { voidMethod(this: void, s: string): string { return s; } - };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function generic argument ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function generic argument ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function generic argument ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function generic argument ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "namespace FuncNestedNs { export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } - }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function generic argument ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "namespace LambdaNestedNs { export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } - }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "namespace LambdaNs { export let nsLambda: (s: string) => string = s => s; - }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function generic argument ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function generic argument ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function generic argument ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function generic argument ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with a 'this' parameter to function 'fn' with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function generic argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function generic argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,23): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function generic argument ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,27): error TSTL: Unable to convert function with no 'this' parameter to function 'fn' with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function overload assignment ("(this: void, s: string) => string"): diagnostics 1`] = `"main.ts(7,52): error TSTL: Unsupported assignment of function with different overloaded types for 'this'. Overloads should all have the same type for 'this'."`; @@ -1037,78 +1037,78 @@ exports[`Invalid function overload assignment ("{(this: any, s1: string, s2: str exports[`Invalid function overload assignment ("{(this: void, s: string): string}"): diagnostics 1`] = `"main.ts(7,52): error TSTL: Unsupported assignment of function with different overloaded types for 'this'. Overloads should all have the same type for 'this'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class AnonFuncNSMergedNoSelfClass { method(s: string): string { return s; } } - namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + namespace AnonFuncNSMergedNoSelfClass { export function nsFunc(s: string) { return s; } }", "value": "AnonFuncNSMergedNoSelfClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class AnonFunctionNestedInNoSelfClass { method() { return function(s: string) { return s; } } } - const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFunctionNestedInNoSelfClass = (new AnonFunctionNestedInNoSelfClass).method();", "value": "anonFunctionNestedInNoSelfClass"}): diagnostics 1`] = `"main.ts(7,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } - const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfAnonMethodClassMergedNS { method(s: string): string { return s; } } namespace NoSelfAnonMethodClassMergedNS { export function nsFunc(s: string) { return s; } } - const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfAnonMethodClassMergedNS = new NoSelfAnonMethodClassMergedNS();", "value": "noSelfAnonMethodClassMergedNS.method"}): diagnostics 2`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } - const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfFuncPropClass { noSelfFuncProp: (s: string) => string = s => s; } - const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfFuncPropClass = new NoSelfFuncPropClass();", "value": "noSelfFuncPropClass.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(5,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfMethodClass { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClass = new NoSelfMethodClass();", "value": "noSelfMethodClass.noSelfMethod"}): diagnostics 2`] = `"main.ts(5,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { static noSelfStaticFuncProp: (s: string) => string = s => s; - }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfStaticFuncPropClass { static noSelfStaticFuncProp: (s: string) => string = s => s; - }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticFuncPropClass.noSelfStaticFuncProp"}): diagnostics 2`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { static noSelfStaticMethod(s: string): string { return s; } - }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ class NoSelfStaticMethodClass { static noSelfStaticMethod(s: string): string { return s; } - }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfStaticMethodClass.noSelfStaticMethod"}): diagnostics 2`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ const NoSelfMethodClassExpression = class { noSelfMethod(s: string): string { return s; } } - const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfMethodClassExpression = new NoSelfMethodClassExpression();", "value": "noSelfMethodClassExpression.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } const noSelfFuncPropInterface: NoSelfFuncPropInterface = { noSelfFuncProp: (s: string): string => s - };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 1`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ interface NoSelfFuncPropInterface { noSelfFuncProp(s: string): string; } const noSelfFuncPropInterface: NoSelfFuncPropInterface = { noSelfFuncProp: (s: string): string => s - };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfFuncPropInterface.noSelfFuncProp"}): diagnostics 2`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } const noSelfMethodInterface: NoSelfMethodInterface = { noSelfMethod: function(s: string): string { return s; } - };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 1`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ interface NoSelfMethodInterface { noSelfMethod(s: string): string; } const noSelfMethodInterface: NoSelfMethodInterface = { noSelfMethod: function(s: string): string { return s; } - };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "noSelfMethodInterface.noSelfMethod"}): diagnostics 2`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { export class AnonFunctionNestedInClass { @@ -1116,7 +1116,7 @@ exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonF } } const anonFunctionNestedInClassInNoSelfNs = - (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 1`] = `"main.ts(10,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonFunctionNestedInClassInNoSelfNs { export class AnonFunctionNestedInClass { @@ -1124,14 +1124,14 @@ exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonF } } const anonFunctionNestedInClassInNoSelfNs = - (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + (new AnonFunctionNestedInClassInNoSelfNs.AnonFunctionNestedInClass).method();", "value": "anonFunctionNestedInClassInNoSelfNs"}): diagnostics 2`] = `"main.ts(10,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonMethodClassInNoSelfNs { export class MethodClass { method(s: string): string { return s; } } } - const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClassInNoSelfNs = new AnonMethodClassInNoSelfNs.MethodClass();", "value": "anonMethodClassInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(9,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonMethodInterfaceInNoSelfNs { export interface MethodInterface { @@ -1140,217 +1140,217 @@ exports[`Invalid function return ({"definition": "/** @noSelf */ namespace AnonM } const anonMethodInterfaceInNoSelfNs: AnonMethodInterfaceInNoSelfNs.MethodInterface = { method: function(s: string): string { return s; } - };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + };", "value": "anonMethodInterfaceInNoSelfNs.method"}): diagnostics 1`] = `"main.ts(11,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } - }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNestedNs { export namespace NestedNs { export function noSelfNestedNsFunc(s: string) { return s; } } - }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfFuncNestedNs.NestedNs.noSelfNestedNsFunc"}): diagnostics 2`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfFuncNs { export function noSelfNsFunc(s: string) { return s; } }", "value": "NoSelfFuncNs.noSelfNsFunc"}): diagnostics 2`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } - }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfLambdaNestedNs { export namespace NestedNs { export let noSelfNestedNsLambda: (s: string) => string = s => s } - }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNestedNs.NestedNs.noSelfNestedNsLambda"}): diagnostics 2`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { export let noSelfNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelf */ namespace NoSelfLambdaNs { export let noSelfNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfLambdaNs.noSelfNsLambda"}): diagnostics 2`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelfInFile */ class NoSelfInFileFuncNestedInClass { method() { return function(s: string) { return s; } } } - const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const noSelfInFileFuncNestedInClass = (new NoSelfInFileFuncNestedInClass).method();", "value": "noSelfInFileFuncNestedInClass"}): diagnostics 1`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"definition": "/** @noSelfInFile */ let noSelfInFileLambda: (s: string) => string = s => s;", "value": "noSelfInFileLambda"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileFuncNs { export function noSelfInFileNsFunc(s: string) { return s; } - }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfInFileFuncNs.noSelfInFileNsFunc"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "/** @noSelfInFile */ namespace NoSelfInFileLambdaNs { export let noSelfInFileNsLambda: (s: string) => string = s => s; - }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "NoSelfInFileLambdaNs.noSelfInFileNsLambda"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class AnonFuncPropClass { anonFuncProp: (s: string) => string = s => s; } - const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFuncPropClass = new AnonFuncPropClass();", "value": "anonFuncPropClass.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "class AnonMethodClass { anonMethod(s: string): string { return s; } } - const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClass = new AnonMethodClass();", "value": "anonMethodClass.anonMethod"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "class AnonMethodClassMergedNoSelfNS { method(s: string): string { return s; } } /** @noSelf */ namespace AnonMethodClassMergedNoSelfNS { export function nsFunc(s: string) { return s; } } - const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonMethodClassMergedNoSelfNS = new AnonMethodClassMergedNoSelfNS();", "value": "anonMethodClassMergedNoSelfNS.method"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "class AnonStaticFuncPropClass { static anonStaticFuncProp: (s: string) => string = s => s; - }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "AnonStaticFuncPropClass.anonStaticFuncProp"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function return ({"definition": "class AnonStaticMethodClass { static anonStaticMethod(s: string): string { return s; } }", "value": "AnonStaticMethodClass.anonStaticMethod"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "class FuncPropClass { funcProp: (this: any, s: string) => string = s => s; } - const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const funcPropClass = new FuncPropClass();", "value": "funcPropClass.funcProp"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "class MethodClass { method(this: any, s: string): string { return s; } } - const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const methodClass = new MethodClass();", "value": "methodClass.method"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class NoSelfAnonFuncNSMergedClass { method(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedClass { export function nsFunc(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedClass.nsFunc"}): diagnostics 2`] = `"main.ts(5,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class StaticFuncPropClass { static staticFuncProp: (this: any, s: string) => string = s => s; - }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "StaticFuncPropClass.staticFuncProp"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "class StaticMethodClass { static staticMethod(this: any, s: string): string { return s; } - }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "StaticMethodClass.staticMethod"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "class StaticVoidFuncPropClass { static staticVoidFuncProp: (this: void, s: string) => string = s => s; - }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class StaticVoidFuncPropClass { static staticVoidFuncProp: (this: void, s: string) => string = s => s; - }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidFuncPropClass.staticVoidFuncProp"}): diagnostics 2`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class StaticVoidMethodClass { static staticVoidMethod(this: void, s: string): string { return s; } - }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class StaticVoidMethodClass { static staticVoidMethod(this: void, s: string): string { return s; } - }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + }", "value": "StaticVoidMethodClass.staticVoidMethod"}): diagnostics 2`] = `"main.ts(6,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class VoidFuncPropClass { voidFuncProp: (this: void, s: string) => string = s => s; } - const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 1`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class VoidFuncPropClass { voidFuncProp: (this: void, s: string) => string = s => s; } - const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidFuncPropClass = new VoidFuncPropClass();", "value": "voidFuncPropClass.voidFuncProp"}): diagnostics 2`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class VoidMethodClass { voidMethod(this: void, s: string): string { return s; } } - const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 1`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "class VoidMethodClass { voidMethod(this: void, s: string): string { return s; } } - const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + const voidMethodClass = new VoidMethodClass();", "value": "voidMethodClass.voidMethod"}): diagnostics 2`] = `"main.ts(7,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "interface AnonFuncPropInterface { anonFuncProp: (s: string) => string; } - const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const anonFuncPropInterface: AnonFuncPropInterface = { anonFuncProp: (s: string): string => s };", "value": "anonFuncPropInterface.anonFuncProp"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "interface AnonMethodInterface { anonMethod(s: string): string; } const anonMethodInterface: AnonMethodInterface = { anonMethod: function(this: any, s: string): string { return s; } - };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + };", "value": "anonMethodInterface.anonMethod"}): diagnostics 1`] = `"main.ts(7,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "interface FuncPropInterface { funcProp: (this: any, s: string) => string; } - const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const funcPropInterface: FuncPropInterface = { funcProp: function(this: any, s: string) { return s; } };", "value": "funcPropInterface.funcProp"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "interface MethodInterface { method(this: any, s: string): string; } - const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + const methodInterface: MethodInterface = { method: function(this: any, s: string): string { return s; } }", "value": "methodInterface.method"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "interface VoidFuncPropInterface { voidFuncProp: (this: void, s: string) => string; } const voidFuncPropInterface: VoidFuncPropInterface = { voidFuncProp: function(this: void, s: string): string { return s; } - };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 1`] = `"main.ts(9,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "interface VoidFuncPropInterface { voidFuncProp: (this: void, s: string) => string; } const voidFuncPropInterface: VoidFuncPropInterface = { voidFuncProp: function(this: void, s: string): string { return s; } - };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidFuncPropInterface.voidFuncProp"}): diagnostics 2`] = `"main.ts(9,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "interface VoidMethodInterface { voidMethod(this: void, s: string): string; } const voidMethodInterface: VoidMethodInterface = { voidMethod(this: void, s: string): string { return s; } - };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 1`] = `"main.ts(9,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "interface VoidMethodInterface { voidMethod(this: void, s: string): string; } const voidMethodInterface: VoidMethodInterface = { voidMethod(this: void, s: string): string { return s; } - };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + };", "value": "voidMethodInterface.voidMethod"}): diagnostics 2`] = `"main.ts(9,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function return ({"definition": "let anonFunc: {(s: string): string} = function(s) { return s; };", "value": "anonFunc"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function return ({"definition": "let anonLambda: (s: string) => string = s => s;", "value": "anonLambda"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function return ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function return ({"definition": "let selfLambda: (this: any, s: string) => string = s => s;", "value": "selfLambda"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"definition": "let voidLambda: (this: void, s: string) => string = s => s;", "value": "voidLambda"}): diagnostics 2`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "namespace FuncNestedNs { export namespace NestedNs { export function nestedNsFunc(s: string) { return s; } } - }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "FuncNestedNs.NestedNs.nestedNsFunc"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function return ({"definition": "namespace FuncNs { export function nsFunc(s: string) { return s; } }", "value": "FuncNs.nsFunc"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "namespace LambdaNestedNs { export namespace NestedNs { export let nestedNsLambda: (s: string) => string = s => s } - }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "LambdaNestedNs.NestedNs.nestedNsLambda"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "namespace LambdaNs { export let nsLambda: (s: string) => string = s => s; - }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + }", "value": "LambdaNs.nsLambda"}): diagnostics 1`] = `"main.ts(6,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; exports[`Invalid function return ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; + /** @noSelf */ namespace NoSelfAnonFuncNSMergedSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "NoSelfAnonFuncNSMergedSelfNS.nsFuncNoSelf"}): diagnostics 2`] = `"main.ts(5,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return ({"definition": "namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncSelf(s: string): string { return s; } } - /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; + /** @noSelf */ namespace SelfAnonFuncNSMergedNoSelfNS { export function nsFuncNoSelf(s: string) { return s; } }", "value": "SelfAnonFuncNSMergedNoSelfNS.nsFuncSelf"}): diagnostics 1`] = `"main.ts(5,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function return ({"value": "(function(this: any, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"value": "(function(this: void, s) { return s; })"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"value": "(function(this: void, s) { return s; })"}): diagnostics 2`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; +exports[`Invalid function return ({"value": "function(this: any, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'."`; -exports[`Invalid function return ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"value": "function(this: void, s) { return s; }"}): diagnostics 1`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; -exports[`Invalid function return ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; +exports[`Invalid function return ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = ` "main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. diff --git a/test/unit/functions/validation/functionPermutations.ts b/test/unit/functions/validation/functionPermutations.ts index b5e233d7c..c6c51be91 100644 --- a/test/unit/functions/validation/functionPermutations.ts +++ b/test/unit/functions/validation/functionPermutations.ts @@ -348,7 +348,11 @@ export const anonTestFunctionType = "(s: string) => string"; export const selfTestFunctionType = "(this: any, s: string) => string"; export const noSelfTestFunctionType = "(this: void, s: string) => string"; -type TestFunctionCast = [TestFunction, string]; +type TestFunctionCast = [ + /* testFunction: */ TestFunction, + /* castedFunction: */ string, + /* isSelfConversion?: */ boolean? +]; export const validTestFunctionCasts: TestFunctionCast[] = [ [selfTestFunctions[0], `<${anonTestFunctionType}>(${selfTestFunctions[0].value})`], [selfTestFunctions[0], `(${selfTestFunctions[0].value}) as (${anonTestFunctionType})`], @@ -362,17 +366,21 @@ export const validTestFunctionCasts: TestFunctionCast[] = [ [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${noSelfTestFunctionType})`], ]; export const invalidTestFunctionCasts: TestFunctionCast[] = [ - [noSelfTestFunctions[0], `<${anonTestFunctionType}>(${noSelfTestFunctions[0].value})`], - [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${anonTestFunctionType})`], - [noSelfTestFunctions[0], `<${selfTestFunctionType}>(${noSelfTestFunctions[0].value})`], - [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${selfTestFunctionType})`], - [noSelfInFileTestFunctions[0], `<${selfTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`], - [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${selfTestFunctionType})`], - [selfTestFunctions[0], `<${noSelfTestFunctionType}>(${selfTestFunctions[0].value})`], - [selfTestFunctions[0], `(${selfTestFunctions[0].value}) as (${noSelfTestFunctionType})`], + [noSelfTestFunctions[0], `<${anonTestFunctionType}>(${noSelfTestFunctions[0].value})`, false], + [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${anonTestFunctionType})`, false], + [noSelfTestFunctions[0], `<${selfTestFunctionType}>(${noSelfTestFunctions[0].value})`, false], + [noSelfTestFunctions[0], `(${noSelfTestFunctions[0].value}) as (${selfTestFunctionType})`, false], + [noSelfInFileTestFunctions[0], `<${selfTestFunctionType}>(${noSelfInFileTestFunctions[0].value})`, false], + [noSelfInFileTestFunctions[0], `(${noSelfInFileTestFunctions[0].value}) as (${selfTestFunctionType})`, false], + [selfTestFunctions[0], `<${noSelfTestFunctionType}>(${selfTestFunctions[0].value})`, true], + [selfTestFunctions[0], `(${selfTestFunctions[0].value}) as (${noSelfTestFunctionType})`, true], ]; -export type TestFunctionAssignment = [TestFunction, string]; +export type TestFunctionAssignment = [ + /* testFunction: */ TestFunction, + /* functionType: */ string, + /* isSelfConversion?: */ boolean? +]; export const validTestFunctionAssignments: TestFunctionAssignment[] = [ ...selfTestFunctions.map((f): TestFunctionAssignment => [f, anonTestFunctionType]), ...selfTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), @@ -387,11 +395,11 @@ export const validTestFunctionAssignments: TestFunctionAssignment[] = [ ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), ]; export const invalidTestFunctionAssignments: TestFunctionAssignment[] = [ - ...selfTestFunctions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), - ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, anonTestFunctionType]), - ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), - ...noSelfInFileTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), - ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType]), - ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, anonTestFunctionType]), - ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, selfTestFunctionType]), + ...selfTestFunctions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType, false]), + ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, anonTestFunctionType, true]), + ...noSelfTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), + ...noSelfInFileTestFunctions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), + ...selfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, noSelfTestFunctionType, false]), + ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, anonTestFunctionType, true]), + ...noSelfTestFunctionExpressions.map((f): TestFunctionAssignment => [f, selfTestFunctionType, true]), ]; diff --git a/test/unit/functions/validation/invalidFunctionAssignments.spec.ts b/test/unit/functions/validation/invalidFunctionAssignments.spec.ts index cf20aaefd..afabd7e6b 100644 --- a/test/unit/functions/validation/invalidFunctionAssignments.spec.ts +++ b/test/unit/functions/validation/invalidFunctionAssignments.spec.ts @@ -1,23 +1,37 @@ +import { + unsupportedOverloadAssignment, + unsupportedNoSelfFunctionConversion, + unsupportedSelfFunctionConversion, +} from "../../../../src/transformation/utils/diagnostics"; import * as util from "../../../util"; import { invalidTestFunctionAssignments, invalidTestFunctionCasts } from "./functionPermutations"; test.each(invalidTestFunctionAssignments)( "Invalid function variable declaration (%p)", - (testFunction, functionType) => { + (testFunction, functionType, isSelfConversion) => { util.testModule` ${testFunction.definition || ""} const fn: ${functionType} = ${testFunction.value}; - `.expectDiagnosticsToMatchSnapshot(undefined, true); + `.expectDiagnosticsToMatchSnapshot( + [isSelfConversion ? unsupportedSelfFunctionConversion.code : unsupportedNoSelfFunctionConversion.code], + true + ); } ); -test.each(invalidTestFunctionAssignments)("Invalid function assignment (%p)", (testFunction, functionType) => { - util.testModule` - ${testFunction.definition || ""} - let fn: ${functionType}; - fn = ${testFunction.value}; - `.expectDiagnosticsToMatchSnapshot(undefined, true); -}); +test.each(invalidTestFunctionAssignments)( + "Invalid function assignment (%p)", + (testFunction, functionType, isSelfConversion) => { + util.testModule` + ${testFunction.definition || ""} + let fn: ${functionType}; + fn = ${testFunction.value}; + `.expectDiagnosticsToMatchSnapshot( + [isSelfConversion ? unsupportedSelfFunctionConversion.code : unsupportedNoSelfFunctionConversion.code], + true + ); + } +); test.each(invalidTestFunctionCasts)("Invalid function assignment with cast (%p)", (testFunction, castedFunction) => { util.testModule` @@ -27,20 +41,26 @@ test.each(invalidTestFunctionCasts)("Invalid function assignment with cast (%p)" `.expectDiagnosticsToMatchSnapshot(undefined, true); }); -test.each(invalidTestFunctionAssignments)("Invalid function argument (%p)", (testFunction, functionType) => { - util.testModule` - ${testFunction.definition || ""} - declare function takesFunction(fn: ${functionType}); - takesFunction(${testFunction.value}); - `.expectDiagnosticsToMatchSnapshot(undefined, true); -}); +test.each(invalidTestFunctionAssignments)( + "Invalid function argument (%p)", + (testFunction, functionType, isSelfConversion) => { + util.testModule` + ${testFunction.definition || ""} + declare function takesFunction(fn: ${functionType}); + takesFunction(${testFunction.value}); + `.expectDiagnosticsToMatchSnapshot( + [isSelfConversion ? unsupportedSelfFunctionConversion.code : unsupportedNoSelfFunctionConversion.code], + true + ); + } +); test("Invalid lua lib function argument", () => { util.testModule` declare function foo(this: void, value: string): void; declare const a: string[]; a.forEach(foo); - `.expectDiagnosticsToMatchSnapshot(undefined, true); + `.expectDiagnosticsToMatchSnapshot([unsupportedSelfFunctionConversion.code], true); }); test.each(invalidTestFunctionCasts)("Invalid function argument with cast (%p)", (testFunction, castedFunction) => { @@ -51,22 +71,34 @@ test.each(invalidTestFunctionCasts)("Invalid function argument with cast (%p)", `.expectDiagnosticsToMatchSnapshot(undefined, true); }); -test.each(invalidTestFunctionAssignments)("Invalid function generic argument (%p)", (testFunction, functionType) => { - util.testModule` - ${testFunction.definition || ""} - declare function takesFunction(fn: T); - takesFunction(${testFunction.value}); - `.expectDiagnosticsToMatchSnapshot(undefined, true); -}); +test.each(invalidTestFunctionAssignments)( + "Invalid function generic argument (%p)", + (testFunction, functionType, isSelfConversion) => { + util.testModule` + ${testFunction.definition || ""} + declare function takesFunction(fn: T); + takesFunction(${testFunction.value}); + `.expectDiagnosticsToMatchSnapshot( + [isSelfConversion ? unsupportedSelfFunctionConversion.code : unsupportedNoSelfFunctionConversion.code], + true + ); + } +); -test.each(invalidTestFunctionAssignments)("Invalid function return (%p)", (testFunction, functionType) => { - util.testModule` - ${testFunction.definition || ""} - function returnsFunction(): ${functionType} { - return ${testFunction.value}; - } - `.expectDiagnosticsToMatchSnapshot(undefined, true); -}); +test.each(invalidTestFunctionAssignments)( + "Invalid function return (%p)", + (testFunction, functionType, isSelfConversion) => { + util.testModule` + ${testFunction.definition || ""} + function returnsFunction(): ${functionType} { + return ${testFunction.value}; + } + `.expectDiagnosticsToMatchSnapshot( + [isSelfConversion ? unsupportedSelfFunctionConversion.code : unsupportedNoSelfFunctionConversion.code], + true + ); + } +); test.each(invalidTestFunctionCasts)("Invalid function return with cast (%p)", (testFunction, castedFunction) => { util.testModule` @@ -83,7 +115,7 @@ test("Invalid function tuple assignment", () => { interface Meth { (this: {}, s: string): string; } declare function getTuple(): [number, Meth]; let [i, f]: [number, Func] = getTuple(); - `.expectDiagnosticsToMatchSnapshot(undefined, true); + `.expectDiagnosticsToMatchSnapshot([2322, unsupportedNoSelfFunctionConversion.code], true); }); test("Invalid method tuple assignment", () => { @@ -92,7 +124,7 @@ test("Invalid method tuple assignment", () => { interface Meth { (this: {}, s: string): string; } declare function getTuple(): [number, Func]; let [i, f]: [number, Meth] = getTuple(); - `.expectDiagnosticsToMatchSnapshot(undefined, true); + `.expectDiagnosticsToMatchSnapshot([unsupportedSelfFunctionConversion.code], true); }); test("Invalid interface method assignment", () => { @@ -101,7 +133,7 @@ test("Invalid interface method assignment", () => { interface B { fn(this: void, s: string): string; } declare const a: A; const b: B = a; - `.expectDiagnosticsToMatchSnapshot(undefined, true); + `.expectDiagnosticsToMatchSnapshot([unsupportedNoSelfFunctionConversion.code], true); }); test.each([ @@ -117,5 +149,5 @@ test.each([ } declare const o: O; let f: ${assignType} = o; - `.expectDiagnosticsToMatchSnapshot(undefined, true); + `.expectDiagnosticsToMatchSnapshot([unsupportedOverloadAssignment.code], true); }); diff --git a/test/unit/identifiers.spec.ts b/test/unit/identifiers.spec.ts index 551ed6bae..842c9f4c8 100644 --- a/test/unit/identifiers.spec.ts +++ b/test/unit/identifiers.spec.ts @@ -1,3 +1,4 @@ +import { invalidAmbientIdentifierName } from "../../src/transformation/utils/diagnostics"; import { luaKeywords } from "../../src/transformation/utils/safe-names"; import * as util from "../util"; @@ -81,7 +82,7 @@ test.each([ local; ` .disableSemanticCheck() - .expectDiagnosticsToMatchSnapshot(); + .expectDiagnosticsToMatchSnapshot([invalidAmbientIdentifierName.code]); }); test.each([ @@ -98,11 +99,7 @@ test.each([ util.testModule` declare ${statement} $$$; - `.expectDiagnosticsToMatchSnapshot(); -}); - -test.each(["const x = ;", "({})[]"])("missing expression (%p)", statement => { - util.testModule(statement).expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidAmbientIdentifierName.code]); }); test.each(validTsInvalidLuaNames)( @@ -111,7 +108,7 @@ test.each(validTsInvalidLuaNames)( util.testModule` declare var ${name}: any; const foo = { ${name} }; - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([invalidAmbientIdentifierName.code]); } ); @@ -120,7 +117,7 @@ test.each(validTsInvalidLuaNames)("undeclared identifier must be a valid lua ide const foo = ${name}; ` .disableSemanticCheck() - .expectDiagnosticsToMatchSnapshot(); + .expectDiagnosticsToMatchSnapshot([invalidAmbientIdentifierName.code]); }); test.each(validTsInvalidLuaNames)( @@ -130,7 +127,7 @@ test.each(validTsInvalidLuaNames)( const foo = { ${name} }; ` .disableSemanticCheck() - .expectDiagnosticsToMatchSnapshot(); + .expectDiagnosticsToMatchSnapshot([invalidAmbientIdentifierName.code]); } ); diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index 6e02e47e1..a2bef4c01 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -1,4 +1,5 @@ import * as tstl from "../../src"; +import { forbiddenForIn, unsupportedForTarget } from "../../src/transformation/utils/diagnostics"; import * as util from "../util"; test("while", () => { @@ -215,7 +216,7 @@ test("forin[Array]", () => { util.testFunction` const array = []; for (const key in array) {} - `.expectDiagnosticsToMatchSnapshot(); + `.expectDiagnosticsToMatchSnapshot([forbiddenForIn.code]); }); test.each([{ inp: { a: 0, b: 1, c: 2, d: 3, e: 4 }, expected: { a: 0, b: 0, c: 2, d: 0, e: 4 } }])( @@ -529,7 +530,7 @@ for (const testCase of [ expect(builder.getMainLuaCodeChunk()).toMatch("::__continue2::"); util.testEachVersion(`loop continue (${testCase})`, () => util.testModule(testCase), { - [tstl.LuaTarget.Lua51]: builder => builder.expectDiagnosticsToMatchSnapshot(), + [tstl.LuaTarget.Lua51]: builder => builder.expectDiagnosticsToMatchSnapshot([unsupportedForTarget.code]), [tstl.LuaTarget.Lua52]: expectContinueGotoLabel, [tstl.LuaTarget.Lua53]: expectContinueGotoLabel, [tstl.LuaTarget.LuaJIT]: expectContinueGotoLabel, diff --git a/test/unit/modules/resolution.spec.ts b/test/unit/modules/resolution.spec.ts index cdbf239fe..1b0a6a8f9 100644 --- a/test/unit/modules/resolution.spec.ts +++ b/test/unit/modules/resolution.spec.ts @@ -1,4 +1,5 @@ import * as ts from "typescript"; +import { unresolvableRequirePath } from "../../../src/transformation/utils/diagnostics"; import * as util from "../../util"; const requireRegex = /require\("(.*?)"\)/; @@ -82,7 +83,7 @@ test("doesn't resolve paths out of root dir", () => { .setMainFileName("src/main.ts") .setOptions({ rootDir: "./src" }) .disableSemanticCheck() - .expectDiagnosticsToMatchSnapshot(); + .expectDiagnosticsToMatchSnapshot([unresolvableRequirePath.code]); }); test.each([ From e11d018d5393d40b139dcdd077b7ce3cbb5864e9 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Mar 2020 11:49:33 +0000 Subject: [PATCH 35/42] Add expected diagnostics to function assignability cast tests --- test/setup.ts | 2 +- .../invalidFunctionAssignments.spec.ts.snap | 32 ++++++++--------- .../invalidFunctionAssignments.spec.ts | 34 +++++++++++++------ 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/test/setup.ts b/test/setup.ts index bc3123703..ebaa4e2fd 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -34,7 +34,7 @@ expect.extend({ const message = this.isNot ? diagnosticMessages : expected - ? `Expected:\n${expected.join("\n")}\nReceived:\n${diagnosticMessages}\n` + ? `Expected:\n${expected.join("\n")}\nReceived:\n${diagnostics.map(diag => diag.code).join("\n")}\n` : `Received: ${this.utils.printReceived([])}\n`; return matcherHint + "\n\n" + message; diff --git a/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap b/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap index 5147e6055..9f112f305 100644 --- a/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap +++ b/test/unit/functions/validation/__snapshots__/invalidFunctionAssignments.spec.ts.snap @@ -1353,43 +1353,43 @@ exports[`Invalid function return ({"value": "function(this: void, s) { return s; exports[`Invalid function return ({"value": "function(this: void, s) { return s; }"}): diagnostics 2`] = `"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'."`; exports[`Invalid function return with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 1`] = ` -"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. -main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,24): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." `; exports[`Invalid function return with cast ({"definition": "/** @noSelfInFile */ let noSelfInFileFunc: {(s: string): string} = function(s) { return s; };", "value": "noSelfInFileFunc"}): diagnostics 2`] = ` -"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. -main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,24): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." `; exports[`Invalid function return with cast ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 1`] = ` -"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'. -main.ts(4,20): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'." +"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'. +main.ts(4,24): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'." `; exports[`Invalid function return with cast ({"definition": "let selfFunc: {(this: any, s: string): string} = function(s) { return s; };", "value": "selfFunc"}): diagnostics 2`] = ` -"main.ts(4,13): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'. -main.ts(4,20): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'." +"main.ts(4,17): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'. +main.ts(4,24): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'." `; exports[`Invalid function return with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 1`] = ` -"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. -main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,24): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." `; exports[`Invalid function return with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 2`] = ` -"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. -main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,24): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." `; exports[`Invalid function return with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 3`] = ` -"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. -main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,24): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." `; exports[`Invalid function return with cast ({"definition": "let voidFunc: {(this: void, s: string): string} = function(s) { return s; };", "value": "voidFunc"}): diagnostics 4`] = ` -"main.ts(4,13): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. -main.ts(4,20): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." +"main.ts(4,17): error TSTL: Unable to convert function with a 'this' parameter to function with no 'this'. To fix, wrap in an arrow function, or declare with 'this: void'. +main.ts(4,24): error TSTL: Unable to convert function with no 'this' parameter to function with 'this'. To fix, wrap in an arrow function, or declare with 'this: any'." `; exports[`Invalid function tuple assignment: diagnostics 1`] = ` diff --git a/test/unit/functions/validation/invalidFunctionAssignments.spec.ts b/test/unit/functions/validation/invalidFunctionAssignments.spec.ts index afabd7e6b..7d678496b 100644 --- a/test/unit/functions/validation/invalidFunctionAssignments.spec.ts +++ b/test/unit/functions/validation/invalidFunctionAssignments.spec.ts @@ -38,7 +38,10 @@ test.each(invalidTestFunctionCasts)("Invalid function assignment with cast (%p)" ${testFunction.definition || ""} let fn: typeof ${testFunction.value}; fn = ${castedFunction}; - `.expectDiagnosticsToMatchSnapshot(undefined, true); + `.expectDiagnosticsToMatchSnapshot( + [unsupportedNoSelfFunctionConversion.code, unsupportedSelfFunctionConversion.code], + true + ); }); test.each(invalidTestFunctionAssignments)( @@ -68,7 +71,10 @@ test.each(invalidTestFunctionCasts)("Invalid function argument with cast (%p)", ${testFunction.definition || ""} declare function takesFunction(fn: typeof ${testFunction.value}); takesFunction(${castedFunction}); - `.expectDiagnosticsToMatchSnapshot(undefined, true); + `.expectDiagnosticsToMatchSnapshot( + [unsupportedNoSelfFunctionConversion.code, unsupportedSelfFunctionConversion.code], + true + ); }); test.each(invalidTestFunctionAssignments)( @@ -100,14 +106,22 @@ test.each(invalidTestFunctionAssignments)( } ); -test.each(invalidTestFunctionCasts)("Invalid function return with cast (%p)", (testFunction, castedFunction) => { - util.testModule` - ${testFunction.definition || ""} - function returnsFunction(): typeof ${testFunction.value} { - return ${castedFunction}; - } - `.expectDiagnosticsToMatchSnapshot(undefined, true); -}); +test.each(invalidTestFunctionCasts)( + "Invalid function return with cast (%p)", + (testFunction, castedFunction, isSelfConversion) => { + util.testModule` + ${testFunction.definition || ""} + function returnsFunction(): typeof ${testFunction.value} { + return ${castedFunction}; + } + `.expectDiagnosticsToMatchSnapshot( + isSelfConversion + ? [unsupportedSelfFunctionConversion.code, unsupportedNoSelfFunctionConversion.code] + : [unsupportedNoSelfFunctionConversion.code, unsupportedSelfFunctionConversion.code], + true + ); + } +); test("Invalid function tuple assignment", () => { util.testModule` From 51574a82cc6733ad59c4f6c823865ce4c7079365 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Mar 2020 11:51:09 +0000 Subject: [PATCH 36/42] Add expected diagnostics to bundle tests --- test/unit/bundle.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/bundle.spec.ts b/test/unit/bundle.spec.ts index b6abf4ae1..ef76c82fe 100644 --- a/test/unit/bundle.spec.ts +++ b/test/unit/bundle.spec.ts @@ -90,7 +90,7 @@ test("LuaLibImportKind.Inline generates a warning", () => { result.push(3); ` .setOptions({ luaLibImport: LuaLibImportKind.Inline }) - .expectDiagnosticsToMatchSnapshot(undefined, true) + .expectDiagnosticsToMatchSnapshot([0], true) .expectToEqual({ result: [1, 2, 3] }); }); @@ -113,9 +113,9 @@ test("cyclic imports", () => { }); test("no entry point", () => { - util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot(undefined, true); + util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot([0], true); }); test("luaEntry doesn't exist", () => { - util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot(undefined, true); + util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot([0], true); }); From 9eaa4adcc857a744c13199e1fef3588ab0f5d2e6 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Wed, 11 Mar 2020 15:58:49 +0000 Subject: [PATCH 37/42] Add changelog entry --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac2e2d9f8..cc134834f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## Unreleased + +- Errors reported during transpilation now are created as TypeScript diagnostics, instead of being thrown as JavaScript errors. This makes TypeScriptToLua always try to generate valid code (even in presence of errors) and allows multiple errors to be reported in a single file: + + + ```ts + for (var x in []) {} + ``` + + ```shell + # Before + + $ tstl file.ts + file.ts:1:1 - error TSTL: Iterating over arrays with 'for ... in' is not allowed. + + $ cat file.lua + error("Iterating over arrays with 'for ... in' is not allowed.") + ``` + + ```shell + # Now + + $ tstl file.ts + file.ts:1:1 - error TSTL: Iterating over arrays with 'for ... in' is not allowed. + file.ts:1:6 - error TSTL: `var` declarations are not supported. Use `let` or `const` instead. + + $ cat file.lua + for x in pairs({}) do + end + ``` + ## 0.31.0 - **Breaking:** The old annotation syntax (`/* !varArg */`) **no longer works**, the only currently supported syntax is: From 9434b22f15c68e10635318e802cba6528260ec27 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Fri, 13 Mar 2020 18:52:30 +0000 Subject: [PATCH 38/42] Refactor for initializer variable transformation --- src/transformation/visitors/loops/for-in.ts | 36 +----- src/transformation/visitors/loops/for-of.ts | 129 +++----------------- src/transformation/visitors/loops/utils.ts | 36 +++++- 3 files changed, 54 insertions(+), 147 deletions(-) diff --git a/src/transformation/visitors/loops/for-in.ts b/src/transformation/visitors/loops/for-in.ts index 1aab1e0ef..296045056 100644 --- a/src/transformation/visitors/loops/for-in.ts +++ b/src/transformation/visitors/loops/for-in.ts @@ -3,9 +3,7 @@ import * as lua from "../../../LuaAST"; import { FunctionVisitor } from "../../context"; import { forbiddenForIn } from "../../utils/diagnostics"; import { isArrayType } from "../../utils/typescript"; -import { transformIdentifier } from "../identifier"; -import { transformAssignment } from "../binary-expression/assignments"; -import { getVariableDeclarationBinding, transformLoopBody } from "./utils"; +import { transformForInitializer, transformLoopBody } from "./utils"; export const transformForInStatement: FunctionVisitor = (statement, context) => { if (isArrayType(context, context.checker.getTypeAtLocation(statement.expression))) { @@ -19,34 +17,6 @@ export const transformForInStatement: FunctionVisitor = (stat const body = lua.createBlock(transformLoopBody(context, statement)); - // Transform iteration variable - // TODO: After the transformation pipeline refactor we should look at refactoring this together with the - // for-of initializer transformation. - let iterationVariable: lua.Identifier; - if (ts.isVariableDeclarationList(statement.initializer)) { - const binding = getVariableDeclarationBinding(context, statement.initializer); - if (!ts.isIdentifier(binding)) { - // TODO: - throw new Error(`Unsupported for...in variable kind: ${ts.SyntaxKind[binding.kind]}.`); - } - - iterationVariable = transformIdentifier(context, binding); - } else if (ts.isIdentifier(statement.initializer)) { - // Iteration variable becomes ____key - iterationVariable = lua.createIdentifier("____key"); - // Push variable = ____key to the start of the loop body to match TS scoping - const assignment = transformAssignment( - context, - statement.initializer, - iterationVariable, - statement.initializer - ); - - body.statements.unshift(...assignment); - } else { - // TODO: - throw new Error(`Unsupported for...in variable kind: ${ts.SyntaxKind[statement.initializer.kind]}.`); - } - - return lua.createForInStatement(body, [iterationVariable], [pairsCall], statement); + const valueVariable = transformForInitializer(context, statement.initializer, body); + return lua.createForInStatement(body, [valueVariable], [pairsCall], statement); }; diff --git a/src/transformation/visitors/loops/for-of.ts b/src/transformation/visitors/loops/for-of.ts index e3d233ed0..c682c042e 100644 --- a/src/transformation/visitors/loops/for-of.ts +++ b/src/transformation/visitors/loops/for-of.ts @@ -1,50 +1,15 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; -import { assert, cast, castEach } from "../../../utils"; +import { assert, castEach } from "../../../utils"; import { FunctionVisitor, TransformationContext } from "../../context"; import { AnnotationKind, getTypeAnnotations, isForRangeType, isLuaIteratorType } from "../../utils/annotations"; import { invalidForRangeCall, luaIteratorForbiddenUsage } from "../../utils/diagnostics"; import { LuaLibFeature, transformLuaLibFunction } from "../../utils/lualib"; -import { isArrayType, isAssignmentPattern, isNumberType } from "../../utils/typescript"; -import { transformAssignment } from "../binary-expression/assignments"; -import { transformAssignmentPattern } from "../binary-expression/destructuring-assignments"; +import { isArrayType, isNumberType } from "../../utils/typescript"; import { transformArguments } from "../call"; import { transformIdentifier } from "../identifier"; -import { - transformArrayBindingElement, - transformBindingPattern, - transformVariableDeclaration, -} from "../variable-declaration"; -import { getVariableDeclarationBinding, transformLoopBody } from "./utils"; - -function transformForOfInitializer( - context: TransformationContext, - initializer: ts.ForInitializer, - expression: lua.Identifier -): lua.Statement[] { - if (ts.isVariableDeclarationList(initializer)) { - const binding = getVariableDeclarationBinding(context, initializer); - // Declaration of new variable - if (ts.isArrayBindingPattern(binding) || ts.isObjectBindingPattern(binding)) { - return transformBindingPattern(context, binding, expression); - } - - const assignmentStatement = cast( - transformVariableDeclaration(context, initializer.declarations[0])[0], - lua.isVariableDeclarationStatement - ); - - return [lua.createVariableDeclarationStatement(assignmentStatement.left, expression)]; - } else { - // Assignment to existing variable(s) - - if (isAssignmentPattern(initializer)) { - return transformAssignmentPattern(context, initializer, expression); - } - - return transformAssignment(context, initializer, expression); - } -} +import { transformArrayBindingElement } from "../variable-declaration"; +import { getVariableDeclarationBinding, transformForInitializer, transformLoopBody } from "./utils"; function transformForRangeStatement( context: TransformationContext, @@ -115,10 +80,7 @@ function transformForOfLuaIteratorStatement( const binding = getVariableDeclarationBinding(context, statement.initializer); if (ts.isArrayBindingPattern(binding)) { - identifiers = castEach( - binding.elements.map(e => transformArrayBindingElement(context, e)), - lua.isIdentifier - ); + identifiers = binding.elements.map(e => transformArrayBindingElement(context, e)); } else { context.diagnostics.push(luaIteratorForbiddenUsage(binding)); } @@ -145,32 +107,14 @@ function transformForOfLuaIteratorStatement( } } else { // LuaIterator (no TupleReturn) - if ( - ts.isVariableDeclarationList(statement.initializer) && - statement.initializer.declarations.length > 0 && - ts.isIdentifier(statement.initializer.declarations[0].name) - ) { - // Single variable declared in for loop - // for ${initializer} in ${iterator} do - identifiers.push(transformIdentifier(context, statement.initializer.declarations[0].name)); - } else { - // Destructuring or variable NOT declared in for loop - // for ____value in ${iterator} do - // local ${initializer} = ____value - const valueVariable = lua.createIdentifier("____value"); - const initializer = transformForOfInitializer(context, statement.initializer, valueVariable); - if (initializer) { - identifiers.push(valueVariable); - block.statements.unshift(...initializer); - } - } + identifiers.push(transformForInitializer(context, statement.initializer, block)); } if (identifiers.length === 0) { identifiers.push(lua.createAnonymousIdentifier()); } - return lua.createForInStatement(block, identifiers, [luaIterator]); + return lua.createForInStatement(block, identifiers, [luaIterator], statement); } function transformForOfArrayStatement( @@ -178,28 +122,7 @@ function transformForOfArrayStatement( statement: ts.ForOfStatement, block: lua.Block ): lua.Statement { - let valueVariable: lua.Identifier; - if (ts.isVariableDeclarationList(statement.initializer)) { - // Declaration of new variable - const binding = getVariableDeclarationBinding(context, statement.initializer); - if (ts.isArrayBindingPattern(binding) || ts.isObjectBindingPattern(binding)) { - valueVariable = lua.createIdentifier("____values"); - const initializer = transformForOfInitializer(context, statement.initializer, valueVariable); - if (initializer) { - block.statements.unshift(...initializer); - } - } else { - valueVariable = transformIdentifier(context, binding); - } - } else { - // Assignment to existing variable - valueVariable = lua.createIdentifier("____value"); - const initializer = transformForOfInitializer(context, statement.initializer, valueVariable); - if (initializer) { - block.statements.unshift(...initializer); - } - } - + const valueVariable = transformForInitializer(context, statement.initializer, block); const ipairsCall = lua.createCallExpression(lua.createIdentifier("ipairs"), [ context.transformExpression(statement.expression), ]); @@ -212,35 +135,15 @@ function transformForOfIteratorStatement( statement: ts.ForOfStatement, block: lua.Block ): lua.Statement { - const iterable = context.transformExpression(statement.expression); - if ( - ts.isVariableDeclarationList(statement.initializer) && - statement.initializer.declarations.length > 0 && - ts.isIdentifier(statement.initializer.declarations[0].name) - ) { - // Single variable declared in for loop - // for ${initializer} in __TS__iterator(${iterator}) do - return lua.createForInStatement( - block, - [transformIdentifier(context, statement.initializer.declarations[0].name)], - [transformLuaLibFunction(context, LuaLibFeature.Iterator, statement.expression, iterable)] - ); - } else { - // Destructuring or variable NOT declared in for loop - // for ____value in __TS__iterator(${iterator}) do - // local ${initializer} = ____value - const valueVariable = lua.createIdentifier("____value"); - const initializer = transformForOfInitializer(context, statement.initializer, valueVariable); - if (initializer) { - block.statements.unshift(...initializer); - } + const valueVariable = transformForInitializer(context, statement.initializer, block); + const iterable = transformLuaLibFunction( + context, + LuaLibFeature.Iterator, + statement.expression, + context.transformExpression(statement.expression) + ); - return lua.createForInStatement( - block, - [valueVariable], - [transformLuaLibFunction(context, LuaLibFeature.Iterator, statement.expression, iterable)] - ); - } + return lua.createForInStatement(block, [valueVariable], [iterable], statement); } export const transformForOfStatement: FunctionVisitor = (node, context) => { diff --git a/src/transformation/visitors/loops/utils.ts b/src/transformation/visitors/loops/utils.ts index a3b44c177..8ee86f4ea 100644 --- a/src/transformation/visitors/loops/utils.ts +++ b/src/transformation/visitors/loops/utils.ts @@ -2,8 +2,12 @@ import * as ts from "typescript"; import * as lua from "../../../LuaAST"; import { TransformationContext } from "../../context"; import { performHoisting, popScope, pushScope, ScopeType } from "../../utils/scope"; +import { isAssignmentPattern } from "../../utils/typescript"; +import { transformAssignment } from "../binary-expression/assignments"; +import { transformAssignmentPattern } from "../binary-expression/destructuring-assignments"; import { transformBlockOrStatement } from "../block"; -import { checkVariableDeclarationList } from "../variable-declaration"; +import { transformIdentifier } from "../identifier"; +import { checkVariableDeclarationList, transformBindingPattern } from "../variable-declaration"; export function transformLoopBody( context: TransformationContext, @@ -37,3 +41,33 @@ export function getVariableDeclarationBinding( return node.declarations[0].name; } + +export function transformForInitializer( + context: TransformationContext, + initializer: ts.ForInitializer, + block: lua.Block +): lua.Identifier { + const valueVariable = lua.createIdentifier("____value"); + + if (ts.isVariableDeclarationList(initializer)) { + // Declaration of new variable + + const binding = getVariableDeclarationBinding(context, initializer); + if (ts.isArrayBindingPattern(binding) || ts.isObjectBindingPattern(binding)) { + block.statements.unshift(...transformBindingPattern(context, binding, valueVariable)); + } else { + // Single variable declared in for loop + return transformIdentifier(context, binding); + } + } else { + // Assignment to existing variable(s) + + block.statements.unshift( + ...(isAssignmentPattern(initializer) + ? transformAssignmentPattern(context, initializer, valueVariable) + : transformAssignment(context, initializer, valueVariable)) + ); + } + + return valueVariable; +} From 70211863cd3fb7dcab095d4c0b882496a8479814 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Fri, 13 Mar 2020 19:19:55 +0000 Subject: [PATCH 39/42] Update tests --- .../unit/annotations/__snapshots__/extension.spec.ts.snap | 8 ++------ test/unit/annotations/__snapshots__/luaTable.spec.ts.snap | 8 ++------ test/unit/builtins/set.spec.ts | 4 ++-- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/test/unit/annotations/__snapshots__/extension.spec.ts.snap b/test/unit/annotations/__snapshots__/extension.spec.ts.snap index 41e3de7cf..f69a1315a 100644 --- a/test/unit/annotations/__snapshots__/extension.spec.ts.snap +++ b/test/unit/annotations/__snapshots__/extension.spec.ts.snap @@ -19,9 +19,7 @@ exports[`Class extends extension ("extension"): code 1`] = ` "require(\\"lualib_bundle\\"); C = __TS__Class() C.name = \\"C\\" -C.____super = B -setmetatable(C, C.____super) -setmetatable(C.prototype, C.____super.prototype)" +__TS__ClassExtends(C, B)" `; exports[`Class extends extension ("extension"): diagnostics 1`] = `"main.ts(5,9): error TSTL: Cannot extend classes with '@extension' or '@metaExtension' annotation."`; @@ -31,9 +29,7 @@ exports[`Class extends extension ("metaExtension"): code 1`] = ` local __meta__A = debug.getregistry().A C = __TS__Class() C.name = \\"C\\" -C.____super = B -setmetatable(C, C.____super) -setmetatable(C.prototype, C.____super.prototype)" +__TS__ClassExtends(C, B)" `; exports[`Class extends extension ("metaExtension"): diagnostics 1`] = `"main.ts(5,9): error TSTL: Cannot extend classes with '@extension' or '@metaExtension' annotation."`; diff --git a/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap b/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap index 5b7332187..bd428c3eb 100644 --- a/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap +++ b/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap @@ -4,9 +4,7 @@ exports[`Cannot extend LuaTable class ("class Ext extends Table {}"): code 1`] = "require(\\"lualib_bundle\\"); Ext = __TS__Class() Ext.name = \\"Ext\\" -Ext.____super = Table -setmetatable(Ext, Ext.____super) -setmetatable(Ext.prototype, Ext.____super.prototype)" +__TS__ClassExtends(Ext, Table)" `; exports[`Cannot extend LuaTable class ("class Ext extends Table {}"): diagnostics 1`] = `"main.ts(11,19): error TSTL: Cannot extend classes with the '@luaTable' annotation."`; @@ -16,9 +14,7 @@ exports[`Cannot extend LuaTable class ("const c = class Ext extends Table {}"): c = (function() local Ext = __TS__Class() Ext.name = \\"Ext\\" - Ext.____super = Table - setmetatable(Ext, Ext.____super) - setmetatable(Ext.prototype, Ext.____super.prototype) + __TS__ClassExtends(Ext, Table) return Ext end)()" `; diff --git a/test/unit/builtins/set.spec.ts b/test/unit/builtins/set.spec.ts index cbd8cb3f4..2c58e5df8 100644 --- a/test/unit/builtins/set.spec.ts +++ b/test/unit/builtins/set.spec.ts @@ -109,7 +109,7 @@ test("set keys", () => { util.testFunction` let myset = new Set([5, 6, 7]); let count = 0; - for (var key of myset.keys()) { count += key; } + for (const key of myset.keys()) { count += key; } return count; `.expectToMatchJsResult(); }); @@ -118,7 +118,7 @@ test("set values", () => { util.testFunction` let myset = new Set([5, 6, 7]); let count = 0; - for (var value of myset.values()) { count += value; } + for (const value of myset.values()) { count += value; } return count; `.expectToMatchJsResult(); }); From 3040f6e1a42bcc8a9629c13e42a1be68431125cc Mon Sep 17 00:00:00 2001 From: ark120202 Date: Sat, 14 Mar 2020 21:38:22 +0000 Subject: [PATCH 40/42] Refactor diagnostc factories --- src/CompilerOptions.ts | 30 +++------------------ src/cli/diagnostics.ts | 22 ++++----------- src/transformation/utils/diagnostics.ts | 27 ++++++------------- src/transpilation/bundle.ts | 4 +-- src/transpilation/diagnostics.ts | 25 +++++++++-------- src/utils.ts | 28 +++++++++++++++++++ test/unit/__snapshots__/bundle.spec.ts.snap | 2 +- test/unit/bundle.spec.ts | 18 +++++++++---- 8 files changed, 74 insertions(+), 82 deletions(-) diff --git a/src/CompilerOptions.ts b/src/CompilerOptions.ts index 788f15d76..48c8abe82 100644 --- a/src/CompilerOptions.ts +++ b/src/CompilerOptions.ts @@ -1,4 +1,5 @@ import * as ts from "typescript"; +import * as diagnosticFactories from "./transpilation/diagnostics"; type KnownKeys = { [K in keyof T]: string extends K ? never : number extends K ? never : K } extends { [_ in keyof T]: infer U; @@ -47,37 +48,12 @@ export function validateOptions(options: CompilerOptions): ts.Diagnostic[] { const diagnostics: ts.Diagnostic[] = []; if (options.luaBundle && !options.luaBundleEntry) { - diagnostics.push(configErrorDiagnostic(`'luaBundleEntry' is required when 'luaBundle' is enabled.`)); + diagnostics.push(diagnosticFactories.luaBundleEntryIsRequired()); } if (options.luaBundle && options.luaLibImport === LuaLibImportKind.Inline) { - diagnostics.push( - configWarningDiagnostic( - `Using 'luaBundle' with 'luaLibImport: "inline"' might generate duplicate code. ` + - `It is recommended to use 'luaLibImport: "require"'` - ) - ); + diagnostics.push(diagnosticFactories.usingLuaBundleWithInlineMightGenerateDuplicateCode()); } return diagnostics; } - -const configErrorDiagnostic = (message: string): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, - category: ts.DiagnosticCategory.Error, - code: 0, - source: "typescript-to-lua", - messageText: message, -}); - -const configWarningDiagnostic = (message: string): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, - category: ts.DiagnosticCategory.Warning, - code: 0, - source: "typescript-to-lua", - messageText: message, -}); diff --git a/src/cli/diagnostics.ts b/src/cli/diagnostics.ts index 9e950710f..e386fa391 100644 --- a/src/cli/diagnostics.ts +++ b/src/cli/diagnostics.ts @@ -1,16 +1,12 @@ import * as ts from "typescript"; +import { createSerialDiagnosticFactory, createDiagnosticFactoryWithCode } from "../utils"; -export const tstlOptionsAreMovingToTheTstlObject = (tstl: Record): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, +export const tstlOptionsAreMovingToTheTstlObject = createSerialDiagnosticFactory((tstl: Record) => ({ category: ts.DiagnosticCategory.Warning, - code: 0, - source: "typescript-to-lua", messageText: 'TSTL options are moving to the "tstl" object. Adjust your tsconfig to look like\n' + `"tstl": ${JSON.stringify(tstl, undefined, 4)}`, -}); +})); export const watchErrorSummary = (errorCount: number): ts.Diagnostic => ({ file: undefined, @@ -24,16 +20,8 @@ export const watchErrorSummary = (errorCount: number): ts.Diagnostic => ({ : `Found ${errorCount} errors. Watching for file changes.`, }); -const createCommandLineError = (code: number, getMessage: (...args: Args) => string) => ( - ...args: Args -): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, - category: ts.DiagnosticCategory.Error, - code, - messageText: getMessage(...args), -}); +const createCommandLineError = (code: number, getMessage: (...args: TArgs) => string) => + createDiagnosticFactoryWithCode(code, (...args: TArgs) => ({ messageText: getMessage(...args) })); export const unknownCompilerOption = createCommandLineError( 5023, diff --git a/src/transformation/utils/diagnostics.ts b/src/transformation/utils/diagnostics.ts index 331d2cb11..5b7b2de38 100644 --- a/src/transformation/utils/diagnostics.ts +++ b/src/transformation/utils/diagnostics.ts @@ -1,26 +1,15 @@ import * as ts from "typescript"; import { LuaTarget } from "../../CompilerOptions"; +import { createSerialDiagnosticFactory } from "../../utils"; import { AnnotationKind } from "./annotations"; -let diagnosticCodeCounter = 100000; -const createDiagnosticFactory = ( - message: string | ((...args: TArgs) => string), - category = ts.DiagnosticCategory.Error -) => { - const code = diagnosticCodeCounter++; - return Object.assign( - (node: ts.Node, ...args: TArgs): ts.Diagnostic => ({ - file: node.getSourceFile(), - start: node.getStart(), - length: node.getWidth(), - category, - code, - source: "typescript-to-lua", - messageText: typeof message === "string" ? message : message(...args), - }), - { code } - ); -}; +const createDiagnosticFactory = (message: string | ((...args: TArgs) => string)) => + createSerialDiagnosticFactory((node: ts.Node, ...args: TArgs) => ({ + file: node.getSourceFile(), + start: node.getStart(), + length: node.getWidth(), + messageText: typeof message === "string" ? message : message(...args), + })); export const forbiddenForIn = createDiagnosticFactory(`Iterating over arrays with 'for ... in' is not allowed.`); diff --git a/src/transpilation/bundle.ts b/src/transpilation/bundle.ts index 7c587055c..c60a5b7cc 100644 --- a/src/transpilation/bundle.ts +++ b/src/transpilation/bundle.ts @@ -5,7 +5,7 @@ import { CompilerOptions } from "../CompilerOptions"; import { getLuaLibBundle } from "../LuaLib"; import { escapeString } from "../LuaPrinter"; import { formatPathToLuaPath, normalizeSlashes, trimExtension } from "../utils"; -import { couldNotFindBundleEntryPoint } from "./diagnostics"; +import * as diagnosticFactories from "./diagnostics"; import { EmitHost, TranspiledFile } from "./transpile"; const createModulePath = (baseDir: string, pathToResolve: string) => @@ -33,7 +33,7 @@ export function bundleTranspiledFiles( // Resolve source files relative to common source directory. const sourceRootDir = program.getCommonSourceDirectory(); if (!transpiledFiles.some(f => path.resolve(sourceRootDir, f.fileName) === resolvedEntryModule)) { - return [[couldNotFindBundleEntryPoint(entryModule)], { fileName: bundleFile }]; + return [[diagnosticFactories.couldNotFindBundleEntryPoint(entryModule)], { fileName: bundleFile }]; } // For each file: [""] = function() end, diff --git a/src/transpilation/diagnostics.ts b/src/transpilation/diagnostics.ts index 25425a135..9467bb606 100644 --- a/src/transpilation/diagnostics.ts +++ b/src/transpilation/diagnostics.ts @@ -1,16 +1,8 @@ import * as ts from "typescript"; +import { createSerialDiagnosticFactory } from "../utils"; -const createDiagnosticFactory = (getMessage: (...args: TArgs) => string) => ( - ...args: TArgs -): ts.Diagnostic => ({ - file: undefined, - start: undefined, - length: undefined, - category: ts.DiagnosticCategory.Error, - code: 0, - source: "typescript-to-lua", - messageText: getMessage(...args), -}); +const createDiagnosticFactory = (getMessage: (...args: TArgs) => string) => + createSerialDiagnosticFactory((...args: TArgs) => ({ messageText: getMessage(...args) })); export const toLoadTransformerItShouldBeTranspiled = createDiagnosticFactory( (transform: string) => @@ -33,3 +25,14 @@ export const transformerShouldBeATsTransformerFactory = createDiagnosticFactory( export const couldNotFindBundleEntryPoint = createDiagnosticFactory( (entryPoint: string) => `Could not find bundle entry point '${entryPoint}'. It should be a file in the project.` ); + +export const luaBundleEntryIsRequired = createDiagnosticFactory( + () => "'luaBundleEntry' is required when 'luaBundle' is enabled." +); + +export const usingLuaBundleWithInlineMightGenerateDuplicateCode = createSerialDiagnosticFactory(() => ({ + category: ts.DiagnosticCategory.Warning, + messageText: + `Using 'luaBundle' with 'luaLibImport: "inline"' might generate duplicate code. ` + + `It is recommended to use 'luaLibImport: "require"'.`, +})); diff --git a/src/utils.ts b/src/utils.ts index 19031bf50..822c5df3a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,34 @@ +import * as ts from "typescript"; import * as nativeAssert from "assert"; import * as path from "path"; +export const createDiagnosticFactoryWithCode = < + T extends (...args: any) => Partial & Pick +>( + code: number, + create: T +) => { + return Object.assign( + (...args: Parameters): ts.Diagnostic => ({ + file: undefined, + start: undefined, + length: undefined, + category: ts.DiagnosticCategory.Error, + code, + source: "typescript-to-lua", + ...create(...(args as any)), + }), + { code } + ); +}; + +let serialDiagnosticCodeCounter = 100000; +export const createSerialDiagnosticFactory = < + T extends (...args: any) => Partial & Pick +>( + create: T +) => createDiagnosticFactoryWithCode(serialDiagnosticCodeCounter++, create); + export const normalizeSlashes = (filePath: string) => filePath.replace(/\\/g, "/"); export const trimExtension = (filePath: string) => filePath.slice(0, -path.extname(filePath).length); diff --git a/test/unit/__snapshots__/bundle.spec.ts.snap b/test/unit/__snapshots__/bundle.spec.ts.snap index 516991b33..84c10f3d5 100644 --- a/test/unit/__snapshots__/bundle.spec.ts.snap +++ b/test/unit/__snapshots__/bundle.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`LuaLibImportKind.Inline generates a warning: diagnostics 1`] = `"warning TSTL: Using 'luaBundle' with 'luaLibImport: \\"inline\\"' might generate duplicate code. It is recommended to use 'luaLibImport: \\"require\\"'"`; +exports[`LuaLibImportKind.Inline generates a warning: diagnostics 1`] = `"warning TSTL: Using 'luaBundle' with 'luaLibImport: \\"inline\\"' might generate duplicate code. It is recommended to use 'luaLibImport: \\"require\\"'."`; exports[`luaEntry doesn't exist: diagnostics 1`] = `"error TSTL: Could not find bundle entry point 'entry.ts'. It should be a file in the project."`; diff --git a/test/unit/bundle.spec.ts b/test/unit/bundle.spec.ts index ef76c82fe..3d9520da4 100644 --- a/test/unit/bundle.spec.ts +++ b/test/unit/bundle.spec.ts @@ -1,6 +1,7 @@ import * as path from "path"; import * as ts from "typescript"; import { LuaLibImportKind } from "../../src"; +import * as diagnosticFactories from "../../src/transpilation/diagnostics"; import * as util from "../util"; test("import module -> main", () => { @@ -13,8 +14,8 @@ test("import module -> main", () => { test("bundle file name", () => { const { transpiledFiles } = util.testModule` - export { value } from "./module"; -` + export { value } from "./module"; + ` .addExtraFile("module.ts", "export const value = true") .setOptions({ luaBundle: "mybundle.lua", luaBundleEntry: "main.ts" }) .expectToHaveNoDiagnostics() @@ -90,7 +91,10 @@ test("LuaLibImportKind.Inline generates a warning", () => { result.push(3); ` .setOptions({ luaLibImport: LuaLibImportKind.Inline }) - .expectDiagnosticsToMatchSnapshot([0], true) + .expectDiagnosticsToMatchSnapshot( + [diagnosticFactories.usingLuaBundleWithInlineMightGenerateDuplicateCode.code], + true + ) .expectToEqual({ result: [1, 2, 3] }); }); @@ -113,9 +117,13 @@ test("cyclic imports", () => { }); test("no entry point", () => { - util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot([0], true); + util.testBundle`` + .setOptions({ luaBundleEntry: undefined }) + .expectDiagnosticsToMatchSnapshot([diagnosticFactories.luaBundleEntryIsRequired.code], true); }); test("luaEntry doesn't exist", () => { - util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot([0], true); + util.testBundle`` + .setEntryPoint("entry.ts") + .expectDiagnosticsToMatchSnapshot([diagnosticFactories.couldNotFindBundleEntryPoint.code], true); }); From c19626a2da3099b57569592045d33662951a1fd6 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Sat, 14 Mar 2020 22:05:32 +0000 Subject: [PATCH 41/42] Fix `luaTable` interface declaration tests --- .../__snapshots__/luaTable.spec.ts.snap | 32 +++++++++---------- test/unit/annotations/luaTable.spec.ts | 5 +-- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap b/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap index bd428c3eb..fae2b1f20 100644 --- a/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap +++ b/test/unit/annotations/__snapshots__/luaTable.spec.ts.snap @@ -27,7 +27,7 @@ exports[`Cannot isolate LuaTable method ("get"): code 2`] = `"property = tbl.get exports[`Cannot isolate LuaTable method ("get"): diagnostics 1`] = `"main.ts(11,21): error TSTL: LuaTable.get is unsupported."`; -exports[`Cannot isolate LuaTable method ("get"): diagnostics 2`] = `"main.ts(11,21): error TSTL: LuaTable.get is unsupported."`; +exports[`Cannot isolate LuaTable method ("get"): diagnostics 2`] = `"main.ts(13,21): error TSTL: LuaTable.get is unsupported."`; exports[`Cannot isolate LuaTable method ("set"): code 1`] = `"property = tbl.set"`; @@ -35,7 +35,7 @@ exports[`Cannot isolate LuaTable method ("set"): code 2`] = `"property = tbl.set exports[`Cannot isolate LuaTable method ("set"): diagnostics 1`] = `"main.ts(11,21): error TSTL: LuaTable.set is unsupported."`; -exports[`Cannot isolate LuaTable method ("set"): diagnostics 2`] = `"main.ts(11,21): error TSTL: LuaTable.set is unsupported."`; +exports[`Cannot isolate LuaTable method ("set"): diagnostics 2`] = `"main.ts(13,21): error TSTL: LuaTable.set is unsupported."`; exports[`Cannot set LuaTable length: code 1`] = `"tbl.length = 2"`; @@ -43,7 +43,7 @@ exports[`Cannot set LuaTable length: code 2`] = `"tbl.length = 2"`; exports[`Cannot set LuaTable length: diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: A LuaTable object's length cannot be re-assigned."`; -exports[`Cannot set LuaTable length: diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: A LuaTable object's length cannot be re-assigned."`; +exports[`Cannot set LuaTable length: diagnostics 2`] = `"main.ts(13,1): error TSTL: Invalid @luaTable usage: A LuaTable object's length cannot be re-assigned."`; exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"field\\")"): code 1`] = `"tbl.get(tbl, \\"field\\")"`; @@ -51,7 +51,7 @@ exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"fi exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"field\\")"): diagnostics 1`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; -exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"field\\")"): diagnostics 2`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"get\\"](\\"field\\")"): diagnostics 2`] = `"main.ts(13,1): error TSTL: @luaTable cannot be accessed dynamically."`; exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): code 1`] = `"local ____ = tbl.length"`; @@ -59,7 +59,7 @@ exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): diagnostics 1`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; -exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): diagnostics 2`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"length\\"]"): diagnostics 2`] = `"main.ts(13,1): error TSTL: @luaTable cannot be accessed dynamically."`; exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"field\\")"): code 1`] = `"tbl.set(tbl, \\"field\\")"`; @@ -67,7 +67,7 @@ exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"fi exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"field\\")"): diagnostics 1`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; -exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"field\\")"): diagnostics 2`] = `"main.ts(11,1): error TSTL: @luaTable cannot be accessed dynamically."`; +exports[`Cannot use ElementAccessExpression on a LuaTable ("tbl[\\"set\\"](\\"field\\")"): diagnostics 2`] = `"main.ts(13,1): error TSTL: @luaTable cannot be accessed dynamically."`; exports[`Cannot use instanceof on a LuaTable class ("tbl instanceof Table"): code 1`] = ` "require(\\"lualib_bundle\\"); @@ -82,7 +82,7 @@ exports[`Forbidden LuaTable use ("tbl.get()"): code 2`] = `"local ____ = tbl[nil exports[`Forbidden LuaTable use ("tbl.get()"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 0."`; -exports[`Forbidden LuaTable use ("tbl.get()"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 0."`; +exports[`Forbidden LuaTable use ("tbl.get()"): diagnostics 2`] = `"main.ts(13,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 0."`; exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): code 1`] = `"local ____ = tbl.field"`; @@ -90,7 +90,7 @@ exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): code 2`] exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 2."`; -exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 2."`; +exports[`Forbidden LuaTable use ("tbl.get(\\"field\\", \\"field2\\")"): diagnostics 2`] = `"main.ts(13,1): error TSTL: Invalid @luaTable usage: Expected 1 arguments, but got 2."`; exports[`Forbidden LuaTable use ("tbl.set()"): code 1`] = `"tbl[nil] = nil"`; @@ -98,7 +98,7 @@ exports[`Forbidden LuaTable use ("tbl.set()"): code 2`] = `"tbl[nil] = nil"`; exports[`Forbidden LuaTable use ("tbl.set()"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 0."`; -exports[`Forbidden LuaTable use ("tbl.set()"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 0."`; +exports[`Forbidden LuaTable use ("tbl.set()"): diagnostics 2`] = `"main.ts(13,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 0."`; exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): code 1`] = `"tbl[table.unpack({\\"field\\", 0})] = nil"`; @@ -106,7 +106,7 @@ exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): cod exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 1`] = `"main.ts(11,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; -exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 2`] = `"main.ts(11,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; +exports[`Forbidden LuaTable use ("tbl.set(...([\\"field\\", 0] as const))"): diagnostics 2`] = `"main.ts(13,9): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): code 1`] = `"tbl.field = nil"`; @@ -114,7 +114,7 @@ exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): code 2`] = `"tbl.field exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1."`; -exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1."`; +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\")"): diagnostics 2`] = `"main.ts(13,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 1."`; exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): code 1`] = `"tbl.field = table.unpack({0})"`; @@ -122,7 +122,7 @@ exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): cod exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): diagnostics 1`] = `"main.ts(11,18): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; -exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): diagnostics 2`] = `"main.ts(11,18): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", ...([0] as const))"): diagnostics 2`] = `"main.ts(13,18): error TSTL: Invalid @luaTable usage: Arguments cannot be spread."`; exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): code 1`] = `"tbl.field = 0"`; @@ -130,7 +130,7 @@ exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): code 2`] = `"tbl exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 1`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3."`; -exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 2`] = `"main.ts(11,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3."`; +exports[`Forbidden LuaTable use ("tbl.set(\\"field\\", 0, 1)"): diagnostics 2`] = `"main.ts(13,1): error TSTL: Invalid @luaTable usage: Expected 2 arguments, but got 3."`; exports[`LuaTable classes must be ambient ("/** @luaTable */ class Table {}"): code 1`] = ` "require(\\"lualib_bundle\\"); @@ -174,7 +174,7 @@ exports[`LuaTable set() cannot be used in a LuaTable call expression: code 2`] = exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 1`] = `"main.ts(11,17): error TSTL: LuaTable.set is unsupported."`; -exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 2`] = `"main.ts(11,17): error TSTL: LuaTable.set is unsupported."`; +exports[`LuaTable set() cannot be used in a LuaTable call expression: diagnostics 2`] = `"main.ts(13,17): error TSTL: LuaTable.set is unsupported."`; exports[`LuaTables cannot be constructed with arguments: code 1`] = `"____table = {}"`; @@ -190,8 +190,8 @@ exports[`LuaTables cannot have other members: code 4`] = `"x = tbl:other()"`; exports[`LuaTables cannot have other members: diagnostics 1`] = `"main.ts(11,5): error TSTL: LuaTable.other is unsupported."`; -exports[`LuaTables cannot have other members: diagnostics 2`] = `"main.ts(11,5): error TSTL: LuaTable.other is unsupported."`; +exports[`LuaTables cannot have other members: diagnostics 2`] = `"main.ts(13,5): error TSTL: LuaTable.other is unsupported."`; exports[`LuaTables cannot have other members: diagnostics 3`] = `"main.ts(11,13): error TSTL: LuaTable.other is unsupported."`; -exports[`LuaTables cannot have other members: diagnostics 4`] = `"main.ts(11,13): error TSTL: LuaTable.other is unsupported."`; +exports[`LuaTables cannot have other members: diagnostics 4`] = `"main.ts(13,13): error TSTL: LuaTable.other is unsupported."`; diff --git a/test/unit/annotations/luaTable.spec.ts b/test/unit/annotations/luaTable.spec.ts index 78b23d78d..ec7d1af35 100644 --- a/test/unit/annotations/luaTable.spec.ts +++ b/test/unit/annotations/luaTable.spec.ts @@ -20,16 +20,17 @@ declare class Table { declare let tbl: Table; `; -// TODO: `constructor()` is not valid in interfaces const tableLibInterface = ` /** @luaTable */ declare interface Table { length: number; - constructor(notAllowed?: any); set(key?: K, value?: V, notAllowed?: any): void; get(key?: K, notAllowed?: any): V; other(): void; } + +/** @luaTable */ +declare const Table: new (notAllowed?: any) => Table; declare let tbl: Table; `; From 58cb0a0256794f039d3a66657119c9653f771266 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Sat, 14 Mar 2020 22:14:42 +0000 Subject: [PATCH 42/42] Make condition more readable --- .../visitors/binary-expression/assignments.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/transformation/visitors/binary-expression/assignments.ts b/src/transformation/visitors/binary-expression/assignments.ts index 18419891c..6a785699a 100644 --- a/src/transformation/visitors/binary-expression/assignments.ts +++ b/src/transformation/visitors/binary-expression/assignments.ts @@ -17,9 +17,9 @@ export function transformAssignmentLeftHandSideExpression( node: ts.Expression ): lua.AssignmentLeftHandSideExpression { const symbol = context.checker.getSymbolAtLocation(node); - const left = - (ts.isPropertyAccessExpression(node) && transformLuaTablePropertyAccessInAssignment(context, node)) || - context.transformExpression(node); + const left = ts.isPropertyAccessExpression(node) + ? transformLuaTablePropertyAccessInAssignment(context, node) ?? context.transformExpression(node) + : context.transformExpression(node); return lua.isIdentifier(left) && symbol && isSymbolExported(context, symbol) ? createExportedIdentifier(context, left)