@@ -1480,6 +1480,25 @@ namespace ts.FindAllReferences {
14801480 state . addStringOrCommentReference ( sourceFile . fileName , createTextSpan ( position , search . text . length ) ) ;
14811481 }
14821482
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+ }
14831502 return ;
14841503 }
14851504
@@ -2004,20 +2023,52 @@ namespace ts.FindAllReferences {
20042023
20052024 function getReferencesForStringLiteral ( node : StringLiteralLike , sourceFiles : readonly SourceFile [ ] , checker : TypeChecker , cancellationToken : CancellationToken ) : SymbolAndEntries [ ] {
20062025 const type = getContextualTypeFromParentOrAncestorTypeNode ( node , checker ) ;
2026+ const callExpr = findAncestor ( node , isCallExpression ) ;
20072027 const references = flatMap ( sourceFiles , sourceFile => {
20082028 cancellationToken . throwIfCancellationRequested ( ) ;
20092029 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 )
2039+ ? getTextOfIdentifierOrLiteral ( ref ) === node . text : false ;
2040+
2041+ if ( type && isStringLiteralLike ( ref ) && refHasSameText ) {
2042+ const refType = getContextualTypeFromParentOrAncestorTypeNode ( ref , checker ) ;
2043+ if ( ( refHasSameScope || ! type . isStringLiteral ( ) || type . isUnionOrIntersection ( ) ) && type === refType ) {
2044+ // Reference globally or contextually matches the given string literal by referencing
2045+ // the same union or intersection type or sharing a similar scope.
20182046 return nodeEntry ( ref , EntryKind . StringLiteral ) ;
20192047 }
20202048 }
2049+ if ( callExpr ) {
2050+ if ( refHasSameScope && isPropertyNameLiteral ( ref ) && refHasSameText ) {
2051+ // Reference is the property name of an object literal argument.
2052+ return nodeEntry ( ref , EntryKind . SearchedLocalFoundProperty ) ;
2053+ }
2054+
2055+ const sig = checker . getResolvedSignature ( callExpr ) ;
2056+ if ( sig ) {
2057+ const params = sig . getParameters ( ) ;
2058+ for ( let i = 0 ; i < params . length ; i ++ ) {
2059+ const paramType = checker . getParameterType ( sig , i ) ;
2060+ if ( isLiteralTypeNode ( ref . parent ) && paramType . isStringLiteral ( ) && refHasSameText ) {
2061+ // Reference is the definition of a string literal parameter.
2062+ return nodeEntry ( ref , EntryKind . StringLiteral ) ;
2063+ }
2064+ const prop = paramType . getProperty ( node . text ) ;
2065+ if ( prop && prop === checker . getSymbolAtLocation ( ref ) ) {
2066+ // Reference is a property name in one of the parameter types.
2067+ return nodeEntry ( ref , EntryKind . SearchedLocalFoundProperty ) ;
2068+ }
2069+ }
2070+ }
2071+ }
20212072 } ) ;
20222073 } ) ;
20232074
0 commit comments