private boolean callsWritingConstructor( MethodDeclaration methodDeclaration, HashSet writingConstructorBindings, Set visitedMethodDeclarations) { Block body = methodDeclaration.getBody(); if (body == null) return false; List statements = body.statements(); if (statements.size() == 0) return false; Statement statement = (Statement) statements.get(0); if (!(statement instanceof ConstructorInvocation)) return false; ConstructorInvocation invocation = (ConstructorInvocation) statement; IMethodBinding constructorBinding = invocation.resolveConstructorBinding(); if (constructorBinding == null) return false; if (writingConstructorBindings.contains(constructorBinding)) { return true; } else { ASTNode declaration = ASTNodes.findDeclaration(constructorBinding, methodDeclaration.getParent()); if (!(declaration instanceof MethodDeclaration)) return false; if (visitedMethodDeclarations.contains(declaration)) { return false; } visitedMethodDeclarations.add(methodDeclaration); return callsWritingConstructor( (MethodDeclaration) declaration, writingConstructorBindings, visitedMethodDeclarations); } }
@Override public void run(IProgressMonitor monitor) throws CoreException { if (monitor == null) monitor = new NullProgressMonitor(); try { monitor.beginTask("", 1); // $NON-NLS-1$ monitor.setTaskName(CodeGenerationMessages.GenerateToStringOperation_description); AbstractTypeDeclaration declaration = (AbstractTypeDeclaration) ASTNodes.findDeclaration(fContext.getTypeBinding(), fRewrite.getRoot()); ListRewrite rewriter = fRewrite .getASTRewrite() .getListRewrite(declaration, declaration.getBodyDeclarationsProperty()); if (fContext.getTypeBinding() != null && rewriter != null) { MethodDeclaration toStringMethod = fGenerator.generateToStringMethod(); List<BodyDeclaration> list = declaration.bodyDeclarations(); BodyDeclaration replace = findMethodToReplace(list, toStringMethod); if (replace == null || ((Boolean) toStringMethod.getProperty(AbstractToStringGenerator.OVERWRITE_METHOD_PROPERTY)) .booleanValue()) insertMethod(toStringMethod, rewriter, replace); List<MethodDeclaration> helperMethods = fGenerator.generateHelperMethods(); for (Iterator<MethodDeclaration> iterator = helperMethods.iterator(); iterator.hasNext(); ) { MethodDeclaration method = iterator.next(); replace = findMethodToReplace(list, method); if (replace == null || ((Boolean) method.getProperty(AbstractToStringGenerator.OVERWRITE_METHOD_PROPERTY)) .booleanValue()) { insertMethod(method, rewriter, replace); } } JavaModelUtil.applyEdit( (ICompilationUnit) fUnit.getJavaElement(), fRewrite.createChange(true).getEdit(), false, monitor); } } finally { monitor.done(); } }
private void computeOutput(RefactoringStatus status) { // First find all writes inside the selection. FlowContext flowContext = new FlowContext(0, fMaxVariableId + 1); flowContext.setConsiderAccessMode(true); flowContext.setComputeMode(FlowContext.RETURN_VALUES); FlowInfo returnInfo = new InOutFlowAnalyzer(flowContext).perform(getSelectedNodes()); IVariableBinding[] returnValues = returnInfo.get(flowContext, FlowInfo.WRITE | FlowInfo.WRITE_POTENTIAL | FlowInfo.UNKNOWN); // Compute a selection that exactly covers the selected nodes IRegion region = getSelectedNodeRange(); Selection selection = Selection.createFromStartLength(region.getOffset(), region.getLength()); List<IVariableBinding> localReads = new ArrayList<>(); flowContext.setComputeMode(FlowContext.ARGUMENTS); FlowInfo argInfo = new InputFlowAnalyzer(flowContext, selection, true).perform(fEnclosingBodyDeclaration); IVariableBinding[] reads = argInfo.get(flowContext, FlowInfo.READ | FlowInfo.READ_POTENTIAL | FlowInfo.UNKNOWN); outer: for (int i = 0; i < returnValues.length && localReads.size() < returnValues.length; i++) { IVariableBinding binding = returnValues[i]; for (int x = 0; x < reads.length; x++) { if (reads[x] == binding) { localReads.add(binding); fReturnValue = binding; continue outer; } } } switch (localReads.size()) { case 0: fReturnValue = null; break; case 1: break; default: fReturnValue = null; StringBuffer affectedLocals = new StringBuffer(); for (int i = 0; i < localReads.size(); i++) { IVariableBinding binding = localReads.get(i); String bindingName = BindingLabelProvider.getBindingLabel( binding, BindingLabelProvider.DEFAULT_TEXTFLAGS | JavaElementLabels.F_PRE_TYPE_SIGNATURE); affectedLocals.append(bindingName); if (i != localReads.size() - 1) { affectedLocals.append('\n'); } } String message = MessageFormat.format( RefactoringCoreMessages.ExtractMethodAnalyzer_assignments_to_local, new Object[] {affectedLocals.toString()}); status.addFatalError(message, JavaStatusContext.create(fCUnit, getSelection())); return; } List<IVariableBinding> callerLocals = new ArrayList<>(5); FlowInfo localInfo = new InputFlowAnalyzer(flowContext, selection, false).perform(fEnclosingBodyDeclaration); IVariableBinding[] writes = localInfo.get(flowContext, FlowInfo.WRITE | FlowInfo.WRITE_POTENTIAL | FlowInfo.UNKNOWN); for (int i = 0; i < writes.length; i++) { IVariableBinding write = writes[i]; if (getSelection().covers(ASTNodes.findDeclaration(write, fEnclosingBodyDeclaration))) callerLocals.add(write); } fCallerLocals = callerLocals.toArray(new IVariableBinding[callerLocals.size()]); if (fReturnValue != null && getSelection().covers(ASTNodes.findDeclaration(fReturnValue, fEnclosingBodyDeclaration))) fReturnLocal = fReturnValue; }