@Override public void setInput(RefactoringStatusContext context) { if (context instanceof DartStatusContext) { DartStatusContext jsc = (DartStatusContext) context; IDocument document = null; { CompilationUnit cunit = jsc.getCompilationUnit(); if (cunit.isWorkingCopy()) { try { document = newDocument(cunit.getSource()); } catch (DartModelException e) { // document is null which is a valid input. } } else { IEditorInput editorInput = new FileEditorInput((IFile) cunit.getResource()); document = getDocument( DartToolsPlugin.getDefault().getCompilationUnitDocumentProvider(), editorInput); } if (document == null) { document = new Document(RefactoringMessages.DartStatusContextViewer_no_source_available); } updateTitle(cunit); } setInput(document, createRegion(jsc.getSourceRange())); } else if (context instanceof DartStringStatusContext) { updateTitle(null); DartStringStatusContext sc = (DartStringStatusContext) context; setInput(newDocument(sc.getSource()), createRegion(sc.getSourceRange())); } }
/** * Parse the source for the specified compilation unit. Any exceptions thrown by the {@link * DartParser} will be logged and a {@link DartModelException} thrown. * * @param compilationUnit the compilation unit (not <code>null</code>) * @param parseErrors a collection to which parse errors are appended or <code>null</code> if * parse errors should be ignored * @return the parse result */ public static DartUnit parseUnit( CompilationUnit compilationUnit, Collection<DartCompilationError> parseErrors) throws DartModelException { String name = compilationUnit.getElementName(); String source = compilationUnit.getSource(); return parseSource(name, source, parseErrors); }
/** Test for {@link DartFunction#isGlobal()} and {@link DartFunction#isLocal()}. */ public void test_isGlobal_isLocal() throws Exception { TestProject testProject = new TestProject("Test"); try { CompilationUnit unit = testProject.setUnitContent( "Test.dart", Joiner.on("\n") .join( "// filler filler filler filler filler filler filler filler filler filler", "f() {", " v() {};", "}", "")); // global function DartFunction globalFunction = (DartFunction) unit.getChildren()[0]; assertTrue(globalFunction.isGlobal()); assertFalse(globalFunction.isLocal()); // local functions DartElement[] functions = globalFunction.getChildren(); assertThat(functions).hasSize(1); // v { DartFunction f = (DartFunction) functions[0]; assertFalse(f.isGlobal()); assertTrue(f.isLocal()); } } finally { testProject.dispose(); } }
/** Initialize this index with information from the user libraries. */ private boolean indexUserLibraries() { boolean librariesIndexed = true; try { AnalysisServer analysisServer = PackageLibraryManagerProvider.getDefaultAnalysisServer(); SavedContext savedContext = analysisServer.getSavedContext(); DartModel model = DartCore.create(ResourcesPlugin.getWorkspace().getRoot()); for (DartProject project : model.getDartProjects()) { for (DartLibrary library : project.getDartLibraries()) { CompilationUnit compilationUnit = library.getDefiningCompilationUnit(); if (compilationUnit == null) { continue; } IResource libraryResource = compilationUnit.getResource(); if (libraryResource == null) { continue; } IPath libraryLocation = libraryResource.getLocation(); if (libraryLocation == null) { continue; } File libraryFile = libraryLocation.toFile(); savedContext.resolve(libraryFile, null); } } } catch (Exception exception) { librariesIndexed = false; DartCore.logError("Could not index user libraries", exception); } return librariesIndexed; }
private boolean isValidSelectedFile() { if (selectedFile == null) { return false; } if (!DartCore.isDartLikeFileName(selectedFile.getName())) { return false; } DartElement element = DartCore.create(selectedFile); if (element instanceof CompilationUnit) { CompilationUnit cu = (CompilationUnit) element; DartLibrary lib = cu.getLibrary(); if (lib instanceof DartLibraryImpl) { DartLibraryImpl impl = (DartLibraryImpl) lib; return impl.hasMain() && !impl.isBrowserApplication(); } } return false; }
@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 visitStringLiteral(DartStringLiteral node) { if (foundElement == null) { int start = node.getSourceInfo().getOffset(); int length = node.getSourceInfo().getLength(); int end = start + length; if (end == 0) { return null; } if (start <= startOffset && end >= endOffset) { wordRegion = computeInternalStringRegion(start, length); DartNode parent = node.getParent(); if (parent instanceof DartSourceDirective && ((DartSourceDirective) parent).getSourceUri() == node) { // resolvedElement = ((DartSourceDirective) parent).getElement(); DartLibrary library = compilationUnit.getLibrary(); String fileName = getFileName(library, node.getValue()); CompilationUnit sourcedUnit = library.getCompilationUnit(fileName); if (sourcedUnit != null && sourcedUnit.exists()) { foundElement = sourcedUnit; } } else if (parent instanceof DartResourceDirective && ((DartResourceDirective) parent).getResourceUri() == node) { // resolvedElement = ((DartResourceDirective) parent).getElement(); DartLibrary library = compilationUnit.getLibrary(); try { DartSource unitSource = compilationUnit.getSourceRef(); if (unitSource != null) { LibrarySource librarySource = unitSource.getLibrary(); if (librarySource != null) { DartSource resourceSource = librarySource.getSourceFor(node.getValue()); if (resourceSource != null) { URI resourceUri = resourceSource.getUri(); DartResource resource = library.getResource(resourceUri); if (resource != null && resource.exists()) { foundElement = resource; } } } } } catch (DartModelException exception) { foundElement = null; } } throw new DartElementFoundException(); } } return null; }
/** Test for {@link DartFunction#getVisibleRange()} for local functions. */ public void test_getVisibleRange() throws Exception { TestProject testProject = new TestProject("Test"); try { CompilationUnit unit = testProject.setUnitContent( "Test.dart", Joiner.on("\n") .join( "// filler filler filler filler filler filler filler filler filler filler", "f() {", " v1() {};", " {", " v2() {};", " }//marker1", " v3() {};", "}//marker2", "")); String source = unit.getSource(); DartFunction globalFunction = (DartFunction) unit.getChildren()[0]; DartElement[] functions = globalFunction.getChildren(); assertThat(functions).hasSize(3); // v1 { DartFunction f = (DartFunction) functions[0]; SourceRange range = f.getVisibleRange(); assertEquals("v1", f.getElementName()); assertEquals(source.indexOf("v1"), range.getOffset()); assertEquals(source.indexOf("marker2") - 1, range.getOffset() + range.getLength()); } // v2 { DartFunction f = (DartFunction) functions[1]; SourceRange range = f.getVisibleRange(); assertEquals("v2", f.getElementName()); assertEquals(source.indexOf("v2"), range.getOffset()); assertEquals(source.indexOf("marker1") - 1, range.getOffset() + range.getLength()); } // v3 { DartFunction f = (DartFunction) functions[2]; SourceRange range = f.getVisibleRange(); assertEquals("v3", f.getElementName()); assertEquals(source.indexOf("v3"), range.getOffset()); assertEquals(source.indexOf("marker2") - 1, range.getOffset() + range.getLength()); } } finally { testProject.dispose(); } }
/** Checks if created method will shadow or will be shadowed by other elements. */ private RefactoringStatus checkPossibleConflicts(IProgressMonitor pm) throws CoreException { List<SearchMatch> references = Lists.newArrayList(); // top-level function if (parentMember.getParent() instanceof DartUnit) { RefactoringStatus conflictsStatus = RenameTopLevelProcessor.analyzePossibleConflicts( unit.getLibrary(), DartElement.FUNCTION, false, references, methodName); if (!conflictsStatus.isOK()) { return convertRenameToCreateStatus(conflictsStatus); } } // method of class if (parentMember.getParent() instanceof DartClass) { ClassElement enclosingClassElement = (ClassElement) parentMember.getParent().getElement(); Type enclosingType = (Type) BindingUtils.getDartElement(enclosingClassElement); RefactoringStatus conflictsStatus = RenameTypeMemberProcessor.analyzePossibleConflicts( DartElement.FUNCTION, enclosingType, methodName, references, methodName, pm); if (!conflictsStatus.isOK()) { return convertRenameToCreateStatus(conflictsStatus); } } // OK return new RefactoringStatus(); }
@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); }
/** Attempts to find {@link DartElement} at the <code>offset</code> position. */ @SuppressWarnings("unchecked") protected static <T extends DartElement> T findElement(CompilationUnit unit, int offset) throws Exception { DartElement[] elements = unit.codeSelect(offset, 0); assertThat(elements).hasSize(1); return (T) elements[0]; }
/** * Compute a region that represents the portion of the string literal between the opening and * closing quotes. * * @param nodeStart the index of the first character of the string literal * @param nodeLength the length of the string literal (including quotes) * @return the region that was computed */ private IRegion computeInternalStringRegion(int nodeStart, int nodeLength) { int start = nodeStart; int end = nodeStart + nodeLength - 1; try { String source = compilationUnit.getBuffer().getContents(); if (source.charAt(start) == '@') { start++; } if (source.charAt(start) == '\'') { while (source.charAt(start) == '\'') { start++; } while (source.charAt(end) == '\'') { end--; } } else { while (source.charAt(start) == '"') { start++; } while (source.charAt(end) == '"') { end--; } } } catch (DartModelException exception) { } if (start >= end) { return new Region(nodeStart, nodeLength); } return new Region(start, end - start + 1); }
/** * Return the existing document for the given compilation unit, or a DocumentAdapter if none. * * @return the existing document for the given compilation unit */ protected IDocument getDocument(CompilationUnit cu) throws DartModelException { Buffer buffer = cu.getBuffer(); if (buffer instanceof IDocument) { return (IDocument) buffer; } return new DocumentAdapter(buffer); }
private DartElement getEnclosingMethod(CompilationUnit input, ITextSelection selection) { try { DartElement enclosingElement = input.getElementAt(selection.getOffset()); if (enclosingElement instanceof Method || enclosingElement instanceof Field) { // opening on the enclosing type would be too confusing (since the type resolves to the // constructors) return enclosingElement; } } catch (DartModelException e) { DartToolsPlugin.log(e); } return null; }
/** * Parse the source for the specified compilation unit and resolve any elements found in it. Any * exceptions thrown by the {@link DartParser} will be added to the given collection. * * @param compilationUnit the compilation unit (not <code>null</code>) * @param parseErrors a collection to which parse errors are added or <code>null</code> if parse * errors should be ignored * @return the parse result */ public static DartUnit resolveUnit( CompilationUnit compilationUnit, Collection<DartCompilationError> parseErrors) throws DartModelException { long start = System.currentTimeMillis(); DartLibraryImpl library = (DartLibraryImpl) compilationUnit.getLibrary(); if (library == null) { // If we cannot get the library, we cannot resolve any elements so we // revert to simply parsing the compilation unit. DartUnit ret = parseUnit(compilationUnit, parseErrors); long elapsed = System.currentTimeMillis() - start; Instrumentation.metric("DartCompilerUtils-resolveUnit", elapsed) .with("ParseOnlyFallback", "true") .log(); Instrumentation.operation("DartCompilerUtils-resolveUnit", elapsed) .with("ParseOnlyFallback", "true") .with("CompilaitonUnit-ElementName", compilationUnit.getElementName()) .log(); return ret; } IResource resource = compilationUnit.getResource(); URI unitUri = null; if (resource != null) { unitUri = resource.getLocationURI(); } if (unitUri == null && compilationUnit instanceof ExternalCompilationUnitImpl) { unitUri = ((ExternalCompilationUnitImpl) compilationUnit).getUri(); } if (unitUri == null) { unitUri = ((CompilationUnitImpl) compilationUnit).getSourceRef().getUri(); } String unitSource = compilationUnit.getSource(); Map<URI, String> suppliedSources = new HashMap<URI, String>(); if (unitSource != null) { suppliedSources.put(unitUri, unitSource); } DartUnit ret = resolveUnit(library.getLibrarySourceFile(), unitUri, suppliedSources, parseErrors); long elapsed = System.currentTimeMillis() - start; Instrumentation.metric("DartCompilerUtils-resolveUnit", elapsed) .with("ParseOnlyFallback", "false") .log(); Instrumentation.operation("DartCompilerUtils-resolveUnit", elapsed) .with("ParseOnlyFallback", "false") .with("CompilaitonUnit-ElementName", compilationUnit.getElementName()) .with("compilationUnit.LastModified", compilationUnit.getModificationStamp()) .log(); return ret; }
/** * 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 } } }
/** * Search within the given AST node for an identifier representing a {@link DartElement Dart * element} in the specified source range. Return the element that was found, or <code>null</code> * if no element was found. * * @param node the AST node within which to search * @return the element that was found */ public DartElement searchWithin(DartNode node) { try { node.accept(this); } catch (DartElementFoundException exception) { // A node with the right source position was found. } catch (Exception exception) { DartCore.logInformation( "Unable to locate element at offset (" + startOffset + " - " + endOffset + ") in " + compilationUnit.getElementName(), exception); return null; } return foundElement; }
/** * Compute a region representing the portion of the source containing a binary operator. * * @param left the index of the first character to the right of the left operand * @param right the index of the first character to the left of the right operand * @return the region that was computed */ private IRegion computeOperatorRegion(int left, int right) { int start = left; int end = right; try { String source = compilationUnit.getBuffer().getContents(); // TODO(brianwilkerson) This doesn't handle comments that occur between left and right, but // should. while (Character.isWhitespace(source.charAt(start))) { start++; } while (Character.isWhitespace(source.charAt(end))) { end--; } } catch (DartModelException exception) { } if (start > end) { return new Region(left, right - left + 1); } return new Region(start, end - start + 1); }
private void acceptPotentialMethodDeclaration(CompletionProposal proposal) { try { DartElement enclosingElement = null; if (getContext().isExtended()) { enclosingElement = getContext().getEnclosingElement(); } else if (fCompilationUnit != null) { enclosingElement = fCompilationUnit.getElementAt(proposal.getCompletionLocation() + 1); } if (enclosingElement == null) { return; } Type type = enclosingElement.getAncestor(Type.class); if (type != null) { String prefix = String.valueOf(proposal.getName()); int completionStart = proposal.getReplaceStart(); int completionEnd = proposal.getReplaceEnd(); int relevance = computeRelevance(proposal); GetterSetterCompletionProposal.evaluateProposals( type, prefix, completionStart, completionEnd - completionStart, proposal.getReplaceEndIdentifier() - completionStart, relevance + 2, fSuggestedMethodNames, fDartProposals); MethodDeclarationCompletionProposal.evaluateProposals( type, prefix, completionStart, completionEnd - completionStart, proposal.getReplaceEndIdentifier() - completionStart, relevance, fSuggestedMethodNames, fDartProposals); } } catch (CoreException e) { DartToolsPlugin.log(e); } }
/** @return the offset of given <code>search</code> string. Fails test if not found. */ protected static int findOffset(CompilationUnit unit, String search) throws Exception { String source = unit.getSource(); int offset = source.indexOf(search); assertThat(offset).describedAs(source).isNotEqualTo(-1); return offset; }
/** * Creates a new instance ready to collect proposals. If the passed <code>CompilationUnit</code> * is not contained in an {@link DartProject}, no Dart doc will be available as {@link * org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() additional * info} on the created proposals. * * @param cu the compilation unit that the result collector will operate on * @param ignoreAll <code>true</code> to ignore all kinds of completion proposals */ public CompletionProposalCollector(CompilationUnit cu, boolean ignoreAll) { this(cu == null ? null : cu.getDartProject(), cu, ignoreAll); // TODO Remove getDartProject() }
@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(); } }
/** Asserts that {@link CompilationUnit} has expected content. */ protected static void assertUnitContent(CompilationUnit unit, String... lines) throws Exception { assertEquals(makeSource(lines), unit.getSource()); }
/** Prints lines of code to insert into {@link #assertUnitContent(String...)}. */ protected static void printUnitLinesSource(CompilationUnit unit) throws Exception { String source = unit.getSource(); Iterable<String> lines = Splitter.on('\n').split(source); System.out.println(getLinesForSource(lines)); }
/** * Creates a new instance ready to collect proposals. If the passed <code>CompilationUnit</code> * is not contained in an {@link DartProject}, no Dart doc will be available as {@link * org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() additional * info} on the created proposals. * * @param cu the compilation unit that the result collector will operate on */ public CompletionProposalCollector(CompilationUnit cu) { this(cu.getDartProject(), cu, false); }