FlattenScope { public static List<Node> flattenScope( TypeResolver typeResolver, Expression expressionWithScope ) { List<Node> res = new ArrayList<>(); if (expressionWithScope instanceof FieldAccessExpr) { FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) expressionWithScope; res.addAll(flattenScope( typeResolver, fieldAccessExpr.getScope() )); res.add(fieldAccessExpr.getName()); } else if (expressionWithScope instanceof NullSafeFieldAccessExpr) { NullSafeFieldAccessExpr fieldAccessExpr = (NullSafeFieldAccessExpr) expressionWithScope; res.addAll(flattenScope( typeResolver, fieldAccessExpr.getScope() )); res.add(fieldAccessExpr.getName()); } else if (expressionWithScope instanceof MethodCallExpr) { MethodCallExpr methodCallExpr = (MethodCallExpr) expressionWithScope; if (methodCallExpr.getScope().isPresent()) { Expression scope = methodCallExpr.getScope().get(); if (isFullyQualifiedClassName( typeResolver, scope )) { res.add(scope); } else { res.addAll( flattenScope( typeResolver, scope ) ); } } res.add(methodCallExpr); } else if (expressionWithScope instanceof NullSafeMethodCallExpr) { NullSafeMethodCallExpr methodCallExpr = (NullSafeMethodCallExpr) expressionWithScope; if (methodCallExpr.getScope().isPresent()) { res.addAll(flattenScope(typeResolver, methodCallExpr.getScope().orElseThrow(() -> new IllegalStateException("Scope expression is not present!")))); } res.add(methodCallExpr); } else if (expressionWithScope instanceof InlineCastExpr && ((InlineCastExpr) expressionWithScope).getExpression() instanceof FieldAccessExpr) { InlineCastExpr inlineCastExpr = (InlineCastExpr) expressionWithScope; Expression internalScope = ((FieldAccessExpr) inlineCastExpr.getExpression()).getScope(); res.addAll(flattenScope( typeResolver, internalScope )); res.add(expressionWithScope); } else if (expressionWithScope instanceof ArrayAccessExpr) { ArrayAccessExpr arrayAccessExpr = (ArrayAccessExpr) expressionWithScope; res.addAll(flattenScope( typeResolver, arrayAccessExpr.getName()) ); res.add(arrayAccessExpr); } else { res.add(expressionWithScope); } return res; } private  FlattenScope(); static List<Node> flattenScope( TypeResolver typeResolver, Expression expressionWithScope );  }
@Test public void flattenUnaryExpression() { List<Node> actual = flattenScope(MockTypeResolver.INSTANCE, expr("getMessageId")); List<Node> expected = Collections.singletonList(new NameExpr("getMessageId")); compareArrays(actual, expected); }
@Test public void flattenFields() { List<Node> actual = flattenScope(MockTypeResolver.INSTANCE, expr("Field.INT")); List<Node> expected = asList(new NameExpr("Field"), new SimpleName("INT")); compareArrays(actual, expected); }
@Test public void flattenMethodCall() { List<Node> actual = flattenScope(MockTypeResolver.INSTANCE, expr("name.startsWith(\"M\")")); MethodCallExpr methodCallExpr = new MethodCallExpr(new NameExpr("name"), "startsWith", nodeList(new StringLiteralExpr("M"))); methodCallExpr.setTypeArguments(NodeList.nodeList()); List<Node> expected = asList(new NameExpr("name"), methodCallExpr); compareArrays(actual, expected); }
@Test public void flattenArrayAccess() { List<Node> actual = flattenScope(MockTypeResolver.INSTANCE, expr("$p.getChildrenA()[0]")); NameExpr name = new NameExpr("$p"); final MethodCallExpr mc = new MethodCallExpr(name, "getChildrenA", nodeList()); mc.setTypeArguments(NodeList.nodeList()); List<Node> expected = asList(name, mc, new ArrayAccessExpr(mc, new IntegerLiteralExpr(0))); compareArrays(actual, expected); }