Merge pull request #52 from kno10/patch-qualify-generics

add -!qualifyGenerics option that strips package names only in generics
This commit is contained in:
Diomidis Spinellis 2018-10-24 12:25:55 +03:00 committed by GitHub
commit b5238b3bdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 36 deletions

View File

@ -46,6 +46,7 @@ UMLGraph would not be in its current state without their contributions.
<li>Soraya Santana de la Fe</li>
<li>Jonathan R. Santos</li>
<li>Jan Schl&#252;ter</li>
<li>Erich Schubert</li>
<li>Sebastian Setzer</li>
<li>J&#246;rn Guy S&#252;&#223;</li>
<li>Andreas Studer</li>

View File

@ -1,9 +1,10 @@
<?xml version="1.0" ?>
<notes>
A number of options contol the operation of UMLGraph
A number of options control the operation of UMLGraph
class diagram generator.
These can be specified on the command line, and most can also
be specified through javadoc tags within the diagram, affecting all or some elements.
be specified through javadoc <code>@opt</code> tags within the diagram, affecting all or some elements.
Most have a negated version by prefixing an exclamation mark.
<p/>
<h2>What Gets Drawn</h2> <!-- {{{1 -->
<dl>
@ -32,6 +33,7 @@ be specified through javadoc tags within the diagram, affecting all or some elem
in the package view (which would by default filter to only include package members).</dd>
<dt>-operations</dt><dd>Show class operations (Java methods) </dd>
<dt>-qualify</dt><dd>Produce fully-qualified class names. </dd>
<dt>-qualifyGenerics</dt><dd>Use fully-qualified class names in Java generics.</dd>
<dt>-types</dt><dd>Add type information to attributes and operations </dd>
<dt>-view</dt><dd>Specify the fully qualified name of a class that contains
a view definition. Only the class diagram specified by this view will be generated.

View File

@ -7,6 +7,12 @@
<li>The <code>@opt include</code> option can be used to include classes from
foreign packages in the package view (unless hidden with <code>@opt hide</code>).</li>
<li>You can now also use <code>@opt</code> in <code>package-info.java</code>.</li>
<li>Added <code>-qualifyGenerics</code> option to separately control the inclusion of
package names for the class (<code>-qualify</code>) and its generics. In particular
this works well with <code>-qualify -postfixpackage</code> (and <code>-!qualifyGenerics</code>).<br />
To get the old <code>-qualify</code> behavior, you need to add <code>-qualifyGenerics</code>,
the default is off, and it will not inherit from <code>-qualify</code>.</li>
<li>Better handling of complex names with generics and inner classes such as <code>pkg.Outer&lt;T&gt;.Inner</code>.</li>
</ul>
</dd>

View File

@ -129,24 +129,34 @@ class ClassGraph {
/** Return the class's name, possibly by stripping the leading path */
private String qualifiedName(Options opt, String r) {
if (!opt.showQualified) {
// Create readable string by stripping leading path
for (;;) {
int dotpos = r.lastIndexOf('.');
if (dotpos == -1) break; // Work done!
/*
* Change all occurences of
* "p1.p2.myClass<S extends dummy.Otherclass>" into
* "myClass<S extends Otherclass>"
*/
int start = dotpos;
while (start > 0 && Character.isJavaIdentifierPart(r.charAt(start - 1)))
start--;
r = r.substring(0, start) + r.substring(dotpos + 1);
private static String qualifiedName(Options opt, String r) {
// Nothing to do:
if (opt.showQualified && (opt.showQualifiedGenerics || r.indexOf('<') < 0))
return r;
StringBuilder buf = new StringBuilder(r.length());
int last = 0, depth = 0;
boolean strip = !opt.showQualified;
for (int i = 0; i < r.length();) {
char c = r.charAt(i++);
// The last condition prevents losing the dot in A<V>.B
if ((c == '.' || c == '$') && strip && last + 1 < i)
last = i; // skip
if (Character.isJavaIdentifierPart(c))
continue;
// Handle nesting of generics
if (c == '<') {
++depth;
strip = !opt.showQualifiedGenerics;
} else if (c == '>' && --depth == 0)
strip = !opt.showQualified;
if (last < i) {
buf.append(r, last, i);
last = i;
}
}
return r;
if (last < r.length())
buf.append(r, last, r.length());
return buf.toString();
}
/**
@ -263,9 +273,9 @@ class ClassGraph {
}
/** Print a a basic type t */
private String type(Options opt, Type t) {
private String type(Options opt, Type t, boolean generics) {
String type;
if (opt.showQualified)
if (generics ? opt.showQualifiedGenerics : opt.showQualified)
type = t.qualifiedTypeName();
else
type = t.typeName();
@ -281,7 +291,7 @@ class ClassGraph {
Type args[] = t.typeArguments();
tp += "&lt;";
for (int i = 0; i < args.length; i++) {
tp += type(opt, args[i]);
tp += type(opt, args[i], true);
if (i != args.length - 1)
tp += ", ";
}
@ -291,11 +301,10 @@ class ClassGraph {
/** Annotate an field/argument with its type t */
private String typeAnnotation(Options opt, Type t) {
String ta = "";
if (t.typeName().equals("void"))
return ta;
ta += " : ";
ta += type(opt, t);
return "";
String ta = " : ";
ta += type(opt, t, false);
ta += t.dimension();
return ta;
}
@ -506,16 +515,12 @@ class ClassGraph {
Font font = c.isAbstract() && !c.isInterface() ? Font.CLASS_ABSTRACT : Font.CLASS;
String qualifiedName = qualifiedName(opt, r);
int startTemplate = qualifiedName.indexOf('<');
int idx;
if(startTemplate < 0)
idx = qualifiedName.lastIndexOf('.');
else
idx = qualifiedName.lastIndexOf('.', startTemplate);
int idx = qualifiedName.lastIndexOf('.', startTemplate < 0 ? qualifiedName.length() - 1 : startTemplate);
if (opt.showComment)
tableLine(Align.LEFT, htmlNewline(escape(c.commentText())), opt, Font.CLASS);
else if(opt.postfixPackage && idx > 0 && idx < (qualifiedName.length() - 1)) {
String packageName = qualifiedName.substring(0, idx);
String cn = className.substring(idx + 1);
String cn = qualifiedName.substring(idx + 1);
tableLine(Align.CENTER, escape(cn), opt, font);
tableLine(Align.CENTER, packageName, opt, Font.PACKAGE);
} else {
@ -781,14 +786,16 @@ class ClassGraph {
w.print("\t" + info.name + "[label=");
externalTableStart(opt, className, classToUrl(className));
innerTableStart();
int idx = className.lastIndexOf(".");
if(opt.postfixPackage && idx > 0 && idx < (className.length() - 1)) {
String packageName = className.substring(0, idx);
String cn = className.substring(idx + 1);
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, escape(cn), opt, Font.CLASS);
tableLine(Align.CENTER, packageName, opt, Font.PACKAGE);
} else {
tableLine(Align.CENTER, escape(className), opt, Font.CLASS);
tableLine(Align.CENTER, escape(qualifiedName), opt, Font.CLASS);
}
innerTableEnd();
externalTableEnd();

View File

@ -71,6 +71,7 @@ public class Options implements Cloneable, OptionProvider {
List<Pattern> hidePatterns;
List<Pattern> includePatterns;
boolean showQualified;
boolean showQualifiedGenerics;
boolean showAttributes;
boolean showEnumerations;
boolean showEnumConstants;
@ -141,6 +142,7 @@ public class Options implements Cloneable, OptionProvider {
Options() {
showQualified = false;
showQualifiedGenerics = false;
showAttributes = false;
showEnumConstants = false;
showOperations = false;
@ -303,6 +305,10 @@ public class Options implements Cloneable, OptionProvider {
showQualified = true;
} else if (opt[0].equals("-!qualify")) {
showQualified = false;
} else if(opt[0].equals("-qualifyGenerics")) {
showQualifiedGenerics = true;
} else if (opt[0].equals("-!qualifyGenerics")) {
showQualifiedGenerics = false;
} else if(opt[0].equals("-horizontal")) {
horizontal = true;
} else if (opt[0].equals("-!horizontal")) {