mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-16 10:33:43 +08:00
refactor: add tslint-sonarts and a lot of tslint rules
This should clean up the code a bit. Note: at first I added the no-useless-cast rule, but after getting frustrated with it (as it has many false positive), I decided to remove the rule but some useless casts were removed so I let those in the PR.
This commit is contained in:
parent
c1702d3579
commit
483cbe2665
4625
package-lock.json
generated
4625
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -130,6 +130,7 @@
|
|||||||
"tree-kill": "^1.2.0",
|
"tree-kill": "^1.2.0",
|
||||||
"ts-node": "^5.0.0",
|
"ts-node": "^5.0.0",
|
||||||
"tslint": "^5.9.1",
|
"tslint": "^5.9.1",
|
||||||
|
"tslint-sonarts": "^1.7.0",
|
||||||
"tsutils": "~2.22.2",
|
"tsutils": "~2.22.2",
|
||||||
"typescript": "~2.7.2",
|
"typescript": "~2.7.2",
|
||||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||||
|
@ -22,8 +22,6 @@ export default class VersionCommand extends Command {
|
|||||||
public readonly options: Option[] = [];
|
public readonly options: Option[] = [];
|
||||||
|
|
||||||
public run() {
|
public run() {
|
||||||
let angularCoreVersion = '';
|
|
||||||
const angularSameAsCore: string[] = [];
|
|
||||||
const pkg = require(path.resolve(__dirname, '..', 'package.json'));
|
const pkg = require(path.resolve(__dirname, '..', 'package.json'));
|
||||||
let projPkg;
|
let projPkg;
|
||||||
try {
|
try {
|
||||||
@ -95,6 +93,8 @@ export default class VersionCommand extends Command {
|
|||||||
|
|
||||||
ngCliVersion = `local (v${pkg.version}, branch: ${gitBranch})`;
|
ngCliVersion = `local (v${pkg.version}, branch: ${gitBranch})`;
|
||||||
}
|
}
|
||||||
|
let angularCoreVersion = '';
|
||||||
|
const angularSameAsCore: string[] = [];
|
||||||
|
|
||||||
if (projPkg) {
|
if (projPkg) {
|
||||||
// Filter all angular versions that are the same as core.
|
// Filter all angular versions that are the same as core.
|
||||||
@ -107,6 +107,9 @@ export default class VersionCommand extends Command {
|
|||||||
delete versions[angularPackage];
|
delete versions[angularPackage];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we list them in alphabetical order.
|
||||||
|
angularSameAsCore.sort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +131,7 @@ export default class VersionCommand extends Command {
|
|||||||
Node: ${process.versions.node}
|
Node: ${process.versions.node}
|
||||||
OS: ${process.platform} ${process.arch}
|
OS: ${process.platform} ${process.arch}
|
||||||
Angular: ${angularCoreVersion}
|
Angular: ${angularCoreVersion}
|
||||||
... ${angularSameAsCore.sort().reduce<string[]>((acc, name) => {
|
... ${angularSameAsCore.reduce<string[]>((acc, name) => {
|
||||||
// Perform a simple word wrap around 60.
|
// Perform a simple word wrap around 60.
|
||||||
if (acc.length == 0) {
|
if (acc.length == 0) {
|
||||||
return [name];
|
return [name];
|
||||||
|
@ -15,7 +15,7 @@ export type NpmInstall = (packageName: string,
|
|||||||
logger: logging.Logger,
|
logger: logging.Logger,
|
||||||
packageManager: string,
|
packageManager: string,
|
||||||
projectRoot: string,
|
projectRoot: string,
|
||||||
save?: boolean) => void;
|
save?: boolean) => Promise<void>;
|
||||||
|
|
||||||
export default async function (packageName: string,
|
export default async function (packageName: string,
|
||||||
logger: logging.Logger,
|
logger: logging.Logger,
|
||||||
|
@ -119,7 +119,7 @@ export function getWorkspaceRaw(
|
|||||||
throw new Error('Invalid JSON');
|
throw new Error('Invalid JSON');
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ast as JsonAstObject, configPath];
|
return [ast, configPath];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateWorkspace(json: JsonObject) {
|
export function validateWorkspace(json: JsonObject) {
|
||||||
|
@ -34,8 +34,7 @@ export class TestProjectHost extends NodeJsSyncHost {
|
|||||||
throw new Error('TestProjectHost must be initialized before being used.');
|
throw new Error('TestProjectHost must be initialized before being used.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable-next-line:non-null-operator
|
return this._currentRoot;
|
||||||
return this._currentRoot!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scopedSync(): virtualFs.SyncDelegateHost<Stats> {
|
scopedSync(): virtualFs.SyncDelegateHost<Stats> {
|
||||||
@ -43,8 +42,7 @@ export class TestProjectHost extends NodeJsSyncHost {
|
|||||||
throw new Error('TestProjectHost must be initialized before being used.');
|
throw new Error('TestProjectHost must be initialized before being used.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable-next-line:non-null-operator
|
return this._scopedSyncHost;
|
||||||
return this._scopedSyncHost!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize(): Observable<void> {
|
initialize(): Observable<void> {
|
||||||
@ -100,7 +98,7 @@ export class TestProjectHost extends NodeJsSyncHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
writeMultipleFiles(files: { [path: string]: string | ArrayBufferLike | Buffer }): void {
|
writeMultipleFiles(files: { [path: string]: string | ArrayBufferLike | Buffer }): void {
|
||||||
Object.keys(files).map(fileName => {
|
Object.keys(files).forEach(fileName => {
|
||||||
let content = files[fileName];
|
let content = files[fileName];
|
||||||
if (typeof content == 'string') {
|
if (typeof content == 'string') {
|
||||||
content = virtualFs.stringToFileBuffer(content);
|
content = virtualFs.stringToFileBuffer(content);
|
||||||
|
@ -290,13 +290,13 @@ export class DevServerBuilder implements Builder<DevServerBuilderOptions> {
|
|||||||
let sslKey: string | undefined = undefined;
|
let sslKey: string | undefined = undefined;
|
||||||
let sslCert: string | undefined = undefined;
|
let sslCert: string | undefined = undefined;
|
||||||
if (options.sslKey) {
|
if (options.sslKey) {
|
||||||
const keyPath = path.resolve(root, options.sslKey as string);
|
const keyPath = path.resolve(root, options.sslKey);
|
||||||
if (existsSync(keyPath)) {
|
if (existsSync(keyPath)) {
|
||||||
sslKey = readFileSync(keyPath, 'utf-8');
|
sslKey = readFileSync(keyPath, 'utf-8');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (options.sslCert) {
|
if (options.sslCert) {
|
||||||
const certPath = path.resolve(root, options.sslCert as string);
|
const certPath = path.resolve(root, options.sslCert);
|
||||||
if (existsSync(certPath)) {
|
if (existsSync(certPath)) {
|
||||||
sslCert = readFileSync(certPath, 'utf-8');
|
sslCert = readFileSync(certPath, 'utf-8');
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ export class KarmaBuilder implements Builder<KarmaBuilderSchema> {
|
|||||||
|
|
||||||
// TODO: inside the configs, always use the project root and not the workspace root.
|
// TODO: inside the configs, always use the project root and not the workspace root.
|
||||||
// Until then we pretend the app root is relative (``) but the same as `projectRoot`.
|
// Until then we pretend the app root is relative (``) but the same as `projectRoot`.
|
||||||
(karmaOptions.buildWebpack.options as any).root = ''; // tslint:disable-line:no-any
|
karmaOptions.buildWebpack.options.root = '';
|
||||||
|
|
||||||
// Assign additional karmaConfig options to the local ngapp config
|
// Assign additional karmaConfig options to the local ngapp config
|
||||||
karmaOptions.configFile = karmaConfig;
|
karmaOptions.configFile = karmaConfig;
|
||||||
@ -112,7 +112,7 @@ export class KarmaBuilder implements Builder<KarmaBuilderSchema> {
|
|||||||
) {
|
) {
|
||||||
let wco: WebpackConfigOptions;
|
let wco: WebpackConfigOptions;
|
||||||
|
|
||||||
const tsConfigPath = getSystemPath(resolve(root, normalize(options.tsConfig as string)));
|
const tsConfigPath = getSystemPath(resolve(root, normalize(options.tsConfig)));
|
||||||
const tsConfig = readTsconfig(tsConfigPath);
|
const tsConfig = readTsconfig(tsConfigPath);
|
||||||
|
|
||||||
const projectTs = requireProjectModule(getSystemPath(projectRoot), 'typescript') as typeof ts;
|
const projectTs = requireProjectModule(getSystemPath(projectRoot), 'typescript') as typeof ts;
|
||||||
|
@ -106,8 +106,8 @@ export class ServerBuilder implements Builder<BuildWebpackServerSchema> {
|
|||||||
|
|
||||||
if (wco.buildOptions.main || wco.buildOptions.polyfills) {
|
if (wco.buildOptions.main || wco.buildOptions.polyfills) {
|
||||||
const typescriptConfigPartial = wco.buildOptions.aot
|
const typescriptConfigPartial = wco.buildOptions.aot
|
||||||
? getAotConfig(wco, host as virtualFs.Host<Stats>)
|
? getAotConfig(wco, host)
|
||||||
: getNonAotConfig(wco, host as virtualFs.Host<Stats>);
|
: getNonAotConfig(wco, host);
|
||||||
webpackConfigs.push(typescriptConfigPartial);
|
webpackConfigs.push(typescriptConfigPartial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
|
|
||||||
import { DefaultTimeout, TestLogger, runTargetSpec } from '@angular-devkit/architect/testing';
|
import { DefaultTimeout, TestLogger, runTargetSpec } from '@angular-devkit/architect/testing';
|
||||||
import { join, normalize, virtualFs } from '@angular-devkit/core';
|
import { join, normalize, virtualFs } from '@angular-devkit/core';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
|
|
||||||
import { DefaultTimeout, runTargetSpec } from '@angular-devkit/architect/testing';
|
import { DefaultTimeout, runTargetSpec } from '@angular-devkit/architect/testing';
|
||||||
import { normalize, tags, virtualFs } from '@angular-devkit/core';
|
import { normalize, tags, virtualFs } from '@angular-devkit/core';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
// tslint:disable-next-line:no-implicit-dependencies
|
// tslint:disable-next-line:no-implicit-dependencies
|
||||||
import { tags } from '@angular-devkit/core';
|
import { tags } from '@angular-devkit/core';
|
||||||
import { RawSourceMap } from 'source-map';
|
import { RawSourceMap } from 'source-map';
|
||||||
|
@ -22,20 +22,22 @@ export function collectDeepNodes<T extends ts.Node>(node: ts.Node, kind: ts.Synt
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function drilldownNodes<T extends ts.Node>(
|
export function drilldownNodes<T extends ts.Node>(
|
||||||
startingNode: ts.Node,
|
startingNode: T,
|
||||||
path: { prop: string | null, kind: ts.SyntaxKind }[],
|
path: { prop: keyof T, kind: ts.SyntaxKind }[],
|
||||||
): T | null {
|
): T | null {
|
||||||
let currentNode: T | ts.Node | undefined = startingNode;
|
let currentNode: T = startingNode;
|
||||||
for (const segment of path) {
|
for (const segment of path) {
|
||||||
if (segment.prop) {
|
if (segment.prop) {
|
||||||
// ts.Node has no index signature, so we need to cast it as any.
|
// ts.Node has no index signature, so we need to cast it as any.
|
||||||
|
const tempNode = currentNode[segment.prop];
|
||||||
|
if (!tempNode || typeof tempNode != 'object' || currentNode.kind !== segment.kind) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// tslint:disable-next-line:no-any
|
// tslint:disable-next-line:no-any
|
||||||
currentNode = (currentNode as any)[segment.prop];
|
currentNode = tempNode as any as T;
|
||||||
}
|
|
||||||
if (!currentNode || currentNode.kind !== segment.kind) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentNode as T;
|
return currentNode;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ export function getFoldFileTransformer(program: ts.Program): ts.TransformerFacto
|
|||||||
// Check if node is a class to add statements to.
|
// Check if node is a class to add statements to.
|
||||||
const clazz = classes.find((cl) => cl.classFunction === node);
|
const clazz = classes.find((cl) => cl.classFunction === node);
|
||||||
if (clazz) {
|
if (clazz) {
|
||||||
const functionExpression = node as ts.FunctionExpression;
|
const functionExpression: ts.FunctionExpression = node as ts.FunctionExpression;
|
||||||
|
|
||||||
const newExpressions = clazz.statements.map((st) =>
|
const newExpressions = clazz.statements.map((st) =>
|
||||||
ts.createStatement(st.expressionStatement.expression));
|
ts.createStatement(st.expressionStatement.expression));
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
// tslint:disable-next-line:no-implicit-dependencies
|
// tslint:disable-next-line:no-implicit-dependencies
|
||||||
import { tags } from '@angular-devkit/core';
|
import { tags } from '@angular-devkit/core';
|
||||||
import { transformJavascript } from '../helpers/transform-javascript';
|
import { transformJavascript } from '../helpers/transform-javascript';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
// tslint:disable-next-line:no-implicit-dependencies
|
// tslint:disable-next-line:no-implicit-dependencies
|
||||||
import { tags } from '@angular-devkit/core';
|
import { tags } from '@angular-devkit/core';
|
||||||
import { transformJavascript } from '../helpers/transform-javascript';
|
import { transformJavascript } from '../helpers/transform-javascript';
|
||||||
|
@ -542,13 +542,13 @@ function _readBlanks(context: JsonParserContext): (JsonAstComment | JsonAstMulti
|
|||||||
if ((context.mode & JsonParseMode.CommentsAllowed) != 0) {
|
if ((context.mode & JsonParseMode.CommentsAllowed) != 0) {
|
||||||
const comments: (JsonAstComment | JsonAstMultilineComment)[] = [];
|
const comments: (JsonAstComment | JsonAstMultilineComment)[] = [];
|
||||||
while (true) {
|
while (true) {
|
||||||
let char = context.original[context.position.offset];
|
const char = context.original[context.position.offset];
|
||||||
if (char == '/' && context.original[context.position.offset + 1] == '*') {
|
if (char == '/' && context.original[context.position.offset + 1] == '*') {
|
||||||
const start = context.position;
|
const start = context.position;
|
||||||
// Multi line comment.
|
// Multi line comment.
|
||||||
_next(context);
|
_next(context);
|
||||||
_next(context);
|
_next(context);
|
||||||
char = context.original[context.position.offset];
|
|
||||||
while (context.original[context.position.offset] != '*'
|
while (context.original[context.position.offset] != '*'
|
||||||
|| context.original[context.position.offset + 1] != '/') {
|
|| context.original[context.position.offset + 1] != '/') {
|
||||||
_next(context);
|
_next(context);
|
||||||
@ -572,7 +572,7 @@ function _readBlanks(context: JsonParserContext): (JsonAstComment | JsonAstMulti
|
|||||||
// Multi line comment.
|
// Multi line comment.
|
||||||
_next(context);
|
_next(context);
|
||||||
_next(context);
|
_next(context);
|
||||||
char = context.original[context.position.offset];
|
|
||||||
while (context.original[context.position.offset] != '\n') {
|
while (context.original[context.position.offset] != '\n') {
|
||||||
_next(context);
|
_next(context);
|
||||||
if (context.position.offset >= context.original.length) {
|
if (context.position.offset >= context.original.length) {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
import { JsonParseMode, parseJson, parseJsonAst } from './parser';
|
import { JsonParseMode, parseJson, parseJsonAst } from './parser';
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
// tslint:disable:no-any
|
// tslint:disable:no-any non-null-operator no-big-function
|
||||||
// tslint:disable:non-null-operator
|
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { map, mergeMap } from 'rxjs/operators';
|
import { map, mergeMap } from 'rxjs/operators';
|
||||||
import { CoreSchemaRegistry } from './registry';
|
import { CoreSchemaRegistry } from './registry';
|
||||||
|
@ -138,7 +138,7 @@ export function templateParser(sourceText: string, fileName: string): TemplateAs
|
|||||||
// Optimization that uses the fact that the end of a node is always the beginning of the next
|
// Optimization that uses the fact that the end of a node is always the beginning of the next
|
||||||
// node, so we keep the positioning of the nodes in memory.
|
// node, so we keep the positioning of the nodes in memory.
|
||||||
let start = _positionFor(sourceText, offset);
|
let start = _positionFor(sourceText, offset);
|
||||||
let end = null as Position | null;
|
let end: Position | null;
|
||||||
|
|
||||||
const increment = reExpressions.length + 1;
|
const increment = reExpressions.length + 1;
|
||||||
for (let i = 0; i < parsed.length; i += increment) {
|
for (let i = 0; i < parsed.length; i += increment) {
|
||||||
|
@ -179,7 +179,7 @@ export class SimpleMemoryHost implements Host<{}> {
|
|||||||
protected _delete(path: Path): void {
|
protected _delete(path: Path): void {
|
||||||
path = this._toAbsolute(path);
|
path = this._toAbsolute(path);
|
||||||
if (this._isDirectory(path)) {
|
if (this._isDirectory(path)) {
|
||||||
for (const [cachePath, _] of this._cache.entries()) {
|
for (const [cachePath] of this._cache.entries()) {
|
||||||
if (path.startsWith(cachePath + NormalizedSep)) {
|
if (path.startsWith(cachePath + NormalizedSep)) {
|
||||||
this._cache.delete(cachePath);
|
this._cache.delete(cachePath);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
// tslint:disable:no-any
|
// tslint:disable:no-any no-big-function
|
||||||
import { path } from '../path';
|
import { path } from '../path';
|
||||||
import { fileBuffer } from './buffer';
|
import { fileBuffer } from './buffer';
|
||||||
import { CordHost } from './record';
|
import { CordHost } from './record';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
|
|
||||||
import { tap } from 'rxjs/operators';
|
import { tap } from 'rxjs/operators';
|
||||||
import { schema } from '..';
|
import { schema } from '..';
|
||||||
|
@ -94,7 +94,7 @@ export class DryRunSink extends HostSink {
|
|||||||
|
|
||||||
this._filesToDelete.forEach(path => {
|
this._filesToDelete.forEach(path => {
|
||||||
// Check if this is a renaming.
|
// Check if this is a renaming.
|
||||||
for (const [from, _] of this._filesToRename) {
|
for (const [from] of this._filesToRename) {
|
||||||
if (from == path) {
|
if (from == path) {
|
||||||
// The event is sent later on.
|
// The event is sent later on.
|
||||||
return;
|
return;
|
||||||
@ -108,7 +108,7 @@ export class DryRunSink extends HostSink {
|
|||||||
});
|
});
|
||||||
this._filesToCreate.forEach((content, path) => {
|
this._filesToCreate.forEach((content, path) => {
|
||||||
// Check if this is a renaming.
|
// Check if this is a renaming.
|
||||||
for (const [_, to] of this._filesToRename) {
|
for (const [, to] of this._filesToRename) {
|
||||||
if (to == path) {
|
if (to == path) {
|
||||||
// The event is sent later on.
|
// The event is sent later on.
|
||||||
return;
|
return;
|
||||||
|
@ -33,7 +33,8 @@ describe('DryRunSink', () => {
|
|||||||
const files = ['/hello', '/sub/directory/file2', '/sub/file1', '/test'];
|
const files = ['/hello', '/sub/directory/file2', '/sub/file1', '/test'];
|
||||||
const treeFiles: Path[] = [];
|
const treeFiles: Path[] = [];
|
||||||
tree.visit(path => treeFiles.push(path));
|
tree.visit(path => treeFiles.push(path));
|
||||||
expect(treeFiles.sort()).toEqual(files.map(normalize));
|
treeFiles.sort();
|
||||||
|
expect(treeFiles).toEqual(files.map(normalize));
|
||||||
|
|
||||||
const sink = new DryRunSink(new virtualFs.SimpleMemoryHost());
|
const sink = new DryRunSink(new virtualFs.SimpleMemoryHost());
|
||||||
sink.reporter.pipe(toArray())
|
sink.reporter.pipe(toArray())
|
||||||
@ -62,7 +63,8 @@ describe('DryRunSink', () => {
|
|||||||
const files = ['/hello', '/sub/directory/file2', '/sub/file1', '/test'];
|
const files = ['/hello', '/sub/directory/file2', '/sub/file1', '/test'];
|
||||||
const treeFiles: Path[] = [];
|
const treeFiles: Path[] = [];
|
||||||
tree.visit(path => treeFiles.push(path));
|
tree.visit(path => treeFiles.push(path));
|
||||||
expect(treeFiles.sort()).toEqual(files.map(normalize));
|
treeFiles.sort();
|
||||||
|
expect(treeFiles).toEqual(files.map(normalize));
|
||||||
|
|
||||||
// Need to create this file on the filesystem, otherwise the commit phase will fail.
|
// Need to create this file on the filesystem, otherwise the commit phase will fail.
|
||||||
const outputHost = new virtualFs.SimpleMemoryHost();
|
const outputHost = new virtualFs.SimpleMemoryHost();
|
||||||
|
@ -30,7 +30,8 @@ describe('FileSystemSink', () => {
|
|||||||
const files = ['/hello', '/sub/directory/file2', '/sub/file1', '/test'];
|
const files = ['/hello', '/sub/directory/file2', '/sub/file1', '/test'];
|
||||||
const treeFiles: string[] = [];
|
const treeFiles: string[] = [];
|
||||||
tree.visit(path => treeFiles.push(path));
|
tree.visit(path => treeFiles.push(path));
|
||||||
expect(treeFiles.sort()).toEqual(files);
|
treeFiles.sort();
|
||||||
|
expect(treeFiles).toEqual(files);
|
||||||
|
|
||||||
const outputHost = new virtualFs.test.TestHost();
|
const outputHost = new virtualFs.test.TestHost();
|
||||||
const sink = new HostSink(outputHost);
|
const sink = new HostSink(outputHost);
|
||||||
|
@ -47,7 +47,8 @@ describe('FilterHostTree', () => {
|
|||||||
const filtered = new FilterHostTree(tree, p => p != '/file2');
|
const filtered = new FilterHostTree(tree, p => p != '/file2');
|
||||||
const filteredFiles: string[] = [];
|
const filteredFiles: string[] = [];
|
||||||
filtered.visit(path => filteredFiles.push(path));
|
filtered.visit(path => filteredFiles.push(path));
|
||||||
expect(filteredFiles.sort()).toEqual(['/file1', '/file3'].map(normalize));
|
filteredFiles.sort();
|
||||||
|
expect(filteredFiles).toEqual(['/file1', '/file3'].map(normalize));
|
||||||
expect(filtered.actions.length).toEqual(2);
|
expect(filtered.actions.length).toEqual(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -61,7 +62,8 @@ describe('FilterHostTree', () => {
|
|||||||
const filtered2 = new FilterHostTree(filtered, p => p != '/file3');
|
const filtered2 = new FilterHostTree(filtered, p => p != '/file3');
|
||||||
const filteredFiles: string[] = [];
|
const filteredFiles: string[] = [];
|
||||||
filtered2.visit(path => filteredFiles.push(path));
|
filtered2.visit(path => filteredFiles.push(path));
|
||||||
expect(filteredFiles.sort()).toEqual(['/file1'].map(normalize));
|
filteredFiles.sort();
|
||||||
|
expect(filteredFiles).toEqual(['/file1'].map(normalize));
|
||||||
expect(filtered2.actions.map(a => a.kind)).toEqual(['c']);
|
expect(filtered2.actions.map(a => a.kind)).toEqual(['c']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -77,7 +79,8 @@ describe('FilterHostTree', () => {
|
|||||||
const filtered2 = new FilterHostTree(filtered, p => p != '/file3');
|
const filtered2 = new FilterHostTree(filtered, p => p != '/file3');
|
||||||
const filteredFiles: string[] = [];
|
const filteredFiles: string[] = [];
|
||||||
filtered2.visit(path => filteredFiles.push(path));
|
filtered2.visit(path => filteredFiles.push(path));
|
||||||
expect(filteredFiles.sort()).toEqual(['/file1'].map(normalize));
|
filteredFiles.sort();
|
||||||
|
expect(filteredFiles).toEqual(['/file1'].map(normalize));
|
||||||
expect(filtered2.actions.map(a => a.kind)).toEqual([]);
|
expect(filtered2.actions.map(a => a.kind)).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -91,7 +94,8 @@ describe('FilterHostTree', () => {
|
|||||||
const filtered2 = new FilterHostTree(filtered, p => p != '/file3');
|
const filtered2 = new FilterHostTree(filtered, p => p != '/file3');
|
||||||
const filteredFiles: string[] = [];
|
const filteredFiles: string[] = [];
|
||||||
filtered2.visit(path => filteredFiles.push(path));
|
filtered2.visit(path => filteredFiles.push(path));
|
||||||
expect(filteredFiles.sort()).toEqual(['/dir1/file1'].map(normalize));
|
filteredFiles.sort();
|
||||||
|
expect(filteredFiles).toEqual(['/dir1/file1'].map(normalize));
|
||||||
expect(filtered2.actions.map(a => a.kind)).toEqual(['c']);
|
expect(filtered2.actions.map(a => a.kind)).toEqual(['c']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -107,7 +111,8 @@ describe('FilterHostTree', () => {
|
|||||||
const filtered2 = new FilterHostTree(filtered, p => p != '/file3');
|
const filtered2 = new FilterHostTree(filtered, p => p != '/file3');
|
||||||
const filteredFiles: string[] = [];
|
const filteredFiles: string[] = [];
|
||||||
filtered2.visit(path => filteredFiles.push(path));
|
filtered2.visit(path => filteredFiles.push(path));
|
||||||
expect(filteredFiles.sort()).toEqual(['/dir1/file1'].map(normalize));
|
filteredFiles.sort();
|
||||||
|
expect(filteredFiles).toEqual(['/dir1/file1'].map(normalize));
|
||||||
expect(filtered2.actions.map(a => a.kind)).toEqual([]);
|
expect(filtered2.actions.map(a => a.kind)).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
// tslint:disable:non-null-operator
|
// tslint:disable:non-null-operator no-big-function
|
||||||
import { normalize, virtualFs } from '@angular-devkit/core';
|
import { normalize, virtualFs } from '@angular-devkit/core';
|
||||||
import { FileAlreadyExistException, FileDoesNotExistException } from '../exception/exception';
|
import { FileAlreadyExistException, FileDoesNotExistException } from '../exception/exception';
|
||||||
import { testTreeVisit } from './common_spec';
|
import { testTreeVisit } from './common_spec';
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
// tslint:disable:no-any
|
// tslint:disable:no-any no-big-function no-implicit-dependencies
|
||||||
// tslint:disable:no-implicit-dependencies
|
|
||||||
import { normalize, virtualFs } from '@angular-devkit/core';
|
import { normalize, virtualFs } from '@angular-devkit/core';
|
||||||
import { HostSink, HostTree, SchematicEngine } from '@angular-devkit/schematics';
|
import { HostSink, HostTree, SchematicEngine } from '@angular-devkit/schematics';
|
||||||
import { FileSystemEngineHost } from '@angular-devkit/schematics/tools';
|
import { FileSystemEngineHost } from '@angular-devkit/schematics/tools';
|
||||||
|
@ -208,7 +208,7 @@ export class AngularCompilerPlugin {
|
|||||||
|
|
||||||
this._rootNames = config.rootNames.concat(...this._singleFileIncludes);
|
this._rootNames = config.rootNames.concat(...this._singleFileIncludes);
|
||||||
this._compilerOptions = { ...config.options, ...options.compilerOptions };
|
this._compilerOptions = { ...config.options, ...options.compilerOptions };
|
||||||
this._basePath = config.options.basePath || '';
|
this._basePath = config.options.basePath || basePath || '';
|
||||||
|
|
||||||
// Overwrite outDir so we can find generated files next to their .ts origin in compilerHost.
|
// Overwrite outDir so we can find generated files next to their .ts origin in compilerHost.
|
||||||
this._compilerOptions.outDir = '';
|
this._compilerOptions.outDir = '';
|
||||||
|
@ -71,7 +71,7 @@ function getDecoratorOrigin(
|
|||||||
const symbol = typeChecker.getSymbolAtLocation(identifier);
|
const symbol = typeChecker.getSymbolAtLocation(identifier);
|
||||||
if (symbol && symbol.declarations && symbol.declarations.length > 0) {
|
if (symbol && symbol.declarations && symbol.declarations.length > 0) {
|
||||||
const declaration = symbol.declarations[0];
|
const declaration = symbol.declarations[0];
|
||||||
let module: string | undefined = undefined;
|
let module: string | undefined;
|
||||||
if (ts.isImportSpecifier(declaration)) {
|
if (ts.isImportSpecifier(declaration)) {
|
||||||
name = (declaration.propertyName || declaration.name).text;
|
name = (declaration.propertyName || declaration.name).text;
|
||||||
module = declaration.parent
|
module = declaration.parent
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
import { tags } from '@angular-devkit/core'; // tslint:disable-line:no-implicit-dependencies
|
import { tags } from '@angular-devkit/core'; // tslint:disable-line:no-implicit-dependencies
|
||||||
import { createTypescriptContext, transformTypescript } from './ast_helpers';
|
import { createTypescriptContext, transformTypescript } from './ast_helpers';
|
||||||
import { removeDecorators } from './remove_decorators';
|
import { removeDecorators } from './remove_decorators';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
import { tags } from '@angular-devkit/core'; // tslint:disable-line:no-implicit-dependencies
|
import { tags } from '@angular-devkit/core'; // tslint:disable-line:no-implicit-dependencies
|
||||||
import { createTypescriptContext, transformTypescript } from './ast_helpers';
|
import { createTypescriptContext, transformTypescript } from './ast_helpers';
|
||||||
import { replaceServerBootstrap } from './replace_server_bootstrap';
|
import { replaceServerBootstrap } from './replace_server_bootstrap';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { latestVersions } from '../utility/latest-versions';
|
import { latestVersions } from '../utility/latest-versions';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { Schema as ApplicationOptions } from '../application/schema';
|
import { Schema as ApplicationOptions } from '../application/schema';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { getFileContent } from '../../angular/utility/test';
|
import { getFileContent } from '../../angular/utility/test';
|
||||||
|
@ -217,6 +217,9 @@ function extractArchitectConfig(_config: CliConfig): JsonObject | null {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function is too big, but also really hard to refactor properly as the whole config
|
||||||
|
// depends on all parts of the config.
|
||||||
|
// tslint:disable-next-line:no-big-function
|
||||||
function extractProjectsConfig(
|
function extractProjectsConfig(
|
||||||
config: CliConfig, tree: Tree, logger: logging.LoggerApi,
|
config: CliConfig, tree: Tree, logger: logging.LoggerApi,
|
||||||
): JsonObject {
|
): JsonObject {
|
||||||
@ -254,6 +257,9 @@ function extractProjectsConfig(
|
|||||||
const serverApps = apps.filter(app => app.platform === 'server');
|
const serverApps = apps.filter(app => app.platform === 'server');
|
||||||
|
|
||||||
const projectMap = browserApps
|
const projectMap = browserApps
|
||||||
|
// This function is too big, but also really hard to refactor properly as the whole config
|
||||||
|
// depends on all parts of the config.
|
||||||
|
// tslint:disable-next-line:no-big-function
|
||||||
.map((app, idx) => {
|
.map((app, idx) => {
|
||||||
const defaultAppName = idx === 0 ? defaultAppNamePrefix : `${defaultAppNamePrefix}${idx}`;
|
const defaultAppName = idx === 0 ? defaultAppNamePrefix : `${defaultAppNamePrefix}${idx}`;
|
||||||
const name = app.name || defaultAppName;
|
const name = app.name || defaultAppName;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
import { JsonObject } from '@angular-devkit/core';
|
import { JsonObject } from '@angular-devkit/core';
|
||||||
import { EmptyTree } from '@angular-devkit/schematics';
|
import { EmptyTree } from '@angular-devkit/schematics';
|
||||||
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
||||||
|
@ -189,7 +189,8 @@ export function insertAfterLastOccurrence(nodes: ts.Node[],
|
|||||||
file: string,
|
file: string,
|
||||||
fallbackPos: number,
|
fallbackPos: number,
|
||||||
syntaxKind?: ts.SyntaxKind): Change {
|
syntaxKind?: ts.SyntaxKind): Change {
|
||||||
let lastItem = nodes.sort(nodesByPosition).pop();
|
// sort() has a side effect, so make a copy so that we won't overwrite the parent's object.
|
||||||
|
let lastItem = [...nodes].sort(nodesByPosition).pop();
|
||||||
if (!lastItem) {
|
if (!lastItem) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// tslint:disable:no-big-function
|
||||||
|
|
||||||
import { normalize, virtualFs } from '@angular-devkit/core';
|
import { normalize, virtualFs } from '@angular-devkit/core';
|
||||||
import { HostTree } from '@angular-devkit/schematics';
|
import { HostTree } from '@angular-devkit/schematics';
|
||||||
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
|
||||||
|
27
rules/Rule.ts
Normal file
27
rules/Rule.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* @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 * as Lint from 'tslint';
|
||||||
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
|
|
||||||
|
// An empty rule so that tslint does not error on rules '//' (which are comments).
|
||||||
|
export class Rule extends Lint.Rules.AbstractRule {
|
||||||
|
public static metadata: Lint.IRuleMetadata = {
|
||||||
|
ruleName: '//',
|
||||||
|
type: 'typescript',
|
||||||
|
description: ``,
|
||||||
|
rationale: '',
|
||||||
|
options: null,
|
||||||
|
optionsDescription: `Not configurable.`,
|
||||||
|
typescriptOnly: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,7 @@ require('source-map-support').install({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
declare const global: {} & {
|
declare const global: {
|
||||||
benchmarkReporter: {};
|
benchmarkReporter: {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,6 +79,8 @@ const ignoredPackages = [
|
|||||||
'@webassemblyjs/ieee754@1.5.10', // MIT but no LICENSE file. `license` field in package.json.
|
'@webassemblyjs/ieee754@1.5.10', // MIT but no LICENSE file. `license` field in package.json.
|
||||||
'@webassemblyjs/leb128@1.5.10', // Apache 2.0 license, but get discovered as "Apache".
|
'@webassemblyjs/leb128@1.5.10', // Apache 2.0 license, but get discovered as "Apache".
|
||||||
'@webassemblyjs/leb128@1.4.3', // Apache 2.0 license, but get discovered as "Apache".
|
'@webassemblyjs/leb128@1.4.3', // Apache 2.0 license, but get discovered as "Apache".
|
||||||
|
|
||||||
|
'tslint-sonarts@1.7.0', // LGPL-3.0 but only used as a tool, not linked in the build.
|
||||||
];
|
];
|
||||||
|
|
||||||
// Find all folders directly under a `node_modules` that have a package.json.
|
// Find all folders directly under a `node_modules` that have a package.json.
|
||||||
|
@ -44,7 +44,8 @@ export default async function (options: { verbose: boolean }, logger: logging.Lo
|
|||||||
|
|
||||||
logger.info('');
|
logger.info('');
|
||||||
logger.info('Running license validation...');
|
logger.info('Running license validation...');
|
||||||
error = await validateLicenses({}, logger.createChild('validate-commits')) != 0;
|
error = await validateLicenses({}, logger.createChild('validate-commits')) != 0
|
||||||
|
|| error;
|
||||||
|
|
||||||
logger.info('');
|
logger.info('');
|
||||||
logger.info('Running BUILD files validation...');
|
logger.info('Running BUILD files validation...');
|
||||||
|
44
tslint.json
44
tslint.json
@ -1,17 +1,53 @@
|
|||||||
{
|
{
|
||||||
"extends": "tslint-no-circular-imports",
|
"//": "Consider using no-identical-functions and disabling in faulty tests",
|
||||||
|
"//": "Consider using cognitive-complexity and refactor",
|
||||||
|
"//": "Consider using no-useless-cast but it's annoying",
|
||||||
|
"extends": [
|
||||||
|
"tslint-no-circular-imports"
|
||||||
|
],
|
||||||
"rulesDirectory": [
|
"rulesDirectory": [
|
||||||
"dist/rules"
|
"dist/rules",
|
||||||
|
"node_modules/tslint-sonarts/lib/rules"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"//": "==================================================================================================",
|
||||||
|
"//": "custom rules defined in dist/rules/**",
|
||||||
"defocus": true,
|
"defocus": true,
|
||||||
"import-groups": true,
|
"import-groups": true,
|
||||||
"non-null-operator": true,
|
"non-null-operator": true,
|
||||||
"no-global-tslint-disable": true,
|
"no-global-tslint-disable": true,
|
||||||
"single-eof-line": true,
|
"single-eof-line": true,
|
||||||
|
"//": "==================================================================================================",
|
||||||
|
|
||||||
|
"//": "==================================================================================================",
|
||||||
|
"//": "tslint-sonarts rules. See https://github.com/SonarSource/SonarTS",
|
||||||
|
"//": "These rules are part of the bug detection section of tslint-sonarts",
|
||||||
|
"no-big-function": true,
|
||||||
|
"no-all-duplicated-branches": true,
|
||||||
|
"no-case-with-or": true,
|
||||||
|
"no-collection-size-mischeck": true,
|
||||||
|
"no-element-overwrite": true,
|
||||||
|
"no-empty-destructuring": true,
|
||||||
|
"no-identical-conditions": true,
|
||||||
|
"no-ignored-initial-value": true,
|
||||||
|
"no-ignored-return": true,
|
||||||
|
"no-in-misuse": true,
|
||||||
|
"no-misleading-array-reverse": true,
|
||||||
|
"no-misspelled-operator": true,
|
||||||
|
"no-self-assignment": true,
|
||||||
|
"no-unthrown-error": true,
|
||||||
|
"no-use-of-empty-return-value": true,
|
||||||
|
"no-useless-increment": true,
|
||||||
|
"no-useless-intersection": true,
|
||||||
|
|
||||||
|
"//": "These rules are part of the code smell detection section of tslint-sonarts",
|
||||||
|
"no-dead-store": true,
|
||||||
|
"no-useless-intersection": true,
|
||||||
|
"//": "==================================================================================================",
|
||||||
|
|
||||||
|
"//": "==================================================================================================",
|
||||||
|
"//": "base tslint rules",
|
||||||
"no-floating-promises": true,
|
"no-floating-promises": true,
|
||||||
|
|
||||||
|
|
||||||
"no-implicit-dependencies": true,
|
"no-implicit-dependencies": true,
|
||||||
"no-import-side-effect": [true, {"ignore-module": "^(?!rxjs\/)"}],
|
"no-import-side-effect": [true, {"ignore-module": "^(?!rxjs\/)"}],
|
||||||
"align": [
|
"align": [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user