FragmentVariableInfos (@NotNull final GrStatement first, @NotNull final GrStatement last, @NotNull final GrControlFlowOwner flowOwner, @NotNull GroovyControlFlow flow) { final Int2ObjectMap<int[]> dfaResult = inferDfaResult(flow.getFlow()); final LinkedHashSet<Integer> fragmentInstructions = getFragmentInstructions(first, last, flow.getFlow()); final int[] postorder = reversedPostOrder(flow.getFlow()); LinkedHashSet<Integer> reachableFromFragmentReads = getReachable(fragmentInstructions, flow.getFlow(), dfaResult, postorder); LinkedHashSet<Integer> fragmentReads = filterReads(fragmentInstructions, flow.getFlow()); final Map<String, VariableInfo> imap = new LinkedHashMap<>(); final Map<String, VariableInfo> omap = new LinkedHashMap<>(); final PsiManager manager = first.getManager(); for (final Integer ref : fragmentReads) { ReadWriteVariableInstruction rwInstruction = (ReadWriteVariableInstruction)flow.getFlow()[ref]; final int[] defs = dfaResult.get((int)ref); assert defs != null; int descriptorId = rwInstruction.getDescriptor(); VariableDescriptor descriptor = flow.getVarIndices()[descriptorId]; if (!allDefsInFragment(defs, fragmentInstructions) || isLocallyDeclaredOutOf(rwInstruction.getElement(), descriptor, flowOwner)) { addVariable(descriptor.getName(), imap, manager, getType(rwInstruction.getElement())); } } Set<Integer> outerBound = getFragmentOuterBound(fragmentInstructions, flow.getFlow()); for (final Integer ref : reachableFromFragmentReads) { ReadWriteVariableInstruction rwInstruction = (ReadWriteVariableInstruction)flow.getFlow()[ref]; int descriptorId = rwInstruction.getDescriptor(); VariableDescriptor descriptor = flow.getVarIndices()[descriptorId]; final int[] defs = dfaResult.get((int)ref); assert defs != null; if (anyDefInFragment(defs, fragmentInstructions)) { for (int insnNum : outerBound) { addVariable(descriptor.getName(), omap, manager, getVariableTypeAt(flowOwner, flow.getFlow()[insnNum], descriptorId, descriptor)); } if (!allProperDefsInFragment(defs, ref, fragmentInstructions, postorder)) { PsiType inputType = getType(rwInstruction.getElement()); addVariable(descriptor.getName(), imap, manager, inputType); } } } addClosureUsages(imap, omap, first, last, flowOwner); return new FragmentVariableInfos() { @Override public VariableInfo[] getInputVariableNames() { return imap.values().toArray(VariableInfo.EMPTY_ARRAY); } @Override public VariableInfo[] getOutputVariableNames() { return omap.values().toArray(VariableInfo.EMPTY_ARRAY); } }; }