code: void analyze(JCStatement statement, Env<AttrContext> env) {
          AnalysisContext context = new AnalysisContext();
          StatementScanner statementScanner = new StatementScanner(context);
          statementScanner.scan(statement);
  
          if (!context.treesToAnalyzer.isEmpty()) {
  
              //add a block to hoist potential dangling variable declarations
              JCBlock fakeBlock = make.Block(SYNTHETIC, List.of(statement));
  
              TreeMapper treeMapper = new TreeMapper(context);
              //TODO: to further refine the analysis, try all rewriting combinations
              deferredAttr.attribSpeculative(fakeBlock, env, attr.statInfo, treeMapper,
                      t -> new AnalyzeDeferredDiagHandler(context),
                      argumentAttr.withLocalCacheContext());
              context.treeMap.entrySet().forEach(e -> {
                  context.treesToAnalyzer.get(e.getKey())
                          .process(e.getKey(), e.getValue(), context.errors.nonEmpty());
              });
          }
      }
docs: Analyze an AST node; this involves collecting a list of all the nodes that needs rewriting,
  and speculatively type-check the rewritten code to compare results against previously attributed code.