diff --git a/packages/utils/src/ts-eslint/Linter.ts b/packages/utils/src/ts-eslint/Linter.ts index 77c338f5a753..c2a8e67fe3a3 100644 --- a/packages/utils/src/ts-eslint/Linter.ts +++ b/packages/utils/src/ts-eslint/Linter.ts @@ -76,7 +76,7 @@ declare class LinterBase { /** * Performs multiple autofix passes over the text until as many fixes as possible have been applied. - * @param text The source text to apply fixes to. + * @param code The source text to apply fixes to. * @param config The ESLint config object to use. * @param options The ESLint options object to use. * @returns The result of the fix operation as returned from the SourceCodeFixer. @@ -316,7 +316,7 @@ namespace Linter { export interface ESLintParseResult { ast: TSESTree.Program; - parserServices?: ParserServices; + services?: ParserServices; scopeManager?: Scope.ScopeManager; visitorKeys?: SourceCode.VisitorKeys; } diff --git a/packages/website-eslint/src/linter/CompilerHost.js b/packages/website-eslint/src/linter/CompilerHost.js deleted file mode 100644 index f48c77109c96..000000000000 --- a/packages/website-eslint/src/linter/CompilerHost.js +++ /dev/null @@ -1,92 +0,0 @@ -import { - getDefaultLibFileName, - ScriptKind, - createSourceFile, - ScriptTarget, -} from 'typescript'; - -function getScriptKind(isJsx, filePath) { - const extension = (/(\.[a-z]+)$/.exec(filePath)?.[0] || '').toLowerCase(); - - switch (extension) { - case '.ts': - return ScriptKind.TS; - case '.tsx': - return ScriptKind.TSX; - case '.js': - return ScriptKind.JS; - - case '.jsx': - return ScriptKind.JSX; - - case '.json': - return ScriptKind.JSON; - - default: - // unknown extension, force typescript to ignore the file extension, and respect the user's setting - return isJsx ? ScriptKind.TSX : ScriptKind.TS; - } -} - -export class CompilerHost { - constructor(libs, isJsx) { - this.files = []; - this.isJsx = isJsx || false; - - if (libs) { - for (const [key, value] of libs) { - this.files[key] = value; - } - } - } - - fileExists(name) { - return !!this.files[name]; - } - - getCanonicalFileName(name) { - return name; - } - - getCurrentDirectory() { - return '/'; - } - - getDirectories() { - return []; - } - - getDefaultLibFileName(options) { - return '/' + getDefaultLibFileName(options); - } - - getNewLine() { - return '\n'; - } - - useCaseSensitiveFileNames() { - return true; - } - - writeFile() { - return null; - } - - readFile(name) { - if (this.fileExists(name)) { - return this.files[name]; - } else { - return ''; // fallback, in case if file is not available - } - } - - getSourceFile(name) { - return createSourceFile( - name, - this.readFile(name), - ScriptTarget.Latest, - /* setParentNodes */ true, - getScriptKind(this.isJsx, name), - ); - } -} diff --git a/packages/website-eslint/src/linter/linter.js b/packages/website-eslint/src/linter/linter.js index 06a4db0d3fb2..fede1540f98c 100644 --- a/packages/website-eslint/src/linter/linter.js +++ b/packages/website-eslint/src/linter/linter.js @@ -1,74 +1,16 @@ import 'vs/language/typescript/tsWorker'; -import { parseForESLint } from './parser'; import { Linter } from 'eslint'; import rules from '@typescript-eslint/eslint-plugin/dist/rules'; -const PARSER_NAME = '@typescript-eslint/parser'; - -export function loadLinter(libs, options) { +export function createLinter() { const linter = new Linter(); - let storedAST; - let storedTsAST; - let storedScope; - - let compilerOptions = options; - - linter.defineParser(PARSER_NAME, { - parseForESLint(code, eslintOptions) { - const toParse = parseForESLint( - code, - eslintOptions, - compilerOptions, - libs, - ); - storedAST = toParse.ast; - storedTsAST = toParse.tsAst; - storedScope = toParse.scopeManager; - return toParse; - }, - // parse(code: string, options: ParserOptions): ParseForESLintResult['ast'] { - // const toParse = parseForESLint(code, options); - // storedAST = toParse.ast; - // return toParse.ast; - // }, - }); - - for (const name of Object.keys(rules)) { + for (const name in rules) { linter.defineRule(`@typescript-eslint/${name}`, rules[name]); } - - const ruleNames = Array.from(linter.getRules()).map(value => { - return { - name: value[0], - description: value[1]?.meta?.docs?.description, - }; - }); - - return { - ruleNames: ruleNames, - - updateOptions(options) { - compilerOptions = options || {}; - }, - - getScope() { - return storedScope; - }, - - getAst() { - return storedAST; - }, - - getTsAst() { - return storedTsAST; - }, - - lint(code, parserOptions, rules) { - return linter.verify(code, { - parser: PARSER_NAME, - parserOptions, - rules, - }); - }, - }; + return linter; } + +export { analyze } from '@typescript-eslint/scope-manager/dist/analyze'; +export { visitorKeys } from '@typescript-eslint/visitor-keys/dist/visitor-keys'; +export { astConverter } from '@typescript-eslint/typescript-estree/dist/ast-converter'; +export { getScriptKind } from '@typescript-eslint/typescript-estree/dist/create-program/getScriptKind'; diff --git a/packages/website-eslint/src/linter/parser.js b/packages/website-eslint/src/linter/parser.js deleted file mode 100644 index fc637fe65b7d..000000000000 --- a/packages/website-eslint/src/linter/parser.js +++ /dev/null @@ -1,62 +0,0 @@ -import { analyze } from '@typescript-eslint/scope-manager/dist/analyze'; -import { visitorKeys } from '@typescript-eslint/visitor-keys/dist/visitor-keys'; -import { astConverter } from '@typescript-eslint/typescript-estree/dist/ast-converter'; -import { extra } from './config.js'; -import { CompilerHost } from './CompilerHost'; -import { createProgram } from 'typescript'; - -export function createASTProgram(code, isJsx, compilerOptions, libs) { - const fileName = isJsx ? '/demo.tsx' : '/demo.ts'; - const compilerHost = new CompilerHost(libs, isJsx); - - compilerHost.files[fileName] = code; - const program = createProgram( - Object.keys(compilerHost.files), - compilerOptions, - compilerHost, - ); - const ast = program.getSourceFile(fileName); - return { - ast, - program, - }; -} - -export function parseForESLint(code, eslintOptions, compilerOptions, libs) { - const isJsx = eslintOptions.ecmaFeatures?.jsx ?? false; - - const { ast: tsAst, program } = createASTProgram( - code, - isJsx, - compilerOptions, - libs, - ); - - const { estree: ast, astMaps } = astConverter( - tsAst, - { ...extra, code, jsx: isJsx }, - true, - ); - - const services = { - hasFullTypeInformation: true, - program, - esTreeNodeToTSNodeMap: astMaps.esTreeNodeToTSNodeMap, - tsNodeToESTreeNodeMap: astMaps.tsNodeToESTreeNodeMap, - }; - - const scopeManager = analyze(ast, { - ecmaVersion: - eslintOptions.ecmaVersion === 'latest' ? 1e8 : eslintOptions.ecmaVersion, - globalReturn: eslintOptions.ecmaFeatures?.globalReturn ?? false, - sourceType: eslintOptions.sourceType ?? 'script', - }); - - return { - ast, - tsAst, - services, - scopeManager, - visitorKeys, - }; -} diff --git a/packages/website-eslint/types/index.d.ts b/packages/website-eslint/types/index.d.ts index aa5a2a43ed7f..7673f6d10a27 100644 --- a/packages/website-eslint/types/index.d.ts +++ b/packages/website-eslint/types/index.d.ts @@ -1,38 +1,13 @@ -import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; -import type { ParserOptions } from '@typescript-eslint/types'; -import type { SourceFile, CompilerOptions } from 'typescript'; - -export type LintMessage = TSESLint.Linter.LintMessage; -export type RuleFix = TSESLint.RuleFix; -export type RulesRecord = TSESLint.Linter.RulesRecord; -export type RuleEntry = TSESLint.Linter.RuleEntry; - -export interface WebLinter { - ruleNames: { name: string; description?: string }[]; - - getAst(): TSESTree.Program; - getTsAst(): SourceFile; - getScope(): Record; - updateOptions(options?: Record): void; - - lint( - code: string, - parserOptions: ParserOptions, - rules?: RulesRecord, - ): LintMessage[]; +import type { TSESLint } from '@typescript-eslint/utils'; + +import { analyze } from '@typescript-eslint/scope-manager/dist/analyze'; +import { astConverter } from '@typescript-eslint/typescript-estree/dist/ast-converter'; +import { getScriptKind } from '@typescript-eslint/typescript-estree/dist/create-program/getScriptKind'; + +export interface LintUtils { + createLinter: () => TSESLint.Linter; + analyze: typeof analyze; + visitorKeys: TSESLint.SourceCode.VisitorKeys; + astConverter: typeof astConverter; + getScriptKind: typeof getScriptKind; } - -export interface LinterLoader { - loadLinter( - libMap: Map, - compilerOptions: CompilerOptions, - ): WebLinter; -} - -export type { - DebugLevel, - EcmaVersion, - ParserOptions, - SourceType, - TSESTree, -} from '@typescript-eslint/types'; diff --git a/packages/website/src/components/ASTViewerESTree.tsx b/packages/website/src/components/ASTViewerESTree.tsx index 7d46efdfb110..7dfcef130cf2 100644 --- a/packages/website/src/components/ASTViewerESTree.tsx +++ b/packages/website/src/components/ASTViewerESTree.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import ASTViewer from './ast/ASTViewer'; import type { ASTViewerBaseProps, ASTViewerModelMap } from './ast/types'; -import type { TSESTree } from '@typescript-eslint/website-eslint'; +import type { TSESTree } from '@typescript-eslint/utils'; import { serialize } from './ast/serializer/serializer'; import { createESTreeSerializer } from './ast/serializer/serializerESTree'; diff --git a/packages/website/src/components/Playground.tsx b/packages/website/src/components/Playground.tsx index 577d69022f6a..d602e4574825 100644 --- a/packages/website/src/components/Playground.tsx +++ b/packages/website/src/components/Playground.tsx @@ -17,7 +17,7 @@ import ASTViewerTS from './ASTViewerTS'; import type { RuleDetails, SelectedRange } from './types'; -import type { TSESTree } from '@typescript-eslint/website-eslint'; +import type { TSESTree } from '@typescript-eslint/utils'; import type { SourceFile } from 'typescript'; import ASTViewerScope from '@site/src/components/ASTViewerScope'; @@ -44,7 +44,7 @@ function Playground(): JSX.Element { showAST: false, sourceType: 'module', code: '', - ts: process.env.TS_VERSION, + ts: process.env.TS_VERSION!, rules: {}, tsConfig: {}, }); diff --git a/packages/website/src/components/ast/serializer/serializerESTree.ts b/packages/website/src/components/ast/serializer/serializerESTree.ts index 7f467757c8a3..76aabfd024bd 100644 --- a/packages/website/src/components/ast/serializer/serializerESTree.ts +++ b/packages/website/src/components/ast/serializer/serializerESTree.ts @@ -1,6 +1,6 @@ import type { ASTViewerModel, Serializer } from '../types'; +import type { TSESTree } from '@typescript-eslint/utils'; import { isRecord } from '../utils'; -import type { TSESTree } from '@typescript-eslint/website-eslint'; export const propsToFilter = ['parent', 'comments', 'tokens']; diff --git a/packages/website/src/components/ast/serializer/serializerScope.ts b/packages/website/src/components/ast/serializer/serializerScope.ts index 176f49f92c5c..b000aba7db1e 100644 --- a/packages/website/src/components/ast/serializer/serializerScope.ts +++ b/packages/website/src/components/ast/serializer/serializerScope.ts @@ -1,5 +1,5 @@ import type { ASTViewerModel, Serializer, SelectedRange } from '../types'; -import type { TSESTree } from '@typescript-eslint/website-eslint'; +import type { TSESTree } from '@typescript-eslint/utils'; import { isRecord } from '../utils'; function isESTreeNode( diff --git a/packages/website/src/components/ast/serializer/serializerTS.ts b/packages/website/src/components/ast/serializer/serializerTS.ts index b89d6e0e1a44..66cffe82b92a 100644 --- a/packages/website/src/components/ast/serializer/serializerTS.ts +++ b/packages/website/src/components/ast/serializer/serializerTS.ts @@ -20,6 +20,7 @@ export const propsToFilter = [ 'jsDocComment', 'lineMap', 'externalModuleIndicator', + 'setExternalModuleIndicator', 'bindDiagnostics', 'transformFlags', 'resolvedModules', diff --git a/packages/website/src/components/config/ConfigEslint.tsx b/packages/website/src/components/config/ConfigEslint.tsx index cb64ae0a46ad..f72e02f342c1 100644 --- a/packages/website/src/components/config/ConfigEslint.tsx +++ b/packages/website/src/components/config/ConfigEslint.tsx @@ -1,8 +1,7 @@ import React, { useCallback, useEffect, useState } from 'react'; -import type { RulesRecord, RuleEntry } from '@typescript-eslint/website-eslint'; import ConfigEditor, { ConfigOptionsType } from './ConfigEditor'; -import type { RuleDetails } from '../types'; +import type { RuleDetails, RulesRecord, RuleEntry } from '../types'; import { shallowEqual } from '../lib/shallowEqual'; export interface ModalEslintProps { diff --git a/packages/website/src/components/editor/LoadedEditor.tsx b/packages/website/src/components/editor/LoadedEditor.tsx index 9e4baa04da5b..d6433bfaee50 100644 --- a/packages/website/src/components/editor/LoadedEditor.tsx +++ b/packages/website/src/components/editor/LoadedEditor.tsx @@ -1,12 +1,12 @@ import React, { useMemo } from 'react'; import type Monaco from 'monaco-editor'; import { useEffect, useRef, useState } from 'react'; -import type { WebLinter } from '@typescript-eslint/website-eslint'; import type { SandboxInstance } from './useSandboxServices'; import type { CommonEditorProps } from './types'; +import type { WebLinter } from '../linter/WebLinter'; import { debounce } from '../lib/debounce'; -import { lintCode, LintCodeAction } from './lintCode'; +import { lintCode, LintCodeAction } from '../linter/lintCode'; import { createProvideCodeActions } from './createProvideCodeActions'; export interface LoadedEditorProps extends CommonEditorProps { @@ -83,9 +83,9 @@ export const LoadedEditor: React.FC = ({ ); } - onEsASTChange(fatalMessage ?? webLinter.getAst()); - onTsASTChange(fatalMessage ?? webLinter.getTsAst()); - onScopeChange(fatalMessage ?? webLinter.getScope()); + onEsASTChange(fatalMessage ?? webLinter.storedAST ?? ''); + onTsASTChange(fatalMessage ?? webLinter.storedTsAST ?? ''); + onScopeChange(fatalMessage ?? webLinter.storedScope ?? ''); onSelect(sandboxInstance.editor.getPosition()); }, 500), [code, jsx, sandboxInstance, rules, sourceType, tsConfig, webLinter], diff --git a/packages/website/src/components/editor/createProvideCodeActions.ts b/packages/website/src/components/editor/createProvideCodeActions.ts index b0930c19b322..1e9dfaca3899 100644 --- a/packages/website/src/components/editor/createProvideCodeActions.ts +++ b/packages/website/src/components/editor/createProvideCodeActions.ts @@ -1,6 +1,6 @@ import type Monaco from 'monaco-editor'; -import { createURI } from './utils'; -import type { LintCodeAction } from './lintCode'; +import type { LintCodeAction } from '../linter/lintCode'; +import { createURI } from '../linter/utils'; export function createProvideCodeActions( fixes: Map, diff --git a/packages/website/src/components/editor/loadSandbox.ts b/packages/website/src/components/editor/loadSandbox.ts index d25d9248bb6b..ac342d8e290c 100644 --- a/packages/website/src/components/editor/loadSandbox.ts +++ b/packages/website/src/components/editor/loadSandbox.ts @@ -1,6 +1,6 @@ import type * as TsWorker from '../../vendor/tsWorker'; import type * as SandboxFactory from '../../vendor/sandbox'; -import type { LinterLoader } from '@typescript-eslint/website-eslint'; +import type { LintUtils } from '@typescript-eslint/website-eslint'; type Monaco = typeof import('monaco-editor'); type TS = typeof import('typescript'); @@ -10,7 +10,7 @@ declare global { main: Monaco, tsWorker: typeof TsWorker, sandboxFactory: typeof SandboxFactory, - linter: LinterLoader, + lintUtils: LintUtils, ) => void; interface WindowRequire { (files: string[], cb: WindowRequireCb): void; @@ -31,7 +31,7 @@ export interface SandboxModel { tsWorker: typeof TsWorker; sandboxFactory: typeof SandboxFactory; ts: TS; - linter: LinterLoader; + lintUtils: LintUtils; } function loadSandbox(tsVersion: string): Promise { @@ -61,7 +61,7 @@ function loadSandbox(tsVersion: string): Promise { 'sandbox/index', 'linter/index', ], - (main, tsWorker, sandboxFactory, linter) => { + (main, tsWorker, sandboxFactory, lintUtils) => { const isOK = main && window.ts && sandboxFactory; if (isOK) { resolve({ @@ -69,7 +69,7 @@ function loadSandbox(tsVersion: string): Promise { tsWorker, sandboxFactory, ts: window.ts, - linter, + lintUtils, }); } else { reject( diff --git a/packages/website/src/components/editor/types.ts b/packages/website/src/components/editor/types.ts index edcbcf842d38..894a4fde6053 100644 --- a/packages/website/src/components/editor/types.ts +++ b/packages/website/src/components/editor/types.ts @@ -1,6 +1,6 @@ import type Monaco from 'monaco-editor'; import type { ConfigModel, SelectedRange } from '../types'; -import type { TSESTree } from '@typescript-eslint/website-eslint'; +import type { TSESTree } from '@typescript-eslint/utils'; import type { SourceFile } from 'typescript'; export interface CommonEditorProps extends ConfigModel { diff --git a/packages/website/src/components/editor/useSandboxServices.ts b/packages/website/src/components/editor/useSandboxServices.ts index e2e47f2f3faa..698f136a9c3b 100644 --- a/packages/website/src/components/editor/useSandboxServices.ts +++ b/packages/website/src/components/editor/useSandboxServices.ts @@ -1,13 +1,14 @@ import { useEffect, useState } from 'react'; import type Monaco from 'monaco-editor'; -import type { LintMessage, WebLinter } from '@typescript-eslint/website-eslint'; +import type { TSESLint } from '@typescript-eslint/utils'; import type { RuleDetails } from '../types'; import type { createTypeScriptSandbox, SandboxConfig, } from '../../vendor/sandbox'; +import { WebLinter } from '../linter/WebLinter'; import { sandboxSingleton } from './loadSandbox'; import { editorEmbedId } from './EditorEmbed'; import { useColorMode } from '@docusaurus/theme-common'; @@ -24,7 +25,7 @@ export interface SandboxServicesProps { export type SandboxInstance = ReturnType; export interface SandboxServices { - fixes: Map; + fixes: Map; main: typeof Monaco; sandboxInstance: SandboxInstance; webLinter: WebLinter; @@ -44,17 +45,17 @@ export const useSandboxServices = ( }, [props.ts, loadedTs]); useEffect(() => { - const fixes = new Map(); + const fixes = new Map(); let sandboxInstance: SandboxInstance | undefined; setLoadedTs(props.ts); sandboxSingleton(props.ts) - .then(async ({ main, sandboxFactory, ts, linter }) => { + .then(async ({ main, sandboxFactory, ts, lintUtils }) => { const compilerOptions: Monaco.languages.typescript.CompilerOptions = { noResolve: true, target: main.languages.typescript.ScriptTarget.ESNext, jsx: props.jsx ? main.languages.typescript.JsxEmit.React : undefined, - lib: ['esnext'], + lib: ['es2021', 'esnext'], module: main.languages.typescript.ModuleKind.ESNext, }; @@ -86,8 +87,9 @@ export const useSandboxServices = ( true, window.ts, ); + const system = sandboxInstance.tsvfs.createSystem(libMap); - const webLinter = linter.loadLinter(libMap, compilerOptions); + const webLinter = new WebLinter(system, compilerOptions, lintUtils); props.onLoaded(webLinter.ruleNames, sandboxInstance.supportedVersions); diff --git a/packages/website/src/components/linter/CompilerHost.ts b/packages/website/src/components/linter/CompilerHost.ts new file mode 100644 index 000000000000..ddf360a2a25d --- /dev/null +++ b/packages/website/src/components/linter/CompilerHost.ts @@ -0,0 +1,37 @@ +import type { System, SourceFile, CompilerHost } from 'typescript'; +import type { LintUtils } from '@typescript-eslint/website-eslint'; + +/** + * Creates an in-memory CompilerHost -which is essentially an extra wrapper to System + * which works with TypeScript objects - returns both a compiler host, and a way to add new SourceFile + * instances to the in-memory file system. + * + * based on typescript-vfs + * @see https://github.com/microsoft/TypeScript-Website/blob/d2613c0e57ae1be2f3a76e94b006819a1fc73d5e/packages/typescript-vfs/src/index.ts#L480 + */ +export function createVirtualCompilerHost( + sys: System, + lintUtils: LintUtils, +): CompilerHost { + return { + ...sys, + getCanonicalFileName: (fileName: string) => fileName, + getDefaultLibFileName: options => + '/' + window.ts.getDefaultLibFileName(options), + getNewLine: () => sys.newLine, + getSourceFile(fileName, languageVersionOrOptions): SourceFile | undefined { + if (this.fileExists(fileName)) { + const file = this.readFile(fileName) ?? ''; + return window.ts.createSourceFile( + fileName, + file, + languageVersionOrOptions, + true, + lintUtils.getScriptKind(fileName, false), + ); + } + return undefined; + }, + useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, + }; +} diff --git a/packages/website/src/components/linter/WebLinter.ts b/packages/website/src/components/linter/WebLinter.ts new file mode 100644 index 000000000000..d3c045eaf427 --- /dev/null +++ b/packages/website/src/components/linter/WebLinter.ts @@ -0,0 +1,121 @@ +import type { + CompilerOptions, + SourceFile, + CompilerHost, + System, +} from 'typescript'; +import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; +import type { ParserServices } from '@typescript-eslint/utils/dist/ts-estree'; +import type { ParserOptions } from '@typescript-eslint/types'; +import type { LintUtils } from '@typescript-eslint/website-eslint'; + +import { createVirtualCompilerHost } from '@site/src/components/linter/CompilerHost'; +import { extra } from '@site/src/components/linter/config'; + +const PARSER_NAME = '@typescript-eslint/parser'; + +export class WebLinter { + private readonly host: CompilerHost; + + public storedAST?: TSESTree.Program; + public storedTsAST?: SourceFile; + public storedScope?: Record; + + private compilerOptions: CompilerOptions; + private linter: TSESLint.Linter; + private lintUtils: LintUtils; + + public ruleNames: { name: string; description?: string }[]; + + constructor( + system: System, + compilerOptions: CompilerOptions, + lintUtils: LintUtils, + ) { + this.compilerOptions = compilerOptions; + this.lintUtils = lintUtils; + this.linter = lintUtils.createLinter(); + + this.host = createVirtualCompilerHost(system, lintUtils); + + this.linter.defineParser(PARSER_NAME, { + parseForESLint: (text, options?: ParserOptions) => { + return this.eslintParse(text, compilerOptions, options); + }, + }); + + this.ruleNames = Array.from(this.linter.getRules()).map(value => { + return { + name: value[0], + description: value[1]?.meta?.docs?.description, + }; + }); + } + + lint( + code: string, + parserOptions: ParserOptions, + rules: TSESLint.Linter.RulesRecord, + ): TSESLint.Linter.LintMessage[] { + return this.linter.verify(code, { + parser: PARSER_NAME, + parserOptions, + rules, + }); + } + + updateOptions(options: CompilerOptions = {}): void { + this.compilerOptions = options; + } + + eslintParse( + code: string, + compilerOptions: CompilerOptions, + eslintOptions: ParserOptions = {}, + ): TSESLint.Linter.ESLintParseResult { + const isJsx = eslintOptions?.ecmaFeatures?.jsx ?? false; + const fileName = isJsx ? '/demo.tsx' : '/demo.ts'; + + this.host.writeFile(fileName, code, false); + + const program = window.ts.createProgram( + [fileName], + compilerOptions, + this.host, + ); + const tsAst = program.getSourceFile(fileName)!; + + const { estree: ast, astMaps } = this.lintUtils.astConverter( + tsAst, + { ...extra, code, jsx: isJsx }, + true, + ); + + const scopeManager = this.lintUtils.analyze(ast, { + ecmaVersion: + eslintOptions.ecmaVersion === 'latest' + ? 1e8 + : eslintOptions.ecmaVersion, + globalReturn: eslintOptions.ecmaFeatures?.globalReturn ?? false, + sourceType: eslintOptions.sourceType ?? 'script', + }); + + this.storedAST = ast; + this.storedTsAST = tsAst; + this.storedScope = scopeManager as unknown as Record; + + const services: ParserServices = { + hasFullTypeInformation: true, + program, + esTreeNodeToTSNodeMap: astMaps.esTreeNodeToTSNodeMap, + tsNodeToESTreeNodeMap: astMaps.tsNodeToESTreeNodeMap, + }; + + return { + ast, + services, + scopeManager, + visitorKeys: this.lintUtils.visitorKeys, + }; + } +} diff --git a/packages/website-eslint/src/linter/config.js b/packages/website/src/components/linter/config.ts similarity index 76% rename from packages/website-eslint/src/linter/config.js rename to packages/website/src/components/linter/config.ts index 06e9ec28b3e7..cad38a3e28fa 100644 --- a/packages/website-eslint/src/linter/config.js +++ b/packages/website/src/components/linter/config.ts @@ -1,4 +1,6 @@ -export const extra = { +import type { Extra } from '@typescript-eslint/typescript-estree/dist/parser-options'; + +export const extra: Extra = { code: '', comment: true, comments: [], @@ -10,6 +12,7 @@ export const extra = { filePath: '', jsx: false, loc: true, + // eslint-disable-next-line no-console log: console.log, preserveNodeMaps: true, projects: [], diff --git a/packages/website/src/components/editor/lintCode.ts b/packages/website/src/components/linter/lintCode.ts similarity index 91% rename from packages/website/src/components/editor/lintCode.ts rename to packages/website/src/components/linter/lintCode.ts index b601a6cdcb36..33f6c216bf35 100644 --- a/packages/website/src/components/editor/lintCode.ts +++ b/packages/website/src/components/linter/lintCode.ts @@ -1,5 +1,6 @@ -import type { RulesRecord, WebLinter } from '@typescript-eslint/website-eslint'; +import type { TSESLint } from '@typescript-eslint/utils'; import type Monaco from 'monaco-editor'; +import type { WebLinter } from './WebLinter'; import { createURI, ensurePositiveInt } from './utils'; export interface LintCodeAction { @@ -15,7 +16,7 @@ export type LintCodeActionGroup = [string, LintCodeAction]; export function lintCode( linter: WebLinter, code: string, - rules: RulesRecord | undefined, + rules: TSESLint.Linter.RulesRecord | undefined, jsx?: boolean, sourceType?: 'module' | 'script', ): [Monaco.editor.IMarkerData[], string | undefined, LintCodeActionGroup[]] { @@ -26,11 +27,11 @@ export function lintCode( jsx: jsx ?? false, globalReturn: false, }, - ecmaVersion: 2020, + ecmaVersion: 'latest', project: ['./tsconfig.json'], sourceType: sourceType ?? 'module', }, - rules, + rules ?? {}, ); const markers: Monaco.editor.IMarkerData[] = []; let fatalMessage: string | undefined = undefined; diff --git a/packages/website/src/components/editor/utils.ts b/packages/website/src/components/linter/utils.ts similarity index 100% rename from packages/website/src/components/editor/utils.ts rename to packages/website/src/components/linter/utils.ts diff --git a/packages/website/src/components/types.ts b/packages/website/src/components/types.ts index bb774a436f49..51cd4e98b40c 100644 --- a/packages/website/src/components/types.ts +++ b/packages/website/src/components/types.ts @@ -1,13 +1,11 @@ -import type { - ParserOptions, - RulesRecord, -} from '@typescript-eslint/website-eslint'; +import type { TSESLint } from '@typescript-eslint/utils'; export type CompilerFlags = Record; -export type SourceType = ParserOptions['sourceType']; +export type SourceType = TSESLint.SourceType; -export type { RulesRecord } from '@typescript-eslint/website-eslint'; +export type RulesRecord = TSESLint.Linter.RulesRecord; +export type RuleEntry = TSESLint.Linter.RuleEntry; export interface RuleDetails { name: string; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy