Skip to content

Commit 0debd21

Browse files
authored
Feat: Add no-member-access rule (#5)
1 parent 61f3f3b commit 0debd21

File tree

11 files changed

+718
-8
lines changed

11 files changed

+718
-8
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ dist/
33
sample_cases/
44
wasm-toolchain
55
coverage
6-
.vscode
76
reference

Readme.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,22 @@ Optimizes code for better WebAssembly performance:
2525

2626
- `array-init-style`: Recommends using `new Array<T>()` instead of `[]` for initializing empty arrays
2727

28+
- `no-repeated-member-access`: Recommends extracting repeated member access to improve performance
29+
2830
## Configuration
2931

3032
See `sample_config/sample_eslint.config.mjs` for a detailed example of how to configure and use this plugin.
3133

34+
It includes some other pre-written rules including:
35+
36+
- `no-implicit-globals`: Warns against creating implicit global variables
37+
- `curly`: Requires curly braces for all control statements to prevent error-prone one-liner code
38+
- `@typescript-eslint/no-restricted-types`: Enforces AssemblyScript-specific type usage:
39+
- Use `string` instead of `String`
40+
- Use `bool` instead of `Boolean`
41+
- Disallows unsupported types like `undefined` and `object`
42+
- `@typescript-eslint/adjacent-overload-signatures`: Requires overload signatures to be adjacent
43+
3244
## Documentation
3345

3446
For detailed rule documentation, see the [docs/rules](./docs/rules) directory.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# no-repeated-member-access
2+
3+
> Optimize repeated member access patterns by extracting variables
4+
5+
## Rule Details
6+
7+
This rule identifies repeated member access patterns in your code and suggests extracting them to variables for better performance and readability. In AssemblyScript, repeated property access can have performance implications (due to when they are compiled to WASM bytecode, they will induce more instructions), especially in loops or frequently called functions.
8+
9+
This rule doesn't extract computed properties/array index. These can change unexpectedly and therefore should be avoid for extraction. Examples include:
10+
11+
```ts
12+
arr[0];
13+
arr[0][1];
14+
arr[0].property;
15+
obj.arr[0].value;
16+
data.items[0].config;
17+
obj["prop"];
18+
obj[getKey()];
19+
```
20+
21+
The rule will also avoid to warn when functions are invoked upon properties, as this could have implications that alter the extracted value.
22+
Examples include:
23+
24+
```ts
25+
x = a.b.c;
26+
a.b.doSomething(); // this line will prevent a.b.c from being warned although it is used multiple times, as doSomething() could potentially change the value of a.b
27+
y = a.b.c;
28+
z = a.b.c;
29+
```
30+
31+
## Examples
32+
33+
### Incorrect
34+
35+
```ts
36+
// Repeated access to the same property chain (3+ times)
37+
function processData(obj: MyObject): void {
38+
if (obj.config.settings.enabled) {
39+
obj.config.settings.value = 10;
40+
console.log(obj.config.settings.name);
41+
obj.config.settings.timestamp = Date.now();
42+
}
43+
}
44+
45+
// Deep property chains accessed multiple times
46+
function renderUI(app: Application): void {
47+
app.ui.layout.header.title.text = "New Title";
48+
app.ui.layout.header.title.fontSize = 16;
49+
app.ui.layout.header.title.color = "blue";
50+
}
51+
```
52+
53+
### Correct
54+
55+
```ts
56+
// Extract repeated property access to variables
57+
function processData(obj: MyObject): void {
58+
const settings = obj.config.settings;
59+
if (settings.enabled) {
60+
settings.value = 10;
61+
console.log(settings.name);
62+
settings.timestamp = Date.now();
63+
}
64+
}
65+
66+
// Extract deep property chains
67+
function renderUI(app: Application): void {
68+
const title = app.ui.layout.header.title;
69+
title.text = "New Title";
70+
title.fontSize = 16;
71+
title.color = "blue";
72+
}
73+
74+
// Single or infrequent access is allowed
75+
function singleAccess(obj: MyObject): void {
76+
console.log(obj.config.settings.enabled); // Only accessed once
77+
}
78+
```
79+
80+
## Benefits
81+
82+
- **Performance**: Reduces redundant property lookups, especially in tight loops
83+
- **Readability**: Makes code more readable by giving meaningful names to complex property chains
84+
- **Maintainability**: Easier to update property references when extracted to variables
85+
86+
## When Not To Use
87+
88+
- If the property chains are very short (single level) and performance is not critical
89+
- When the object properties are frequently modified, making extraction less beneficial
90+
- In very simple functions where the overhead of variable extraction outweighs the benefits
91+
92+
## Related Rules
93+
94+
- Consider using this rule alongside other performance-focused rules for optimal AssemblyScript code generation

eslint.config.mjs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ import { baseConfig } from "@schleifner/eslint-config-base/config.mjs";
44

55
export default tseslint.config(
66
{
7-
ignores: [
8-
"dist/**",
9-
"**/*.mjs",
10-
],
7+
ignores: ["dist/**", "**/*.mjs"],
118
},
12-
...baseConfig
9+
...baseConfig,
10+
{
11+
files: ["**/*.ts"],
12+
rules: {
13+
curly: ["error", "all"]
14+
},
15+
}
1316
);

package-lock.json

Lines changed: 158 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"mocha": "^11.2.2",
5757
"npm-run-all": "^4.1.5",
5858
"prettier": "^3.5.3",
59+
"ts-node": "^10.9.2",
5960
"tsx": "^4.19.3"
6061
},
6162
"dependencies": {

0 commit comments

Comments
 (0)