Skip to content

Commit

Permalink
refactor: ESLint whole Tact codebase (#157)
Browse files Browse the repository at this point in the history
Most changes are `let` -> `const` using the following command:

```shell
yarn eslint . --fix --rule 'prefer-const: "error"'
```

* change code generation of `./src/imports/stdlib.ts` file to fix the `prefer-const` error.

* refactor `writeParserCell` and `writeParserField` functions

* refactor `resolveFuncTupledType`: remove unused parameter

* add ESLint to CI
  • Loading branch information
anton-trunov authored Feb 29, 2024
1 parent 8ae9866 commit 6c35689
Show file tree
Hide file tree
Showing 116 changed files with 4,142 additions and 1,268 deletions.
11 changes: 11 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules/
dist/
coverage/
**/output/
./src/test/bugs/output/
./src/test/features/output/
src/func/funcfiftlib.js
src/grammar/grammar.ohm*.ts
src/grammar/grammar.ohm*.js
jest.setup.js
jest.teardown.js
26 changes: 26 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-env node */
module.exports = {
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
root: true,
env: {
node: true,
es2021: true,
},
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
}
],
"@typescript-eslint/no-var-requires": ['error',
{
allow: ['/package\\.json$']
}
],
},
};
4 changes: 4 additions & 0 deletions .github/workflows/tact.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ jobs:
yarn gen
yarn build
yarn coverage
- name: Check there are no errors reported by ESLint
run: |
yarn lint
- name: Compare Tact version from CLI flag `--version` against package.json
if: runner.os != 'Windows'
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The equality and non-equality operators (`==` and `!=`) now support slices and strings by comparing the hashes of the left-hand and right-hand sides : PR [#105](https://github.com/tact-lang/tact/pull/105)
- Continuous integration now tests the dev [tact-template](https://github.com/tact-lang/tact-template)'s version with the dev version of Tact: PR [#111](https://github.com/tact-lang/tact/pull/111)
- Continuous integration now tests the latest [Blueprint](https://github.com/ton-org/blueprint)'s version with the dev version of Tact: PR [#152](https://github.com/tact-lang/tact/pull/152)
- Continuous integration now checks there are no ESLint warnings: PR [#157](https://github.com/tact-lang/tact/pull/157)

### Fixed
- Relative imports from parent directories: PR [#125](https://github.com/tact-lang/tact/pull/125)
- The typechecker failed to identify different types when using the `==` and `!=` operators: PR [#127](https://github.com/tact-lang/tact/pull/127)
- ESLint warnings for the whole Tact codebase: PR [#157](https://github.com/tact-lang/tact/pull/157)

## [1.1.5] - 2023-12-01

Expand Down
21 changes: 4 additions & 17 deletions examples/increment.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ describe('increment', () => {
it('should deploy', async () => {

// Create wallet
let system = await ContractSystem.create();
let treasure = system.treasure('treasure');
let contract = system.open(await IncrementContract.fromInit());
let tracker = system.track(contract.address);
const system = await ContractSystem.create();
const treasure = system.treasure('treasure');
const contract = system.open(await IncrementContract.fromInit());
const tracker = system.track(contract.address);
await contract.send(treasure, { value: toNano('10') }, { $$type: 'Deploy', queryId: 0n });
await system.run();
expect(tracker.collect()).toMatchSnapshot();
Expand All @@ -18,18 +18,5 @@ describe('increment', () => {
await contract.send(treasure, { value: toNano('10') }, { $$type: 'Increment', key: 0n, value: -1232n });
await system.run();
expect(tracker.collect()).toMatchSnapshot();

// Get counters
let counters = await contract.getCounters();
let counters2 = await contract.getCounters2();

// let res = await executor.get('counters');
// let dict = parseDict(res.stack.readCell().beginParse(), 257, (sc) => sc.readInt(257).toString(10));
// // console.warn(dict);

// let res2 = await executor.get('counters2');
// let dict2 = parseDict(res2.stack.readCell().beginParse(), 267, (sc) => sc.readInt(257).toString(10));
// // console.warn(dict2);
// // new BN(Array.from(dict.keys())[0]).toString('hex');
});
});
14 changes: 7 additions & 7 deletions examples/multisig-3.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ describe('muiltisig-3', () => {
it('should deploy', async () => {

// Init contract
let key1 = 1n;
let key2 = 1n;
let key3 = 1n;
let system = await ContractSystem.create();
let treasure = system.treasure('treasure');
let contract = system.open(await MultisigContract.fromInit(key1, key2, key3));
let tracker = system.track(contract.address);
const key1 = 1n;
const key2 = 1n;
const key3 = 1n;
const system = await ContractSystem.create();
const treasure = system.treasure('treasure');
const contract = system.open(await MultisigContract.fromInit(key1, key2, key3));
const tracker = system.track(contract.address);
await contract.send(treasure, { value: toNano('10') }, 'Deploy');
await system.run();
expect(tracker.collect()).toMatchSnapshot();
Expand Down
16 changes: 8 additions & 8 deletions examples/wallet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ describe('wallet', () => {
it('should deploy', async () => {

// Create wallet
let key = testKey('wallet-key');
let publicKey = beginCell().storeBuffer(key.publicKey).endCell().beginParse().loadUintBig(256);
let system = await ContractSystem.create();
let treasure = system.treasure('treasure');
let contract = system.open(await Wallet.fromInit(publicKey, 0n));
let tracker = system.track(contract.address);
const key = testKey('wallet-key');
const publicKey = beginCell().storeBuffer(key.publicKey).endCell().beginParse().loadUintBig(256);
const system = await ContractSystem.create();
const treasure = system.treasure('treasure');
const contract = system.open(await Wallet.fromInit(publicKey, 0n));
const tracker = system.track(contract.address);
await contract.send(treasure, { value: toNano('10') }, 'Deploy');
await system.run();

Expand All @@ -22,15 +22,15 @@ describe('wallet', () => {
expect(await contract.getSeqno()).toBe(0n);

// Send transfer and check seqno
let transfer: Transfer = {
const transfer: Transfer = {
$$type: 'Transfer',
seqno: 0n,
mode: 1n,
amount: toNano(10),
to: treasure.address,
body: null
};
let signature = sign(beginCell().store(storeTransfer(transfer)).endCell().hash(), key.secretKey);
const signature = sign(beginCell().store(storeTransfer(transfer)).endCell().hash(), key.secretKey);
await contract.send(treasure, { value: toNano(1) }, {
$$type: 'TransferMessage',
transfer,
Expand Down
1 change: 1 addition & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const coverage = require('@tact-lang/coverage');

module.exports = async () => {
Expand Down
16 changes: 10 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"build": "tsc && cp ./src/grammar/grammar.ohm* ./dist/grammar/ && cp ./src/func/funcfiftlib.* ./dist/func",
"test": "jest",
"coverage": "cross-env COVERAGE=true jest",
"release": "yarn clean && yarn build && yarn coverage && yarn release-it --npm.yarn1"
"release": "yarn clean && yarn build && yarn coverage && yarn release-it --npm.yarn1",
"lint": "yarn eslint ."
},
"files": [
"dist/**/*",
Expand All @@ -30,6 +31,8 @@
"dependencies": {
"@ipld/dag-pb": "2.1.18",
"@tact-lang/opcode": "^0.0.14",
"@ton/core": "0.49.2",
"@ton/crypto": "^3.2.0",
"arg": "^5.0.2",
"blockstore-core": "1.0.5",
"change-case": "^4.1.2",
Expand All @@ -40,21 +43,24 @@
"path-normalize": "^6.0.10",
"prando": "^6.0.1",
"qs": "^6.11.0",
"@ton/core": "0.49.2",
"@ton/crypto": "^3.2.0",
"zod": "^3.20.2"
},
"devDependencies": {
"@ohm-js/cli": "^1.1.0",
"@release-it/keep-a-changelog": "^3.1.0",
"@tact-lang/coverage": "^0.0.8",
"@tact-lang/emulator": "^4.2.3",
"@tact-lang/ton-abi": "^0.0.3",
"@tact-lang/ton-jest": "^0.0.4",
"@types/glob": "^8.1.0",
"@types/jest": "^29.2.3",
"@types/js-yaml": "^4.0.5",
"@types/node": "^18.11.9",
"@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"cross-env": "^7.0.3",
"eslint": "^8.56.0",
"glob": "^8.1.0",
"jest": "^29.3.1",
"js-yaml": "^4.1.0",
Expand All @@ -63,11 +69,9 @@
"rollup": "^3.17.2",
"shiki": "^0.12.1",
"ton-compiler": "^2.3.0",
"@tact-lang/ton-jest": "^0.0.4",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"typescript": "^4.9.3",
"@tact-lang/ton-abi": "^0.0.3"
"typescript": "^4.9.3"
},
"publishConfig": {
"access": "public",
Expand Down
27 changes: 15 additions & 12 deletions scripts/grammar.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { getHighlighter, BUNDLED_LANGUAGES, BUNDLED_THEMES } from 'shiki';
import { getHighlighter, BUNDLED_LANGUAGES, BUNDLED_THEMES, ILanguageRegistration } from 'shiki';
import fs from 'fs';
import yaml from 'js-yaml';
import path from 'path';

(async () => {

// Patch grammar bundler
let grammarBundlePath = path.resolve(__dirname, '..', 'src', 'grammar', 'grammar.ohm-bundle.js');
const grammarBundlePath = path.resolve(__dirname, '..', 'src', 'grammar', 'grammar.ohm-bundle.js');
let src = fs.readFileSync(grammarBundlePath, 'utf-8');
src = src.replace(`require('ohm-js')`, `(require('ohm-js').default || require('ohm-js'))`);
fs.writeFileSync(grammarBundlePath, src, 'utf-8');

// Load textmate grammar
let sourceGrammar = fs.readFileSync(require.resolve('../grammar/tact.tmLanguage.yaml'), 'utf-8');
const sourceGrammar = fs.readFileSync(require.resolve('../grammar/tact.tmLanguage.yaml'), 'utf-8');
let loadedGrammar = yaml.load(sourceGrammar);

// Process grammar
Expand All @@ -23,6 +23,7 @@ import path from 'path';
}
return result;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function transformGrammarRule(rule: any, propertyNames: string[], transformProperty: (ruleProperty: string) => string) {
for (const propertyName of propertyNames) {
const value = rule[propertyName];
Expand All @@ -31,22 +32,24 @@ import path from 'path';
}
}

for (var propertyName in rule) {
for (const propertyName in rule) {
const value = rule[propertyName];
if (typeof value === 'object') {
transformGrammarRule(value, propertyNames, transformProperty);
}
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function transformGrammarRepository(grammar: any, propertyNames: string[], transformProperty: (ruleProperty: string) => string) {
const repository = grammar.repository;
for (let key in repository) {
for (const key in repository) {
transformGrammarRule(repository[key], propertyNames, transformProperty);
}
}
type VariableReplacer = [RegExp, string];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function processGrammar(src: any) {
let variables = src.variables;
const variables = src.variables;
delete src.variables;
const variableReplacers: VariableReplacer[] = [];
for (const variableName in variables) {
Expand All @@ -68,11 +71,11 @@ import path from 'path';
// Generate sample highlight
const grammarTact = JSON.parse(fs.readFileSync(require.resolve('../grammar/tact.tmLanguage.json'), 'utf-8'));

for (let f of fs.readdirSync(path.resolve(__dirname, '..', 'grammar'))) {
for (const f of fs.readdirSync(path.resolve(__dirname, '..', 'grammar'))) {
if (f.endsWith('.tact')) {
let name = f.substring(0, f.length - '.tact'.length);
const name = f.substring(0, f.length - '.tact'.length);
const grammarSample = fs.readFileSync(path.resolve(__dirname, '..', 'grammar', name + '.tact'), 'utf-8');
let highlighter = await getHighlighter({
const highlighter = await getHighlighter({
themes: BUNDLED_THEMES,
langs: [
...BUNDLED_LANGUAGES,
Expand All @@ -82,16 +85,16 @@ import path from 'path';
grammar: grammarTact,
aliases: ['tact'],
}
] as any,
] as ILanguageRegistration[],
});

let theme = 'dark-plus'; // Most features
const theme = 'dark-plus'; // Most features

let res = highlighter.codeToHtml(grammarSample, { lang: 'tact', theme });
res = `<html><head><meta charset="utf-8"></head><body>${res}</body></html>`;
fs.writeFileSync(path.resolve(__dirname, '..', 'grammar', name + '.html'), res);

let tokens = highlighter.codeToThemedTokens(grammarSample, 'tact', theme);
const tokens = highlighter.codeToThemedTokens(grammarSample, 'tact', theme);
fs.writeFileSync(path.resolve(__dirname, '..', 'grammar', name + '.json'), JSON.stringify(tokens, null, 2));
}
}
Expand Down
12 changes: 6 additions & 6 deletions scripts/pack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import glob from 'glob';
import { posixNormalize } from '../src/utils/filePath';

// Pack func
let wasmBase64 = fs.readFileSync(path.resolve(__dirname, '..', 'src', 'func', 'funcfiftlib.wasm')).toString('base64');
let wasmBase64js = `module.exports = { FuncFiftLibWasm: '${wasmBase64}' };`;
const wasmBase64 = fs.readFileSync(path.resolve(__dirname, '..', 'src', 'func', 'funcfiftlib.wasm')).toString('base64');
const wasmBase64js = `module.exports = { FuncFiftLibWasm: '${wasmBase64}' };`;
fs.writeFileSync(path.resolve(__dirname, '..', 'src', 'func', 'funcfiftlib.wasm.js'), wasmBase64js);

// Pack stdlib
let stdlibFiles = glob.sync(path.resolve(__dirname, '..', 'stdlib', '**', '*.@(tact|fc)'), {windowsPathsNoEscape: true});
const stdlibFiles = glob.sync(path.resolve(__dirname, '..', 'stdlib', '**', '*.@(tact|fc)'), {windowsPathsNoEscape: true});
const dirPrefixToRemove = posixNormalize(path.resolve(__dirname, '..', 'stdlib')) + '/'; // Remove also the leading slash
let output: string = '';
output = 'let files: { [key: string]: string } = {};\n';
for (let f of stdlibFiles) {
output = 'const files: { [key: string]: string } = {};\n';
for (const f of stdlibFiles) {
let code = fs.readFileSync(f).toString('base64');
let name = f.replace(dirPrefixToRemove, '');
const name = f.replace(dirPrefixToRemove, '');
output += `files['${name}'] =\n`;
let first = true;
while (code.length > 0) {
Expand Down
Loading

0 comments on commit 6c35689

Please sign in to comment.