@@ -66,55 +66,22 @@ public static bool CombineAssignmentWithSingleUse(this SyntaxNode rootNode)
66
66
n = declParent . NextNonComment ;
67
67
68
68
// If next operation isn't an assignment, ignore...
69
- var nextAssignment = n as VariableAssignmentSyntaxNode ;
70
- if ( nextAssignment == null )
71
- continue ;
72
-
73
- // The next assignment must be for a different variable.
74
- if ( nextAssignment . Name == assignment . Name )
75
- continue ;
76
-
77
- // The assignment must happen in the same scope as the variable declaration.
78
- if ( variableDecl . FindAncestor < BraceSyntaxNode > ( ) != nextAssignment . FindAncestor < BraceSyntaxNode > ( ) )
79
- continue ;
80
-
81
- // ...and must use the variable exactly once...
82
- var nextAssignmentUsesOfVar =
83
- nextAssignment
84
- . TheTree
85
- . OfType < GenericSyntaxNode > ( )
86
- . Where ( o => o . IsVarName ( assignment . Name ) )
87
- . ToList ( ) ;
88
- if ( nextAssignmentUsesOfVar . Count != 1 )
89
- continue ;
90
-
91
- var usage = nextAssignmentUsesOfVar . Single ( ) ;
92
-
93
- // Don't join if the next assignment uses a function call.
94
- // (Just in case it modifies the variable.)
95
- var intermediateNodes = nextAssignment . TheTree . TakeWhile ( o => o != usage ) ;
96
- var hasFunctionCall = intermediateNodes . OfType < FunctionCallSyntaxNode > ( ) . Any ( o => o . HasOutParam ) ;
97
- if ( hasFunctionCall )
98
- continue ;
99
-
100
- // Inline the variable!
101
- var addBrackets = assignment . Children . Any ( o => o . Token is SymbolOperatorToken ) ;
102
- if ( addBrackets )
69
+ if ( n is VariableAssignmentSyntaxNode nextAssignment )
103
70
{
104
- usage . ReplaceWith ( new RoundBracketSyntaxNode ( assignment . Children ) ) ;
105
-
106
- // Try to remove the brackets if we can.
107
- var customOptions = CustomOptions . None ( ) ;
108
- customOptions . SimplifyArithmetic = true ;
109
- nextAssignment . Simplify ( customOptions ) ;
71
+ if ( ! TryCombineWithNextAssignment ( variableDecl , assignment , nextAssignment ) )
72
+ continue ;
73
+ }
74
+ else if ( n is IfSyntaxNode ifNode )
75
+ {
76
+ if ( ! TryCombineWithNextIf ( variableDecl , assignment , ifNode ) )
77
+ continue ;
110
78
}
111
79
else
112
80
{
113
- usage . ReplaceWith ( assignment . Children . ToArray ( ) ) ;
81
+ // No change made.
82
+ continue ;
114
83
}
115
84
116
- assignment . Remove ( ) ;
117
-
118
85
// If the declaration isn't declaring any variables any more, remove it.
119
86
if ( declParent != null && ! declParent . Children . Any ( ) )
120
87
declParent . Remove ( ) ;
@@ -130,5 +97,88 @@ public static bool CombineAssignmentWithSingleUse(this SyntaxNode rootNode)
130
97
131
98
return anyChanges ;
132
99
}
100
+
101
+ private static bool TryCombineWithNextAssignment ( VariableDeclarationSyntaxNode variableDecl , VariableAssignmentSyntaxNode assignment , VariableAssignmentSyntaxNode nextAssignment )
102
+ {
103
+ // The next assignment must be for a different variable.
104
+ if ( nextAssignment . Name == assignment . Name )
105
+ return false ;
106
+
107
+ // The assignment must happen in the same scope as the variable declaration.
108
+ if ( variableDecl . FindAncestor < BraceSyntaxNode > ( ) != nextAssignment . FindAncestor < BraceSyntaxNode > ( ) )
109
+ return false ;
110
+
111
+ // ...and must use the variable exactly once...
112
+ var nextAssignmentUsesOfVar =
113
+ nextAssignment
114
+ . TheTree
115
+ . OfType < GenericSyntaxNode > ( )
116
+ . Where ( o => o . IsVarName ( assignment . Name ) )
117
+ . ToList ( ) ;
118
+ if ( nextAssignmentUsesOfVar . Count != 1 )
119
+ return false ;
120
+
121
+ var usage = nextAssignmentUsesOfVar . Single ( ) ;
122
+
123
+ // Don't join if the next assignment uses a function call.
124
+ // (Just in case it modifies the variable.)
125
+ var intermediateNodes = nextAssignment . TheTree . TakeWhile ( o => o != usage ) ;
126
+ var hasFunctionCall = intermediateNodes . OfType < FunctionCallSyntaxNode > ( ) . Any ( o => o . HasOutParam ) ;
127
+ if ( hasFunctionCall )
128
+ return false ;
129
+
130
+ // Inline the variable!
131
+ var addBrackets = assignment . Children . Any ( o => o . Token is SymbolOperatorToken ) ;
132
+ if ( addBrackets )
133
+ {
134
+ usage . ReplaceWith ( new RoundBracketSyntaxNode ( assignment . Children ) ) ;
135
+
136
+ // Try to remove the brackets if we can.
137
+ var customOptions = CustomOptions . None ( ) ;
138
+ customOptions . SimplifyArithmetic = true ;
139
+ nextAssignment . Simplify ( customOptions ) ;
140
+ }
141
+ else
142
+ {
143
+ usage . ReplaceWith ( assignment . Children . ToArray ( ) ) ;
144
+ }
145
+
146
+ assignment . Remove ( ) ;
147
+ return true ;
148
+ }
149
+
150
+ private static bool TryCombineWithNextIf ( VariableDeclarationSyntaxNode variableDecl , VariableAssignmentSyntaxNode assignment , IfSyntaxNode ifNode )
151
+ {
152
+ var conditionTree = ifNode . Conditions . TheTree ;
153
+
154
+ // The 'if' condition must use the variable exactly once.
155
+ var usages = conditionTree . OfType < GenericSyntaxNode > ( ) . Where ( o => o . IsVarName ( assignment . Name ) ) . ToList ( ) ;
156
+ if ( usages . Count != 1 )
157
+ return false ;
158
+
159
+ // ...and cannot use it with an array index or vector field.
160
+ if ( conditionTree . OfType < GenericSyntaxNode > ( ) . Count ( o => o . StartsWithVarName ( assignment . Name ) ) != 1 )
161
+ return false ;
162
+
163
+ // Don't join if the 'if' condition uses a function call.
164
+ // (Just in case it modifies the variable.)
165
+ var hasFunctionCall = conditionTree . OfType < FunctionCallSyntaxNode > ( ) . Any ( o => o . HasOutParam ) ;
166
+ if ( hasFunctionCall )
167
+ return false ;
168
+
169
+ // Inline the variable!
170
+ usages . Single ( ) . ReplaceWith ( assignment . Children . ToArray ( ) ) ;
171
+ assignment . Remove ( ) ;
172
+
173
+ // Remove the declaration too?
174
+ var assDef = variableDecl . Definitions . FirstOrDefault ( o => o . Name == assignment . Name ) ;
175
+ if ( assDef ? . FindDeclarationScope ( ) . OfType < GenericSyntaxNode > ( ) . Any ( o => o . StartsWithVarName ( assignment . Name ) ) == false )
176
+ assDef . Remove ( ) ;
177
+
178
+ if ( ! variableDecl . Children . Any ( ) )
179
+ variableDecl . Remove ( ) ;
180
+
181
+ return true ;
182
+ }
133
183
}
134
184
}
0 commit comments