Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
*/
import {RuleFailure, Rules} from 'tslint';
import * as ts from 'typescript';
import {NgComponentTemplateVisitor} from '../../utils/ng_component_template';
import {createHtmlSourceFile} from '../../utils/tslint/tslint_html_source_file';
import {analyzeResolvedTemplate} from '../template-var-assignment/analyze_template';
const FAILURE_MESSAGE = 'Found assignment to template variable. This does not work with Ivy and ' +
'needs to be updated.';
/**
* Rule that reports if an Angular template contains property assignments to template variables.
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
const typeChecker = program.getTypeChecker();
const templateVisitor = new NgComponentTemplateVisitor(typeChecker);
const failures: RuleFailure[] = [];
// Analyze the current source files by detecting all referenced HTML templates.
templateVisitor.visitNode(sourceFile);
const {resolvedTemplates} = templateVisitor;
// Analyze each resolved template and print a warning for property writes to
// template variables.
resolvedTemplates.forEach(template => {
const filePath = template.filePath;
const nodes = analyzeResolvedTemplate(template);
const templateFile =
import {bold, green, red} from 'chalk';
import {ProgramAwareRuleWalker, RuleFailure, Rules} from 'tslint';
import * as ts from 'typescript';
import {propertyNames} from '../material/component-data';
/**
* Rule that walks through every property access expression and updates properties that have
* been changed in favor of the new name.
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
return this.applyWithWalker(
new SwitchPropertyNamesWalker(sourceFile, this.getOptions(), program));
}
}
export class SwitchPropertyNamesWalker extends ProgramAwareRuleWalker {
visitPropertyAccessExpression(prop: ts.PropertyAccessExpression) {
// Recursively call this method for the expression of the current property expression.
// It can happen that there is a chain of property access expressions.
// For example: "mySortInstance.mdSortChange.subscribe()"
if (prop.expression && prop.expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
this.visitPropertyAccessExpression(prop.expression as ts.PropertyAccessExpression);
}
// TODO(mmalerba): This is prrobably a bad way to get the property host...
import {NgComponentTemplateVisitor} from '../../utils/ng_component_template';
import {NgQueryResolveVisitor} from '../static-queries/angular/ng_query_visitor';
import {QueryTiming} from '../static-queries/angular/query-definition';
import {QueryUsageStrategy} from '../static-queries/strategies/usage_strategy/usage_strategy';
import {getTransformedQueryCallExpr} from '../static-queries/transform';
const FAILURE_MESSAGE = 'Query does not explicitly specify its timing. Read more here: ' +
'https://github.com/angular/angular/pull/28810';
/**
* Rule that reports if an Angular "ViewChild" or "ContentChild" query is not explicitly
* specifying its timing. The rule also provides TSLint automatic replacements that can
* be applied in order to automatically migrate to the explicit query timing API.
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
const typeChecker = program.getTypeChecker();
const queryVisitor = new NgQueryResolveVisitor(program.getTypeChecker());
const templateVisitor = new NgComponentTemplateVisitor(typeChecker);
const rootSourceFiles = program.getRootFileNames().map(f => program.getSourceFile(f) !);
const printer = ts.createPrinter();
const failures: RuleFailure[] = [];
// Analyze source files by detecting queries, class relations and component templates.
rootSourceFiles.forEach(sourceFile => {
queryVisitor.visitNode(sourceFile);
templateVisitor.visitNode(sourceFile);
});
const {resolvedQueries, classMetadata} = queryVisitor;
* 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 {Replacement, RuleFailure, Rules} from 'tslint';
import * as ts from 'typescript';
import {HelperFunction, getHelper} from '../renderer-to-renderer2/helpers';
import {migrateExpression, replaceImport} from '../renderer-to-renderer2/migration';
import {findCoreImport, findRendererReferences} from '../renderer-to-renderer2/util';
/**
* TSLint rule that migrates from `Renderer` to `Renderer2`. More information on how it works:
* https://hackmd.angular.io/UTzUZTnPRA-cSa_4mHyfYw
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
const typeChecker = program.getTypeChecker();
const printer = ts.createPrinter();
const failures: RuleFailure[] = [];
const rendererImport = findCoreImport(sourceFile, 'Renderer');
// If there are no imports for the `Renderer`, we can exit early.
if (!rendererImport) {
return failures;
}
const {typedNodes, methodCalls, forwardRefs} =
findRendererReferences(sourceFile, typeChecker, rendererImport);
const helpersToAdd = new Set();
failures.push(this._getNamedImportsFailure(rendererImport, sourceFile, printer));
import {RuleFailure, Rules} from 'tslint';
import * as ts from 'typescript';
import {NgDefinitionCollector} from '../missing-injectable/definition_collector';
import {TslintUpdateRecorder} from '../missing-injectable/google3/tslint_update_recorder';
import {MissingInjectableTransform} from '../missing-injectable/transform';
/**
* TSLint rule that flags classes which are declared as providers in "NgModule",
* "Directive" or "Component" definitions while not being decorated with any
* Angular decorator (e.g. "@Injectable").
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
const ruleName = this.ruleName;
const typeChecker = program.getTypeChecker();
const sourceFiles = program.getSourceFiles().filter(
s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s));
const definitionCollector = new NgDefinitionCollector(typeChecker);
const failures: RuleFailure[] = [];
// Analyze source files by detecting all "NgModule", "Directive" or
// "Component" definitions.
sourceFiles.forEach(sourceFile => definitionCollector.visitNode(sourceFile));
const {resolvedModules, resolvedDirectives} = definitionCollector;
const transformer = new MissingInjectableTransform(typeChecker, getUpdateRecorder);
const updateRecorders = new Map();
createSpeedFactorConvertExpression,
} from './ripple-speed-factor';
/**
* Note that will be added whenever a speed factor expression has been converted to calculate
* the according duration. This note should encourage people to clean up their code by switching
* away from the speed factors to explicit durations.
*/
const removeNote = `TODO: Cleanup duration calculation.`;
/**
* Rule that walks through every property assignment and switches the global `baseSpeedFactor`
* ripple option to the new global animation config. Also updates every class member assignment
* that refers to MatRipple#speedFactor.
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program));
}
}
export class Walker extends ProgramAwareRuleWalker {
/** Switches binary expressions (e.g. myRipple.speedFactor = 0.5) to the new animation config. */
visitBinaryExpression(expression: ts.BinaryExpression) {
if (!ts.isPropertyAccessExpression(expression.left)) {
return;
}
// Left side expression consists of target object and property name (e.g. myInstance.val)
const leftExpression = expression.left as ts.PropertyAccessExpression;
const targetTypeNode = this.getTypeChecker().getTypeAtLocation(leftExpression.expression);
*
* 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 {Replacement, RuleFailure, Rules} from 'tslint';
import * as ts from 'typescript';
import {InjectablePipeVisitor} from '../injectable-pipe/angular/injectable_pipe_visitor';
import {INJECTABLE_DECORATOR_NAME, addImport, getNamedImports} from '../injectable-pipe/util';
/**
* TSLint rule that flags `@Pipe` classes that haven't been marked as `@Injectable`.
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
const visitor = new InjectablePipeVisitor(program.getTypeChecker());
const printer = ts.createPrinter();
const failures: RuleFailure[] = [];
visitor.visitNode(sourceFile);
visitor.missingInjectablePipes.forEach(data => {
const {pipeDecorator, importDeclarationMissingImport} = data;
const fixes = [new Replacement(
pipeDecorator.getStart(), pipeDecorator.getWidth(),
`@${INJECTABLE_DECORATOR_NAME}()\n${pipeDecorator.getText()}`)];
if (importDeclarationMissingImport) {
const namedImports = getNamedImports(importDeclarationMissingImport);
* @license
* Copyright Google LLC 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 {bold, green, red} from 'chalk';
import {ProgramAwareRuleWalker, RuleFailure, Rules} from 'tslint';
import * as ts from 'typescript';
/**
* Rule that walks through every property access expression and and reports to TSLint if
* a given property name is no longer existing but cannot be automatically migrated.
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program));
}
}
export class Walker extends ProgramAwareRuleWalker {
visitPropertyAccessExpression(node: ts.PropertyAccessExpression) {
const hostType = this.getTypeChecker().getTypeAtLocation(node.expression);
const typeName = hostType && hostType.symbol && hostType.symbol.getName();
if (typeName === 'MatListOption' && node.name.text === 'selectionChange') {
this.addFailureAtNode(node, `Found deprecated property "${red('selectionChange')}" of ` +
`class "${bold('MatListOption')}". Use the "${green('selectionChange')}" property on ` +
`the parent "${bold('MatSelectionList')}" instead.`);
}
*
* 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 {bold} from 'chalk';
import {ProgramAwareRuleWalker, RuleFailure, Rules} from 'tslint';
import * as ts from 'typescript';
import {color} from '../material/color';
import {methodCallChecks} from '../material/component-data';
/**
* Rule that walks through every property access expression and updates properties that have
* been changed in favor of the new name.
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
return this.applyWithWalker(
new CheckMethodCallsWalker(sourceFile, this.getOptions(), program));
}
}
export class CheckMethodCallsWalker extends ProgramAwareRuleWalker {
visitNewExpression(expression: ts.NewExpression) {
const symbol = this.getTypeChecker().getTypeAtLocation(expression).symbol;
if (symbol) {
const className = symbol.name;
this.checkConstructor(expression, className);
}
}
visitCallExpression(expression: ts.CallExpression) {
* Copyright Google LLC 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 {bold, green} from 'chalk';
import {ProgramAwareRuleWalker, RuleFailure, Rules} from 'tslint';
import * as ts from 'typescript';
import {determineBaseTypes} from '@angular/cdk/schematics';
/**
* Rule that checks for classes that extend Angular Material classes which have changed
* their API.
*/
export class Rule extends Rules.TypedRule {
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program));
}
}
export class Walker extends ProgramAwareRuleWalker {
visitClassDeclaration(node: ts.ClassDeclaration) {
const baseTypes = determineBaseTypes(node);
const className = node.name ? node.name.text : '{unknown-name}';
if (!baseTypes) {
return;
}
if (baseTypes.includes('MatFormFieldControl')) {