@@ -1480,6 +1480,25 @@ namespace ts.FindAllReferences {
1480
1480
state . addStringOrCommentReference ( sourceFile . fileName , createTextSpan ( position , search . text . length ) ) ;
1481
1481
}
1482
1482
1483
+ const callExpr = findAncestor ( referenceLocation , isCallExpression ) ;
1484
+ if ( callExpr && isStringLiteralLike ( referenceLocation ) ) {
1485
+ // In the case where the reference node is a string literal within a
1486
+ // call expression, the current symbol we're searching for might be
1487
+ // a reference to a property name for one of the parameters of the
1488
+ // call's resolved signature.
1489
+ const sig = state . checker . getResolvedSignature ( callExpr ) ;
1490
+ if ( sig ) {
1491
+ const params = sig . getParameters ( ) ;
1492
+ for ( let i = 0 ; i < params . length ; i ++ ) {
1493
+ const paramType = state . checker . getParameterType ( sig , i ) ;
1494
+ const prop = paramType . getProperty ( referenceLocation . text ) ;
1495
+ if ( prop ) {
1496
+ const relatedSymbol = getRelatedSymbol ( search , prop , referenceLocation , state ) ;
1497
+ if ( relatedSymbol ) addReference ( referenceLocation , relatedSymbol , state ) ;
1498
+ }
1499
+ }
1500
+ }
1501
+ }
1483
1502
return ;
1484
1503
}
1485
1504
@@ -2004,20 +2023,51 @@ namespace ts.FindAllReferences {
2004
2023
2005
2024
function getReferencesForStringLiteral ( node : StringLiteralLike , sourceFiles : readonly SourceFile [ ] , checker : TypeChecker , cancellationToken : CancellationToken ) : SymbolAndEntries [ ] {
2006
2025
const type = getContextualTypeFromParentOrAncestorTypeNode ( node , checker ) ;
2026
+ const callExpr = findAncestor ( node , isCallExpression ) ;
2007
2027
const references = flatMap ( sourceFiles , sourceFile => {
2008
2028
cancellationToken . throwIfCancellationRequested ( ) ;
2009
2029
return mapDefined ( getPossibleSymbolReferenceNodes ( sourceFile , node . text ) , ref => {
2010
- if ( isStringLiteralLike ( ref ) && ref . text === node . text ) {
2011
- if ( type ) {
2012
- const refType = getContextualTypeFromParentOrAncestorTypeNode ( ref , checker ) ;
2013
- if ( type !== checker . getStringType ( ) && type === refType ) {
2014
- return nodeEntry ( ref , EntryKind . StringLiteral ) ;
2015
- }
2016
- }
2017
- else {
2030
+ // Special case: Every string literal refers at least to itself.
2031
+ if ( node === ref ) return nodeEntry ( ref , EntryKind . StringLiteral ) ;
2032
+
2033
+ // When evaluating references for a string literal, guarantee that the string literal
2034
+ // node is either global or that any reference shares the same scope. Global literals
2035
+ // might all refer to each other, but if the string literal being considered is in a
2036
+ // call expression, any reference should also be from the same call expression.
2037
+ const refHasSameScope = ! callExpr || callExpr === findAncestor ( ref , isCallExpression ) ;
2038
+ const refHasSameText = isStringLiteralLike ( ref ) || isPropertyNameLiteral ( ref ) && getTextOfIdentifierOrLiteral ( ref ) === node . text ;
2039
+
2040
+ if ( type && isStringLiteralLike ( ref ) && refHasSameText ) {
2041
+ const refType = getContextualTypeFromParentOrAncestorTypeNode ( ref , checker ) ;
2042
+ if ( ( refHasSameScope || ! type . isStringLiteral ( ) || type . isUnionOrIntersection ( ) ) && type === refType ) {
2043
+ // Reference globally or contextually matches the given string literal by referencing
2044
+ // the same union or intersection type or sharing a similar scope.
2018
2045
return nodeEntry ( ref , EntryKind . StringLiteral ) ;
2019
2046
}
2020
2047
}
2048
+ if ( callExpr ) {
2049
+ if ( refHasSameScope && isPropertyNameLiteral ( ref ) && refHasSameText ) {
2050
+ // Reference is the property name of an object literal argument.
2051
+ return nodeEntry ( ref , EntryKind . SearchedLocalFoundProperty ) ;
2052
+ }
2053
+
2054
+ const sig = checker . getResolvedSignature ( callExpr ) ;
2055
+ if ( sig ) {
2056
+ const params = sig . getParameters ( ) ;
2057
+ for ( let i = 0 ; i < params . length ; i ++ ) {
2058
+ const paramType = checker . getParameterType ( sig , i ) ;
2059
+ if ( isLiteralTypeNode ( ref . parent ) && paramType . isStringLiteral ( ) && refHasSameText ) {
2060
+ // Reference is the definition of a string literal parameter.
2061
+ return nodeEntry ( ref , EntryKind . StringLiteral ) ;
2062
+ }
2063
+ const prop = paramType . getProperty ( node . text ) ;
2064
+ if ( prop && prop === checker . getSymbolAtLocation ( ref ) ) {
2065
+ // Reference is a property name in one of the parameter types.
2066
+ return nodeEntry ( ref , EntryKind . SearchedLocalFoundProperty ) ;
2067
+ }
2068
+ }
2069
+ }
2070
+ }
2021
2071
} ) ;
2022
2072
} ) ;
2023
2073
0 commit comments