Simplify classinfo handling.

This commit is contained in:
Erich Schubert 2018-10-27 23:06:34 +02:00
parent 867dec5d9c
commit e27eeb4bc3
3 changed files with 69 additions and 88 deletions

View File

@ -331,24 +331,33 @@ class ClassGraph {
.matchesHideExpression(c.toString()); .matchesHideExpression(c.toString());
} }
protected ClassInfo getClassInfo(String className) { protected ClassInfo getClassInfo(ClassDoc cd, boolean create) {
return classnames.get(removeTemplate(className)); return getClassInfo(cd, cd.toString(), create);
} }
private ClassInfo newClassInfo(String className, boolean hidden) { protected ClassInfo getClassInfo(String className, boolean create) {
ClassInfo ci = new ClassInfo(hidden); return getClassInfo(null, className, create);
classnames.put(removeTemplate(className), ci); }
return ci;
protected ClassInfo getClassInfo(ClassDoc cd, String className, boolean create) {
className = removeTemplate(className);
ClassInfo ci = classnames.get(className);
if (ci == null && create) {
Options o = optionProvider.getOptionsFor(className);
boolean hidden = cd != null ? hidden(cd) : o.matchesHideExpression(className);
ci = new ClassInfo(hidden, o.shape.landingPort());
classnames.put(className, ci);
}
return ci;
} }
/** Return true if the class name is associated to an hidden class or matches a hide expression */ /** Return true if the class name is associated to an hidden class or matches a hide expression */
private boolean hidden(String s) { private boolean hidden(String className) {
ClassInfo ci = getClassInfo(s); className = removeTemplate(className);
return (ci != null && ci.hidden) || optionProvider.getOptionsFor(s).matchesHideExpression(s); ClassInfo ci = classnames.get(className);
return ci != null ? ci.hidden : optionProvider.getOptionsFor(className).matchesHideExpression(className);
} }
/** /**
* Prints the class if needed. * Prints the class if needed.
* <p> * <p>
@ -357,14 +366,13 @@ class ClassGraph {
* relative links in diagrams for UMLDoc * relative links in diagrams for UMLDoc
*/ */
public String printClass(ClassDoc c, boolean rootClass) { public String printClass(ClassDoc c, boolean rootClass) {
String className = c.toString(); ClassInfo ci = getClassInfo(c, true);
ClassInfo ci = getClassInfo(className);
ci = ci != null ? ci : newClassInfo(className, hidden(c));
if(ci.nodePrinted || ci.hidden) if(ci.nodePrinted || ci.hidden)
return ci.name; return ci.name;
Options opt = optionProvider.getOptionsFor(c); Options opt = optionProvider.getOptionsFor(c);
if (c.isEnum() && !opt.showEnumerations) if (c.isEnum() && !opt.showEnumerations)
return ci.name; return ci.name;
String className = c.toString();
// Associate classname's alias // Associate classname's alias
w.println(linePrefix + "// " + className); w.println(linePrefix + "// " + className);
// Create label // Create label
@ -469,7 +477,8 @@ class ClassGraph {
innerTableEnd(); innerTableEnd();
externalTableEnd(); externalTableEnd();
nodeProperties(UmlGraph.getCommentOptions()); nodeProperties(UmlGraph.getCommentOptions());
w.print(linePrefix + noteName + " -> " + relationNode(c) + "[arrowhead=none];\n"); ClassInfo ci1 = getClassInfo(c, true);
w.print(linePrefix + noteName + " -> " + ci1.name + ci1.port + "[arrowhead=none];\n");
ni++; ni++;
} }
ci.nodePrinted = true; ci.nodePrinted = true;
@ -518,7 +527,8 @@ class ClassGraph {
headLabel = (headLabel != null && !headLabel.isEmpty()) ? ",headlabel=\"" + headLabel + "\"" : ""; headLabel = (headLabel != null && !headLabel.isEmpty()) ? ",headlabel=\"" + headLabel + "\"" : "";
boolean unLabeled = tailLabel.isEmpty() && label.isEmpty() && headLabel.isEmpty(); boolean unLabeled = tailLabel.isEmpty() && label.isEmpty() && headLabel.isEmpty();
String n1 = relationNode(from, fromName), n2 = relationNode(to, toName); ClassInfo ci1 = getClassInfo(from, fromName, true), ci2 = getClassInfo(to, toName, true);
String n1 = ci1.name + ci1.port, n2 = ci2.name + ci2.port;
// For ranking we need to output extends/implements backwards. // For ranking we need to output extends/implements backwards.
if (rt.backorder) { // Swap: if (rt.backorder) { // Swap:
String tmp = n1; String tmp = n1;
@ -544,8 +554,8 @@ class ClassGraph {
RelationDirection d = RelationDirection.BOTH; RelationDirection d = RelationDirection.BOTH;
if(rt == RelationType.NAVASSOC || rt == RelationType.DEPEND) if(rt == RelationType.NAVASSOC || rt == RelationType.DEPEND)
d = RelationDirection.OUT; d = RelationDirection.OUT;
getClassInfo(fromName).addRelation(toName, rt, d); ci1.addRelation(toName, rt, d);
getClassInfo(toName).addRelation(fromName, rt, d.inverse()); ci2.addRelation(fromName, rt, d.inverse());
} }
/** /**
@ -559,30 +569,6 @@ class ClassGraph {
} }
/** Return the full name of a relation's node.
* This may involve appending the port :p for the standard nodes
* whose outline is rendered through an inner table.
*/
private String relationNode(ClassDoc c) {
String className = c.toString();
ClassInfo ci = getClassInfo(className);
return (ci != null ? ci : newClassInfo(className, hidden(c))).name //
+ optionProvider.getOptionsFor(c).shape.landingPort();
}
/** Return the full name of a relation's node c.
* This may involve appending the port :p for the standard nodes
* whose outline is rendered through an inner table.
* @param c the node's class (may be null)
* @param cName the node's class name
*/
private String relationNode(ClassDoc c, String cName) {
Options opt = c == null ? optionProvider.getOptionsFor(cName) : optionProvider.getOptionsFor(c);
ClassInfo ci = getClassInfo(cName);
return (ci != null ? ci : newClassInfo(cName, false)).name //
+ opt.shape.landingPort();
}
/** Print a class's relations */ /** Print a class's relations */
public void printRelations(ClassDoc c) { public void printRelations(ClassDoc c) {
Options opt = optionProvider.getOptionsFor(c); Options opt = optionProvider.getOptionsFor(c);
@ -617,37 +603,38 @@ class ClassGraph {
public void printExtraClasses(RootDoc root) { public void printExtraClasses(RootDoc root) {
Set<String> names = new HashSet<String>(classnames.keySet()); Set<String> names = new HashSet<String>(classnames.keySet());
for(String className: names) { for(String className: names) {
ClassInfo info = getClassInfo(className); ClassInfo info = getClassInfo(className, true);
if (!info.nodePrinted) { if (info.nodePrinted)
ClassDoc c = root.classNamed(className); continue;
if(c != null) { ClassDoc c = root.classNamed(className);
printClass(c, false); if(c != null) {
} else { printClass(c, false);
Options opt = optionProvider.getOptionsFor(className); continue;
if(opt.matchesHideExpression(className))
continue;
w.println(linePrefix + "// " + className);
w.print(linePrefix + info.name + "[label=");
externalTableStart(opt, className, classToUrl(className));
innerTableStart();
String qualifiedName = qualifiedName(opt, className);
int startTemplate = qualifiedName.indexOf('<');
int idx = qualifiedName.lastIndexOf('.', startTemplate < 0 ? qualifiedName.length() - 1 : startTemplate);
if(opt.postfixPackage && idx > 0 && idx < (qualifiedName.length() - 1)) {
String packageName = qualifiedName.substring(0, idx);
String cn = qualifiedName.substring(idx + 1);
tableLine(Align.CENTER, Font.CLASS.wrap(opt, escape(cn)));
tableLine(Align.CENTER, Font.PACKAGE.wrap(opt, packageName));
} else {
tableLine(Align.CENTER, Font.CLASS.wrap(opt, escape(qualifiedName)));
}
innerTableEnd();
externalTableEnd();
if (className == null || className.length() == 0)
w.print(",URL=\"" + classToUrl(className) + "\"");
nodeProperties(opt);
}
} }
// Handle missing classes:
Options opt = optionProvider.getOptionsFor(className);
if(opt.matchesHideExpression(className))
continue;
w.println(linePrefix + "// " + className);
w.print(linePrefix + info.name + "[label=");
externalTableStart(opt, className, classToUrl(className));
innerTableStart();
String qualifiedName = qualifiedName(opt, className);
int startTemplate = qualifiedName.indexOf('<');
int idx = qualifiedName.lastIndexOf('.', startTemplate < 0 ? qualifiedName.length() - 1 : startTemplate);
if(opt.postfixPackage && idx > 0 && idx < (qualifiedName.length() - 1)) {
String packageName = qualifiedName.substring(0, idx);
String cn = qualifiedName.substring(idx + 1);
tableLine(Align.CENTER, Font.CLASS.wrap(opt, escape(cn)));
tableLine(Align.CENTER, Font.PACKAGE.wrap(opt, packageName));
} else {
tableLine(Align.CENTER, Font.CLASS.wrap(opt, escape(qualifiedName)));
}
innerTableEnd();
externalTableEnd();
if (className == null || className.length() == 0)
w.print(",URL=\"" + classToUrl(className) + "\"");
nodeProperties(opt);
} }
} }
@ -657,31 +644,28 @@ class ClassGraph {
* @param classes * @param classes
*/ */
public void printInferredRelations(ClassDoc c) { public void printInferredRelations(ClassDoc c) {
Options opt = optionProvider.getOptionsFor(c);
// check if the source is excluded from inference // check if the source is excluded from inference
if (hidden(c)) if (hidden(c))
return; return;
Options opt = optionProvider.getOptionsFor(c);
for (FieldDoc field : c.fields(false)) { for (FieldDoc field : c.fields(false)) {
if(hidden(field)) if(hidden(field))
continue; continue;
// skip statics // skip statics
if(field.isStatic()) if(field.isStatic())
continue; continue;
// skip primitives // skip primitives
FieldRelationInfo fri = getFieldRelationInfo(field); FieldRelationInfo fri = getFieldRelationInfo(field);
if (fri == null) if (fri == null)
continue; continue;
// check if the destination is excluded from inference // check if the destination is excluded from inference
if (hidden(fri.cd)) if (hidden(fri.cd))
continue; continue;
// if source and dest are not already linked, add a dependency // if source and dest are not already linked, add a dependency
RelationPattern rp = getClassInfo(c.toString()).getRelation(fri.cd.toString()); RelationPattern rp = getClassInfo(c, true).getRelation(fri.cd.toString());
if (rp == null) { if (rp == null) {
String destAdornment = fri.multiple ? "*" : ""; String destAdornment = fri.multiple ? "*" : "";
relation(opt, opt.inferRelationshipType, c, fri.cd, "", "", destAdornment); relation(opt, opt.inferRelationshipType, c, fri.cd, "", "", destAdornment);
@ -705,12 +689,10 @@ class ClassGraph {
* @param classes * @param classes
*/ */
public void printInferredDependencies(ClassDoc c) { public void printInferredDependencies(ClassDoc c) {
Options opt = optionProvider.getOptionsFor(c);
String sourceName = c.toString();
if (hidden(c)) if (hidden(c))
return; return;
Options opt = optionProvider.getOptionsFor(c);
Set<Type> types = new HashSet<Type>(); Set<Type> types = new HashSet<Type>();
// harvest method return and parameter types // harvest method return and parameter types
for (MethodDoc method : filterByVisibility(c.methods(false), opt.inferDependencyVisibility)) { for (MethodDoc method : filterByVisibility(c.methods(false), opt.inferDependencyVisibility)) {
@ -760,7 +742,7 @@ class ClassGraph {
continue; continue;
// if source and dest are not already linked, add a dependency // if source and dest are not already linked, add a dependency
RelationPattern rp = getClassInfo(sourceName).getRelation(fc.toString()); RelationPattern rp = getClassInfo(c, true).getRelation(fc.toString());
if (rp == null || rp.matchesOne(new RelationPattern(RelationDirection.OUT))) { if (rp == null || rp.matchesOne(new RelationPattern(RelationDirection.OUT))) {
relation(opt, RelationType.DEPEND, c, fc, "", "", ""); relation(opt, RelationType.DEPEND, c, fc, "", "", "");
} }

View File

@ -31,7 +31,7 @@ import java.util.Map;
class ClassInfo { class ClassInfo {
private static int classNumber; private static int classNumber;
/** Alias name for the class */ /** Alias name for the class */
String name; final String name, port;
/** True if the class class node has been printed */ /** True if the class class node has been printed */
boolean nodePrinted; boolean nodePrinted;
/** True if the class class node is hidden */ /** True if the class class node is hidden */
@ -43,9 +43,10 @@ class ClassInfo {
*/ */
Map<String, RelationPattern> relatedClasses = new HashMap<String, RelationPattern>(); Map<String, RelationPattern> relatedClasses = new HashMap<String, RelationPattern>();
ClassInfo(boolean h) { ClassInfo(boolean h, String port) {
hidden = h; hidden = h;
name = "c" + classNumber; name = "c" + classNumber;
this.port = port;
classNumber++; classNumber++;
} }

View File

@ -141,10 +141,8 @@ public class ContextMatcher implements ClassMatcher {
return true; return true;
for (ClassDoc mcd : matched) { for (ClassDoc mcd : matched) {
String mcName = mcd.toString(); RelationPattern rp = cg.getClassInfo(mcd, true).getRelation(name);
ClassInfo ciMatched = cg.getClassInfo(mcName); if (rp != null && opt.contextRelationPattern.matchesOne(rp))
RelationPattern rp = ciMatched.getRelation(name);
if (ciMatched != null && rp != null && opt.contextRelationPattern.matchesOne(rp))
return true; return true;
} }
return false; return false;