@@ -505,7 +505,16 @@ class TrivialProperty extends Property {
505505 * A `Property` which holds a type with an indexer.
506506 */
507507class IndexerProperty extends Property {
508- IndexerProperty ( ) { exists ( getType ( ) .( RefType ) .getABaseType * ( ) .getAnIndexer ( ) ) }
508+ Indexer i ;
509+
510+ IndexerProperty ( ) { this .getType ( ) .( RefType ) .hasMember ( i ) }
511+
512+ pragma [ nomagic]
513+ private IndexerCall getAnIndexerCall0 ( ) {
514+ exists ( Expr qualifier | qualifier = result .getQualifier ( ) |
515+ DataFlow:: localFlow ( DataFlow:: exprNode ( this .getAnAccess ( ) ) , DataFlow:: exprNode ( qualifier ) )
516+ )
517+ }
509518
510519 /**
511520 * Gets a call to the indexer of the type returned by this property, for a value returned by this
@@ -514,10 +523,27 @@ class IndexerProperty extends Property {
514523 * This tracks instances returned by the property using local data flow.
515524 */
516525 IndexerCall getAnIndexerCall ( ) {
517- result = getType ( ) .( RefType ) .getAnIndexer ( ) .getAnAccessor ( ) .getACall ( ) and
518- // The qualifier of this indexer call should be a value returned from an access of this property
519- exists ( Expr qualifier | qualifier = result .( IndexerAccess ) .getQualifier ( ) |
520- DataFlow:: localFlow ( DataFlow:: exprNode ( this .getAnAccess ( ) ) , DataFlow:: exprNode ( qualifier ) )
521- )
526+ result = this .getAnIndexerCall0 ( ) and
527+ // Omitting the constraint below would potentially include
528+ // too many indexer calls, for example the call to the indexer
529+ // setter at `dict[0]` in
530+ //
531+ // ```
532+ // class A
533+ // {
534+ // Dictionary<int, string> dict;
535+ // public IReadonlyDictionary<int, string> Dict { get => dict; }
536+ // }
537+ //
538+ // class B
539+ // {
540+ // void M(A a)
541+ // {
542+ // var dict = (Dictionary<int, string>) a.Dict;
543+ // dict[0] = "";
544+ // }
545+ // }
546+ // ```
547+ result .getIndexer ( ) = i
522548 }
523549}
0 commit comments