Skip to content

Commit fdcd37a

Browse files
committed
final edits to clean the code
1 parent a0569d0 commit fdcd37a

File tree

6 files changed

+137
-178
lines changed

6 files changed

+137
-178
lines changed

client/modules/IDE/components/Editor/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ class Editor extends React.Component {
227227
}
228228

229229
this._cm.on('keydown', (_cm, e) => {
230-
if ((e.ctrlKey || e.metaKey) && e.key === 'v') {
230+
if (
231+
((e.ctrlKey || e.metaKey) && e.key === 'v') ||
232+
e.ctrlKey ||
233+
e.altKey
234+
) {
231235
return;
232236
}
233237
const mode = this._cm.getOption('mode');

client/modules/IDE/components/contextAwareHinter.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,10 @@ export default function contextAwareHinter(cm, options = {}) {
116116
varName.toLowerCase().startsWith(lowerCurrentWord) && isInScope(varName)
117117
)
118118
.map((varName) => {
119-
const isFunc = (() => {
120-
const inCurrentScope =
121-
scopeToDeclaredVarsMap[currentContext]?.[varName];
122-
const inGlobalScope = scopeToDeclaredVarsMap['global']?.[varName];
123-
124-
if (inCurrentScope && inCurrentScope !== 'fun') return false;
125-
return inGlobalScope === 'fun';
126-
})();
119+
const isFunc =
120+
scopeToDeclaredVarsMap[currentContext]?.[varName] === 'fun' ||
121+
(!scopeToDeclaredVarsMap[currentContext]?.[varName] &&
122+
scopeToDeclaredVarsMap['global']?.[varName] === 'fun');
127123

128124
const baseItem = isFunc
129125
? { ...userDefinedFunctionMetadata[varName] }
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* eslint-disable */
2+
import p5CodeAstAnalyzer from './p5CodeAstAnalyzer';
3+
import * as parser from '@babel/parser';
4+
import announceToScreenReader from '../utils/ScreenReaderHelper';
5+
const traverse = require('@babel/traverse').default;
6+
7+
export function getScriptLoadOrder(files) {
8+
const indexHtmlFile = files.find((f) => f.name.endsWith('index.html'));
9+
if (!indexHtmlFile) return [];
10+
11+
const scriptRegex = /<script\s+[^>]*src=["']([^"']+)["']/g;
12+
const scripts = [];
13+
let match;
14+
while ((match = scriptRegex.exec(indexHtmlFile.content)) !== null) {
15+
scripts.push(match[1]);
16+
}
17+
return scripts;
18+
}
19+
20+
export function buildProjectSymbolTable(files, scriptOrder) {
21+
const symbolTable = {};
22+
23+
for (const scriptName of scriptOrder) {
24+
const file = files.find((f) => f.name.endsWith(scriptName));
25+
if (!file) continue;
26+
27+
let ast;
28+
try {
29+
ast = parser.parse(file.content, {
30+
sourceType: 'script',
31+
plugins: ['jsx', 'typescript']
32+
});
33+
} catch (e) {
34+
continue;
35+
}
36+
37+
traverse(ast, {
38+
FunctionDeclaration(path) {
39+
const name = path.node.id?.name;
40+
if (name && !symbolTable[name]) {
41+
symbolTable[name] = {
42+
file: file.name,
43+
pos: path.node.start
44+
};
45+
}
46+
},
47+
VariableDeclarator(path) {
48+
const name = path.node.id?.name;
49+
if (name && !symbolTable[name]) {
50+
symbolTable[name] = {
51+
file: file.name,
52+
pos: path.node.start
53+
};
54+
}
55+
}
56+
});
57+
}
58+
59+
return symbolTable;
60+
}
61+
62+
export function announceJump(cm, fromPos, toPos, varName) {
63+
cm.setCursor(toPos);
64+
cm.focus();
65+
announceToScreenReader(
66+
`Jumped to line ${toPos.line + 1} at definition of ${varName}`
67+
);
68+
}

client/modules/IDE/components/jump-to-definition.js

Lines changed: 18 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -5,93 +5,28 @@ import { getContext, getAST } from '../utils/renameVariableHelper';
55
import { selectFiles } from '../selectors/files';
66
import { setSelectedFile } from '../actions/ide';
77
import announceToScreenReader from '../utils/ScreenReaderHelper';
8+
import {
9+
getScriptLoadOrder,
10+
buildProjectSymbolTable,
11+
announceJump
12+
} from './jump-to-def-helper';
813
import store from '../../../index';
914
const traverse = require('@babel/traverse').default;
1015

11-
function getScriptLoadOrder(files) {
12-
const indexHtmlFile = files.find((f) => f.name.endsWith('index.html'));
13-
if (!indexHtmlFile) return [];
14-
15-
const scriptRegex = /<script\s+[^>]*src=["']([^"']+)["']/g;
16-
const scripts = [];
17-
let match;
18-
while ((match = scriptRegex.exec(indexHtmlFile.content)) !== null) {
19-
scripts.push(match[1]);
20-
}
21-
return scripts;
22-
}
23-
24-
function buildProjectSymbolTable(files, scriptOrder) {
25-
const symbolTable = {};
26-
27-
for (const scriptName of scriptOrder) {
28-
const file = files.find((f) => f.name.endsWith(scriptName));
29-
if (!file) continue;
30-
31-
let ast;
32-
try {
33-
ast = parser.parse(file.content, {
34-
sourceType: 'script',
35-
plugins: ['jsx', 'typescript']
36-
});
37-
} catch (e) {
38-
continue;
39-
}
40-
41-
traverse(ast, {
42-
FunctionDeclaration(path) {
43-
const name = path.node.id?.name;
44-
if (name && !symbolTable[name]) {
45-
symbolTable[name] = {
46-
file: file.name,
47-
pos: path.node.start
48-
};
49-
}
50-
},
51-
VariableDeclarator(path) {
52-
const name = path.node.id?.name;
53-
if (name && !symbolTable[name]) {
54-
symbolTable[name] = {
55-
file: file.name,
56-
pos: path.node.start
57-
};
58-
}
59-
}
60-
});
61-
}
62-
63-
return symbolTable;
64-
}
65-
66-
const jumpToLineChAfterLoad = (targetFileId, pos) => {
67-
let tries = 10;
68-
const tryJump = () => {
69-
const stateNow = store.getState();
70-
const filesNow = selectFiles(stateNow);
71-
const freshTarget = filesNow.find((f) => f.id === targetFileId); // get fresh copy
72-
const cm = freshTarget?.cmInstance;
73-
74-
if (cm) {
75-
cm.setCursor(pos);
76-
cm.focus();
77-
} else if (tries-- > 0) {
78-
setTimeout(tryJump, 30);
79-
}
80-
};
81-
tryJump();
82-
};
83-
8416
export function jumpToDefinition(pos) {
8517
const state = store.getState();
8618
const files = selectFiles(state);
8719

8820
const cm = this._cm;
8921
const token = cm.getTokenAt(pos);
9022
const tokenType = token.type;
23+
const varName = token.string;
9124

92-
if (!tokenType || tokenType === 'def') return;
25+
if (!tokenType || tokenType === 'def') {
26+
announceToScreenReader(`Already at definition of ${varName}`);
27+
return;
28+
}
9329

94-
const varName = token.string;
9530
const ast = getAST(cm);
9631
const { scopeToDeclaredVarsMap = {}, userDefinedFunctionMetadata = {} } =
9732
p5CodeAstAnalyzer(cm) || {};
@@ -101,36 +36,9 @@ export function jumpToDefinition(pos) {
10136
const isDeclaredVar =
10237
scopeToDeclaredVarsMap[currentContext]?.[varName] !== undefined;
10338

104-
let isAtDeclaration = false;
105-
106-
traverse(ast, {
107-
VariableDeclarator(path) {
108-
if (
109-
path.node.id.name === varName &&
110-
path.node.start === cm.indexFromPos(pos)
111-
) {
112-
isAtDeclaration = true;
113-
path.stop();
114-
}
115-
},
116-
FunctionDeclaration(path) {
117-
if (
118-
path.node.id?.name === varName &&
119-
path.node.start === cm.indexFromPos(pos)
120-
) {
121-
isAtDeclaration = true;
122-
path.stop();
123-
}
124-
}
125-
});
126-
127-
if (isAtDeclaration) {
128-
announceToScreenReader(`Already at definition of ${varName}`);
129-
return;
130-
}
131-
13239
let found = false;
13340

41+
// search project-wide definitions (script load order)
13442
if (!found) {
13543
const scriptOrder = getScriptLoadOrder(files);
13644

@@ -205,6 +113,7 @@ export function jumpToDefinition(pos) {
205113
}
206114
}
207115

116+
// Search in current file, same context
208117
traverse(ast, {
209118
VariableDeclarator(path) {
210119
if (found) return;
@@ -215,13 +124,7 @@ export function jumpToDefinition(pos) {
215124
const defContext = getContext(cm, ast, defPos, scopeToDeclaredVarsMap);
216125
if (defContext === currentContext) {
217126
found = true;
218-
cm.setCursor(defPos);
219-
cm.focus();
220-
announceToScreenReader(
221-
`Jumped from line ${pos.line + 1} to line ${
222-
defPos.line + 1
223-
} at definition of ${varName}`
224-
);
127+
announceJump(cm, pos, defPos, varName);
225128
}
226129
}
227130
},
@@ -236,13 +139,7 @@ export function jumpToDefinition(pos) {
236139
const defContext = getContext(cm, ast, defPos, scopeToDeclaredVarsMap);
237140
if (defContext === currentContext) {
238141
found = true;
239-
cm.setCursor(defPos);
240-
cm.focus();
241-
announceToScreenReader(
242-
`Jumped from line ${pos.line + 1} to line ${
243-
defPos.line + 1
244-
} at definition of ${varName}`
245-
);
142+
announceJump(cm, pos, defPos, varName);
246143
}
247144
}
248145

@@ -258,19 +155,14 @@ export function jumpToDefinition(pos) {
258155
);
259156
if (defContext === currentContext) {
260157
found = true;
261-
cm.setCursor(defPos);
262-
cm.focus();
263-
announceToScreenReader(
264-
`Jumped from line ${pos.line + 1} to line ${
265-
defPos.line + 1
266-
} at definition of ${varName}`
267-
);
158+
announceJump(cm, pos, defPos, varName);
268159
}
269160
}
270161
}
271162
}
272163
});
273164

165+
// Fallback search in current file
274166
if (!found) {
275167
traverse(ast, {
276168
VariableDeclarator(path) {
@@ -280,13 +172,7 @@ export function jumpToDefinition(pos) {
280172
if (node.id.name === varName && node.loc) {
281173
const defPos = cm.posFromIndex(node.start);
282174
found = true;
283-
cm.setCursor(defPos);
284-
cm.focus();
285-
announceToScreenReader(
286-
`Jumped from line ${pos.line + 1} to line ${
287-
defPos.line + 1
288-
} at definition of ${varName}`
289-
);
175+
announceJump(cm, pos, defPos, varName);
290176
}
291177
},
292178

@@ -297,13 +183,7 @@ export function jumpToDefinition(pos) {
297183
if (node.id?.name === varName) {
298184
const defPos = cm.posFromIndex(node.start);
299185
found = true;
300-
cm.setCursor(defPos);
301-
cm.focus();
302-
announceToScreenReader(
303-
`Jumped from line ${pos.line + 1} to line ${
304-
defPos.line + 1
305-
} at definition of ${varName}`
306-
);
186+
announceJump(cm, pos, defPos, varName);
307187
}
308188
}
309189
});

client/modules/IDE/components/rename-variable.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@ import {
1111
const parser = require('@babel/parser');
1212
const traverse = require('@babel/traverse').default;
1313

14-
function SearchState(oldName) {
15-
this.posFrom = this.posTo = null;
16-
this.query = oldName;
17-
this.regexp = false;
18-
this.caseInsensitive = true;
19-
this.wholeWord = true;
20-
}
21-
2214
export function handleRename(fromPos, oldName, newName, cm) {
2315
if (!cm) {
2416
return;
@@ -36,6 +28,7 @@ function startRenaming(cm, ast, fromPos, newName, oldName) {
3628
userDefinedFunctionMetadata = {}
3729
} = p5CodeAstAnalyzer(cm) || {};
3830

31+
// Determine the context at the position where rename started
3932
const baseContext = getContext(
4033
cm,
4134
ast,
@@ -104,6 +97,7 @@ function startRenaming(cm, ast, fromPos, newName, oldName) {
10497
let shouldRenameGlobalVar = false;
10598
const isThis = isThisReference(cm, ast, pos, oldName);
10699

100+
// Handle renaming inside classes
107101
if (isInsideClassContext) {
108102
const classContext = getClassContext(cm, ast, fromPos);
109103
let baseMethodName = null;
@@ -156,6 +150,7 @@ function startRenaming(cm, ast, fromPos, newName, oldName) {
156150
}
157151
}
158152

153+
// Rename constructor parameters, class fields, and method variables carefully
159154
if (
160155
classMeta.fields?.includes(oldName) &&
161156
isThis === isBaseThis &&
@@ -169,7 +164,9 @@ function startRenaming(cm, ast, fromPos, newName, oldName) {
169164
shouldRename = isGlobal && !thisScopeVars.hasOwnProperty(oldName);
170165
}
171166
shouldRenameGlobalVar = isGlobal && thisContext === 'global';
172-
} else {
167+
}
168+
// Handle renaming outside classes
169+
else {
173170
const thisScopeVars = scopeToDeclaredVarsMap[thisContext] || {};
174171
const baseScopeVars = scopeToDeclaredVarsMap[baseContext] || {};
175172
const globalScopeVars = scopeToDeclaredVarsMap['global'] || {};

0 commit comments

Comments
 (0)