private SourcePattern getSourcePattern(final SourceRange partRange) { String originalSource = utils.getText(partRange.getOffset(), partRange.getLength()); final SourcePattern pattern = new SourcePattern(); final List<ReplaceEdit> replaceEdits = Lists.newArrayList(); unitNode.accept( new ASTVisitor<Void>() { @Override public Void visitIdentifier(DartIdentifier node) { SourceRange nodeRange = SourceRangeFactory.create(node); if (SourceRangeUtils.covers(partRange, nodeRange)) { VariableElement variableElement = ASTNodes.getVariableOrParameterElement(node); if (variableElement != null) { String originalName = variableElement.getName(); String patternName = pattern.originalToPatternNames.get(originalName); if (patternName == null) { patternName = "__dartEditorVariable" + pattern.originalToPatternNames.size(); pattern.originalToPatternNames.put(originalName, patternName); } replaceEdits.add( new ReplaceEdit( nodeRange.getOffset() - partRange.getOffset(), nodeRange.getLength(), patternName)); } } return null; } }); pattern.patternSource = ExtractUtils.applyReplaceEdits(originalSource, replaceEdits); return pattern; }
@Override public Void visitIdentifier(DartIdentifier node) { if (foundElement == null) { int start = node.getSourceInfo().getOffset(); int length = node.getSourceInfo().getLength(); int end = start + length; if (start <= startOffset && endOffset <= end) { wordRegion = new Region(start, length); Element targetElement = DartAstUtilities.getElement(node, includeDeclarations); if (targetElement == null) { foundElement = null; } else { if (targetElement instanceof VariableElement) { VariableElement variableElement = (VariableElement) targetElement; resolvedElement = variableElement; if (variableElement.getKind() == ElementKind.PARAMETER || variableElement.getKind() == ElementKind.VARIABLE) { foundElement = BindingUtils.getDartElement(compilationUnit.getLibrary(), variableElement); candidateRegion = new Region( variableElement.getNameLocation().getOffset(), variableElement.getNameLocation().getLength()); } else { foundElement = null; } } else { findElementFor(targetElement); // Import prefix is resolved into LibraryElement, so it is correct that corresponding // DartElement is DartLibrary, but this is not what we (and user) wants, because // it looses information. We want DartImport, it gives both DartLibrary and name. if (foundElement instanceof DartLibrary) { try { DartImport[] imports = compilationUnit.getLibrary().getImports(); for (DartImport imprt : imports) { if (Objects.equal(imprt.getLibrary(), foundElement) && Objects.equal(imprt.getPrefix(), node.getName())) { foundElement = imprt; SourceRange range = imprt.getNameRange(); candidateRegion = new Region(range.getOffset(), range.getLength()); } } } catch (DartModelException e) { DartCore.logError("Cannot resolve import " + foundElement.getElementName(), e); } } } } throw new DartElementFoundException(); } } return null; }
@Override public Void visitImportDirective(DartImportDirective node) { DartLibrary library = compilationUnit.getLibrary(); try { if (Objects.equal(compilationUnit, library.getDefiningCompilationUnit())) { DartImport[] imports = library.getImports(); for (DartImport imprt : imports) { // on URI of library - return defining Unit of imported Library SourceRange uriRange = imprt.getUriRange(); if (SourceRangeUtils.contains(uriRange, startOffset)) { resolvedElement = null; foundElement = imprt.getLibrary().getDefiningCompilationUnit(); wordRegion = new Region(uriRange.getOffset(), uriRange.getLength()); candidateRegion = new Region(0, 0); throw new DartElementFoundException(); } // on #import directive - return DartImport element SourceRange sourceRange = imprt.getSourceRange(); if (SourceRangeUtils.contains(sourceRange, startOffset)) { resolvedElement = null; foundElement = imprt; wordRegion = new Region(sourceRange.getOffset(), sourceRange.getLength()); candidateRegion = new Region(sourceRange.getOffset(), sourceRange.getLength()); throw new DartElementFoundException(); } } } } catch (DartModelException e) { DartCore.logError("Cannot access imports of " + library.getElementName(), e); } return super.visitImportDirective(node); }
public final SourceRange getNewSelectionRange(SourceRange oldSourceRange, SourceReference sr) { try { DartUnit root = getAST(sr); if (root == null) { return oldSourceRange; } Selection selection = Selection.createFromStartLength(oldSourceRange.getOffset(), oldSourceRange.getLength()); SelectionAnalyzer selAnalyzer = new SelectionAnalyzer(selection, true); root.accept(selAnalyzer); return internalGetNewSelectionRange(oldSourceRange, sr, selAnalyzer); } catch (DartModelException e) { DartToolsPlugin.log(e); // dialog would be too heavy here return newSourceRange(oldSourceRange.getOffset(), oldSourceRange.getLength()); } }
/* * Method declared in IAction. */ @Override public final void run() { DartElement inputElement = EditorUtility.getEditorInputJavaElement(fEditor, false); if (!(inputElement instanceof SourceReference && inputElement.exists())) { return; } SourceReference source = (SourceReference) inputElement; SourceRange sourceRange; try { sourceRange = source.getSourceRange(); if (sourceRange == null || sourceRange.getLength() == 0) { MessageDialog.openInformation( fEditor.getEditorSite().getShell(), SelectionActionMessages.StructureSelect_error_title, SelectionActionMessages.StructureSelect_error_message); return; } } catch (DartModelException e) { } ITextSelection selection = getTextSelection(); SourceRange newRange = getNewSelectionRange(createSourceRange(selection), source); // Check if new selection differs from current selection if (selection.getOffset() == newRange.getOffset() && selection.getLength() == newRange.getLength()) { return; } fSelectionHistory.remember(newSourceRange(selection.getOffset(), selection.getLength())); try { fSelectionHistory.ignoreSelectionChanges(); fEditor.selectAndReveal(newRange.getOffset(), newRange.getLength()); } finally { fSelectionHistory.listenToSelectionChanges(); } }
/** @return the selected {@link DartExpression} source, with applying new parameter names. */ private String getMethodBodySource() { String source = utils.getText(selectionStart, selectionLength); // prepare ReplaceEdit operators to replace variables with parameters List<ReplaceEdit> replaceEdits = Lists.newArrayList(); for (Entry<String, List<SourceRange>> entry : selectionParametersToRanges.entrySet()) { String name = entry.getKey(); for (ParameterInfo parameter : parameters) { if (StringUtils.equals(name, parameter.getOldName())) { for (SourceRange range : entry.getValue()) { replaceEdits.add( new ReplaceEdit( range.getOffset() - selectionStart, range.getLength(), parameter.getNewName())); } } } } // apply replacements source = ExtractUtils.applyReplaceEdits(source, replaceEdits); // change indentation if (selectionStatements != null) { String eol = utils.getEndOfLine(); String selectionIndent = utils.getNodePrefix(selectionStatements.get(0)); String targetIndent = utils.getNodePrefix(parentMember) + " "; String[] lines = StringUtils.splitPreserveAllTokens(source, eol); StringBuilder sb = new StringBuilder(); for (int i = 0; i < lines.length; i++) { String line = lines[i]; line = targetIndent + StringUtils.removeStart(line, selectionIndent); sb.append(line); sb.append(eol); } source = sb.toString(); source = StringUtils.stripEnd(source, null); source += eol; } // done return source; }
/** * Given a compiler element representing some portion of the code base, set {@link #foundElement} * to the editor model element that corresponds to it. * * @param targetSymbol the compiler element representing some portion of the code base */ private void findElementFor(Element targetSymbol) { if (targetSymbol == null) { return; } LibraryElement definingLibraryElement = BindingUtils.getLibrary(targetSymbol); DartLibrary definingLibrary = null; if (definingLibraryElement != null) { definingLibrary = BindingUtils.getDartElement(compilationUnit.getLibrary(), definingLibraryElement); } if (definingLibrary == null) { definingLibrary = compilationUnit.getLibrary(); } resolvedElement = targetSymbol; foundElement = BindingUtils.getDartElement(definingLibrary, targetSymbol); if (foundElement instanceof SourceReference) { try { SourceRange range = ((SourceReference) foundElement).getNameRange(); candidateRegion = new Region(range.getOffset(), range.getLength()); } catch (DartModelException exception) { // Ignored } } }
private static IRegion createRegion(SourceRange range) { return new Region(range.getOffset(), range.getLength()); }
@Override public Change createChange(IProgressMonitor pm) throws CoreException { pm.beginTask("", 1 + occurrences.size()); // $NON-NLS-1$ try { // configure Change { change = new CompilationUnitChange(unit.getElementName(), unit); change.setEdit(new MultiTextEdit()); change.setKeepPreviewEdits(true); } // replace occurrences with method invocation for (Occurrence occurence : occurrences) { pm.worked(1); SourceRange range = occurence.range; // may be replacement of duplicates disabled if (!replaceAllOccurrences && !occurence.isSelection) { continue; } // prepare invocation source String invocationSource; { StringBuilder sb = new StringBuilder(); // may be returns value if (returnVariable != null) { String varTypeName = ExtractUtils.getTypeSource(returnVariable.getType()); String originalName = returnVariable.getName(); String occurrenceName = occurence.parameterOldToOccurrenceName.get(originalName); if (varTypeName.equals("dynamic")) { sb.append("var "); } else { sb.append(varTypeName); sb.append(" "); } sb.append(occurrenceName); sb.append(" = "); } // invocation itself sb.append(methodName); sb.append("("); boolean firstParameter = true; for (ParameterInfo parameter : parameters) { // may be comma if (firstParameter) { firstParameter = false; } else { sb.append(", "); } // argument name { String parameterOldName = parameter.getOldName(); String argumentName = occurence.parameterOldToOccurrenceName.get(parameterOldName); sb.append(argumentName); } } sb.append(")"); invocationSource = sb.toString(); // statements as extracted with their ";", so add new one after invocation if (selectionStatements != null) { invocationSource += ";"; } } // add replace edit TextEdit edit = new ReplaceEdit(range.getOffset(), range.getLength(), invocationSource); change.addEdit(edit); String msg = Messages.format( occurence.isSelection ? RefactoringCoreMessages.ExtractMethodRefactoring_substitute_with_call : RefactoringCoreMessages.ExtractMethodRefactoring_duplicates_single, methodName); change.addTextEditGroup(new TextEditGroup(msg, edit)); } // add method declaration { // prepare environment String prefix = utils.getNodePrefix(parentMember); String eol = utils.getEndOfLine(); // prepare annotations String annotations = ""; { // may be "static" if (staticContext) { annotations = "static "; } } // prepare declaration source String declarationSource = null; { String returnExpressionSource = getMethodBodySource(); // expression if (selectionExpression != null) { // add return type String returnTypeName = ExtractUtils.getTypeSource(selectionExpression); if (returnTypeName != null && !returnTypeName.equals("dynamic")) { annotations += returnTypeName + " "; } // just return expression declarationSource = annotations + getSignature() + " => " + returnExpressionSource + ";"; } // statements if (selectionStatements != null) { if (returnVariable != null) { String returnTypeName = ExtractUtils.getTypeSource(returnVariable.getType()); if (returnTypeName != null && !returnTypeName.equals("dynamic")) { annotations += returnTypeName + " "; } } else { annotations += "void "; } declarationSource = annotations + getSignature() + " {" + eol; declarationSource += returnExpressionSource; if (returnVariable != null) { declarationSource += prefix + " return " + returnVariable.getName() + ";" + eol; } declarationSource += prefix + "}"; } } // insert declaration if (declarationSource != null) { int offset = parentMember.getSourceInfo().getEnd(); TextEdit edit = new ReplaceEdit(offset, 0, eol + eol + prefix + declarationSource); change.addEdit(edit); change.addTextEditGroup( new TextEditGroup( Messages.format( selectionExpression != null ? RefactoringCoreMessages.ExtractMethodRefactoring_add_method_expression : RefactoringCoreMessages.ExtractMethodRefactoring_add_method, methodName), edit)); } } pm.worked(1); // done return change; } finally { pm.done(); } }