• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import * as fs from 'node:fs';
17import * as os from 'node:os';
18import * as path from 'node:path';
19import * as readline from 'node:readline';
20import type { CommandLineOptions } from '../lib/CommandLineOptions';
21import { lint } from '../lib/LinterRunner';
22import { Logger } from '../lib/Logger';
23import type { ProblemInfo } from '../lib/ProblemInfo';
24import { TypeScriptLinter } from '../lib/TypeScriptLinter';
25import { parseCommandLine } from './CommandLineParser';
26import { compileLintOptions } from './Compiler';
27
28export function run(): void {
29  const commandLineArgs = process.argv.slice(2);
30  if (commandLineArgs.length === 0) {
31    Logger.info('Command line error: no arguments');
32    process.exit(-1);
33  }
34
35  const cmdOptions = parseCommandLine(commandLineArgs);
36
37  if (cmdOptions.testMode) {
38    TypeScriptLinter.testMode = true;
39  }
40
41  TypeScriptLinter.initGlobals();
42
43  if (!cmdOptions.ideMode) {
44    const result = lint(compileLintOptions(cmdOptions));
45    process.exit(result.errorNodes > 0 ? 1 : 0);
46  } else {
47    runIDEMode(cmdOptions);
48  }
49}
50
51function getTempFileName(): string {
52  return path.join(os.tmpdir(), Math.floor(Math.random() * 10000000).toString() + '_linter_tmp_file.ts');
53}
54
55function showJSONMessage(problems: ProblemInfo[][]): void {
56  const jsonMessage = problems[0].map((x) => {
57    return {
58      line: x.line,
59      column: x.column,
60      start: x.start,
61      end: x.end,
62      type: x.type,
63      suggest: x.suggest,
64      rule: x.rule,
65      severity: x.severity,
66      autofix: x.autofix
67    };
68  });
69  Logger.info(`{"linter messages":${JSON.stringify(jsonMessage)}}`);
70}
71
72function runIDEMode(cmdOptions: CommandLineOptions): void {
73  TypeScriptLinter.ideMode = true;
74  const tmpFileName = getTempFileName();
75  // read data from stdin
76  const writeStream = fs.createWriteStream(tmpFileName, { flags: 'w' });
77  const rl = readline.createInterface({
78    input: process.stdin,
79    output: writeStream,
80    terminal: false
81  });
82
83  rl.on('line', (line: string) => {
84    fs.appendFileSync(tmpFileName, line + '\n');
85  });
86  rl.once('close', () => {
87    // end of input
88    writeStream.close();
89    cmdOptions.inputFiles = [tmpFileName];
90    if (cmdOptions.parsedConfigFile) {
91      cmdOptions.parsedConfigFile.fileNames.push(tmpFileName);
92    }
93    const result = lint(compileLintOptions(cmdOptions));
94    const problems = Array.from(result.problemsInfos.values());
95    if (problems.length === 1) {
96      showJSONMessage(problems);
97    } else {
98      Logger.error('Unexpected error: could not lint file');
99    }
100    fs.unlinkSync(tmpFileName);
101  });
102}
103