📄 createLinter.ts
¶
📊 Analysis Summary¶
Metric | Count |
---|---|
🔧 Functions | 8 |
📦 Imports | 16 |
📊 Variables & Constants | 12 |
📐 Interfaces | 1 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/website/src/components/linter/createLinter.ts
📦 Imports¶
Name | Source |
---|---|
JSONSchema |
@typescript-eslint/utils |
TSESTree |
@typescript-eslint/utils |
ClassicConfig |
@typescript-eslint/utils/ts-eslint |
Linter |
@typescript-eslint/utils/ts-eslint |
SourceType |
@typescript-eslint/utils/ts-eslint |
LinterOnLint |
./types |
LinterOnParse |
./types |
PlaygroundSystem |
./types |
WebLinterModule |
./types |
createCompilerOptions |
../lib/createCompilerOptions |
createEventsBinder |
../lib/createEventsBinder |
parseESLintRC |
../lib/parseConfig |
parseTSConfig |
../lib/parseConfig |
defaultEslintConfig |
./config |
PARSER_NAME |
./config |
createParser |
./createParser |
Variables & Constants¶
Name | Type | Kind | Value | Exported |
---|---|---|---|---|
rules |
CreateLinter['rules'] |
const | new Map() |
✗ |
configs |
Map<string, ClassicConfig.Config> |
const | new Map(Object.entries(webLinterModule.configs)) |
✗ |
compilerOptions |
ts.CompilerOptions |
let/var | {} |
✗ |
eslintConfig |
ClassicConfig.Config |
const | { ...defaultEslintConfig } |
✗ |
code |
any |
const | system.readFile(filename) ?? '\n' |
✗ |
lintMessage |
Linter.LintMessage |
const | `{ | |
column: 1, | ||||
line: 1, | ||||
message: String(e instanceof Error ? e.stack : e), | ||||
nodeType: '', | ||||
ruleId: '', | ||||
severity: 2, | ||||
source: 'eslint', | ||||
}` | ✗ | |||
node |
TSESTree.Node |
const | e.currentNode as TSESTree.Node |
✗ |
config |
{ rules: {}; } |
const | { rules: {} } |
✗ |
cfgExtends |
any |
const | `Array.isArray(cfg.extends) | |
? cfg.extends | ||||
: [cfg.extends]` | ✗ | |||
file |
any |
const | system.readFile(fileName) ?? '{}' |
✗ |
file |
any |
const | system.readFile(fileName) ?? '{}' |
✗ |
parsed |
CompilerFlags |
const | parseTSConfig(file).compilerOptions |
✗ |
Functions¶
createLinter(system: PlaygroundSystem, webLinterModule: WebLinterModule, vfs: typeof tsvfs): CreateLinter
¶
Code
export function createLinter(
system: PlaygroundSystem,
webLinterModule: WebLinterModule,
vfs: typeof tsvfs,
): CreateLinter {
const rules: CreateLinter['rules'] = new Map();
const configs = new Map(Object.entries(webLinterModule.configs));
let compilerOptions: ts.CompilerOptions = {};
const eslintConfig: ClassicConfig.Config = { ...defaultEslintConfig };
const onLint = createEventsBinder<LinterOnLint>();
const onParse = createEventsBinder<LinterOnParse>();
const linter = webLinterModule.createLinter();
const parser = createParser(
system,
compilerOptions,
(filename, model): void => {
onParse.trigger(filename, model);
},
webLinterModule,
vfs,
);
linter.defineParser(PARSER_NAME, parser);
linter.getRules().forEach((item, name) => {
rules.set(name, {
description: item.meta?.docs?.description,
name,
schema: item.meta?.schema ?? [],
url: item.meta?.docs?.url,
});
});
const triggerLint = (filename: string): void => {
console.info('[Editor] linting triggered for file', filename);
const code = system.readFile(filename) ?? '\n';
try {
const messages = linter.verify(code, eslintConfig, filename);
onLint.trigger(filename, messages);
} catch (e) {
const lintMessage: Linter.LintMessage = {
column: 1,
line: 1,
message: String(e instanceof Error ? e.stack : e),
nodeType: '',
ruleId: '',
severity: 2,
source: 'eslint',
};
if (typeof e === 'object' && e && 'currentNode' in e) {
const node = e.currentNode as TSESTree.Node;
lintMessage.column = node.loc.start.column + 1;
lintMessage.line = node.loc.start.line;
lintMessage.endColumn = node.loc.end.column + 1;
lintMessage.endLine = node.loc.end.line;
}
onLint.trigger(filename, [lintMessage]);
}
};
const triggerFix = (filename: string): Linter.FixReport | undefined => {
const code = system.readFile(filename);
if (code) {
return linter.verifyAndFix(code, eslintConfig, {
filename,
fix: true,
});
}
return undefined;
};
const updateParserOptions = (sourceType?: SourceType): void => {
eslintConfig.parserOptions ??= {};
eslintConfig.parserOptions.sourceType = sourceType ?? 'module';
};
const resolveEslintConfig = (
cfg: Partial<ClassicConfig.Config>,
): ClassicConfig.Config => {
const config = { rules: {} };
if (cfg.extends) {
const cfgExtends = Array.isArray(cfg.extends)
? cfg.extends
: [cfg.extends];
for (const extendsName of cfgExtends) {
const maybeConfig = configs.get(extendsName);
if (maybeConfig) {
const resolved = resolveEslintConfig(maybeConfig);
if (resolved.rules) {
Object.assign(config.rules, resolved.rules);
}
}
}
}
if (cfg.rules) {
Object.assign(config.rules, cfg.rules);
}
return config;
};
const applyEslintConfig = (fileName: string): void => {
try {
const file = system.readFile(fileName) ?? '{}';
const parsed = resolveEslintConfig(parseESLintRC(file));
eslintConfig.rules = parsed.rules;
console.log('[Editor] Updating', fileName, eslintConfig);
} catch (e) {
console.error(e);
}
};
const applyTSConfig = (fileName: string): void => {
try {
const file = system.readFile(fileName) ?? '{}';
const parsed = parseTSConfig(file).compilerOptions;
compilerOptions = createCompilerOptions(parsed);
console.log('[Editor] Updating', fileName, compilerOptions);
parser.updateConfig(compilerOptions);
} catch (e) {
console.error(e);
}
};
const triggerLintAll = (): void => {
system.searchFiles('/input.*').forEach(triggerLint);
};
system.watchFile('/input.*', triggerLint);
system.watchFile('/.eslintrc', filename => {
applyEslintConfig(filename);
triggerLintAll();
});
system.watchFile('/tsconfig.json', filename => {
applyTSConfig(filename);
triggerLintAll();
});
applyEslintConfig('/.eslintrc');
applyTSConfig('/tsconfig.json');
return {
configs: [...configs.keys()],
onLint: onLint.register,
onParse: onParse.register,
rules,
triggerFix,
triggerLint,
updateParserOptions,
};
}
- Parameters:
system: PlaygroundSystem
webLinterModule: WebLinterModule
vfs: typeof tsvfs
- Return Type:
CreateLinter
- Calls:
Object.entries
createEventsBinder (from ../lib/createEventsBinder)
webLinterModule.createLinter
createParser (from ./createParser)
onParse.trigger
linter.defineParser
linter.getRules().forEach
rules.set
console.info
system.readFile
linter.verify
onLint.trigger
String
linter.verifyAndFix
Array.isArray
configs.get
resolveEslintConfig
Object.assign
parseESLintRC (from ../lib/parseConfig)
console.log
console.error
parseTSConfig (from ../lib/parseConfig)
createCompilerOptions (from ../lib/createCompilerOptions)
parser.updateConfig
system.searchFiles('/input.*').forEach
system.watchFile
applyEslintConfig
triggerLintAll
applyTSConfig
configs.keys
triggerLint(filename: string): void
¶
Code
(filename: string): void => {
console.info('[Editor] linting triggered for file', filename);
const code = system.readFile(filename) ?? '\n';
try {
const messages = linter.verify(code, eslintConfig, filename);
onLint.trigger(filename, messages);
} catch (e) {
const lintMessage: Linter.LintMessage = {
column: 1,
line: 1,
message: String(e instanceof Error ? e.stack : e),
nodeType: '',
ruleId: '',
severity: 2,
source: 'eslint',
};
if (typeof e === 'object' && e && 'currentNode' in e) {
const node = e.currentNode as TSESTree.Node;
lintMessage.column = node.loc.start.column + 1;
lintMessage.line = node.loc.start.line;
lintMessage.endColumn = node.loc.end.column + 1;
lintMessage.endLine = node.loc.end.line;
}
onLint.trigger(filename, [lintMessage]);
}
}
- Parameters:
filename: string
- Return Type:
void
- Calls:
console.info
system.readFile
linter.verify
onLint.trigger
String
triggerFix(filename: string): Linter.FixReport | undefined
¶
Code
- Parameters:
filename: string
- Return Type:
Linter.FixReport | undefined
- Calls:
system.readFile
linter.verifyAndFix
updateParserOptions(sourceType: SourceType): void
¶
Code
- Parameters:
sourceType: SourceType
- Return Type:
void
resolveEslintConfig(cfg: Partial<ClassicConfig.Config>): ClassicConfig.Config
¶
Code
(
cfg: Partial<ClassicConfig.Config>,
): ClassicConfig.Config => {
const config = { rules: {} };
if (cfg.extends) {
const cfgExtends = Array.isArray(cfg.extends)
? cfg.extends
: [cfg.extends];
for (const extendsName of cfgExtends) {
const maybeConfig = configs.get(extendsName);
if (maybeConfig) {
const resolved = resolveEslintConfig(maybeConfig);
if (resolved.rules) {
Object.assign(config.rules, resolved.rules);
}
}
}
}
if (cfg.rules) {
Object.assign(config.rules, cfg.rules);
}
return config;
}
- Parameters:
cfg: Partial<ClassicConfig.Config>
- Return Type:
ClassicConfig.Config
- Calls:
Array.isArray
configs.get
resolveEslintConfig
Object.assign
applyEslintConfig(fileName: string): void
¶
Code
- Parameters:
fileName: string
- Return Type:
void
- Calls:
system.readFile
resolveEslintConfig
parseESLintRC (from ../lib/parseConfig)
console.log
console.error
applyTSConfig(fileName: string): void
¶
Code
(fileName: string): void => {
try {
const file = system.readFile(fileName) ?? '{}';
const parsed = parseTSConfig(file).compilerOptions;
compilerOptions = createCompilerOptions(parsed);
console.log('[Editor] Updating', fileName, compilerOptions);
parser.updateConfig(compilerOptions);
} catch (e) {
console.error(e);
}
}
- Parameters:
fileName: string
- Return Type:
void
- Calls:
system.readFile
parseTSConfig (from ../lib/parseConfig)
createCompilerOptions (from ../lib/createCompilerOptions)
console.log
parser.updateConfig
console.error
triggerLintAll(): void
¶
- Return Type:
void
- Calls:
system.searchFiles('/input.*').forEach
Interfaces¶
CreateLinter
¶
Interface Code
export interface CreateLinter {
configs: string[];
onLint(cb: LinterOnLint): () => void;
onParse(cb: LinterOnParse): () => void;
rules: Map<
string,
{
description?: string;
name: string;
schema: JSONSchema.JSONSchema4 | readonly JSONSchema.JSONSchema4[];
url?: string;
}
>;
triggerFix(filename: string): Linter.FixReport | undefined;
triggerLint(filename: string): void;
updateParserOptions(sourceType?: SourceType): void;
}
Properties¶
Name | Type | Optional | Description |
---|---|---|---|
configs |
string[] |
✗ | |
rules |
`Map< | ||
string, | |||
{ | |||
description?: string; | |||
name: string; | |||
schema: JSONSchema.JSONSchema4 | readonly JSONSchema.JSONSchema4[]; | ||
url?: string; | |||
} | |||
>` | ✗ |