@@ -59,11 +59,12 @@ interface IdentifierReference {
59
59
}
60
60
61
61
export class HammerGesturesRule extends MigrationRule < null > {
62
- // Only enable this rule if the migration targets version 9 and is running
63
- // for a non-test target. We cannot migrate test targets since they have a
64
- // limited scope (in regards to source files) and therefore the HammerJS
65
- // usage detection can be incorrect.
66
- ruleEnabled = this . targetVersion === TargetVersion . V9 && ! this . isTestTarget ;
62
+ // Only enable this rule if the migration targets v9 or v10 and is running for a non-test
63
+ // target. We cannot migrate test targets since they have a limited scope
64
+ // (in regards to source files) and therefore the HammerJS usage detection can be incorrect.
65
+ ruleEnabled =
66
+ ( this . targetVersion === TargetVersion . V9 || this . targetVersion === TargetVersion . V10 ) &&
67
+ ! this . isTestTarget ;
67
68
68
69
private _printer = ts . createPrinter ( ) ;
69
70
private _importManager = new ImportManager ( this . getUpdateRecorder , this . _printer ) ;
@@ -112,6 +113,11 @@ export class HammerGesturesRule extends MigrationRule<null> {
112
113
}
113
114
114
115
postAnalysis ( ) : void {
116
+ // Walk through all hammer config token references and check if there
117
+ // is a potential custom gesture config setup.
118
+ const hasCustomGestureConfigSetup =
119
+ this . _hammerConfigTokenReferences . some ( r => this . _checkForCustomGestureConfigSetup ( r ) ) ;
120
+
115
121
if ( this . _usedInRuntime || this . _usedInTemplate ) {
116
122
// If hammer is only used at runtime, we don't need the gesture config
117
123
// and can remove it (along with the hammer config token if possible)
@@ -121,7 +127,24 @@ export class HammerGesturesRule extends MigrationRule<null> {
121
127
this . _setupHammerGestureConfig ( ) ;
122
128
}
123
129
} else {
124
- this . _removeHammerSetup ( ) ;
130
+ // If HammerJS could not be detected, but we detected a custom gesture
131
+ // config setup, we just remove all references to the Angular Material
132
+ // gesture config. Otherwise we completely remove HammerJS from the app.
133
+ if ( hasCustomGestureConfigSetup ) {
134
+ this . _removeGestureConfigSetup ( ) ;
135
+ // Print a message if we found a custom gesture config setup in combination with
136
+ // references to the Angular Material gesture config. This is ambiguous and the
137
+ // migration just removes the Material gesture config setup, but we still want
138
+ // to create an information message.
139
+ if ( this . _gestureConfigReferences . length ) {
140
+ this . logger . info ( chalk . yellow (
141
+ ' ⚠ The HammerJS v9 migration for Angular components detected that the Angular ' +
142
+ 'Material gesture config is used while a custom gesture config is set up. The ' +
143
+ 'migration removed all references to the Angular Material gesture config.' ) ) ;
144
+ }
145
+ } else {
146
+ this . _removeHammerSetup ( ) ;
147
+ }
125
148
}
126
149
127
150
// Record the changes collected in the import manager. Changes need to be applied
@@ -308,6 +331,32 @@ export class HammerGesturesRule extends MigrationRule<null> {
308
331
}
309
332
}
310
333
334
+ /**
335
+ * Checks if the given Hammer gesture config token reference is part of an
336
+ * Angular provider definition that sets up a custom gesture config.
337
+ */
338
+ private _checkForCustomGestureConfigSetup ( tokenRef : IdentifierReference ) : boolean {
339
+ // Walk up the tree to look for a parent property assignment of the
340
+ // reference to the hammer gesture config token.
341
+ let propertyAssignment : ts . Node = tokenRef . node ;
342
+ while ( propertyAssignment && ! ts . isPropertyAssignment ( propertyAssignment ) ) {
343
+ propertyAssignment = propertyAssignment . parent ;
344
+ }
345
+
346
+ if ( ! propertyAssignment || ! ts . isPropertyAssignment ( propertyAssignment ) ||
347
+ getPropertyNameText ( propertyAssignment . name ) !== 'provide' ) {
348
+ return false ;
349
+ }
350
+
351
+ const objectLiteralExpr = propertyAssignment . parent ;
352
+ const matchingIdentifiers = findMatchingChildNodes ( objectLiteralExpr , ts . isIdentifier ) ;
353
+
354
+ // We naively assume that if there is a reference to the "GestureConfig" export
355
+ // from Angular Material in the provider literal, that the provider sets up the
356
+ // Angular Material gesture config.
357
+ return ! this . _gestureConfigReferences . some ( r => matchingIdentifiers . includes ( r . node ) ) ;
358
+ }
359
+
311
360
/**
312
361
* Determines an available file name for the gesture config which should
313
362
* be stored in the specified file path.
0 commit comments