19
19
*/
20
20
package org .sonar .python .checks .cdk ;
21
21
22
- import java .util .ArrayList ;
23
- import java .util .Collections ;
24
- import java .util .List ;
22
+ import java .util .Deque ;
23
+ import java .util .LinkedList ;
25
24
import java .util .Optional ;
26
25
import java .util .function .Predicate ;
27
26
import org .sonar .plugins .python .api .PythonCheck ;
@@ -68,12 +67,12 @@ public static Optional<CallExpression> getCall(Expression expression, String fqn
68
67
/**
69
68
* Resolve a particular argument of a call or get an empty optional if the argument is not set.
70
69
*/
71
- protected static Optional <ExpressionTrace > getArgument (SubscriptionContext ctx , CallExpression callExpression , String argumentName ) {
70
+ protected static Optional <ExpressionFlow > getArgument (SubscriptionContext ctx , CallExpression callExpression , String argumentName ) {
72
71
return callExpression .arguments ().stream ()
73
72
.map (RegularArgument .class ::cast )
74
73
.filter (regularArgument -> regularArgument .keywordArgument () != null )
75
74
.filter (regularArgument -> argumentName .equals (regularArgument .keywordArgument ().name ()))
76
- .map (regularArgument -> ExpressionTrace .build (ctx , regularArgument .expression ()))
75
+ .map (regularArgument -> ExpressionFlow .build (ctx , regularArgument .expression ()))
77
76
.findAny ();
78
77
}
79
78
@@ -85,43 +84,43 @@ public static Optional<ResolvedKeyValuePair> getKeyValuePair(SubscriptionContext
85
84
}
86
85
87
86
/**
88
- * The expression trace reflects the complete flow of a value across the code .
87
+ * The expression flow represents the propagation of an expression .
89
88
* It serves as a resolution path from the use of the expression up to the value assignment.
90
- * For example, if the value of an argument expression did not occur directly in the function call, the value can be traced back.
91
- * The trace allows on the one hand to check the assigned value
89
+ * For example, if the value of an argument expression did not occur directly in the function call, the value can be tracked back.
90
+ * The flow allows on the one hand to check the assigned value
92
91
* and on the other hand to display the assignment path of the relevant value when creating an issue.
93
92
*/
94
- static class ExpressionTrace {
93
+ static class ExpressionFlow {
95
94
96
95
private static final String TAIL_MESSAGE = "Propagated setting." ;
97
96
98
97
private final SubscriptionContext ctx ;
99
- private final List <Expression > trace ;
98
+ private final Deque <Expression > locations ;
100
99
101
- private ExpressionTrace (SubscriptionContext ctx , List <Expression > trace ) {
100
+ private ExpressionFlow (SubscriptionContext ctx , Deque <Expression > locations ) {
102
101
this .ctx = ctx ;
103
- this .trace = Collections . unmodifiableList ( trace ) ;
102
+ this .locations = locations ;
104
103
}
105
104
106
- protected static ExpressionTrace build (SubscriptionContext ctx , Expression expression ) {
107
- List <Expression > trace = new ArrayList <>();
108
- buildTrace (expression , trace );
109
- return new ExpressionTrace (ctx , trace );
105
+ protected static ExpressionFlow build (SubscriptionContext ctx , Expression expression ) {
106
+ Deque <Expression > locations = new LinkedList <>();
107
+ resolveLocations (expression , locations );
108
+ return new ExpressionFlow (ctx , locations );
110
109
}
111
110
112
- static void buildTrace (Expression expression , List <Expression > trace ) {
113
- trace .add (expression );
111
+ static void resolveLocations (Expression expression , Deque <Expression > locations ) {
112
+ locations .add (expression );
114
113
if (expression .is (Tree .Kind .NAME )) {
115
114
Expression singleAssignedValue = Expressions .singleAssignedValue (((Name ) expression ));
116
- if (singleAssignedValue != null && !trace .contains (singleAssignedValue )) {
117
- buildTrace (singleAssignedValue , trace );
115
+ if (singleAssignedValue != null && !locations .contains (singleAssignedValue )) {
116
+ resolveLocations (singleAssignedValue , locations );
118
117
}
119
118
}
120
119
}
121
120
122
121
public void addIssue (String primaryMessage ) {
123
- PythonCheck .PreciseIssue issue = ctx .addIssue (trace . get ( 0 ).parent (), primaryMessage );
124
- trace .stream ().skip (1 ).forEach (expression -> issue .secondary (expression .parent (), TAIL_MESSAGE ));
122
+ PythonCheck .PreciseIssue issue = ctx .addIssue (locations . getFirst ( ).parent (), primaryMessage );
123
+ locations .stream ().skip (1 ).forEach (expression -> issue .secondary (expression .parent (), TAIL_MESSAGE ));
125
124
}
126
125
127
126
public void addIssueIf (Predicate <Expression > predicate , String primaryMessage ) {
@@ -137,15 +136,15 @@ public void addIssueIf(Predicate<Expression> predicate, String primaryMessage, C
137
136
}
138
137
139
138
public boolean hasExpression (Predicate <Expression > predicate ) {
140
- return trace .stream ().anyMatch (predicate );
139
+ return locations .stream ().anyMatch (predicate );
141
140
}
142
141
143
142
public Optional <Expression > getExpression (Predicate <Expression > predicate ) {
144
- return trace .stream ().filter (predicate ).findFirst ();
143
+ return locations .stream ().filter (predicate ).findFirst ();
145
144
}
146
145
147
- public List <Expression > trace () {
148
- return trace ;
146
+ public Deque <Expression > locations () {
147
+ return locations ;
149
148
}
150
149
}
151
150
@@ -154,16 +153,16 @@ public List<Expression> trace() {
154
153
*/
155
154
static class ResolvedKeyValuePair {
156
155
157
- final ExpressionTrace key ;
158
- final ExpressionTrace value ;
156
+ final ExpressionFlow key ;
157
+ final ExpressionFlow value ;
159
158
160
- private ResolvedKeyValuePair (ExpressionTrace key , ExpressionTrace value ) {
159
+ private ResolvedKeyValuePair (ExpressionFlow key , ExpressionFlow value ) {
161
160
this .key = key ;
162
161
this .value = value ;
163
162
}
164
163
165
164
static ResolvedKeyValuePair build (SubscriptionContext ctx , KeyValuePair pair ) {
166
- return new ResolvedKeyValuePair (ExpressionTrace .build (ctx , pair .key ()), ExpressionTrace .build (ctx , pair .value ()));
165
+ return new ResolvedKeyValuePair (ExpressionFlow .build (ctx , pair .key ()), ExpressionFlow .build (ctx , pair .value ()));
167
166
}
168
167
}
169
168
}
0 commit comments