src.org.python.indexer.demos.DocStringParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython Show documentation
Show all versions of jython Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
/**
* Copyright 2009, Google Inc. All rights reserved.
* Licensed to PSF under a Contributor Agreement.
*/
package org.python.indexer.demos;
import org.python.indexer.Indexer;
import org.python.indexer.NBinding;
import org.python.indexer.Ref;
import org.python.indexer.Scope;
import org.python.indexer.StyleRun;
import org.python.indexer.ast.NStr;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Scans doc strings looking for interesting stuff to highlight or hyperlink.
*/
class DocStringParser {
/**
* Only try to resolve possible qnames of at least this length.
* Helps cut down on noise.
*/
private static final int MIN_TYPE_NAME_LENGTH = 4;
/**
* Matches an unqualified Python identifier.
*/
private static final String IDENT = "[a-zA-Z_][a-zA-Z0-9_]*";
/**
* Matches probable type names. Does loose matching; caller must do more checks.
*/
private static final Pattern TYPE_NAME =
Pattern.compile(
// any two or more identifiers joined with dots.
IDENT + "\\." + IDENT + "(?:\\." + IDENT + ")*\\b"
// a capitalized word that isn't all-caps
+ "|\\b[A-Z][a-zA-Z0-9_]*?[a-z][a-zA-Z0-9_]*\\b"
// an __identifier__
+ "|(? offsets = new HashSet(); // styles we've already added
private List styles = new ArrayList();
private Linker linker;
/**
* Constructor.
* @param start beginning 0-based file offset of the doc string
* @param comment the doc string or doc-comment text
* @param node the AST node for the doc string
*/
public DocStringParser(String comment, NStr node, Linker linker) {
docOffset = node.start();
docString = comment;
docNode = node;
scope = node.getEnclosingNamespace();
file = node.getFile();
this.linker = linker;
}
/**
* Configures whether to highlight syntactically or semantically.
*
* @param resolve {@code true} to do name resolution, {@code false}
* to guess purely based on syntax in the doc string.
* Pass {@code false} if you're using the highlighter to
* syntax-highlight a file (i.e. no code graph or indexing.)
*/
public void setResolveReferences(boolean resolve) {
resolveReferences = resolve;
}
public boolean isResolvingReferences() {
return resolveReferences;
}
/**
* Main entry point.
*
* @return the non-{@code null} but possibly empty list of additional
* styles for the doc string.
*/
public List highlight() {
if (resolveReferences) {
scanCommentForTypeNames();
}
return styles;
}
/**
* Try to match potential type names against the code graph.
* If any match, graph references and styles are added for them.
*/
private void scanCommentForTypeNames() {
Matcher m = TYPE_NAME.matcher(docString);
while (m.find()) {
String qname = m.group();
int beg = m.start() + docOffset;
// If we already added a style here, skip this one.
if (offsets.contains(beg)) {
continue;
}
// Arbitrarily require them to be at least N chars, to reduce noise.
if (qname.length() < MIN_TYPE_NAME_LENGTH) {
continue;
}
checkForReference(beg, qname);
}
}
/**
* Look for the name in the current scope. If found, and its
* qname is a valid binding in the graph, record a reference.
*/
private void checkForReference(int offset, String qname) {
NBinding nb;
if (qname.indexOf('.') == -1) {
nb = scope.lookup(qname);
if (nb == null) {
nb = Indexer.idx.globaltable.lookup(qname);
}
} else {
nb = Indexer.idx.lookupQname(qname);
}
if (nb != null) {
linker.processRef(new Ref(file, offset, qname), nb);
}
}
private void addStyle(int beg, int len, NBinding nb) {
addStyle(beg, len, StyleRun.Type.TYPE_NAME);
offsets.add(beg);
}
private void addStyle(int beg, int len, StyleRun.Type type) {
styles.add(new StyleRun(type, beg, len));
offsets.add(beg);
}
}