public DeclarationLocation getLocation() { PythonTree node = element.getNode(); int lineOffset = node != null ? node.getCharStartIndex() : -1; DeclarationLocation loc = new DeclarationLocation(element.getFileObject(), lineOffset, element); return loc; }
public DeclarationLocation getSuperImplementations(PythonParserResult info, int lexOffset) { // Figure out if we're on a method, and if so, locate the nearest // method it is overriding. // Otherwise, if we're on a class (anywhere, not just definition), // go to the super class. PythonTree root = PythonAstUtils.getRoot(info); if (root != null) { // Determine function or call under caret int astOffset = PythonAstUtils.getAstOffset(info, lexOffset); if (astOffset != -1) { AstPath path = AstPath.get(root, astOffset); PythonTree leaf = path.leaf(); String name = null; boolean findClass = false; // false=function, true=class if (leaf instanceof FunctionDef) { name = ((FunctionDef) leaf).getInternalName(); } else if (leaf instanceof Name) { name = ((Name) leaf).getInternalId(); if (path.leafParent() instanceof ClassDef) { findClass = true; } } else if (leaf instanceof ClassDef) { name = ((ClassDef) leaf).getInternalName(); findClass = true; } Set<IndexedElement> elements = null; PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject()); if (findClass) { elements = index.getSuperClasses(name); } else { ClassDef clz = PythonAstUtils.getClassDef(path); if (clz != null) { elements = index.getOverridingMethods(clz.getInternalName(), name); } } if (elements != null && elements.size() > 0) { // Pick the closest element as the default candidate IndexedElement candidate = null; int depth = Integer.MAX_VALUE; for (IndexedElement element : elements) { if (element.getOrder() < depth) { candidate = element; depth = element.getOrder(); } } return getDeclarationLocation(info, candidate, elements); } } } return DeclarationLocation.NONE; }
public int compareTo(AlternativeLocation alternative) { PythonAltLocation alt = (PythonAltLocation) alternative; // The preferred item should be chosen if (isPreferred) { return -1; } else if (alt.isPreferred) { return 1; } // Can't both be so no else == check if (order != alt.order) { return order - alt.order; } // Nodoced items last if (element.isNoDoc() != alt.element.isNoDoc()) { return element.isNoDoc() ? 1 : -1; } // Documented items on top if (element.isDocumented() != alt.element.isDocumented()) { return element.isDocumented() ? -1 : 1; } // TODO: Sort by classes? String thisClz = element.getClz() != null ? element.getClz() : ""; String thatClz = alt.element.getClz() != null ? alt.element.getClz() : ""; int cmp = thisClz.compareTo(thatClz); if (cmp != 0) { return cmp; } // TODO: Sort by gem? // Sort by containing clz - just do fqn here? String thisIn = element.getIn() != null ? element.getIn() : ""; String thatIn = alt.element.getIn() != null ? alt.element.getIn() : ""; cmp = thisIn.compareTo(thatIn); if (cmp != 0) { return cmp; } // Sort by file String thisFile = element.getFileObject() != null ? element.getFileObject().getNameExt() : ""; String thatFile = alt.element.getFileObject() != null ? alt.element.getFileObject().getNameExt() : ""; cmp = thisFile.compareTo(thatFile); return cmp; }
private DeclarationLocation getDeclarationLocation( PythonParserResult info, IndexedElement candidate, Set<? extends IndexedElement> methods) { BaseDocument doc = (BaseDocument) info.getSnapshot().getSource().getDocument(false); if (doc == null) { return DeclarationLocation.NONE; } if (candidate != null) { FileObject fileObject = candidate.getFileObject(); if (fileObject == null) { return DeclarationLocation.NONE; } PythonTree node = candidate.getNode(); int nodeOffset = 0; if (node != null) { nodeOffset = PythonAstUtils.getNameRange(info, node).getStart(); } DeclarationLocation loc = new DeclarationLocation(fileObject, nodeOffset, candidate); if (PythonUtils.isRstFile(fileObject)) { loc.setInvalidMessage( NbBundle.getMessage( PythonDeclarationFinder.class, "BuiltinPython", candidate.getName())); return loc; } if (methods.size() > 1) { // Could the :nodoc: alternatives: if there is only one nodoc'ed alternative // don't ask user! int not_nodoced = 0; for (final IndexedElement mtd : methods) { if (!mtd.isNoDoc()) { not_nodoced++; } } if (not_nodoced >= 2) { for (final IndexedElement mtd : methods) { loc.addAlternative(new PythonAltLocation(mtd, mtd == candidate)); } } } return loc; } return DeclarationLocation.NONE; }
/** * Compute the declaration location for a test string (such as MosModule::TestBaz/test_qux). * * @param fileInProject a file in the project where to perform the search * @param testString a string represening a test class and method, such as TestFoo/test_bar * @param classLocation if true, returns the location of the class rather then the method. */ public static DeclarationLocation getTestDeclaration( FileObject fileInProject, String testString, boolean classLocation) { int methodIndex = testString.indexOf('/'); // NOI18N if (methodIndex == -1) { return DeclarationLocation.NONE; } String className = testString.substring(0, methodIndex); String methodName = testString.substring(methodIndex + 1); PythonIndex index = PythonIndex.get(fileInProject); Set<IndexedElement> elements = index.getAllMembers(methodName, QuerySupport.Kind.EXACT, null, true); // Look for one that matches our class name if (elements.size() > 0) { IndexedElement candidate = null; for (IndexedElement element : elements) { if (element instanceof IndexedMethod) { IndexedMethod method = (IndexedMethod) element; if (className.startsWith(method.getModule() + ".")) { // Close! candidate = method; if (className.equals(method.getModule() + "." + method.getClz())) { break; } } } } if (candidate != null) { int offset = 0; PythonTree node = candidate.getNode(); if (node != null) { offset = PythonAstUtils.getRange(node).getStart(); } return new DeclarationLocation(candidate.getFileObject(), offset); } } return DeclarationLocation.NONE; }
private IndexedElement findBestMatch( PythonParserResult info, String name, Set<? extends IndexedElement> methodSet, BaseDocument doc, int astOffset, int lexOffset, AstPath path, PythonTree call, PythonIndex index) { // Make sure that the best fit method actually has a corresponding valid source location // and parse tree Set<IndexedElement> methods = new HashSet<IndexedElement>(methodSet); while (!methods.isEmpty()) { IndexedElement method = findBestMatchHelper(info, name, methods, doc, astOffset, lexOffset, path, call, index); PythonTree node = method.getNode(); if (node != null) { return method; } if (!methods.contains(method)) { // Avoid infinite loop when we somehow don't find the node for // the best method and we keep trying it methods.remove(methods.iterator().next()); } else { methods.remove(method); } } // Dynamic methods that don't have source (such as the TableDefinition methods "binary", // "boolean", etc. if (methodSet.size() > 0) { return methodSet.iterator().next(); } return null; }
public String getDisplayHtml(HtmlFormatter formatter) { formatter.setMaxLength(120); if (cachedDisplayItem == null) { formatter.reset(); boolean nodoc = element.isNoDoc(); boolean documented = element.isDocumented(); if (isPreferred) { formatter.emphasis(true); } else if (nodoc) { formatter.deprecated(true); } if (element instanceof IndexedMethod) { // if (element.getFqn() != null) { // formatter.appendText(element.getFqn()); // formatter.appendText("."); // } formatter.appendText(element.getName()); IndexedMethod method = (IndexedMethod) element; String[] parameters = method.getParams(); if ((parameters != null) && (parameters.length > 0)) { formatter.appendText("("); // NOI18N boolean first = true; for (String parameter : parameters) { if (first) { first = false; } else { formatter.appendText(", "); // NOI18N } formatter.parameters(true); formatter.appendText(parameter); formatter.parameters(false); } formatter.appendText(")"); // NOI18N } } else { // formatter.appendText(element.getFqn()); formatter.appendText(element.getName()); } if (element.getClz() != null) { formatter.appendText(" "); formatter.appendText(NbBundle.getMessage(PythonDeclarationFinder.class, "In")); formatter.appendText(" "); formatter.appendText(element.getClz()); formatter.appendHtml(" "); // NOI18N } String filename = null; String url = element.getFilenameUrl(); if (url == null) { // Deleted file? // Just leave out the file name } else if (url.indexOf("pythonstubs") != -1) { // NOI18N filename = NbBundle.getMessage(PythonDeclarationFinder.class, "PythonLib"); // // if (url.indexOf("/stub_") == -1) { // // Not a stub file, such as ftools.py // // TODO - don't hardcode for version // String stub = "pythonstubs/2.5/"; // int stubStart = url.indexOf(stub); // if (stubStart != -1) { // filename = filename+": " + url.substring(stubStart); // } // } } else { FileObject fo = element.getFileObject(); if (fo != null) { filename = fo.getNameExt(); } else { // Perhaps a file that isn't present here, such as something in site_ruby int lastIndex = url.lastIndexOf('/'); if (lastIndex != -1) { String s = url.substring(0, lastIndex); int almostLastIndex = s.lastIndexOf('/'); if (almostLastIndex != -1 && ((url.length() - almostLastIndex) < 40)) { filename = url.substring(almostLastIndex + 1); if (filename.indexOf(':') != -1) { // Don't include prefix like cluster:, file:, etc. filename = url.substring(lastIndex + 1); } } else { filename = url.substring(lastIndex + 1); } } } // // TODO - make this work with 1.9 etc. // //final String GEM_LOC = "lib/ruby/gems/1.8/gems/"; // Pattern p = Pattern.compile("lib/ruby/gems/\\d+\\.\\d+/gems/"); // Matcher m = p.matcher(url); // //int gemIndex = url.indexOf(GEM_LOC); // //if (gemIndex != -1) { // if (m.find()) { // //int gemIndex = m.start(); // //gemIndex += GEM_LOC.length(); // int gemIndex = m.end(); // int gemEnd = url.indexOf('/', gemIndex); // if (gemEnd != -1) { // //int libIndex = url.indexOf("lib/", gemEnd); // //if (libIndex != -1) { // // filename = url.substring(libIndex+4); // //} // filename = url.substring(gemIndex, gemEnd) + ": " + // filename; // } // } } if (filename != null) { formatter.appendText(" "); formatter.appendText(NbBundle.getMessage(PythonDeclarationFinder.class, "In")); formatter.appendText(" "); formatter.appendText(filename); } if (documented) { formatter.appendText(" "); formatter.appendText(NbBundle.getMessage(PythonDeclarationFinder.class, "Documented")); } else if (nodoc) { formatter.appendText(" "); formatter.appendText(NbBundle.getMessage(PythonDeclarationFinder.class, "NoDoced")); } if (isPreferred) { formatter.emphasis(false); } else if (nodoc) { formatter.deprecated(false); } cachedDisplayItem = formatter.getText(); } return cachedDisplayItem; }
PythonAltLocation(IndexedElement element, boolean isPreferred) { this.element = element; this.isPreferred = isPreferred; order = element.getOrder(); }
private IndexedElement findBestMatchHelper( PythonParserResult info, String name, Set<IndexedElement> elements, BaseDocument doc, int astOffset, int lexOffset, AstPath path, PythonTree callNode, PythonIndex index) { Set<IndexedElement> candidates = new HashSet<IndexedElement>(); if (elements.size() == 0) { return null; } else if (elements.size() == 1) { return elements.iterator().next(); } // 1. Prefer matches in the current file String searchUrl = info.getSnapshot().getSource().getFileObject().toURL().toExternalForm(); candidates = new HashSet<IndexedElement>(); for (IndexedElement element : elements) { String url = element.getFilenameUrl(); if (url.equals(searchUrl)) { candidates.add(element); } } if (candidates.size() == 1) { return candidates.iterator().next(); } else if (!candidates.isEmpty()) { elements = candidates; } // 2. See which of the class references are defined in files directly // included by this file. Set<String> included = new HashSet<String>(); candidates = new HashSet<IndexedElement>(); SymbolTable table = PythonAstUtils.getParseResult(info).getSymbolTable(); List<Import> imports = table.getImports(); for (Import imp : imports) { List<alias> names = imp.getInternalNames(); if (names != null) { for (alias at : names) { included.add(at.getInternalName()); } } } List<ImportFrom> importsFrom = table.getImportsFrom(); for (ImportFrom imp : importsFrom) { included.add(imp.getInternalModule()); } if (included.size() > 0) { for (IndexedElement element : elements) { String mod = element.getModule(); if (included.contains(mod)) { candidates.add(element); } } if (candidates.size() == 1) { return candidates.iterator().next(); } else if (!candidates.isEmpty()) { elements = candidates; } } // 4. Prefer builtins candidates = new HashSet<IndexedElement>(); for (IndexedElement element : elements) { String url = element.getFilenameUrl(); if (url != null && url.indexOf("pythonstubs") != -1) { // NOI18N candidates.add(element); } } if (candidates.size() == 1) { return candidates.iterator().next(); } else if (!candidates.isEmpty()) { elements = candidates; } // 5. Prefer documented classes candidates = new HashSet<IndexedElement>(); for (IndexedElement element : elements) { if (element.isDocumented()) { candidates.add(element); } } if (candidates.size() == 1) { return candidates.iterator().next(); } else if (!candidates.isEmpty()) { elements = candidates; } // TODO - use some heuristics here! return elements.iterator().next(); }
private DeclarationLocation findImport( PythonParserResult info, String moduleName, String symbol) { PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject()); Set<IndexedElement> elements = null; if (moduleName != null && symbol != null) { elements = index.getImportedElements( symbol, QuerySupport.Kind.EXACT, Collections.<String>singleton(moduleName), null); } if (symbol != null && (elements == null || elements.size() == 0)) { elements = index.getInheritedElements(null, symbol, QuerySupport.Kind.EXACT); } if (elements == null || elements.size() == 0) { elements = index.getModules(moduleName, QuerySupport.Kind.EXACT); } if (elements != null && elements.size() > 0) { AstPath path = null; PythonTree node = null; int astOffset = -1; int lexOffset = -1; return getDeclaration(info, null /*name*/, elements, path, node, index, astOffset, lexOffset); } // This never gets executed, right? Delete after EA for (IndexedElement candidate : elements) { // TODO - pick the best of the alternatives here? FileObject fileObject = candidate.getFileObject(); if (fileObject == null) { return DeclarationLocation.NONE; } PythonTree node = candidate.getNode(); int nodeOffset = node != null ? node.getCharStartIndex() : 0; DeclarationLocation loc = new DeclarationLocation(fileObject, nodeOffset, candidate); if (elements.size() > 1) { // Could the :nodoc: alternatives: if there is only one nodoc'ed alternative // don't ask user! int not_nodoced = 0; for (final IndexedElement mtd : elements) { if (!mtd.isNoDoc()) { not_nodoced++; } } if (not_nodoced >= 2) { for (final IndexedElement mtd : elements) { loc.addAlternative(new PythonAltLocation(mtd, mtd == candidate)); } } } return loc; } return DeclarationLocation.NONE; }