typescript-to-lua
Advanced tools
Comparing version 0.41.0 to 0.41.1
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.validateOptions = exports.isBundleEnabled = exports.BuildMode = exports.LuaTarget = exports.LuaLibImportKind = void 0; | ||
const typescript_1 = require("typescript"); | ||
const diagnosticFactories = require("./transpilation/diagnostics"); | ||
@@ -39,2 +40,5 @@ var LuaLibImportKind; | ||
} | ||
if (options.jsx && options.jsx !== typescript_1.JsxEmit.React) { | ||
diagnostics.push(diagnosticFactories.unsupportedJsxEmit()); | ||
} | ||
return diagnostics; | ||
@@ -41,0 +45,0 @@ } |
@@ -17,3 +17,5 @@ import * as ts from "typescript"; | ||
Vararg = "vararg", | ||
ForRange = "forRange" | ||
ForRange = "forRange", | ||
Jsx = "jsx", | ||
JsxFrag = "jsxFrag" | ||
} | ||
@@ -20,0 +22,0 @@ export interface Annotation { |
@@ -22,2 +22,4 @@ "use strict"; | ||
AnnotationKind["ForRange"] = "forRange"; | ||
AnnotationKind["Jsx"] = "jsx"; | ||
AnnotationKind["JsxFrag"] = "jsxFrag"; | ||
})(AnnotationKind = exports.AnnotationKind || (exports.AnnotationKind = {})); | ||
@@ -24,0 +26,0 @@ function createAnnotation(name, args) { |
@@ -88,1 +88,4 @@ import * as ts from "typescript"; | ||
}; | ||
export declare const notAllowedOptionalAssignment: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & { | ||
code: number; | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.annotationDeprecated = exports.annotationRemoved = exports.invalidTableSetExpression = exports.invalidTableDeleteExpression = exports.invalidTableExtensionUse = exports.invalidOperatorMappingUse = exports.invalidMultiReturnAccess = exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = exports.invalidMultiTypeToNonArrayLiteral = exports.invalidMultiFunctionReturnType = exports.invalidMultiFunctionUse = exports.unsupportedVarDeclaration = exports.invalidAmbientIdentifierName = exports.unsupportedProperty = exports.unsupportedForTarget = exports.unsupportedRightShiftOperator = exports.unsupportedAccessorInObjectLiteral = exports.invalidMultiIterableWithoutDestructuring = exports.invalidRangeControlVariable = exports.invalidVarargUse = exports.invalidRangeUse = exports.annotationInvalidArgumentCount = exports.decoratorInvalidContext = exports.unsupportedOverloadAssignment = exports.unsupportedSelfFunctionConversion = exports.unsupportedNoSelfFunctionConversion = exports.forbiddenForIn = exports.unsupportedNodeKind = void 0; | ||
exports.notAllowedOptionalAssignment = exports.annotationDeprecated = exports.annotationRemoved = exports.invalidTableSetExpression = exports.invalidTableDeleteExpression = exports.invalidTableExtensionUse = exports.invalidOperatorMappingUse = exports.invalidMultiReturnAccess = exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = exports.invalidMultiTypeToNonArrayLiteral = exports.invalidMultiFunctionReturnType = exports.invalidMultiFunctionUse = exports.unsupportedVarDeclaration = exports.invalidAmbientIdentifierName = exports.unsupportedProperty = exports.unsupportedForTarget = exports.unsupportedRightShiftOperator = exports.unsupportedAccessorInObjectLiteral = exports.invalidMultiIterableWithoutDestructuring = exports.invalidRangeControlVariable = exports.invalidVarargUse = exports.invalidRangeUse = exports.annotationInvalidArgumentCount = exports.decoratorInvalidContext = exports.unsupportedOverloadAssignment = exports.unsupportedSelfFunctionConversion = exports.unsupportedNoSelfFunctionConversion = exports.forbiddenForIn = exports.unsupportedNodeKind = void 0; | ||
const ts = require("typescript"); | ||
@@ -59,2 +59,3 @@ const CompilerOptions_1 = require("../../CompilerOptions"); | ||
`See https://typescripttolua.github.io/docs/advanced/compiler-annotations#${kind.toLowerCase()} for more information.`); | ||
exports.notAllowedOptionalAssignment = createErrorDiagnosticFactory("The left-hand side of an assignment expression may not be an optional property access."); | ||
//# sourceMappingURL=diagnostics.js.map |
@@ -71,5 +71,5 @@ "use strict"; | ||
exports.popScope = popScope; | ||
function isDeclaredInScope(symbol, scopeNode) { | ||
function isHoistableFunctionDeclaredInScope(symbol, scopeNode) { | ||
var _a; | ||
return (_a = symbol === null || symbol === void 0 ? void 0 : symbol.declarations) === null || _a === void 0 ? void 0 : _a.some(d => typescript_1.findFirstNodeAbove(d, (n) => n === scopeNode) && !ts.isParameter(d.parent)); | ||
return (_a = symbol === null || symbol === void 0 ? void 0 : symbol.declarations) === null || _a === void 0 ? void 0 : _a.some(d => ts.isFunctionDeclaration(d) && typescript_1.findFirstNodeAbove(d, (n) => n === scopeNode)); | ||
} | ||
@@ -87,3 +87,3 @@ // Checks for references to local functions which haven't been defined yet, | ||
type.getCallSignatures().length > 0 && | ||
isDeclaredInScope(type.symbol, scope.node)) { | ||
isHoistableFunctionDeclaredInScope(type.symbol, scope.node)) { | ||
return true; | ||
@@ -90,0 +90,0 @@ } |
@@ -18,2 +18,3 @@ "use strict"; | ||
const transform_1 = require("../../utils/transform"); | ||
const diagnostics_1 = require("../../utils/diagnostics"); | ||
function transformAssignmentLeftHandSideExpression(context, node) { | ||
@@ -30,2 +31,6 @@ const symbol = context.checker.getSymbolAtLocation(node); | ||
lhs, right, parent) { | ||
if (ts.isOptionalChain(lhs)) { | ||
context.diagnostics.push(diagnostics_1.notAllowedOptionalAssignment(lhs)); | ||
return []; | ||
} | ||
if (destructuring_assignments_1.isArrayLength(context, lhs)) { | ||
@@ -32,0 +37,0 @@ const arrayLengthAssignment = lua.createExpressionStatement(lualib_1.transformLuaLibFunction(context, lualib_1.LuaLibFeature.ArraySetLength, parent, context.transformExpression(lhs.expression), right)); |
@@ -36,2 +36,3 @@ "use strict"; | ||
const variable_declaration_1 = require("./variable-declaration"); | ||
const jsx_1 = require("./jsx/jsx"); | ||
const transformEmptyStatement = () => undefined; | ||
@@ -42,2 +43,3 @@ const transformParenthesizedExpression = (node, context) => context.transformExpression(node.expression); | ||
...typescript_1.typescriptVisitors, | ||
...jsx_1.jsxVisitors, | ||
[ts.SyntaxKind.ArrowFunction]: function_1.transformFunctionLikeDeclaration, | ||
@@ -44,0 +46,0 @@ [ts.SyntaxKind.BinaryExpression]: binary_expression_1.transformBinaryExpression, |
@@ -10,2 +10,2 @@ import * as ts from "typescript"; | ||
export declare function shouldMultiReturnCallBeWrapped(context: TransformationContext, node: ts.CallExpression): boolean; | ||
export declare function findMultiAssignmentViolations(context: TransformationContext, node: ts.ObjectLiteralExpression): ts.Node[]; | ||
export declare function findMultiAssignmentViolations(context: TransformationContext, node: ts.ObjectLiteralExpressionBase<ts.ObjectLiteralElement>): ts.Node[]; |
import * as ts from "typescript"; | ||
import * as lua from "../../LuaAST"; | ||
import { TransformationContext, Visitors } from "../context"; | ||
import { FunctionVisitor, TransformationContext, Visitors } from "../context"; | ||
export declare function transformPropertyName(context: TransformationContext, node: ts.PropertyName): lua.Expression; | ||
export declare function createShorthandIdentifier(context: TransformationContext, valueSymbol: ts.Symbol | undefined, propertyIdentifier: ts.Identifier): lua.Expression; | ||
export declare const transformJsxAttributes: FunctionVisitor<ts.JsxAttributes>; | ||
export declare const literalVisitors: Visitors; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.literalVisitors = exports.createShorthandIdentifier = exports.transformPropertyName = void 0; | ||
exports.literalVisitors = exports.transformJsxAttributes = exports.createShorthandIdentifier = exports.transformPropertyName = void 0; | ||
const ts = require("typescript"); | ||
@@ -16,2 +16,3 @@ const lua = require("../../LuaAST"); | ||
const multi_1 = require("./language-extensions/multi"); | ||
const jsx_1 = require("./jsx/jsx"); | ||
// TODO: Move to object-literal.ts? | ||
@@ -59,3 +60,3 @@ function transformPropertyName(context, node) { | ||
}; | ||
const transformObjectLiteralExpression = (expression, context) => { | ||
const transformObjectLiteralExpressionOrJsxAttributes = (expression, context) => { | ||
const violations = multi_1.findMultiAssignmentViolations(context, expression); | ||
@@ -74,2 +75,22 @@ if (violations.length > 0) { | ||
} | ||
else if (ts.isJsxAttribute(element)) { | ||
const initializer = element.initializer; | ||
let expression; | ||
if (initializer === undefined) { | ||
expression = lua.createBooleanLiteral(true); | ||
} | ||
else if (ts.isStringLiteral(initializer)) { | ||
const text = jsx_1.formatJSXStringValueLiteral(initializer.text); | ||
expression = lua.createStringLiteral(text, initializer); | ||
} | ||
else if (ts.isJsxExpression(initializer)) { | ||
expression = initializer.expression | ||
? context.transformExpression(initializer.expression) | ||
: lua.createBooleanLiteral(true); | ||
} | ||
else { | ||
utils_1.assertNever(initializer); | ||
} | ||
properties.push(lua.createTableFieldExpression(expression, name, element)); | ||
} | ||
else if (ts.isShorthandPropertyAssignment(element)) { | ||
@@ -87,3 +108,3 @@ const valueSymbol = context.checker.getShorthandAssignmentValueSymbol(element); | ||
} | ||
else if (ts.isSpreadAssignment(element)) { | ||
else if (ts.isSpreadAssignment(element) || ts.isJsxSpreadAttribute(element)) { | ||
// Create a table for preceding properties to preserve property order | ||
@@ -127,2 +148,4 @@ // { x: 0, ...{ y: 2 }, y: 1, z: 2 } --> __TS__ObjectAssign({x = 0}, {y = 2}, {y = 1, z = 2}) | ||
}; | ||
const transformObjectLiteralExpression = transformObjectLiteralExpressionOrJsxAttributes; | ||
exports.transformJsxAttributes = transformObjectLiteralExpressionOrJsxAttributes; | ||
const transformArrayLiteralExpression = (expression, context) => { | ||
@@ -129,0 +152,0 @@ const filteredElements = expression.elements.map(e => ts.isOmittedExpression(e) ? ts.factory.createIdentifier("undefined") : e); |
@@ -32,1 +32,4 @@ import * as ts from "typescript"; | ||
}; | ||
export declare const unsupportedJsxEmit: (() => ts.Diagnostic) & { | ||
code: number; | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.cannotBundleLibrary = exports.usingLuaBundleWithInlineMightGenerateDuplicateCode = exports.luaBundleEntryIsRequired = exports.couldNotFindBundleEntryPoint = exports.transformerShouldBeATsTransformerFactory = exports.shouldHaveAExport = exports.couldNotResolveFrom = exports.toLoadItShouldBeTranspiled = exports.couldNotReadDependency = exports.couldNotResolveRequire = void 0; | ||
exports.unsupportedJsxEmit = exports.cannotBundleLibrary = exports.usingLuaBundleWithInlineMightGenerateDuplicateCode = exports.luaBundleEntryIsRequired = exports.couldNotFindBundleEntryPoint = exports.transformerShouldBeATsTransformerFactory = exports.shouldHaveAExport = exports.couldNotResolveFrom = exports.toLoadItShouldBeTranspiled = exports.couldNotReadDependency = exports.couldNotResolveRequire = void 0; | ||
const ts = require("typescript"); | ||
@@ -21,2 +21,3 @@ const utils_1 = require("../utils"); | ||
exports.cannotBundleLibrary = createDiagnosticFactory(() => 'Cannot bundle probjects with"buildmode": "library". Projects including the library can still bundle (which will include external library files).'); | ||
exports.unsupportedJsxEmit = createDiagnosticFactory(() => 'JSX is only supported with "react" jsx option.'); | ||
//# sourceMappingURL=diagnostics.js.map |
@@ -18,2 +18,70 @@ "use strict"; | ||
}); | ||
class ResolutionContext { | ||
constructor(program, options, emitHost) { | ||
this.program = program; | ||
this.options = options; | ||
this.emitHost = emitHost; | ||
this.resultsCache = new Map(); | ||
} | ||
resolve(file, required) { | ||
const resolvedDependency = resolveDependency(file, required, this.program, this.emitHost); | ||
if (resolvedDependency) { | ||
if (this.options.tstlVerbose) { | ||
console.log(`Resolved ${required} to ${utils_1.normalizeSlashes(resolvedDependency)}`); | ||
} | ||
// Figure out resolved require path and dependency output path | ||
const resolvedRequire = transpiler_1.getEmitPathRelativeToOutDir(resolvedDependency, this.program); | ||
if (shouldRewriteRequires(resolvedDependency, this.program)) { | ||
replaceRequireInCode(file, required, resolvedRequire); | ||
replaceRequireInSourceMap(file, required, resolvedRequire); | ||
} | ||
// Check cache to prevent resolving nested dependencies double to break dependency loops | ||
if (this.resultsCache.has(resolvedDependency)) { | ||
if (this.options.tstlVerbose) { | ||
console.log(`Resolution cache hit for ${utils_1.normalizeSlashes(resolvedDependency)}`); | ||
} | ||
return this.resultsCache.get(resolvedDependency); | ||
} | ||
// If dependency is not part of project, add dependency to output and resolve its dependencies recursively | ||
if (shouldIncludeDependency(resolvedDependency, this.program)) { | ||
// If dependency resolved successfully, read its content | ||
const dependencyContent = this.emitHost.readFile(resolvedDependency); | ||
if (dependencyContent === undefined) { | ||
return { resolvedFiles: [], diagnostics: [diagnostics_1.couldNotReadDependency(resolvedDependency)] }; | ||
} | ||
const dependency = { | ||
fileName: resolvedDependency, | ||
code: dependencyContent, | ||
}; | ||
const nestedDependencies = resolveFileDependencies(dependency, this); | ||
// Cache result and return | ||
const result = { | ||
resolvedFiles: [dependency, ...nestedDependencies.resolvedFiles], | ||
diagnostics: [...nestedDependencies.diagnostics], | ||
}; | ||
this.resultsCache.set(resolvedDependency, result); | ||
return result; | ||
} | ||
else { | ||
const result = { | ||
resolvedFiles: [], | ||
diagnostics: [], | ||
}; | ||
this.resultsCache.set(resolvedDependency, result); | ||
return result; | ||
} | ||
} | ||
else { | ||
const fallbackRequire = fallbackResolve(required, transpiler_1.getSourceDir(this.program), path.dirname(file.fileName)); | ||
replaceRequireInCode(file, required, fallbackRequire); | ||
replaceRequireInSourceMap(file, required, fallbackRequire); | ||
return { | ||
resolvedFiles: [], | ||
diagnostics: [ | ||
diagnostics_1.couldNotResolveRequire(required, path.relative(transpiler_1.getProjectRoot(this.program), file.fileName)), | ||
], | ||
}; | ||
} | ||
} | ||
} | ||
function resolveDependencies(program, files, emitHost) { | ||
@@ -23,2 +91,3 @@ const outFiles = [...files]; | ||
const options = program.getCompilerOptions(); | ||
const resolutionContext = new ResolutionContext(program, options, emitHost); | ||
// Resolve dependencies for all processed files | ||
@@ -29,13 +98,15 @@ for (const file of files) { | ||
} | ||
const resolutionResult = resolveFileDependencies(file, program, emitHost); | ||
const resolutionResult = resolveFileDependencies(file, resolutionContext); | ||
outFiles.push(...resolutionResult.resolvedFiles); | ||
diagnostics.push(...resolutionResult.diagnostics); | ||
} | ||
return { resolvedFiles: outFiles, diagnostics }; | ||
return { resolvedFiles: deduplicateResolvedFiles(outFiles), diagnostics }; | ||
} | ||
exports.resolveDependencies = resolveDependencies; | ||
function resolveFileDependencies(file, program, emitHost) { | ||
function deduplicateResolvedFiles(files) { | ||
return [...new Map(files.map(f => [f.fileName, f])).values()]; | ||
} | ||
function resolveFileDependencies(file, context) { | ||
const dependencies = []; | ||
const diagnostics = []; | ||
const options = program.getCompilerOptions(); | ||
for (const required of findRequiredPaths(file.code)) { | ||
@@ -54,43 +125,11 @@ // Do no resolve lualib | ||
// Try to resolve the import starting from the directory `file` is in | ||
const fileDir = path.dirname(file.fileName); | ||
const resolvedDependency = resolveDependency(fileDir, required, program, emitHost); | ||
if (resolvedDependency) { | ||
if (options.tstlVerbose) { | ||
console.log(`Resolved ${required} to ${utils_1.normalizeSlashes(resolvedDependency)}`); | ||
} | ||
// Figure out resolved require path and dependency output path | ||
const resolvedRequire = transpiler_1.getEmitPathRelativeToOutDir(resolvedDependency, program); | ||
if (shouldRewriteRequires(resolvedDependency, program)) { | ||
replaceRequireInCode(file, required, resolvedRequire); | ||
replaceRequireInSourceMap(file, required, resolvedRequire); | ||
} | ||
// If dependency is not part of project, add dependency to output and resolve its dependencies recursively | ||
if (shouldIncludeDependency(resolvedDependency, program)) { | ||
// If dependency resolved successfully, read its content | ||
const dependencyContent = emitHost.readFile(resolvedDependency); | ||
if (dependencyContent === undefined) { | ||
diagnostics.push(diagnostics_1.couldNotReadDependency(resolvedDependency)); | ||
continue; | ||
} | ||
const dependency = { | ||
fileName: resolvedDependency, | ||
code: dependencyContent, | ||
}; | ||
const nestedDependencies = resolveFileDependencies(dependency, program, emitHost); | ||
dependencies.push(dependency, ...nestedDependencies.resolvedFiles); | ||
diagnostics.push(...nestedDependencies.diagnostics); | ||
} | ||
} | ||
else { | ||
// Could not resolve dependency, add a diagnostic and make some fallback path | ||
diagnostics.push(diagnostics_1.couldNotResolveRequire(required, path.relative(transpiler_1.getProjectRoot(program), file.fileName))); | ||
const fallbackRequire = fallbackResolve(required, transpiler_1.getSourceDir(program), fileDir); | ||
replaceRequireInCode(file, required, fallbackRequire); | ||
replaceRequireInSourceMap(file, required, fallbackRequire); | ||
} | ||
const resolvedDependency = context.resolve(file, required); | ||
dependencies.push(...resolvedDependency.resolvedFiles); | ||
diagnostics.push(...resolvedDependency.diagnostics); | ||
} | ||
return { resolvedFiles: dependencies, diagnostics }; | ||
} | ||
function resolveDependency(fileDirectory, dependency, program, emitHost) { | ||
function resolveDependency(requiringFile, dependency, program, emitHost) { | ||
const options = program.getCompilerOptions(); | ||
const fileDirectory = path.dirname(requiringFile.fileName); | ||
if (options.tstlVerbose) { | ||
@@ -113,6 +152,18 @@ console.log(`Resolving "${dependency}" from ${utils_1.normalizeSlashes(fileDirectory)}`); | ||
} | ||
// Check if this is a lua file in the project sources | ||
const possibleLuaProjectFiles = [ | ||
resolvedPath + ".lua", | ||
path.join(resolvedPath, "index.lua"), // lua index file in sources | ||
]; | ||
for (const possibleFile of possibleLuaProjectFiles) { | ||
if (emitHost.fileExists(possibleFile)) { | ||
return possibleFile; | ||
} | ||
} | ||
// Check if this is a sibling of a required lua file | ||
const luaFilePath = path.resolve(fileDirectory, dependency + ".lua"); | ||
if (emitHost.fileExists(luaFilePath)) { | ||
return luaFilePath; | ||
if (requiringFile.fileName.endsWith(".lua")) { | ||
const luaFilePath = resolveLuaPath(fileDirectory, dependency, emitHost); | ||
if (luaFilePath) { | ||
return luaFilePath; | ||
} | ||
} | ||
@@ -131,2 +182,30 @@ // Not a TS file in our project sources, use resolver to check if we can find dependency | ||
} | ||
function resolveLuaPath(fromPath, dependency, emitHost) { | ||
const splitDependency = dependency.split("."); | ||
if (splitDependency.length === 1) { | ||
// If dependency has just one part (the file), look for a lua file with that name | ||
const fileDirectory = walkUpFileTreeUntil(fromPath, dir => emitHost.fileExists(path.join(dir, dependency) + ".lua")); | ||
if (fileDirectory) { | ||
return path.join(fileDirectory, dependency) + ".lua"; | ||
} | ||
} | ||
else { | ||
// If dependency has multiple parts, look for the first directory of the require path, which must be in the lua root | ||
const luaRoot = walkUpFileTreeUntil(fromPath, dir => emitHost.directoryExists(path.join(dir, splitDependency[0]))); | ||
if (luaRoot) { | ||
return path.join(luaRoot, dependency.replace(".", path.sep)) + ".lua"; | ||
} | ||
} | ||
} | ||
function walkUpFileTreeUntil(fromDirectory, predicate) { | ||
const currentDir = path.normalize(fromDirectory).split(path.sep); | ||
while (currentDir.length > 0) { | ||
const dir = currentDir.join(path.sep); | ||
if (predicate(dir)) { | ||
return dir; | ||
} | ||
currentDir.pop(); | ||
} | ||
return undefined; | ||
} | ||
function shouldRewriteRequires(resolvedDependency, program) { | ||
@@ -133,0 +212,0 @@ return !isNodeModulesFile(resolvedDependency) || !isBuildModeLibrary(program); |
import * as ts from "typescript"; | ||
import * as lua from "../LuaAST"; | ||
export interface EmitHost { | ||
directoryExists(path: string): boolean; | ||
fileExists(path: string): boolean; | ||
@@ -5,0 +6,0 @@ getCurrentDirectory(): string; |
{ | ||
"name": "typescript-to-lua", | ||
"version": "0.41.0", | ||
"version": "0.41.1", | ||
"description": "A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/TypeScriptToLua/TypeScriptToLua", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
761456
299
11936