<commit_before>/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */
import {
  Path,
  dirname,
  getSystemPath,
  logging,
  normalize,
  resolve,
  virtualFs,
} from '@angular-devkit/core';
import { createConsoleLogger } from '@angular-devkit/core/node';
import {
  CompilerHost,
  CompilerOptions,
  DEFAULT_ERROR_CODE,
  Diagnostic,
  EmitFlags,
  Program,
  SOURCE,
  UNKNOWN_ERROR_CODE,
  VERSION,
  createCompilerHost,
  createProgram,
  formatDiagnostics,
  readConfiguration,
} from '@angular/compiler-cli';
import { ChildProcess, ForkOptions, fork } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
import { Compiler, compilation } from 'webpack';
import { time, timeEnd } from './benchmark';
import { WebpackCompilerHost } from './compiler_host';
import { resolveEntryModuleFromMain } from './entry_resolver';
import { DiagnosticMode, gatherDiagnostics, hasErrors } from './gather_diagnostics';
import {
  AngularCompilerPluginOptions,
  ContextElementDependencyConstructor,
  PLATFORM,
} from './interfaces';
import { LazyRouteMap, findLazyRoutes } from './lazy_routes';
import { NgccProcessor } from './ngcc_processor';
import { TypeScriptPathsPlugin } from './paths-plugin';
import { WebpackResourceLoader } from './resource_loader';
import {
  exportLazyModuleMap,
  exportNgFactory,
  findResources,
  importFactory,
  registerLocaleData,
  removeDecorators,
  replaceBootstrap,
  replaceResources,
  replaceServerBootstrap,
} from './transformers';
import { collectDeepNodes } from './transformers/ast_helpers';
import { downlevelConstructorParameters } from './transformers/ctor-parameters';
import {
  AUTO_START_ARG,
} from './type_checker';
import {
  InitMessage,
  LogMessage,
  MESSAGE_KIND,
  UpdateMessage,
} from './type_checker_messages';
import { flattenArray, forwardSlashPath, workaroundResolve } from './utils';
import {
  VirtualFileSystemDecorator,
  VirtualWatchFileSystemDecorator,
} from './virtual_file_system_decorator';
import {
  Callback,
  NodeWatchFileSystemInterface,
  NormalModuleFactoryRequest,
} from './webpack';
import { WebpackInputHost } from './webpack-input-host';

const treeKill = require('tree-kill');

export class AngularCompilerPlugin {
  private _options: AngularCompilerPluginOptions;

  // TS compilation.
  private _compilerOptions: CompilerOptions;
  private _rootNames: string[];
  private _program: (ts.Program | Program) | null;
  private _compilerHost: WebpackCompilerHost & CompilerHost;
  private _moduleResolutionCache: ts.ModuleResolutionCache;
  private _resourceLoader?: WebpackResourceLoader;
  private _discoverLazyRoutes = true;
  private _useFactories = false;
  // Contains `moduleImportPath#exportName` => `fullModulePath`.
  private _lazyRoutes: LazyRouteMap = {};
  private _tsConfigPath: string;
  private _entryModule: string | null;
  private _mainPath: string | undefined;
  private _basePath: string;
  private _transformers: ts.TransformerFactory<ts.SourceFile>[] = [];
  private _platformTransformers: ts.TransformerFactory<ts.SourceFile>[] | null = null;
  private _platform: PLATFORM;
  private _JitMode = false;
  private _emitSkipped = true;
  private _changedFileExtensions = new Set(['ts', 'tsx', 'html', 'css', 'js', 'json']);

  // Webpack plugin.
  private _firstRun = true;
  private _donePromise: Promise<void> | null;
  private _normalizedLocale: string | null;
  private _warnings: (string | Error)[] = [];
  private _errors: (string | Error)[] = [];
  private _contextElementDependencyConstructor: ContextElementDependencyConstructor;

  // TypeChecker process.
  private _forkTypeChecker = true;
  private _typeCheckerProcess: ChildProcess | null;
  private _forkedTypeCheckerInitialized = false;

  // Logging.
  private _logger: logging.Logger;

  private _mainFields: string[] = [];

  constructor(options: AngularCompilerPluginOptions) {
    this._options = Object.assign({}, options);
    this._setupOptions(this._options);
  }

  get options() { return this._options; }
  get done() { return this._donePromise; }
  get entryModule() {
    if (!this._entryModule) {
      return null;
    }
    const splitted = this._entryModule.split(/(#[a-zA-Z_]([\w]+))$/);
    const path = splitted[0];
    const className = !!splitted[1] ? splitted[1].substring(1) : 'default';

    return { path, className };
  }

  get typeChecker(): ts.TypeChecker | null {
    const tsProgram = this._getTsProgram();

    return tsProgram ? tsProgram.getTypeChecker() : null;
  }

  static isSupported() {
    return VERSION && parseInt(VERSION.major) >= 8;
  }

  private _setupOptions(options: AngularCompilerPluginOptions) {
    time('AngularCompilerPlugin._setupOptions');
    this._logger = options.logger || createConsoleLogger();

    // Fill in the missing options.
    if (!options.hasOwnProperty('tsConfigPath')) {
      throw new Error('Must specify "tsConfigPath" in the configuration of @ngtools/webpack.');
    }
    // TS represents paths internally with '/' and expects the tsconfig path to be in this format
    this._tsConfigPath = forwardSlashPath(options.tsConfigPath);

    // Check the base path.
    const maybeBasePath = path.resolve(process.cwd(), this._tsConfigPath);
    let basePath = maybeBasePath;
    if (fs.statSync(maybeBasePath).isFile()) {
      basePath = path.dirname(basePath);
    }
    if (options.basePath !== undefined) {
      basePath = path.resolve(process.cwd(), options.basePath);
    }

    // Parse the tsconfig contents.
    const config = readConfiguration(this._tsConfigPath);
    if (config.errors && config.errors.length) {
      throw new Error(formatDiagnostics(config.errors));
    }
<commit_msg>refactor: deprecate `isSupported` static in `AngularCompilerPlugin`<commit_after>/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */
import {
  Path,
  dirname,
  getSystemPath,
  logging,
  normalize,
  resolve,
  virtualFs,
} from '@angular-devkit/core';
import { createConsoleLogger } from '@angular-devkit/core/node';
import {
  CompilerHost,
  CompilerOptions,
  DEFAULT_ERROR_CODE,
  Diagnostic,
  EmitFlags,
  Program,
  SOURCE,
  UNKNOWN_ERROR_CODE,
  VERSION,
  createCompilerHost,
  createProgram,
  formatDiagnostics,
  readConfiguration,
} from '@angular/compiler-cli';
import { ChildProcess, ForkOptions, fork } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
import { Compiler, compilation } from 'webpack';
import { time, timeEnd } from './benchmark';
import { WebpackCompilerHost } from './compiler_host';
import { resolveEntryModuleFromMain } from './entry_resolver';
import { DiagnosticMode, gatherDiagnostics, hasErrors } from './gather_diagnostics';
import {
  AngularCompilerPluginOptions,
  ContextElementDependencyConstructor,
  PLATFORM,
} from './interfaces';
import { LazyRouteMap, findLazyRoutes } from './lazy_routes';
import { NgccProcessor } from './ngcc_processor';
import { TypeScriptPathsPlugin } from './paths-plugin';
import { WebpackResourceLoader } from './resource_loader';
import {
  exportLazyModuleMap,
  exportNgFactory,
  findResources,
  importFactory,
  registerLocaleData,
  removeDecorators,
  replaceBootstrap,
  replaceResources,
  replaceServerBootstrap,
} from './transformers';
import { collectDeepNodes } from './transformers/ast_helpers';
import { downlevelConstructorParameters } from './transformers/ctor-parameters';
import {
  AUTO_START_ARG,
} from './type_checker';
import {
  InitMessage,
  LogMessage,
  MESSAGE_KIND,
  UpdateMessage,
} from './type_checker_messages';
import { flattenArray, forwardSlashPath, workaroundResolve } from './utils';
import {
  VirtualFileSystemDecorator,
  VirtualWatchFileSystemDecorator,
} from './virtual_file_system_decorator';
import {
  Callback,
  NodeWatchFileSystemInterface,
  NormalModuleFactoryRequest,
} from './webpack';
import { WebpackInputHost } from './webpack-input-host';

const treeKill = require('tree-kill');

export class AngularCompilerPlugin {
  private _options: AngularCompilerPluginOptions;

  // TS compilation.
  private _compilerOptions: CompilerOptions;
  private _rootNames: string[];
  private _program: (ts.Program | Program) | null;
  private _compilerHost: WebpackCompilerHost & CompilerHost;
  private _moduleResolutionCache: ts.ModuleResolutionCache;
  private _resourceLoader?: WebpackResourceLoader;
  private _discoverLazyRoutes = true;
  private _useFactories = false;
  // Contains `moduleImportPath#exportName` => `fullModulePath`.
  private _lazyRoutes: LazyRouteMap = {};
  private _tsConfigPath: string;
  private _entryModule: string | null;
  private _mainPath: string | undefined;
  private _basePath: string;
  private _transformers: ts.TransformerFactory<ts.SourceFile>[] = [];
  private _platformTransformers: ts.TransformerFactory<ts.SourceFile>[] | null = null;
  private _platform: PLATFORM;
  private _JitMode = false;
  private _emitSkipped = true;
  private _changedFileExtensions = new Set(['ts', 'tsx', 'html', 'css', 'js', 'json']);

  // Webpack plugin.
  private _firstRun = true;
  private _donePromise: Promise<void> | null;
  private _normalizedLocale: string | null;
  private _warnings: (string | Error)[] = [];
  private _errors: (string | Error)[] = [];
  private _contextElementDependencyConstructor: ContextElementDependencyConstructor;

  // TypeChecker process.
  private _forkTypeChecker = true;
  private _typeCheckerProcess: ChildProcess | null;
  private _forkedTypeCheckerInitialized = false;

  // Logging.
  private _logger: logging.Logger;

  private _mainFields: string[] = [];

  constructor(options: AngularCompilerPluginOptions) {
    this._options = Object.assign({}, options);
    this._setupOptions(this._options);
  }

  get options() { return this._options; }
  get done() { return this._donePromise; }
  get entryModule() {
    if (!this._entryModule) {
      return null;
    }
    const splitted = this._entryModule.split(/(#[a-zA-Z_]([\w]+))$/);
    const path = splitted[0];
    const className = !!splitted[1] ? splitted[1].substring(1) : 'default';

    return { path, className };
  }

  get typeChecker(): ts.TypeChecker | null {
    const tsProgram = this._getTsProgram();

    return tsProgram ? tsProgram.getTypeChecker() : null;
  }

  /** @deprecated  From 8.0.2 */
  static isSupported() {
    return VERSION && parseInt(VERSION.major) >= 8;
  }

  private _setupOptions(options: AngularCompilerPluginOptions) {
    time('AngularCompilerPlugin._setupOptions');
    this._logger = options.logger || createConsoleLogger();

    // Fill in the missing options.
    if (!options.hasOwnProperty('tsConfigPath')) {
      throw new Error('Must specify "tsConfigPath" in the configuration of @ngtools/webpack.');
    }
    // TS represents paths internally with '/' and expects the tsconfig path to be in this format
    this._tsConfigPath = forwardSlashPath(options.tsConfigPath);

    // Check the base path.
    const maybeBasePath = path.resolve(process.cwd(), this._tsConfigPath);
    let basePath = maybeBasePath;
    if (fs.statSync(maybeBasePath).isFile()) {
      basePath = path.dirname(basePath);
    }
    if (options.basePath !== undefined) {
      basePath = path.resolve(process.cwd(), options.basePath);
    }

    // Parse the tsconfig contents.
    const config = readConfiguration(this._tsConfigPath);
    if (config.errors && config.errors.length) {
      throw new Error(formatDiagnostics(config.errors));
    }

{'fraction_non_alphanumeric': 0.11369224247562526, 'fraction_numerical': 0.0011021619330224672, 'mean_word_length': 4.522471910112359, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1367829', 'n_tokens_mistral': 3458, 'n_tokens_neox': 3422, 'n_words': 872}