@@ -30,7 +30,8 @@ module.exports = {
30
30
31
31
const messageIdsUsed = new Set ( ) ;
32
32
let contextIdentifiers ;
33
- let shouldPerformUnusedCheck = true ;
33
+ let hasSeenUnknownMessageId = false ;
34
+ let hasSeenViolationReport = false ;
34
35
35
36
const messageIdNodes = utils . getMessageIdNodes ( info , scopeManager ) ;
36
37
if ( ! messageIdNodes ) {
@@ -44,22 +45,29 @@ module.exports = {
44
45
} ,
45
46
46
47
'Program:exit' ( ) {
47
- if ( shouldPerformUnusedCheck ) {
48
- const messageIdNodesUnused = messageIdNodes . filter (
49
- ( node ) =>
50
- ! messageIdsUsed . has ( utils . getKeyName ( node , context . getScope ( ) ) )
51
- ) ;
52
-
53
- // Report any messageIds that were never used.
54
- for ( const messageIdNode of messageIdNodesUnused ) {
55
- context . report ( {
56
- node : messageIdNode ,
57
- messageId : 'unusedMessage' ,
58
- data : {
59
- messageId : utils . getKeyName ( messageIdNode , context . getScope ( ) ) ,
60
- } ,
61
- } ) ;
62
- }
48
+ if ( hasSeenUnknownMessageId || ! hasSeenViolationReport ) {
49
+ /*
50
+ Bail out when the rule is likely to have false positives.
51
+ - If we saw a dynamic/unknown messageId
52
+ - If we couldn't find any violation reporting code, likely because a helper function from an external file is handling this
53
+ */
54
+ return ;
55
+ }
56
+
57
+ const messageIdNodesUnused = messageIdNodes . filter (
58
+ ( node ) =>
59
+ ! messageIdsUsed . has ( utils . getKeyName ( node , context . getScope ( ) ) )
60
+ ) ;
61
+
62
+ // Report any messageIds that were never used.
63
+ for ( const messageIdNode of messageIdNodesUnused ) {
64
+ context . report ( {
65
+ node : messageIdNode ,
66
+ messageId : 'unusedMessage' ,
67
+ data : {
68
+ messageId : utils . getKeyName ( messageIdNode , context . getScope ( ) ) ,
69
+ } ,
70
+ } ) ;
63
71
}
64
72
} ,
65
73
@@ -76,6 +84,8 @@ module.exports = {
76
84
return ;
77
85
}
78
86
87
+ hasSeenViolationReport = true ;
88
+
79
89
const reportMessagesAndDataArray =
80
90
utils . collectReportViolationAndSuggestionData ( reportInfo ) ;
81
91
for ( const { messageId } of reportMessagesAndDataArray . filter (
@@ -90,7 +100,7 @@ module.exports = {
90
100
values . some ( ( val ) => val . type !== 'Literal' )
91
101
) {
92
102
// When a dynamic messageId is used and we can't detect its value, disable the rule to avoid false positives.
93
- shouldPerformUnusedCheck = false ;
103
+ hasSeenUnknownMessageId = true ;
94
104
}
95
105
values . forEach ( ( val ) => messageIdsUsed . add ( val . value ) ) ;
96
106
}
@@ -101,17 +111,21 @@ module.exports = {
101
111
// In order to reduce false positives, we will also check for messageId properties anywhere in the file.
102
112
// This is helpful especially in the event that helper functions are used for reporting violations.
103
113
if ( node . key . type === 'Identifier' && node . key . name === 'messageId' ) {
114
+ hasSeenViolationReport = true ;
115
+
104
116
const values =
105
117
node . value . type === 'Literal'
106
118
? [ node . value ]
107
119
: utils . findPossibleVariableValues ( node . value , scopeManager ) ;
120
+
108
121
if (
109
122
values . length === 0 ||
110
123
values . some ( ( val ) => val . type !== 'Literal' )
111
124
) {
112
125
// When a dynamic messageId is used and we can't detect its value, disable the rule to avoid false positives.
113
- shouldPerformUnusedCheck = false ;
126
+ hasSeenUnknownMessageId = true ;
114
127
}
128
+
115
129
values . forEach ( ( val ) => messageIdsUsed . add ( val . value ) ) ;
116
130
}
117
131
} ,
0 commit comments