@@ -56,5 +56,70 @@ module ActiveSupport {
5656 }
5757 }
5858 }
59+
60+ /**
61+ * Extensions to the `Enumerable` module.
62+ */
63+ module Enumerable {
64+ private class ArrayIndex extends int {
65+ ArrayIndex ( ) { this = any ( DataFlow:: Content:: KnownElementContent c ) .getIndex ( ) .getInt ( ) }
66+ }
67+
68+ private class CompactBlankSummary extends SimpleSummarizedCallable {
69+ CompactBlankSummary ( ) { this = "compact_blank" }
70+
71+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
72+ input = "Argument[self].Element[any]" and
73+ output = "ReturnValue.Element[?]" and
74+ preservesValue = true
75+ }
76+ }
77+
78+ private class ExcludingSummary extends SimpleSummarizedCallable {
79+ ExcludingSummary ( ) { this = [ "excluding" , "without" ] }
80+
81+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
82+ input = "Argument[self].Element[any]" and
83+ output = "ReturnValue.Element[?]" and
84+ preservesValue = true
85+ }
86+ }
87+
88+ private class InOrderOfSummary extends SimpleSummarizedCallable {
89+ InOrderOfSummary ( ) { this = "in_order_of" }
90+
91+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
92+ input = "Argument[self].Element[any]" and
93+ output = "ReturnValue.Element[?]" and
94+ preservesValue = true
95+ }
96+ }
97+
98+ /**
99+ * Like `Array#push` but doesn't update the receiver.
100+ */
101+ private class IncludingSummary extends SimpleSummarizedCallable {
102+ IncludingSummary ( ) { this = "including" }
103+
104+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
105+ (
106+ exists ( ArrayIndex i |
107+ input = "Argument[self].Element[" + i + "]" and
108+ output = "ReturnValue.Element[" + i + "]"
109+ )
110+ or
111+ input = "Argument[self].Element[?]" and
112+ output = "ReturnValue.Element[?]"
113+ or
114+ exists ( int i | i in [ 0 .. ( mc .getNumberOfArguments ( ) - 1 ) ] |
115+ input = "Argument[" + i + "]" and
116+ output = [ "ReturnValue.Element[?]" ]
117+ )
118+ ) and
119+ preservesValue = true
120+ }
121+ }
122+ // TODO: index_by, index_with, pick, pluck (they require Hash dataflow)
123+ }
59124 }
60125}
0 commit comments