@@ -128,6 +128,7 @@ import {
128
128
isCallExpression ,
129
129
isCaseBlock ,
130
130
isCaseClause ,
131
+ isCaseKeyword ,
131
132
isCheckJsEnabledForFile ,
132
133
isClassElement ,
133
134
isClassLike ,
@@ -194,6 +195,7 @@ import {
194
195
isNamedImports ,
195
196
isNamedImportsOrExports ,
196
197
isNamespaceImport ,
198
+ isNodeDescendantOf ,
197
199
isObjectBindingPattern ,
198
200
isObjectLiteralExpression ,
199
201
isObjectTypeDeclaration ,
@@ -435,6 +437,7 @@ export const enum SymbolOriginInfoKind {
435
437
ResolvedExport = 1 << 5 ,
436
438
TypeOnlyAlias = 1 << 6 ,
437
439
ObjectLiteralMethod = 1 << 7 ,
440
+ Ignore = 1 << 8 ,
438
441
439
442
SymbolMemberNoExport = SymbolMember ,
440
443
SymbolMemberExport = SymbolMember | Export ,
@@ -513,6 +516,10 @@ function originIsObjectLiteralMethod(origin: SymbolOriginInfo | undefined): orig
513
516
return ! ! ( origin && origin . kind & SymbolOriginInfoKind . ObjectLiteralMethod ) ;
514
517
}
515
518
519
+ function originIsIgnore ( origin : SymbolOriginInfo | undefined ) : boolean {
520
+ return ! ! ( origin && origin . kind & SymbolOriginInfoKind . Ignore ) ;
521
+ }
522
+
516
523
/** @internal */
517
524
export interface UniqueNameSet {
518
525
add ( name : string ) : void ;
@@ -865,7 +872,6 @@ function completionInfoFromData(
865
872
location,
866
873
propertyAccessToConvert,
867
874
keywordFilters,
868
- literals,
869
875
symbolToOriginInfoMap,
870
876
recommendedCompletion,
871
877
isJsxInitializer,
@@ -875,9 +881,12 @@ function completionInfoFromData(
875
881
isRightOfDotOrQuestionDot,
876
882
importStatementCompletion,
877
883
insideJsDocTagTypeExpression,
878
- symbolToSortTextMap : symbolToSortTextMap ,
884
+ symbolToSortTextMap,
879
885
hasUnresolvedAutoImports,
880
886
} = completionData ;
887
+ let literals = completionData . literals ;
888
+
889
+ const checker = program . getTypeChecker ( ) ;
881
890
882
891
// Verify if the file is JSX language variant
883
892
if ( getLanguageVariant ( sourceFile . scriptKind ) === LanguageVariant . JSX ) {
@@ -887,6 +896,25 @@ function completionInfoFromData(
887
896
}
888
897
}
889
898
899
+ // When the completion is for the expression of a case clause (e.g. `case |`),
900
+ // filter literals & enum symbols whose values are already present in existing case clauses.
901
+ const caseClause = findAncestor ( contextToken , isCaseClause ) ;
902
+ if ( caseClause && ( isCaseKeyword ( contextToken ! ) || isNodeDescendantOf ( contextToken ! , caseClause . expression ) ) ) {
903
+ const tracker = newCaseClauseTracker ( checker , caseClause . parent . clauses ) ;
904
+ literals = literals . filter ( literal => ! tracker . hasValue ( literal ) ) ;
905
+ // The `symbols` array cannot be filtered directly, because to each symbol at position i in `symbols`,
906
+ // there might be a corresponding origin at position i in `symbolToOriginInfoMap`.
907
+ // So instead of filtering the `symbols` array, we mark symbols to be ignored.
908
+ symbols . forEach ( ( symbol , i ) => {
909
+ if ( symbol . valueDeclaration && isEnumMember ( symbol . valueDeclaration ) ) {
910
+ const value = checker . getConstantValue ( symbol . valueDeclaration ) ;
911
+ if ( value !== undefined && tracker . hasValue ( value ) ) {
912
+ symbolToOriginInfoMap [ i ] = { kind : SymbolOriginInfoKind . Ignore } ;
913
+ }
914
+ }
915
+ } ) ;
916
+ }
917
+
890
918
const entries = createSortedArray < CompletionEntry > ( ) ;
891
919
const isChecked = isCheckedFile ( sourceFile , compilerOptions ) ;
892
920
if ( isChecked && ! isNewIdentifierLocation && ( ! symbols || symbols . length === 0 ) && keywordFilters === KeywordCompletionFilters . None ) {
@@ -4533,6 +4561,9 @@ function getCompletionEntryDisplayNameForSymbol(
4533
4561
kind : CompletionKind ,
4534
4562
jsxIdentifierExpected : boolean ,
4535
4563
) : CompletionEntryDisplayNameForSymbol | undefined {
4564
+ if ( originIsIgnore ( origin ) ) {
4565
+ return undefined ;
4566
+ }
4536
4567
const name = originIncludesSymbolName ( origin ) ? origin . symbolName : symbol . name ;
4537
4568
if ( name === undefined
4538
4569
// If the symbol is external module, don't show it in the completion list
0 commit comments