88
99import { ProgramAwareRuleWalker , RuleFailure , Rules } from 'tslint' ;
1010import * as ts from 'typescript' ;
11- import { bold , red , green } from 'chalk' ;
12- import { convertSpeedFactorToDuration } from './ripple-speed-factor' ;
11+ import { bold , red } from 'chalk' ;
12+ import {
13+ convertSpeedFactorToDuration ,
14+ createSpeedFactorConvertExpression ,
15+ } from './ripple-speed-factor' ;
16+
17+ /**
18+ * Note that will be added whenever a speed factor expression has been converted to calculate
19+ * the according duration. This note should encourage people to clean up their code by switching
20+ * away from the speed factors to explicit durations.
21+ */
22+ const removeNote = `TODO: Cleanup duration calculation.` ;
1323
1424/**
1525 * Rule that walks through property assignment and switches the global `baseSpeedFactor`
@@ -19,7 +29,7 @@ import {convertSpeedFactorToDuration} from './ripple-speed-factor';
1929export class Rule extends Rules . TypedRule {
2030 applyWithProgram ( sourceFile : ts . SourceFile , program : ts . Program ) : RuleFailure [ ] {
2131 return this . applyWithWalker (
22- new SwitchRippleSpeedFactorRule ( sourceFile , this . getOptions ( ) , program ) ) ;
32+ new SwitchRippleSpeedFactorRule ( sourceFile , this . getOptions ( ) , program ) ) ;
2333 }
2434}
2535
@@ -53,21 +63,32 @@ export class SwitchRippleSpeedFactorRule extends ProgramAwareRuleWalker {
5363 const propertyNameReplacement = this . createReplacement ( leftExpression . name . getStart ( ) ,
5464 leftExpression . name . getWidth ( ) , 'animation' ) ;
5565
66+ // Replace the value assignment with the new animation config.
5667 const rightExpressionReplacement = this . createReplacement ( expression . right . getStart ( ) ,
5768 expression . right . getWidth ( ) , `{enterDuration: ${ newEnterDurationValue } }` ) ;
5869
5970 this . addFailureAtNode (
6071 expression ,
61- `Found deprecated member assignment for "${ bold ( 'MatRipple' ) } #${ red ( 'speedFactor' ) } "` ,
72+ `Found deprecated variable assignment for "${ bold ( 'MatRipple' ) } #${ red ( 'speedFactor' ) } "` ,
6273 [ propertyNameReplacement , rightExpressionReplacement ] ) ;
6374 } else {
64- // In case the speed factor is dynamically calculated or passed to the assignment, we just
65- // print the failure and notify about the breaking change.
75+ // Handle the right expression differently if the previous speed factor value can't
76+ // be resolved statically. In that case, we just create a TypeScript expression that
77+ // calculates the explicit duration based on the non-static speed factor expression.
78+ const newExpression = createSpeedFactorConvertExpression ( expression . right . getText ( ) ) ;
79+
80+ // Replace the `speedFactor` property name with `animation`.
81+ const propertyNameReplacement = this . createReplacement ( leftExpression . name . getStart ( ) ,
82+ leftExpression . name . getWidth ( ) , 'animation' ) ;
83+
84+ // Replace the value assignment with the new animation config and remove todo.
85+ const rightExpressionReplacement = this . createReplacement ( expression . right . getStart ( ) ,
86+ expression . right . getWidth ( ) , `/** ${ removeNote } */ {enterDuration: ${ newExpression } }` ) ;
87+
6688 this . addFailureAtNode (
67- expression , `Found deprecated member assignment for "${ bold ( 'MatRipple' ) } #` +
68- `${ red ( 'speedFactor' ) } . Please manually switch from "${ red ( 'speedFactor' ) } " to ` +
69- `"${ green ( 'animation' ) } ". Note that the animation property only accepts explicit ` +
70- `durations in milliseconds.` ) ;
89+ expression ,
90+ `Found deprecated variable assignment for "${ bold ( 'MatRipple' ) } #${ red ( 'speedFactor' ) } "` ,
91+ [ propertyNameReplacement , rightExpressionReplacement ] ) ;
7192 }
7293 }
7394 }
@@ -94,29 +115,42 @@ export class SwitchRippleSpeedFactorRule extends ProgramAwareRuleWalker {
94115 // immediately in the provider object (e.g. it can happen that someone just imports the
95116 // config from a separate file).
96117
97- if ( assignment . initializer . kind === ts . SyntaxKind . NumericLiteral ) {
98- const numericValue = parseFloat ( ( assignment . initializer as ts . NumericLiteral ) . text ) ;
118+ const { initializer, name} = assignment ;
119+
120+ if ( initializer . kind === ts . SyntaxKind . NumericLiteral ) {
121+ const numericValue = parseFloat ( ( initializer as ts . NumericLiteral ) . text ) ;
99122 const newEnterDurationValue = convertSpeedFactorToDuration ( numericValue ) ;
100123
101- const keyNameReplacement = this . createReplacement ( assignment . name . getStart ( ) ,
124+ const keyNameReplacement = this . createReplacement ( name . getStart ( ) ,
102125 assignment . name . getWidth ( ) , `animation` ) ;
103126
104- const initializerReplacement = this . createReplacement ( assignment . initializer . getStart ( ) ,
105- assignment . initializer . getWidth ( ) , `{enterDuration: ${ newEnterDurationValue } }` ) ;
127+ const initializerReplacement = this . createReplacement ( initializer . getStart ( ) ,
128+ initializer . getWidth ( ) , `{enterDuration: ${ newEnterDurationValue } }` ) ;
106129
107130 this . addFailureAtNode (
108131 assignment ,
109- `Found deprecated property assignment for "${ bold ( 'MAT_RIPPLE_GLOBAL_OPTIONS' ) } -> ` +
132+ `Found deprecated property assignment for "${ bold ( 'MAT_RIPPLE_GLOBAL_OPTIONS' ) } : ` +
110133 `${ red ( 'baseSpeedFactor' ) } "` ,
111134 [ keyNameReplacement , initializerReplacement ] ) ;
112135 } else {
113- // In case the base speed factor is dynamically calculated and inside of an Angular provider,
114- // we just print the failure and notify about the breaking change.
136+ // Handle the right expression differently if the previous speed factor value can't
137+ // be resolved statically. In that case, we just create a TypeScript expression that
138+ // calculates the explicit duration based on the non-static speed factor expression.
139+ const newExpression = createSpeedFactorConvertExpression ( initializer . getText ( ) ) ;
140+
141+ // Replace the `baseSpeedFactor` property name with `animation`.
142+ const propertyNameReplacement = this . createReplacement ( name . getStart ( ) ,
143+ name . getWidth ( ) , 'animation' ) ;
144+
145+ // Replace the value assignment with the new animation config and remove todo.
146+ const rightExpressionReplacement = this . createReplacement ( initializer . getStart ( ) ,
147+ initializer . getWidth ( ) , `/** ${ removeNote } */ {enterDuration: ${ newExpression } }` ) ;
148+
115149 this . addFailureAtNode (
116- assignment , `Found a deprecated property assignment for ` +
117- `"${ bold ( 'MAT_RIPPLE_GLOBAL_OPTIONS' ) } -> ${ red ( 'speedFactor' ) } . Please manually switch ` +
118- `from " ${ red ( 'baseSpeedFactor' ) } " to " ${ green ( 'animation' ) } ". Note that the animation ` +
119- `property only accepts explicit durations in milliseconds.` ) ;
150+ assignment ,
151+ `Found a deprecated property assignment for "${ bold ( 'MAT_RIPPLE_GLOBAL_OPTIONS' ) } : ` +
152+ `${ red ( 'baseSpeedFactor' ) } .` ,
153+ [ propertyNameReplacement , rightExpressionReplacement ] ) ;
120154 }
121155 }
122156}
0 commit comments