@@ -165,7 +165,11 @@ private Collection<? extends IBinding> visibleBindings(ASTNode node) {
165165 visibleBindings .add (typeDecl .resolveBinding ());
166166 }
167167
168- if (node instanceof Block block ) {
168+ if (node instanceof Block block && node .getStartPosition () + node .getLength () > this .offset ) {
169+ // TODO: handle negative if statements eg.
170+ // if (!(node instanceof IfStatement ifStatement))
171+ // return;
172+ // ifState|
169173 var bindings = ((List <Statement >) block .statements ()).stream ()
170174 .filter (statement -> statement .getStartPosition () < this .offset )
171175 .filter (VariableDeclarationStatement .class ::isInstance )
@@ -175,10 +179,91 @@ private Collection<? extends IBinding> visibleBindings(ASTNode node) {
175179 .map (VariableDeclarationFragment ::resolveBinding )
176180 .toList ();
177181 visibleBindings .addAll (bindings );
182+ for (Statement statement : ((List <Statement >)block .statements ())) {
183+ if (statement .getStartPosition () >= this .offset || statement .getStartPosition () + statement .getLength () >= this .offset ) {
184+ break ;
185+ }
186+ if (statement instanceof IfStatement ifStatement && ifStatement .getElseStatement () == null ) {
187+ visibleBindings .addAll (collectTrueFalseBindings (ifStatement .getExpression ()).falseBindings ());
188+ }
189+ }
190+ }
191+
192+ if (node .getParent () instanceof IfStatement ifStatement && node .getStartPosition () + node .getLength () > this .offset ) {
193+ TrueFalseBindings leftRightBindings = collectTrueFalseBindings (ifStatement .getExpression ());
194+ if (ifStatement .getThenStatement () == node ) {
195+ visibleBindings .addAll (leftRightBindings .trueBindings ());
196+ } else {
197+ visibleBindings .addAll (leftRightBindings .falseBindings ());
198+ }
178199 }
200+
201+ if (node instanceof SwitchStatement switchStatement ) {
202+ int i ;
203+ for (i = 0 ; i < switchStatement .statements ().size (); i ++) {
204+ if (((List <Statement >)switchStatement .statements ()).get (i ).getStartPosition () >= this .offset ) {
205+ break ;
206+ }
207+ if (((List <Statement >)switchStatement .statements ()).get (i ) instanceof SwitchCase switchCase ) {
208+ DOMCompletionUtil .visitChildren (switchCase , ASTNode .TYPE_PATTERN , (TypePattern e ) -> {
209+ visibleBindings .add (e .getPatternVariable ().resolveBinding ());
210+ });
211+ }
212+ }
213+ }
214+
215+ if (node instanceof SwitchExpression switchExpression ) {
216+ int i ;
217+ for (i = 0 ; i < switchExpression .statements ().size (); i ++) {
218+ if (((List <Statement >)switchExpression .statements ()).get (i ).getStartPosition () >= this .offset ) {
219+ break ;
220+ }
221+ if (((List <Statement >)switchExpression .statements ()).get (i ) instanceof SwitchCase switchCase ) {
222+ DOMCompletionUtil .visitChildren (switchCase , ASTNode .TYPE_PATTERN , (TypePattern e ) -> {
223+ visibleBindings .add (e .getPatternVariable ().resolveBinding ());
224+ });
225+ }
226+ }
227+ }
228+
179229 return visibleBindings ;
180230 }
181231
232+ /**
233+ * Represents collections of bindings that might be accessible depending on whether a boolean expression is true or false.
234+ *
235+ * @param trueBindings the bindings that are accessible when the expression is true
236+ * @param falseBindings the bindings that are accessible when the expression is false
237+ */
238+ record TrueFalseBindings (List <IVariableBinding > trueBindings , List <IVariableBinding > falseBindings ) {}
239+
240+ private TrueFalseBindings collectTrueFalseBindings (Expression e ) {
241+ if (e instanceof PrefixExpression prefixExpression && prefixExpression .getOperator () == PrefixExpression .Operator .NOT ) {
242+ TrueFalseBindings notBindings = collectTrueFalseBindings (prefixExpression .getOperand ());
243+ return new TrueFalseBindings (notBindings .falseBindings (), notBindings .trueBindings ());
244+ } else if (e instanceof InfixExpression infixExpression && infixExpression .getOperator () == InfixExpression .Operator .AND ) {
245+ TrueFalseBindings left = collectTrueFalseBindings (infixExpression .getLeftOperand ());
246+ TrueFalseBindings right = collectTrueFalseBindings (infixExpression .getRightOperand ());
247+ List <IVariableBinding > combined = new ArrayList <>();
248+ combined .addAll (left .trueBindings ());
249+ combined .addAll (right .trueBindings ());
250+ return new TrueFalseBindings (combined , Collections .emptyList ());
251+ } else if (e instanceof InfixExpression infixExpression && infixExpression .getOperator () == InfixExpression .Operator .OR ) {
252+ TrueFalseBindings left = collectTrueFalseBindings (infixExpression .getLeftOperand ());
253+ TrueFalseBindings right = collectTrueFalseBindings (infixExpression .getRightOperand ());
254+ List <IVariableBinding > combined = new ArrayList <>();
255+ combined .addAll (left .falseBindings ());
256+ combined .addAll (right .falseBindings ());
257+ return new TrueFalseBindings (Collections .emptyList (), combined );
258+ } else {
259+ List <IVariableBinding > typePatternBindings = new ArrayList <>();
260+ DOMCompletionUtil .visitChildren (e , ASTNode .TYPE_PATTERN , (TypePattern patt ) -> {
261+ typePatternBindings .add (patt .getPatternVariable ().resolveBinding ());
262+ });
263+ return new TrueFalseBindings (typePatternBindings , Collections .emptyList ());
264+ }
265+ }
266+
182267 private Collection <? extends ITypeBinding > visibleTypeBindings (ASTNode node ) {
183268 List <ITypeBinding > visibleBindings = new ArrayList <>();
184269 if (node instanceof AbstractTypeDeclaration typeDeclaration ) {
0 commit comments