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-standalone Show documentation
Show all versions of jython-standalone 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);
}
}