Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7fd3735

Browse filesBrowse files
authored
fix: context provided by defineCustomBlocksVisitor (#211)
1 parent cbf1481 commit 7fd3735
Copy full SHA for 7fd3735

File tree

Expand file treeCollapse file tree

2 files changed

+105
-53
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+105
-53
lines changed

‎src/sfc/custom-block/index.ts

Copy file name to clipboardExpand all lines: src/sfc/custom-block/index.ts
+56-44Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -213,26 +213,40 @@ export function createCustomBlockSharedContext({
213213
parserOptions: any
214214
}) {
215215
let sourceCode: SourceCode
216-
let scopeManager: ScopeManager
217216
let currentNode: any
218217
return {
219218
serCurrentNode(node: any) {
220219
currentNode = node
221220
},
222221
context: {
223-
getAncestors: () => getAncestors(currentNode),
224-
222+
getAncestors: () => getSourceCode().getAncestors(currentNode),
225223
getDeclaredVariables: (...args: any[]) =>
226224
// @ts-expect-error -- ignore
227-
getScopeManager().getDeclaredVariables(...args),
228-
getScope: () => getScope(getScopeManager(), currentNode),
225+
getSourceCode().getDeclaredVariables(...args),
226+
getScope: () => getSourceCode().getScope(currentNode),
229227
markVariableAsUsed: (name: string) =>
230-
markVariableAsUsed(
231-
getScopeManager(),
232-
currentNode,
233-
parserOptions,
234-
name,
235-
),
228+
getSourceCode().markVariableAsUsed(name, currentNode),
229+
get parserServices() {
230+
return getSourceCode().parserServices
231+
},
232+
getSourceCode,
233+
get sourceCode() {
234+
return getSourceCode()
235+
},
236+
},
237+
}
238+
239+
function getSourceCode(): SourceCode {
240+
if (sourceCode) {
241+
return sourceCode
242+
}
243+
244+
const scopeManager = getScopeManager()
245+
246+
// eslint-disable-next-line @typescript-eslint/no-require-imports
247+
const originalSourceCode = new (require("eslint").SourceCode)({
248+
text,
249+
ast: parsedResult.ast,
236250
parserServices: {
237251
customBlock,
238252
parseCustomBlockElement(
@@ -251,44 +265,43 @@ export function createCustomBlockSharedContext({
251265
? { parseError: parsedResult.error }
252266
: {}),
253267
},
254-
getSourceCode,
255-
get sourceCode() {
256-
return getSourceCode()
257-
},
258-
},
259-
}
268+
scopeManager,
269+
visitorKeys: parsedResult.visitorKeys,
270+
})
260271

261-
function getSourceCode() {
262-
return (
263-
sourceCode ||
264-
// eslint-disable-next-line @typescript-eslint/no-require-imports
265-
(sourceCode = new (require("eslint").SourceCode)({
266-
text,
267-
ast: parsedResult.ast,
268-
parserServices: parsedResult.services,
269-
scopeManager: getScopeManager(),
270-
visitorKeys: parsedResult.visitorKeys,
271-
}))
272-
)
272+
const polyfills = {
273+
markVariableAsUsed: (name: string, node: any) =>
274+
markVariableAsUsed(scopeManager, node, parsedResult.ast, name),
275+
getScope: (node: any) => getScope(scopeManager, node),
276+
getAncestors: (node: any) => getAncestors(node),
277+
getDeclaredVariables: (...args: any[]) =>
278+
// @ts-expect-error -- ignore
279+
scopeManager.getDeclaredVariables(...args),
280+
}
281+
282+
return (sourceCode = new Proxy(originalSourceCode, {
283+
get(_target, prop) {
284+
return originalSourceCode[prop] || (polyfills as any)[prop]
285+
},
286+
}))
273287
}
274288

275289
function getScopeManager() {
276-
if (parsedResult.scopeManager || scopeManager) {
277-
return parsedResult.scopeManager || scopeManager
290+
if (parsedResult.scopeManager) {
291+
return parsedResult.scopeManager
278292
}
279293

280294
const ecmaVersion = getEcmaVersionIfUseEspree(parserOptions) || 2022
281295
const ecmaFeatures = parserOptions.ecmaFeatures || {}
282296
const sourceType = parserOptions.sourceType || "script"
283-
scopeManager = getEslintScope().analyze(parsedResult.ast, {
297+
return getEslintScope().analyze(parsedResult.ast, {
284298
ignoreEval: true,
285299
nodejsScope: false,
286300
impliedStrict: ecmaFeatures.impliedStrict,
287301
ecmaVersion,
288302
sourceType,
289303
fallback: getFallbackKeys,
290304
})
291-
return scopeManager
292305
}
293306
}
294307

@@ -349,20 +362,19 @@ function getScope(scopeManager: ScopeManager, currentNode: Node) {
349362
function markVariableAsUsed(
350363
scopeManager: ScopeManager,
351364
currentNode: Node,
352-
parserOptions: any,
365+
program: Node,
353366
name: string,
354367
) {
355-
const hasGlobalReturn =
356-
parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn
357-
const specialScope =
358-
hasGlobalReturn || parserOptions.sourceType === "module"
359368
const currentScope = getScope(scopeManager, currentNode)
360-
361-
// Special Node.js scope means we need to start one level deeper
362-
const initialScope =
363-
currentScope.type === "global" && specialScope
364-
? currentScope.childScopes[0]
365-
: currentScope
369+
let initialScope = currentScope
370+
if (
371+
currentScope.type === "global" &&
372+
currentScope.childScopes.length > 0 &&
373+
// top-level scopes refer to a `Program` node
374+
currentScope.childScopes[0].block === program
375+
) {
376+
initialScope = currentScope.childScopes[0]
377+
}
366378

367379
for (let scope: Scope | null = initialScope; scope; scope = scope.upper) {
368380
const variable = scope.variables.find(

‎test/define-custom-blocks-visitor.js

Copy file name to clipboardExpand all lines: test/define-custom-blocks-visitor.js
+49-9Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const LINTER_CONFIG = {
2929
"test-no-number-literal": "error",
3030
"test-no-forbidden-key": "error",
3131
"test-no-parsing-error": "error",
32+
"test-no-parsing-error2": "error",
3233
},
3334
}
3435
const noNumberLiteralRule = {
@@ -61,6 +62,30 @@ const noNoForbiddenKeyRule = {
6162
},
6263
}
6364
const noParsingErrorRule = {
65+
create(context) {
66+
const parseError = context.getSourceCode().parserServices.parseError
67+
if (parseError) {
68+
let loc = undefined
69+
if ("column" in parseError && "lineNumber" in parseError) {
70+
loc = {
71+
line: parseError.lineNumber,
72+
column: parseError.column,
73+
}
74+
}
75+
return {
76+
Program(node) {
77+
context.report({
78+
node,
79+
loc,
80+
message: parseError.message,
81+
})
82+
},
83+
}
84+
}
85+
return {}
86+
},
87+
}
88+
const noParsingErrorRule2 = {
6489
create(context) {
6590
const parseError = context.parserServices.parseError
6691
if (parseError) {
@@ -131,10 +156,10 @@ function createLinter(target = "json") {
131156
...noParsingErrorRule,
132157
}),
133158
)
134-
linter.defineRule("test-no-parsing-error", (context) =>
159+
linter.defineRule("test-no-parsing-error2", (context) =>
135160
context.parserServices.defineCustomBlocksVisitor(context, jsonParser, {
136161
target,
137-
...noParsingErrorRule,
162+
...noParsingErrorRule2,
138163
}),
139164
)
140165
linter.defineRule("test-no-program-exit", (context) =>
@@ -297,22 +322,37 @@ describe("parserServices.defineCustomBlocksVisitor tests", () => {
297322

298323
const messages = linter.verify(code, LINTER_CONFIG)
299324

300-
assert.strictEqual(messages.length, 3)
325+
assert.strictEqual(messages.length, 6)
301326
assert.strictEqual(messages[0].message, "Unexpected token ':'.")
302327
assert.strictEqual(messages[0].line, 3)
303328
assert.strictEqual(messages[0].column, 6)
329+
assert.strictEqual(messages[1].message, "Unexpected token ':'.")
330+
assert.strictEqual(messages[1].line, 3)
331+
assert.strictEqual(messages[1].column, 6)
304332
assert.strictEqual(
305-
messages[1].message,
333+
messages[2].message,
306334
"Expected to be an expression, but got empty.",
307335
)
308-
assert.strictEqual(messages[1].line, 5)
309-
assert.strictEqual(messages[1].column, 19)
336+
assert.strictEqual(messages[2].line, 5)
337+
assert.strictEqual(messages[2].column, 19)
310338
assert.strictEqual(
311-
messages[2].message,
339+
messages[3].message,
312340
"Expected to be an expression, but got empty.",
313341
)
314-
assert.strictEqual(messages[2].line, 6)
315-
assert.strictEqual(messages[2].column, 19)
342+
assert.strictEqual(messages[3].line, 5)
343+
assert.strictEqual(messages[3].column, 19)
344+
assert.strictEqual(
345+
messages[4].message,
346+
"Expected to be an expression, but got empty.",
347+
)
348+
assert.strictEqual(messages[4].line, 6)
349+
assert.strictEqual(messages[4].column, 19)
350+
assert.strictEqual(
351+
messages[5].message,
352+
"Expected to be an expression, but got empty.",
353+
)
354+
assert.strictEqual(messages[5].line, 6)
355+
assert.strictEqual(messages[5].column, 19)
316356
})
317357

318358
it("should work even if error.", () => {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.