• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023-2023 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
16namespace ts {
17export namespace ArkTSLinter_1_0 {
18
19export class TSCCompiledProgram {
20  private diagnosticsExtractor: TypeScriptDiagnosticsExtractor;
21  private wasStrict: boolean;
22
23  constructor(program: ArkTSProgram, reverseStrictBuilderProgram: ArkTSProgram) {
24    const strict = program.wasStrict ? program.builderProgram : reverseStrictBuilderProgram.builderProgram;
25    const nonStrict = program.wasStrict ? reverseStrictBuilderProgram.builderProgram : program.builderProgram;
26    this.diagnosticsExtractor = new TypeScriptDiagnosticsExtractor(strict, nonStrict);
27    this.wasStrict = program.wasStrict;
28  }
29
30  public getOriginalProgram(): Program {
31    return this.wasStrict
32      ? this.diagnosticsExtractor.strictProgram.getProgram()
33      : this.diagnosticsExtractor.nonStrictProgram.getProgram();
34  }
35
36  public getStrictProgram(): Program {
37    return this.diagnosticsExtractor.strictProgram.getProgram();
38  }
39
40  public getStrictBuilderProgram(): BuilderProgram {
41    return this.diagnosticsExtractor.strictProgram;
42  }
43
44  public getNonStrictBuilderProgram(): BuilderProgram {
45    return this.diagnosticsExtractor.nonStrictProgram;
46  }
47
48  public getStrictDiagnostics(fileName: string): Diagnostic[] {
49    return this.diagnosticsExtractor.getStrictDiagnostics(fileName);
50  }
51
52  public doAllGetDiagnostics() {
53    this.diagnosticsExtractor.doAllGetDiagnostics();
54  }
55}
56
57class TypeScriptDiagnosticsExtractor {
58  constructor(public strictProgram: BuilderProgram, public nonStrictProgram: BuilderProgram) {
59  }
60
61  /**
62   * Returns diagnostics which appear in strict compilation mode only
63   */
64   public getStrictDiagnostics(fileName: string): Diagnostic[] {
65    // workaround for a tsc bug
66    const strict = getAllDiagnostics(this.strictProgram, fileName).filter(diag => !(diag.length === 0 && diag.start === 0));
67    const nonStrict = getAllDiagnostics(this.nonStrictProgram, fileName);
68
69    // collect hashes for later easier comparison
70    const nonStrictHashes = nonStrict.reduce((result, value) => {
71      const hash = hashDiagnostic(value);
72      if (hash) {
73        result.add(hash);
74      }
75      return result;
76    }, new Set<string>());
77    // return diagnostics which weren't detected in non-strict mode
78    return strict.filter(value => {
79      const hash = hashDiagnostic(value);
80      return (hash && !nonStrictHashes.has(hash));
81    });
82  }
83
84  public doAllGetDiagnostics() {
85    this.strictProgram.getSemanticDiagnostics();
86    this.strictProgram.getSyntacticDiagnostics();
87    this.nonStrictProgram.getSemanticDiagnostics();
88    this.nonStrictProgram.getSyntacticDiagnostics();
89  }
90}
91
92function getAllDiagnostics(program: BuilderProgram, fileName: string): Diagnostic[] {
93  const sourceFile = program.getSourceFile(fileName);
94  return program.getSemanticDiagnostics(sourceFile)
95    .concat(program.getSyntacticDiagnostics(sourceFile))
96    .filter(diag => diag.file === sourceFile);
97}
98
99function hashDiagnostic(diagnostic: Diagnostic): string | undefined {
100  if (diagnostic.start === undefined || diagnostic.length === undefined) {
101    return undefined;
102  }
103  return `${diagnostic.code}%${diagnostic.start}%${diagnostic.length}`;
104}
105
106}
107}