diff --git a/.eslintrc.cjs b/.eslintrc.cjs index e8b118a98..c37ca37b8 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -37,5 +37,57 @@ module.exports = { "@typescript-eslint/no-unnecessary-boolean-literal-compare": "error", "@typescript-eslint/no-unnecessary-condition": "error", "@typescript-eslint/switch-exhaustiveness-check": "error", + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": "error", + "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/ban-types": "error", + "@typescript-eslint/consistent-generic-constructors": [ + "error", + "type-annotation", + ], + "@typescript-eslint/consistent-indexed-object-style": "error", + "@typescript-eslint/consistent-type-assertions": "error", + "@typescript-eslint/no-array-delete": "error", + "@typescript-eslint/no-confusing-non-null-assertion": "error", + "@typescript-eslint/no-confusing-void-expression": "error", + "@typescript-eslint/no-duplicate-enum-values": "error", + "@typescript-eslint/no-duplicate-type-constituents": "error", + "@typescript-eslint/no-dynamic-delete": "error", + "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-extra-non-null-assertion": "error", + "@typescript-eslint/no-extraneous-class": "error", + "@typescript-eslint/no-floating-promises": "error", + "@typescript-eslint/no-for-in-array": "error", + "no-implied-eval": "off", + "@typescript-eslint/no-implied-eval": "error", + "@typescript-eslint/no-import-type-side-effects": "error", + "@typescript-eslint/no-invalid-void-type": "error", + "no-loss-of-precision": "off", + "@typescript-eslint/no-loss-of-precision": "error", + "@typescript-eslint/no-meaningless-void-operator": "error", + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-misused-promises": "error", + "@typescript-eslint/no-mixed-enums": "error", + "@typescript-eslint/no-namespace": "error", + "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error", + "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-redundant-type-constituents": "error", + "@typescript-eslint/no-this-alias": "error", + "no-throw-literal": "off", + "@typescript-eslint/only-throw-error": "error", + "@typescript-eslint/no-unnecessary-qualifier": "error", + "@typescript-eslint/no-unsafe-unary-minus": "error", + "no-unused-expressions": "off", + "@typescript-eslint/no-unused-expressions": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "error", + "@typescript-eslint/prefer-includes": "error", + "@typescript-eslint/prefer-literal-enum-member": "error", + "@typescript-eslint/prefer-nullish-coalescing": "error", + "@typescript-eslint/prefer-optional-chain": "error", + "@typescript-eslint/prefer-string-starts-ends-with": "error", + "require-await": "off", + "@typescript-eslint/require-await": "error", + "@typescript-eslint/unified-signatures": "error", }, }; diff --git a/scripts/pack.ts b/scripts/pack.ts index a0cc8df80..a98072c20 100644 --- a/scripts/pack.ts +++ b/scripts/pack.ts @@ -23,7 +23,7 @@ const stdlibFiles = glob.sync( const dirPrefixToRemove = posixNormalize(path.resolve(__dirname, "..", "stdlib")) + "/"; // Remove also the leading slash let output: string = ""; -output = "const files: { [key: string]: string } = {};\n"; +output = "const files: Record = {};\n"; for (const f of stdlibFiles) { let code = fs.readFileSync(f).toString("base64"); const name = f.replace(dirPrefixToRemove, ""); diff --git a/scripts/prepare.ts b/scripts/prepare.ts index 13fed6367..a23697b8b 100644 --- a/scripts/prepare.ts +++ b/scripts/prepare.ts @@ -9,7 +9,7 @@ import { consoleLogger } from "../src/logger"; import { __DANGER__disableVersionNumber } from "../src/pipeline/version"; // Read cases -(async () => { +void (async () => { // Disable version number in packages __DANGER__disableVersionNumber(); diff --git a/src/abi/map.ts b/src/abi/map.ts index 371234e01..a2e3b0c9a 100644 --- a/src/abi/map.ts +++ b/src/abi/map.ts @@ -84,21 +84,18 @@ export const MapFunctions: Map = new Map([ if (self.key === "Int") { let bits = 257; let kind = "int"; - if (self.keyAs && self.keyAs.startsWith("int")) { + if (self.keyAs?.startsWith("int")) { bits = parseInt(self.keyAs.slice(3), 10); - } else if (self.keyAs && self.keyAs.startsWith("uint")) { + } else if (self.keyAs?.startsWith("uint")) { bits = parseInt(self.keyAs.slice(4), 10); kind = "uint"; } if (self.value === "Int") { let vBits = 257; let vKind = "int"; - if (self.valueAs && self.valueAs.startsWith("int")) { + if (self.valueAs?.startsWith("int")) { vBits = parseInt(self.valueAs.slice(3), 10); - } else if ( - self.valueAs && - self.valueAs.startsWith("uint") - ) { + } else if (self.valueAs?.startsWith("uint")) { vBits = parseInt(self.valueAs.slice(4), 10); vKind = "uint"; } @@ -148,12 +145,9 @@ export const MapFunctions: Map = new Map([ if (self.value === "Int") { let vBits = 257; let vKind = "int"; - if (self.valueAs && self.valueAs.startsWith("int")) { + if (self.valueAs?.startsWith("int")) { vBits = parseInt(self.valueAs.slice(3), 10); - } else if ( - self.valueAs && - self.valueAs.startsWith("uint") - ) { + } else if (self.valueAs?.startsWith("uint")) { vBits = parseInt(self.valueAs.slice(4), 10); vKind = "uint"; } @@ -258,21 +252,18 @@ export const MapFunctions: Map = new Map([ if (self.key === "Int") { let bits = 257; let kind = "int"; - if (self.keyAs && self.keyAs.startsWith("int")) { + if (self.keyAs?.startsWith("int")) { bits = parseInt(self.keyAs.slice(3), 10); - } else if (self.keyAs && self.keyAs.startsWith("uint")) { + } else if (self.keyAs?.startsWith("uint")) { bits = parseInt(self.keyAs.slice(4), 10); kind = "uint"; } if (self.value === "Int") { let vBits = 257; let vKind = "int"; - if (self.valueAs && self.valueAs.startsWith("int")) { + if (self.valueAs?.startsWith("int")) { vBits = parseInt(self.valueAs.slice(3), 10); - } else if ( - self.valueAs && - self.valueAs.startsWith("uint") - ) { + } else if (self.valueAs?.startsWith("uint")) { vBits = parseInt(self.valueAs.slice(4), 10); vKind = "uint"; } @@ -318,12 +309,9 @@ export const MapFunctions: Map = new Map([ if (self.value === "Int") { let vBits = 257; let vKind = "int"; - if (self.valueAs && self.valueAs.startsWith("int")) { + if (self.valueAs?.startsWith("int")) { vBits = parseInt(self.valueAs.slice(3), 10); - } else if ( - self.valueAs && - self.valueAs.startsWith("uint") - ) { + } else if (self.valueAs?.startsWith("uint")) { vBits = parseInt(self.valueAs.slice(4), 10); vKind = "uint"; } @@ -422,9 +410,9 @@ export const MapFunctions: Map = new Map([ if (self.key === "Int") { let bits = 257; let kind = "int"; - if (self.keyAs && self.keyAs.startsWith("int")) { + if (self.keyAs?.startsWith("int")) { bits = parseInt(self.keyAs.slice(3), 10); - } else if (self.keyAs && self.keyAs.startsWith("uint")) { + } else if (self.keyAs?.startsWith("uint")) { bits = parseInt(self.keyAs.slice(4), 10); kind = "uint"; } diff --git a/src/bindings/typescript/serializers.ts b/src/bindings/typescript/serializers.ts index 81f6a8d90..81c98105f 100644 --- a/src/bindings/typescript/serializers.ts +++ b/src/bindings/typescript/serializers.ts @@ -723,7 +723,7 @@ const map: Serializer = { value = { kind: "cell" }; } } - if (primitiveTypes.indexOf(src.value) === -1) { + if (!primitiveTypes.includes(src.value)) { if ( src.valueFormat === null || src.valueFormat === undefined || diff --git a/src/bindings/writeTypescript.ts b/src/bindings/writeTypescript.ts index 7e8534582..092d1b49f 100644 --- a/src/bindings/writeTypescript.ts +++ b/src/bindings/writeTypescript.ts @@ -78,19 +78,20 @@ export function writeTypescript( `); w.append(); - const allocations: { - [key: string]: { + const allocations: Record< + string, + { size: { bits: number; refs: number }; root: AllocationCell; - }; - } = {}; + } + > = {}; // Structs if (abi.types) { // Allocations const refs = (src: ABIType) => { const res: ABIType[] = []; - const t = new Set(); + const t: Set = new Set(); for (const f of src.fields) { const r = f.type; if (r.kind === "simple") { @@ -142,7 +143,7 @@ export function writeTypescript( // Init if (init) { // Write serializer - const argTypeName = (abi.name || "Contract") + "_init_args"; + const argTypeName = (abi.name ?? "Contract") + "_init_args"; const ops = init.args.map((v) => ({ name: v.name, type: v.type, @@ -191,11 +192,11 @@ export function writeTypescript( ); w.inIndent(() => { if (abi.errors) { - Object.entries(abi.errors).forEach(([k, abiError]) => + Object.entries(abi.errors).forEach(([k, abiError]) => { w.append( `${k}: { message: \`${abiError.message.replaceAll("`", "\\`")}\` },`, - ), - ); + ); + }); } }); w.append(`}`); diff --git a/src/browser.ts b/src/browser.ts index 5dd218640..f6ce4cdd6 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -5,7 +5,7 @@ import { createVirtualFileSystem } from "./vfs/createVirtualFileSystem"; export async function run(args: { config: Config; - files: { [key: string]: string }; + files: Record; logger?: TactLogger | null | undefined; }) { // Verify config diff --git a/src/context.ts b/src/context.ts index 5fab12885..15d1025b9 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,8 +1,8 @@ export class CompilerContext { - readonly shared: { [key: symbol]: object | undefined } = {}; + readonly shared: Record = {}; constructor( - args: { shared: { [key: symbol]: object | undefined } } = { + args: { shared: Record } = { shared: {}, }, ) { @@ -12,7 +12,7 @@ export class CompilerContext { } addShared = (store: symbol, key: string | number, value: T) => { - let sh: { [key: string]: T } = {}; + let sh: Record = {}; if (this.shared[store]) { sh = { ...this.shared[store] }; } @@ -28,18 +28,18 @@ export function createContextStore() { if (!ctx.shared[symbol]) { return null; } - const m = ctx.shared[symbol] as { [key: string | number]: T }; + const m = ctx.shared[symbol] as Record; if (m[key]) { return m[key]; } else { return null; } }, - all(ctx: CompilerContext): { [key: string | number]: T } { + all(ctx: CompilerContext): Record { if (!ctx.shared[symbol]) { - return {} as { [key: string | number]: T }; + return {} as Record; } - const m = ctx.shared[symbol] as { [key: string | number]: T }; + const m = ctx.shared[symbol] as Record; return m; }, set(ctx: CompilerContext, key: string | number, v: T) { diff --git a/src/errors.ts b/src/errors.ts index 0fe11a720..2c7a476d9 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -96,10 +96,6 @@ export function throwConstEvalError( ); } -export function idTextErr(ident: string): string; -export function idTextErr(ident: AstId): string; -export function idTextErr(ident: AstFuncId): string; -export function idTextErr(ident: AstTypeId): string; export function idTextErr( ident: AstId | AstFuncId | AstTypeId | string, ): string { diff --git a/src/generator/Writer.ts b/src/generator/Writer.ts index 5f964b26a..82a4ff0c1 100644 --- a/src/generator/Writer.ts +++ b/src/generator/Writer.ts @@ -32,7 +32,7 @@ export class WriterContext { readonly ctx: CompilerContext; #name: string; #functions: Map = new Map(); - #functionsRendering = new Set(); + #functionsRendering: Set = new Set(); #pendingWriter: Writer | null = null; #pendingCode: Body | null = null; #pendingDepends: Set | null = null; @@ -43,7 +43,7 @@ export class WriterContext { #pendingContext: string | null = null; #nextId = 0; // #headers: string[] = []; - #rendered = new Set(); + #rendered: Set = new Set(); constructor(ctx: CompilerContext, name: string) { this.ctx = ctx; @@ -69,7 +69,7 @@ export class WriterContext { extract(debug: boolean = false) { // Check dependencies - const missing = new Map(); + const missing: Map = new Map(); for (const f of this.#functions.values()) { for (const d of f.depends) { if (!this.#functions.has(d)) { @@ -94,7 +94,7 @@ export class WriterContext { // Remove unused if (!debug) { - const used = new Set(); + const used: Set = new Set(); const visit = (name: string) => { used.add(name); const f = this.#functions.get(name)!; diff --git a/src/generator/createABI.ts b/src/generator/createABI.ts index 2383c47b3..fc714e5e0 100644 --- a/src/generator/createABI.ts +++ b/src/generator/createABI.ts @@ -130,7 +130,7 @@ export function createABI(ctx: CompilerContext, name: string): ContractABI { } // Errors - const errors: { [key: string]: { message: string } } = {}; + const errors: Record = {}; errors["2"] = { message: "Stack underflow" }; errors["3"] = { message: "Stack overflow" }; errors["4"] = { message: "Integer overflow" }; diff --git a/src/generator/writeProgram.ts b/src/generator/writeProgram.ts index 81f4584bd..7262dd674 100644 --- a/src/generator/writeProgram.ts +++ b/src/generator/writeProgram.ts @@ -253,7 +253,7 @@ function tryExtractModule( imported: string[], ): WrittenFunction[] | null { // Put to map - const maps = new Map(); + const maps: Map = new Map(); for (const f of functions) { maps.set(f.name, f); } @@ -378,7 +378,9 @@ function writeAll( // Static functions const sf = getAllStaticFunctions(ctx); - Object.values(sf).forEach((f) => writeFunction(f, wCtx)); + Object.values(sf).forEach((f) => { + writeFunction(f, wCtx); + }); // Extensions for (const c of allTypes) { diff --git a/src/generator/writeReport.ts b/src/generator/writeReport.ts index 8674328f6..5021ac9b7 100644 --- a/src/generator/writeReport.ts +++ b/src/generator/writeReport.ts @@ -40,9 +40,9 @@ export function writeReport(ctx: CompilerContext, pkg: PackageFileFormat) { // Error Codes w.write(`# Error Codes`); - Object.entries(abi.errors!).forEach(([t, abiError]) => - w.write(`${t}: ${abiError.message}`), - ); + Object.entries(abi.errors!).forEach(([t, abiError]) => { + w.write(`${t}: ${abiError.message}`); + }); return w.end(); } diff --git a/src/generator/writers/id.ts b/src/generator/writers/id.ts index 4122115f4..50c55372d 100644 --- a/src/generator/writers/id.ts +++ b/src/generator/writers/id.ts @@ -1,7 +1,5 @@ import { AstId, idText } from "../../grammar/ast"; -export function funcIdOf(ident: string): string; -export function funcIdOf(ident: AstId): string; export function funcIdOf(ident: AstId | string): string { if (typeof ident === "string") { return "$" + ident; @@ -9,8 +7,6 @@ export function funcIdOf(ident: AstId | string): string { return "$" + idText(ident); } -export function funcInitIdOf(ident: string): string; -export function funcInitIdOf(ident: AstId): string; export function funcInitIdOf(ident: AstId | string): string { if (typeof ident === "string") { return ident + "$init"; diff --git a/src/generator/writers/resolveFuncTypeFromAbi.ts b/src/generator/writers/resolveFuncTypeFromAbi.ts index 7ee9634a1..c45b7b5da 100644 --- a/src/generator/writers/resolveFuncTypeFromAbi.ts +++ b/src/generator/writers/resolveFuncTypeFromAbi.ts @@ -41,7 +41,7 @@ export function resolveFuncTypeFromAbi( if (t.kind !== "struct") { throw Error("Unsupported type: " + t.kind); } - if (f.optional || t.fields.length === 0) { + if (f.optional ?? t.fields.length === 0) { res.push("tuple"); } else { const loaded = t.fields.map((v) => v.abi.type); diff --git a/src/generator/writers/resolveFuncTypeFromAbiUnpack.ts b/src/generator/writers/resolveFuncTypeFromAbiUnpack.ts index aacb66038..4652570d7 100644 --- a/src/generator/writers/resolveFuncTypeFromAbiUnpack.ts +++ b/src/generator/writers/resolveFuncTypeFromAbiUnpack.ts @@ -40,7 +40,7 @@ export function resolveFuncTypeFromAbiUnpack( res.push(`${name}'${f.name}`); } else { const t = getType(ctx.ctx, f.type.type); - if (f.type.optional || t.fields.length === 0) { + if (f.type.optional ?? t.fields.length === 0) { res.push(`${name}'${f.name}`); } else { const loaded = t.fields.map((v) => v.abi); diff --git a/src/generator/writers/writeFunction.ts b/src/generator/writers/writeFunction.ts index 8597f33df..66e5c0a6b 100644 --- a/src/generator/writers/writeFunction.ts +++ b/src/generator/writers/writeFunction.ts @@ -275,18 +275,18 @@ export function writeStatement( if (t.key === "Int") { let bits = 257; let kind = "int"; - if (t.keyAs && t.keyAs.startsWith("int")) { + if (t.keyAs?.startsWith("int")) { bits = parseInt(t.keyAs.slice(3), 10); - } else if (t.keyAs && t.keyAs.startsWith("uint")) { + } else if (t.keyAs?.startsWith("uint")) { bits = parseInt(t.keyAs.slice(4), 10); kind = "uint"; } if (t.value === "Int") { let vBits = 257; let vKind = "int"; - if (t.valueAs && t.valueAs.startsWith("int")) { + if (t.valueAs?.startsWith("int")) { vBits = parseInt(t.valueAs.slice(3), 10); - } else if (t.valueAs && t.valueAs.startsWith("uint")) { + } else if (t.valueAs?.startsWith("uint")) { vBits = parseInt(t.valueAs.slice(4), 10); vKind = "uint"; } @@ -372,9 +372,9 @@ export function writeStatement( if (t.value === "Int") { let vBits = 257; let vKind = "int"; - if (t.valueAs && t.valueAs.startsWith("int")) { + if (t.valueAs?.startsWith("int")) { vBits = parseInt(t.valueAs.slice(3), 10); - } else if (t.valueAs && t.valueAs.startsWith("uint")) { + } else if (t.valueAs?.startsWith("uint")) { vBits = parseInt(t.valueAs.slice(4), 10); vKind = "uint"; } diff --git a/src/generator/writers/writeRouter.ts b/src/generator/writers/writeRouter.ts index 396ae6194..9a7835f6d 100644 --- a/src/generator/writers/writeRouter.ts +++ b/src/generator/writers/writeRouter.ts @@ -46,7 +46,7 @@ export function writeRouter( return r.selector.kind === "bounce-fallback"; }); - if (fallbackReceiver || bounceReceivers.length > 0) { + if (fallbackReceiver ?? bounceReceivers.length > 0) { ctx.append(); ctx.append(`;; Skip 0xFFFFFFFF`); ctx.append(`in_msg~skip_bits(32);`); diff --git a/src/grammar/ast.ts b/src/grammar/ast.ts index d961304a2..3f2443e85 100644 --- a/src/grammar/ast.ts +++ b/src/grammar/ast.ts @@ -467,9 +467,6 @@ export type AstFuncId = { loc: SrcInfo; }; -export function idText(ident: AstId): string; -export function idText(ident: AstFuncId): string; -export function idText(ident: AstTypeId): string; export function idText(ident: AstId | AstFuncId | AstTypeId): string { return ident.text; } @@ -518,11 +515,6 @@ export function isRequire(ident: AstId): boolean { return ident.text === "require"; } -export function eqNames(left: string, right: string): boolean; -export function eqNames(left: string, right: AstId): boolean; -export function eqNames(left: AstId, right: string): boolean; -export function eqNames(left: AstId, right: AstId): boolean; -export function eqNames(left: AstId, right: AstId): boolean; export function eqNames( left: AstId | AstTypeId | string, right: AstId | AstTypeId | string, diff --git a/src/grammar/checkConstAttributes.ts b/src/grammar/checkConstAttributes.ts index e4d26ec81..acf5b4286 100644 --- a/src/grammar/checkConstAttributes.ts +++ b/src/grammar/checkConstAttributes.ts @@ -6,7 +6,7 @@ export function checkConstAttributes( attributes: AstConstantAttribute[], loc: SrcInfo, ) { - const k = new Set(); + const k: Set = new Set(); for (const a of attributes) { if (k.has(a.type)) { throwCompilationError( diff --git a/src/grammar/checkFunctionAttributes.ts b/src/grammar/checkFunctionAttributes.ts index 1c99157e6..dce102448 100644 --- a/src/grammar/checkFunctionAttributes.ts +++ b/src/grammar/checkFunctionAttributes.ts @@ -6,7 +6,7 @@ export function checkFunctionAttributes( attrs: AstFunctionAttribute[], loc: SrcInfo, ) { - const k = new Set(); + const k: Set = new Set(); for (const a of attrs) { if (k.has(a.type)) { throwCompilationError( diff --git a/src/grammar/grammar.ts b/src/grammar/grammar.ts index 424bd4eb9..e59d859ec 100644 --- a/src/grammar/grammar.ts +++ b/src/grammar/grammar.ts @@ -108,7 +108,7 @@ semantics.addOperation("astOfModule", { semantics.addOperation("astOfImport", { Import(_importKwd, path, _semicolon) { const pathAST = path.astOfExpression() as AstString; - if (pathAST.value.indexOf("\\") >= 0) { + if (pathAST.value.includes("\\")) { throwCompilationError( 'Import path can\'t contain "\\"', createRef(path), @@ -363,7 +363,7 @@ semantics.addOperation("astOfItem", { receiverBody, _rbrace, ) { - const optParam = optParameter.children[0]; + const optParam = optParameter.children[0] as Node | undefined; const selector: AstReceiverKind = optParam ? { kind: "internal-simple", @@ -667,7 +667,9 @@ semantics.addOperation("astOfStatement", { op = "^"; break; default: - throw "Internal compiler error: unreachable augmented assignment operator. Please report at https://github.com/tact-lang/tact/issues"; + throw Error( + "Internal compiler error: unreachable augmented assignment operator. Please report at https://github.com/tact-lang/tact/issues", + ); } return createAstNode({ kind: "statement_augmentedassign", diff --git a/src/grammar/iterators.ts b/src/grammar/iterators.ts index b7a5f5076..a2f287005 100644 --- a/src/grammar/iterators.ts +++ b/src/grammar/iterators.ts @@ -31,9 +31,9 @@ export function forEachExpression( expr.args.forEach(traverseExpression); break; case "struct_instance": - expr.args.forEach((param) => - traverseExpression(param.initializer), - ); + expr.args.forEach((param) => { + traverseExpression(param.initializer); + }); break; case "init_of": expr.args.forEach(traverseExpression); diff --git a/src/imports/resolveImports.ts b/src/imports/resolveImports.ts index b3d2780f2..f42c5357a 100644 --- a/src/imports/resolveImports.ts +++ b/src/imports/resolveImports.ts @@ -28,7 +28,7 @@ export function resolveImports(args: { []; const importedFunc: { code: string; path: string; origin: ItemOrigin }[] = []; - const processed = new Set(); + const processed: Set = new Set(); const pending: { code: string; path: string; origin: ItemOrigin }[] = []; function processImports(source: string, path: string, origin: ItemOrigin) { const imp = parseImports(source, path, origin); diff --git a/src/imports/stdlib.ts b/src/imports/stdlib.ts index ac2c11533..9806bb6b8 100644 --- a/src/imports/stdlib.ts +++ b/src/imports/stdlib.ts @@ -1,4 +1,4 @@ -const files: { [key: string]: string } = {}; +const files: Record = {}; files['libs/config.tact'] = 'ZnVuIGdldENvbmZpZ0FkZHJlc3MoKTogQWRkcmVzcyB7CiAgICBsZXQgY2VsbDogQ2VsbCA9IGdldENvbmZpZ1BhcmFtKDApISE7CiAgICBsZXQgc2M6IFNsaWNlID0g' + 'Y2VsbC5iZWdpblBhcnNlKCk7CiAgICByZXR1cm4gbmV3QWRkcmVzcygtMSwgc2MubG9hZFVpbnQoMjU2KSk7Cn0KCmZ1biBnZXRFbGVjdG9yQWRkcmVzcygpOiBBZGRy' + diff --git a/src/node.ts b/src/node.ts index acbb8846e..c81eb3da7 100644 --- a/src/node.ts +++ b/src/node.ts @@ -14,9 +14,7 @@ type ConfigWithRootPath = Config & { singleFile: boolean; }; -async function configForSingleFile( - fileName: string, -): Promise { +function configForSingleFile(fileName: string): ConfigWithRootPath { return { projects: [ { @@ -32,10 +30,10 @@ async function configForSingleFile( }; } -async function loadConfig( +function loadConfig( fileName?: string, configPath?: string, -): Promise { +): ConfigWithRootPath | null { if (fileName) return configForSingleFile(fileName); if (!configPath) return null; @@ -103,10 +101,7 @@ export async function run(args: { consoleLogger.log("💼 Compiling project " + config.name + "..."); let cliConfig = { ...config }; - if ( - args.additionalCliOptions !== undefined && - args.additionalCliOptions.mode !== undefined - ) { + if (args.additionalCliOptions?.mode !== undefined) { cliConfig = { ...config, ...args.additionalCliOptions }; } diff --git a/src/pipeline/build.ts b/src/pipeline/build.ts index b49182bfa..bcc35e6a6 100644 --- a/src/pipeline/build.ts +++ b/src/pipeline/build.ts @@ -33,13 +33,13 @@ export async function build(args: { typeof args.stdlib === "string" ? createVirtualFileSystem(args.stdlib, files) : args.stdlib; - const logger: TactLogger = args.logger || consoleLogger; + const logger: TactLogger = args.logger ?? consoleLogger; // Configure context let ctx: CompilerContext = new CompilerContext({ shared: {} }); const cfg: string = JSON.stringify({ entrypoint: posixNormalize(config.path), - options: config.options || {}, + options: config.options ?? {}, }); if (config.options) { if (config.options.debug) { @@ -54,7 +54,7 @@ export async function build(args: { logger.error(" > 👀 Enabling external"); ctx = featureEnable(ctx, "external"); } - if (config.options.experimental && config.options.experimental.inline) { + if (config.options.experimental?.inline) { logger.error(" > 👀 Enabling inline"); ctx = featureEnable(ctx, "inline"); } @@ -80,14 +80,14 @@ export async function build(args: { // Compile contracts let ok = true; - const built: { - [key: string]: - | { - codeBoc: Buffer; - abi: string; - } - | undefined; - } = {}; + const built: Record< + string, + | { + codeBoc: Buffer; + abi: string; + } + | undefined + > = {}; for (const contract of getContracts(ctx)) { const pathAbi = project.resolve( config.output, @@ -245,7 +245,7 @@ export async function build(args: { const systemCell = beginCell().storeDict(depends).endCell(); // Collect sources - const sources: { [key: string]: string } = {}; + const sources: Record = {}; const rawAst = getRawAST(ctx); for (const source of [...rawAst.funcSources, ...rawAst.sources]) { if ( diff --git a/src/storage/resolveAllocation.ts b/src/storage/resolveAllocation.ts index cc5c1fe30..74c2f63fd 100644 --- a/src/storage/resolveAllocation.ts +++ b/src/storage/resolveAllocation.ts @@ -33,7 +33,7 @@ export function getSortedTypes(ctx: CompilerContext) { let structs = types.filter((t) => t.kind === "struct"); const refs = (src: TypeDescription) => { const res: TypeDescription[] = []; - const t = new Set(); + const t: Set = new Set(); for (const f of src.fields) { const r = f.type; if (r.kind === "ref") { diff --git a/src/test/e2e-emulated/dns.spec.ts b/src/test/e2e-emulated/dns.spec.ts index b3c5dae07..3f75a26d1 100644 --- a/src/test/e2e-emulated/dns.spec.ts +++ b/src/test/e2e-emulated/dns.spec.ts @@ -81,12 +81,10 @@ describe("dns", () => { ["t1n.dns", "tin.dns"], ]; - for (let i = 0; i < invalidNames.length; i++) { - it(`should fail on invalid name: ${invalidNames[i]!}`, async () => { - expect(await contract.getStringToInternal(invalidNames[i]!)).toBe( - null, - ); - const internalAddress = convertToInternal(invalidNames[i]!); + for (const invalidName of invalidNames) { + it(`should fail on invalid name: ${invalidName}`, async () => { + expect(await contract.getStringToInternal(invalidName)).toBe(null); + const internalAddress = convertToInternal(invalidName); expect( await contract.getDnsInternalVerify( beginCell().storeBuffer(internalAddress).endCell(), @@ -95,38 +93,36 @@ describe("dns", () => { }); } - for (let i = 0; i < validNames.length; i++) { - it(`should convert valid name: ${validNames[i]!}`, async () => { - const data = (await contract.getStringToInternal(validNames[i]!))!; + for (const validName of validNames) { + it(`should convert valid name: ${validName}`, async () => { + const data = (await contract.getStringToInternal(validName))!; const received = data .beginParse() .loadBuffer(data.bits.length / 8) .toString("hex"); expect(received).toBe( convertToInternal( - validNames[i]!.endsWith(".") && validNames[i]! !== "." - ? validNames[i]!.slice(0, validNames[i]!.length - 1) - : validNames[i]!, + validName.endsWith(".") && validName !== "." + ? validName.slice(0, validName.length - 1) + : validName, ).toString("hex"), ); }); } - for (let i = 0; i < validNames.length; i++) { - if (validNames[i]! !== ".") { - it(`should convert valid name: ${validNames[i]!}`, async () => { - const data = (await contract.getStringToInternal( - validNames[i]!, - ))!; + for (const validName of validNames) { + if (validName !== ".") { + it(`should convert valid name: ${validName}`, async () => { + const data = (await contract.getStringToInternal(validName))!; expect(await contract.getDnsInternalVerify(data)).toBe(true); }); } } - for (let i = 0; i < equalNormalized.length; i++) { - it(`should convert equal normalized names: ${equalNormalized[i]![0]!} ${equalNormalized[i]![1]!}`, async () => { + for (const equalNormalizedElem of equalNormalized) { + it(`should convert equal normalized names: ${equalNormalizedElem[0]!} ${equalNormalizedElem[1]!}`, async () => { let data1 = (await contract.getStringToInternal( - equalNormalized[i]![0]!, + equalNormalizedElem[0]!, ))!; data1 = await contract.getInternalNormalize(data1); const received1 = data1 @@ -134,7 +130,7 @@ describe("dns", () => { .loadBuffer(data1.bits.length / 8) .toString("hex"); let data2 = (await contract.getStringToInternal( - equalNormalized[i]![1]!, + equalNormalizedElem[1]!, ))!; data2 = await contract.getInternalNormalize(data2); const received2 = data2 @@ -145,10 +141,10 @@ describe("dns", () => { expect(received1.length).toBe(received2.length); }); } - for (let i = 0; i < notEqualNormalized.length; i++) { - it(`should convert not equal normalized names: ${notEqualNormalized[i]![0]!} ${notEqualNormalized[i]![1]!}`, async () => { + for (const notEqualNormalizedElem of notEqualNormalized) { + it(`should convert not equal normalized names: ${notEqualNormalizedElem[0]!} ${notEqualNormalizedElem[1]!}`, async () => { let data1 = (await contract.getStringToInternal( - notEqualNormalized[i]![0]!, + notEqualNormalizedElem[0]!, ))!; data1 = await contract.getInternalNormalize(data1); const received1 = data1 @@ -156,7 +152,7 @@ describe("dns", () => { .loadBuffer(data1.bits.length / 8) .toString("hex"); let data2 = (await contract.getStringToInternal( - notEqualNormalized[i]![1]!, + notEqualNormalizedElem[1]!, ))!; data2 = await contract.getInternalNormalize(data2); const received2 = data2 @@ -168,18 +164,18 @@ describe("dns", () => { }); } - for (let i = 0; i < validNames.length; i++) { - it("should resolve name " + validNames[i]!, async () => { - const internalAddress = convertToInternal(validNames[i]!); + for (const validName of validNames) { + it("should resolve name " + validName, async () => { + const internalAddress = convertToInternal(validName); const resolved = (await contract.getDnsresolve( beginCell().storeBuffer(internalAddress).endCell(), 1n, ))!; expect(resolved.prefix).toBe(BigInt(internalAddress.length * 8)); - if (validNames[i]! === ".") { + if (validName === ".") { expect(resolved.record!.bits.length).toBe(0); expect(resolved.record!.refs.length).toBe(0); - } else if (validNames[i]!.endsWith(".")) { + } else if (validName.endsWith(".")) { expect( resolved .record!.beginParse() @@ -197,9 +193,9 @@ describe("dns", () => { }); } - for (let i = 0; i < invalidNames.length; i++) { - it("should not resolve name " + invalidNames[i]!, async () => { - const internalAddress = convertToInternal(invalidNames[i]!); + for (const invalidName of invalidNames) { + it("should not resolve name " + invalidName, async () => { + const internalAddress = convertToInternal(invalidName); await expect( contract.getDnsresolve( beginCell().storeBuffer(internalAddress).endCell(), @@ -209,40 +205,34 @@ describe("dns", () => { }); } - for (let i = 0; i < validNames.length; i++) { - if (validNames[i]!.endsWith(".")) { + for (const validName of validNames) { + if (validName.endsWith(".")) { continue; } - it( - "should resolve name with leading zero " + validNames[i]!, - async () => { - const internalAddress = convertToInternal(validNames[i]!); - const resolved = (await contract.getDnsresolve( - beginCell() - .storeBuffer( - Buffer.concat([ - Buffer.alloc(1, 0), - internalAddress, - ]), - ) - .endCell(), - 1n, - ))!; - expect(resolved.prefix).toBe( - BigInt(internalAddress.length * 8 + 8), - ); - if (validNames[i]! === ".") { - expect(resolved.record!.bits.length).toBe(0); - expect(resolved.record!.refs.length).toBe(0); - } else { - expect( - resolved - .record!.beginParse() - .loadBuffer(internalAddress.length) - .toString("hex"), - ).toBe(internalAddress.toString("hex")); - } - }, - ); + it("should resolve name with leading zero " + validName, async () => { + const internalAddress = convertToInternal(validName); + const resolved = (await contract.getDnsresolve( + beginCell() + .storeBuffer( + Buffer.concat([Buffer.alloc(1, 0), internalAddress]), + ) + .endCell(), + 1n, + ))!; + expect(resolved.prefix).toBe( + BigInt(internalAddress.length * 8 + 8), + ); + if (validName === ".") { + expect(resolved.record!.bits.length).toBe(0); + expect(resolved.record!.refs.length).toBe(0); + } else { + expect( + resolved + .record!.beginParse() + .loadBuffer(internalAddress.length) + .toString("hex"), + ).toBe(internalAddress.toString("hex")); + } + }); } }); diff --git a/src/test/e2e-emulated/masterchain.spec.ts b/src/test/e2e-emulated/masterchain.spec.ts index b920bf0ce..f584c285a 100644 --- a/src/test/e2e-emulated/masterchain.spec.ts +++ b/src/test/e2e-emulated/masterchain.spec.ts @@ -121,7 +121,7 @@ describe("masterchain", () => { await contract.send(treasure, { value: toNano("10") }, "Deploy"); await system.run(); const addr = new Address(-1, Buffer.alloc(32, 0)); - expect( + void expect( contract.getParseAddress(beginCell().storeAddress(addr).endCell()), ).rejects.toThrowError( "Masterchain support is not enabled for this contract", @@ -181,7 +181,7 @@ describe("masterchain", () => { await contract.send(treasure, { value: toNano("10") }, "Deploy"); await system.run(); const addr = new Address(-1, Buffer.alloc(32, 0)); - expect(contract.getSerializeAddress(addr)).rejects.toThrowError( + void expect(contract.getSerializeAddress(addr)).rejects.toThrowError( "Masterchain support is not enabled for this contract", ); }); @@ -237,7 +237,7 @@ describe("masterchain", () => { await system.run(); const addr = new Address(-1, Buffer.alloc(32, 0)); const addr2 = new Address(0, Buffer.alloc(32, 0)); - expect( + void expect( contract.getHandleStruct({ $$type: "TestMessage", address: addr, @@ -246,7 +246,7 @@ describe("masterchain", () => { ).rejects.toThrowError( "Masterchain support is not enabled for this contract", ); - expect( + void expect( contract.getHandleStruct({ $$type: "TestMessage", address: addr2, diff --git a/src/types/createTLBType.ts b/src/types/createTLBType.ts index ec039a26b..088b19f61 100644 --- a/src/types/createTLBType.ts +++ b/src/types/createTLBType.ts @@ -110,13 +110,12 @@ export function createTLBType( } else { const base = cs.snakeCase(name) + " " + fields + " = " + name; const op = - knownHeader !== null - ? knownHeader - : beginCell() - .storeBuffer(sha256_sync(base)) - .endCell() - .beginParse() - .loadUint(32); + knownHeader ?? + beginCell() + .storeBuffer(sha256_sync(base)) + .endCell() + .beginParse() + .loadUint(32); const opText = beginCell() .storeUint(op, 32) .endCell() diff --git a/src/types/resolveABITypeRef.ts b/src/types/resolveABITypeRef.ts index 9554b2ad8..fad934331 100644 --- a/src/types/resolveABITypeRef.ts +++ b/src/types/resolveABITypeRef.ts @@ -21,9 +21,10 @@ import { } from "../errors"; import { TypeRef } from "./types"; -type FormatDef = { - [key: string]: { type: string; format: string | number } | undefined; -}; +type FormatDef = Record< + string, + { type: string; format: string | number } | undefined +>; const intFormats: FormatDef = { int8: { type: "int", format: 8 }, diff --git a/src/types/resolveDescriptors.ts b/src/types/resolveDescriptors.ts index 829c051fb..dd43815d5 100644 --- a/src/types/resolveDescriptors.ts +++ b/src/types/resolveDescriptors.ts @@ -822,7 +822,7 @@ export function resolveDescriptors(ctx: CompilerContext) { } // Check parameter names - const exNames = new Set(); + const exNames: Set = new Set(); for (const param of params) { if (isSelfId(param.name)) { throwCompilationError( @@ -1297,7 +1297,7 @@ export function resolveDescriptors(ctx: CompilerContext) { for (const t of types.values()) { if (t.ast.kind === "trait" || t.ast.kind === "contract") { // Check there are no duplicates in the _immediately_ inherited traits - const traitSet = new Set(t.ast.traits.map(idText)); + const traitSet: Set = new Set(t.ast.traits.map(idText)); if (traitSet.size !== t.ast.traits.length) { const aggregateType = t.ast.kind === "contract" ? "contract" : "trait"; @@ -1308,7 +1308,7 @@ export function resolveDescriptors(ctx: CompilerContext) { } // Flatten traits const traits: TypeDescription[] = []; - const visited = new Set(); + const visited: Set = new Set(); visited.add(t.name); // eslint-disable-next-line no-inner-declarations function visit(name: string) { @@ -1410,7 +1410,7 @@ export function resolveDescriptors(ctx: CompilerContext) { } // Check overrides - if (funInContractOrTrait && funInContractOrTrait.isOverrides) { + if (funInContractOrTrait?.isOverrides) { if ( traitFunction.isGetter && !funInContractOrTrait.isGetter @@ -1503,8 +1503,7 @@ export function resolveDescriptors(ctx: CompilerContext) { // Check overrides if ( - constInContractOrTrait && - constInContractOrTrait.ast.attributes.find( + constInContractOrTrait?.ast.attributes.find( (v) => v.type === "overrides", ) ) { @@ -1635,8 +1634,8 @@ export function resolveDescriptors(ctx: CompilerContext) { // Copy to non-traits to avoid duplicates - const processed = new Set(); - const processing = new Set(); + const processed: Set = new Set(); + const processing: Set = new Set(); function processType(name: string) { // Check if processed @@ -1675,7 +1674,7 @@ export function resolveDescriptors(ctx: CompilerContext) { // for (const [k, t] of types) { - const dependsOn = new Set(); + const dependsOn: Set = new Set(); const handler = (src: AstNode) => { if (src.kind === "init_of") { if (!types.has(idText(src.contract))) { @@ -1720,7 +1719,7 @@ export function resolveDescriptors(ctx: CompilerContext) { } } for (const k of types.keys()) { - const dependsOn = new Set(); + const dependsOn: Set = new Set(); dependsOn.add(k); collectTransient(k, dependsOn); for (const s of dependsOn) { @@ -1801,8 +1800,6 @@ export function resolveDescriptors(ctx: CompilerContext) { return ctx; } -export function getType(ctx: CompilerContext, ident: AstId): TypeDescription; -export function getType(ctx: CompilerContext, ident: string): TypeDescription; export function getType( ctx: CompilerContext, ident: AstId | string, diff --git a/src/types/resolveExpression.ts b/src/types/resolveExpression.ts index b5c02fe62..a14f395d5 100644 --- a/src/types/resolveExpression.ts +++ b/src/types/resolveExpression.ts @@ -125,7 +125,7 @@ function resolveStructNew( } // Process fields - const processed = new Set(); + const processed: Set = new Set(); for (const e of exp.args) { // Check duplicates if (processed.has(idText(e.field))) { diff --git a/src/types/resolveSignatures.ts b/src/types/resolveSignatures.ts index 2f4e9566c..97f4f3941 100644 --- a/src/types/resolveSignatures.ts +++ b/src/types/resolveSignatures.ts @@ -15,10 +15,10 @@ import { commentPseudoOpcode } from "../generator/writers/writeRouter"; export function resolveSignatures(ctx: CompilerContext) { const types = getAllTypes(ctx); - const signatures = new Map< + const signatures: Map< string, { signature: string; tlb: string; id: number | null } - >(); + > = new Map(); function createTypeFormat( type: string, format: string | number | boolean | null, @@ -226,12 +226,14 @@ function checkMessageOpcodesUniqueInContractOrTrait( receivers: ReceiverDescription[], ctx: CompilerContext, ) { - const binBouncedRcvUsedOpcodes = new Map(); - const binExternalRcvUsedOpcodes = new Map(); - const binInternalRcvUsedOpcodes = new Map(); + const binBouncedRcvUsedOpcodes: Map = new Map(); + const binExternalRcvUsedOpcodes: Map = new Map(); + const binInternalRcvUsedOpcodes: Map = new Map(); - const commentExternalRcvUsedOpcodes = new Map(); - const commentInternalRcvUsedOpcodes = new Map(); + const commentExternalRcvUsedOpcodes: Map = + new Map(); + const commentInternalRcvUsedOpcodes: Map = + new Map(); for (const rcv of receivers) { switch (rcv.selector.kind) { diff --git a/src/types/types.ts b/src/types/types.ts index eafd28cd4..554cf00ce 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -63,6 +63,9 @@ export type TypeRef = kind: "null"; }; +// https://github.com/microsoft/TypeScript/issues/35164 and +// https://github.com/microsoft/TypeScript/pull/57293 +// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style export type StructValue = { [key: string]: Value; }; diff --git a/src/utils/calculateIPFSlink.ts b/src/utils/calculateIPFSlink.ts index 379151b9b..cc5eb5a38 100644 --- a/src/utils/calculateIPFSlink.ts +++ b/src/utils/calculateIPFSlink.ts @@ -4,7 +4,7 @@ import { MemoryBlockstore } from "blockstore-core/memory"; export async function calculateIPFSlink(data: Buffer) { const blockstore = new MemoryBlockstore(); const cid = await new Promise((resolve, reject) => { - (async () => { + void (async () => { try { for await (const entry of importer( { content: data }, diff --git a/src/utils/errorToString.ts b/src/utils/errorToString.ts index a0477e996..0d6676e0e 100644 --- a/src/utils/errorToString.ts +++ b/src/utils/errorToString.ts @@ -1,6 +1,6 @@ export function errorToString(src: unknown): string { if (src instanceof Error) { - return src.stack || src.message; + return src.stack ?? src.message; } else { // eslint-disable-next-line @typescript-eslint/restrict-template-expressions return `${src}`; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index f693fecbf..34f3ac662 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -2,8 +2,8 @@ import { crc16 } from "./crc16"; export function topologicalSort(src: T[], references: (src: T) => T[]) { const result: T[] = []; - const visited = new Set(); - const visiting = new Set(); + const visited: Set = new Set(); + const visiting: Set = new Set(); const visit = (src: T) => { if (visiting.has(src)) { throw Error("Cycle detected"); diff --git a/src/verify.ts b/src/verify.ts index 06784f739..b466d3d8c 100644 --- a/src/verify.ts +++ b/src/verify.ts @@ -10,7 +10,7 @@ export type VerifyResult = | { ok: true; package: PackageFileFormat; - files: { [key: string]: string }; + files: Record; } | { ok: false; @@ -26,7 +26,7 @@ export async function verify(args: { pkg: string; logger?: TactLogger | null | undefined; }): Promise { - const logger = args.logger || consoleLogger; + const logger = args.logger ?? consoleLogger; // Loading package let unpacked: PackageFileFormat; diff --git a/src/vfs/createVirtualFileSystem.spec.ts b/src/vfs/createVirtualFileSystem.spec.ts index eddeea9d5..b13b7a867 100644 --- a/src/vfs/createVirtualFileSystem.spec.ts +++ b/src/vfs/createVirtualFileSystem.spec.ts @@ -13,7 +13,7 @@ describe("createVirtualFileSystem", () => { }); it("should read from virtual file system", () => { - const fs: { [key: string]: string } = { + const fs: Record = { ["file.txt"]: Buffer.from("Hello World").toString("base64"), ["empty.txt"]: Buffer.from([]).toString("base64"), }; diff --git a/src/vfs/createVirtualFileSystem.ts b/src/vfs/createVirtualFileSystem.ts index 7129c4edc..66ff5d6ee 100644 --- a/src/vfs/createVirtualFileSystem.ts +++ b/src/vfs/createVirtualFileSystem.ts @@ -3,7 +3,7 @@ import { VirtualFileSystem } from "./VirtualFileSystem"; export function createVirtualFileSystem( root: string, - fs: { [key: string]: string }, + fs: Record, readonly: boolean = true, ): VirtualFileSystem { let normalizedRoot = normalize(root); @@ -21,10 +21,10 @@ export function createVirtualFileSystem( const name = filePath.slice(normalizedRoot.length); return typeof fs[name] === "string"; }, - resolve(...filePath) { + resolve(...filePath): string { return normalize([normalizedRoot, ...filePath].join("/")); }, - readFile(filePath) { + readFile(filePath): Buffer { if (!filePath.startsWith(normalizedRoot)) { throw new Error( `Path '${filePath}' is outside of the root directory '${normalizedRoot}'`, @@ -38,7 +38,7 @@ export function createVirtualFileSystem( return Buffer.from(content, "base64"); } }, - writeFile(filePath, content) { + writeFile(filePath, content): void { if (readonly) { throw new Error("File system is readonly"); } diff --git a/tsconfig.json b/tsconfig.json index 145828e33..e0afe7b19 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -34,7 +34,7 @@ /* Additional Checks */ // "noUnusedLocals": true, /* Report errors on unused locals. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ "noUncheckedIndexedAccess": true /* Include 'undefined' in index signature results */, // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */