1.1 --- a/callgraph/pom.xml Mon Aug 29 13:00:53 2016 -0400
1.2 +++ b/callgraph/pom.xml Sat Sep 03 02:41:36 2016 -0400
1.3 @@ -4,7 +4,7 @@
1.4 <groupId>org.netbeans</groupId>
1.5 <artifactId>callgraph</artifactId>
1.6 <name>Callgraph Utility</name>
1.7 - <version>1.1</version>
1.8 + <version>1.3</version>
1.9 <packaging>jar</packaging>
1.10 <properties>
1.11 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2.1 --- a/callgraph/src/main/java/org/netbeans/lib/callgraph/Arguments.java Mon Aug 29 13:00:53 2016 -0400
2.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/Arguments.java Sat Sep 03 02:41:36 2016 -0400
2.3 @@ -63,6 +63,8 @@
2.4 private static final Command[] commands = new Command[]{
2.5 new NoSelfReferencesCommand(),
2.6 new ShortNamesCommand(),
2.7 + new ExtendedPropertiesCommand(),
2.8 + new AntCommand(),
2.9 new MavenCommand(),
2.10 new GradleCommand(),
2.11 new IgnoreCommand(),
2.12 @@ -75,12 +77,16 @@
2.13 new OmitAbstractCommand(),
2.14 new QuietCommand(),
2.15 new ReverseCommand(),
2.16 + new AggressiveCommand(),
2.17 new VerboseCommand()
2.18 };
2.19 private boolean noSelfReferences = false;
2.20 private boolean shortNames = false;
2.21 private boolean maven = false;
2.22 private boolean gradle = false;
2.23 + private boolean ant = false;
2.24 + private boolean xprop = false;
2.25 + private boolean aggressive = false;
2.26 private File outfile;
2.27 private Set<String> exclude = new HashSet<>();
2.28 private Set<String> ignore = new HashSet<>();
2.29 @@ -141,13 +147,14 @@
2.30 }
2.31 }
2.32 }
2.33 - Set<String> origFolders = folders;
2.34 - if (maven && gradle) {
2.35 - errors.add("--maven and --gradle are mutually exclusive");
2.36 + if ((maven && gradle) || (ant && gradle) || (ant && maven)) {
2.37 + errors.add("--maven, --ant and --gradle are mutually exclusive");
2.38 } else if (maven) {
2.39 findMavenSubfolders(errors);
2.40 } else if (gradle) {
2.41 findGradleSubfolders(errors);
2.42 + } else if (ant) {
2.43 + findAntSubfolders(errors);
2.44 }
2.45 Set<File> toIgnore = new HashSet<>();
2.46 for (String ig : ignore) {
2.47 @@ -193,6 +200,12 @@
2.48 }
2.49 }
2.50 this.folders.removeAll(toIgnore);
2.51 + if (verbose && !this.folders.isEmpty()) {
2.52 + System.err.println("Will scan the following source roots:");
2.53 + for (File f : folders()) {
2.54 + System.err.println(" " + f.getAbsolutePath());
2.55 + }
2.56 + }
2.57
2.58 if (packageGraphFile != null) {
2.59 File parent = packageGraphFile.getParentFile();
2.60 @@ -250,6 +263,36 @@
2.61 return pom.exists() && pom.isFile() && pom.canRead();
2.62 }
2.63
2.64 + void findAntSubfolders(List<String> errors) {
2.65 + Set<File> flds = new HashSet<>(this.folders);
2.66 + this.folders.clear();
2.67 + for (File f : flds) {
2.68 + recurseSubfoldersLookingForAntProjects(f);
2.69 + }
2.70 + if (this.folders.isEmpty()) {
2.71 + errors.add("Did not find any ant projects (looked for build.xml and src/ in all subfolders of folder list)");
2.72 + }
2.73 + }
2.74 +
2.75 + private void recurseSubfoldersLookingForAntProjects(File file) {
2.76 + if (file.isDirectory()) {
2.77 + if (hasBuildXml(file)) {
2.78 + File sources = new File(file, "src");
2.79 + if (sources.exists() && sources.isDirectory()) {
2.80 + this.folders.add(sources);
2.81 + }
2.82 + }
2.83 + for (File child : file.listFiles()) {
2.84 + recurseSubfoldersLookingForAntProjects(child);
2.85 + }
2.86 + }
2.87 + }
2.88 +
2.89 + private boolean hasBuildXml(File fld) {
2.90 + File pom = new File(fld, "build.xml");
2.91 + return pom.exists() && pom.isFile() && pom.canRead();
2.92 + }
2.93 +
2.94 void findGradleSubfolders(List<String> errors) {
2.95 Set<File> flds = new HashSet<>(this.folders);
2.96 this.folders.clear();
2.97 @@ -333,6 +376,20 @@
2.98 }
2.99
2.100 @Override
2.101 + public boolean isAnt() {
2.102 + return ant;
2.103 + }
2.104 +
2.105 + @Override
2.106 + public boolean isExtendedProperties() {
2.107 + return xprop;
2.108 + }
2.109 +
2.110 + public boolean isAggressive() {
2.111 + return aggressive;
2.112 + }
2.113 +
2.114 + @Override
2.115 public File classGraphFile() {
2.116 return classGraphFile;
2.117 }
2.118 @@ -467,7 +524,7 @@
2.119
2.120 @Override
2.121 protected String help() {
2.122 - return "Disable string memory optimizations - runs faster but may run out of memory";
2.123 + return "Disable string memory optimizations - runs faster and supports unicode class names, but may run out of memory";
2.124 }
2.125 }
2.126
2.127 @@ -489,6 +546,25 @@
2.128 }
2.129 }
2.130
2.131 + private static final class AggressiveCommand extends Command {
2.132 +
2.133 + AggressiveCommand() {
2.134 + super(CMD_AGGRESSIVE_MEMORY, "z", true, false);
2.135 + }
2.136 +
2.137 + @Override
2.138 + protected int doParse(int i, String[] args, Arguments toSet) {
2.139 + toSet.aggressive = true;
2.140 + return 1;
2.141 + }
2.142 +
2.143 + @Override
2.144 + protected String help() {
2.145 + return "Aggressively optimize the 8-bit string intern table "
2.146 + + "for large graphs, sacrificing performace for space";
2.147 + }
2.148 + }
2.149 +
2.150 private static final class ShortNamesCommand extends Command {
2.151
2.152 ShortNamesCommand() {
2.153 @@ -507,6 +583,42 @@
2.154 }
2.155 }
2.156
2.157 + private static final class ExtendedPropertiesCommand extends Command {
2.158 +
2.159 + ExtendedPropertiesCommand() {
2.160 + super(CMD_EXTENDED_PROPERTIES, "x", true, false);
2.161 + }
2.162 +
2.163 + @Override
2.164 + protected int doParse(int i, String[] args, Arguments toSet) {
2.165 + toSet.xprop = true;
2.166 + return 1;
2.167 + }
2.168 +
2.169 + @Override
2.170 + protected String help() {
2.171 + return "Find all maven projects that are children of the passed folders, and scan their src/main/java subfolders";
2.172 + }
2.173 + }
2.174 +
2.175 + private static final class AntCommand extends Command {
2.176 +
2.177 + AntCommand() {
2.178 + super(CMD_ANT, "a", true, false);
2.179 + }
2.180 +
2.181 + @Override
2.182 + protected int doParse(int i, String[] args, Arguments toSet) {
2.183 + toSet.ant = true;
2.184 + return 1;
2.185 + }
2.186 +
2.187 + @Override
2.188 + protected String help() {
2.189 + return "Find all ant projects that are children of the passed folders, and scan their src/ subfolders";
2.190 + }
2.191 + }
2.192 +
2.193 private static final class MavenCommand extends Command {
2.194
2.195 MavenCommand() {
3.1 --- a/callgraph/src/main/java/org/netbeans/lib/callgraph/Callgraph.java Mon Aug 29 13:00:53 2016 -0400
3.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/Callgraph.java Sat Sep 03 02:41:36 2016 -0400
3.3 @@ -1,7 +1,7 @@
3.4 /*
3.5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3.6 *
3.7 - * Copyright (C) 1997-2015 Oracle and/or its affiliates. All rights reserved.
3.8 + * Copyright (C) 1997-2016 Oracle and/or its affiliates. All rights reserved.
3.9 *
3.10 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
3.11 * Other names may be trademarks of their respective owners.
3.12 @@ -70,10 +70,8 @@
3.13 import java.util.LinkedList;
3.14 import java.util.List;
3.15 import java.util.Set;
3.16 -import java.util.TreeSet;
3.17 import java.util.concurrent.atomic.AtomicReference;
3.18 import java.util.function.Consumer;
3.19 -import org.netbeans.lib.callgraph.util.ComparableCharSequence;
3.20
3.21 /**
3.22 * Scans a source folder and runs javac against any Java sources present, and
3.23 @@ -134,7 +132,7 @@
3.24 * @throws IOException If i/o fails
3.25 */
3.26 static List<SourceElement> invoke(CallgraphControl arguments, Listener listener) throws IOException {
3.27 - SourcesInfo info = new SourcesInfo(arguments.isDisableEightBitStrings());
3.28 + SourcesInfo info = new SourcesInfo(arguments.isDisableEightBitStrings(), arguments.isAggressive());
3.29 // Build an iterable of all Java sources (without collecting them all ahead of time)
3.30 List<Iterable<File>> iterables = new LinkedList<>();
3.31 for (File folder : arguments) {
3.32 @@ -158,8 +156,15 @@
3.33 // duplicate avoidance
3.34 Set<CharSequence> emittedPackageLines = new HashSet<>();
3.35 Set<CharSequence> emittedClassLines = new HashSet<>();
3.36 + List<Object> clazz = new ArrayList<>(5);
3.37 + CharSequence lastClass = null;
3.38 +
3.39 + List<Object> pkg = new ArrayList<>(5);
3.40 + CharSequence lastPackage = null;
3.41 +
3.42 try {
3.43 // Iterate every method
3.44 + outer:
3.45 for (SourceElement sce : all) {
3.46 if (arguments.isExcluded(sce.qname().toString())) { // Ignore matches
3.47 continue;
3.48 @@ -167,7 +172,32 @@
3.49 List<SourceElement> outbounds = new ArrayList<>(arguments.isReverse() ? sce.getInboundReferences() : sce.getOutboundReferences());
3.50 Collections.sort(outbounds); // also sort connections
3.51 // Iterate the current method's connections
3.52 - Set<ComparableCharSequence> mth = new TreeSet<>();
3.53 + List<Object> mth = new ArrayList<>(5);
3.54 + CharSequence currClazz = arguments.isShortNames() ? sce.typeName() : info.strings.concat(sce.packageName(), info.strings.DOT, sce.typeName());
3.55 + if (!currClazz.equals(lastClass)) {
3.56 + if (classStream != null) {
3.57 + writeLine(clazz, info, emittedClassLines, classStream);
3.58 + }
3.59 + clazz.clear();
3.60 + lastClass = currClazz;
3.61 + }
3.62 + if (clazz.isEmpty()) {
3.63 + clazz.add(currClazz);
3.64 + if (arguments.isExtendedProperties()) {
3.65 + clazz.add(sce.isAbstract());
3.66 + }
3.67 + }
3.68 + CharSequence currPkg = sce.packageName();
3.69 + if (pkg.isEmpty()) {
3.70 + pkg.add(currPkg);
3.71 + }
3.72 + if (!currPkg.equals(lastPackage)) {
3.73 + if (packageStream != null) {
3.74 + writeLine(pkg, info, emittedPackageLines, packageStream);
3.75 + }
3.76 + lastPackage = currPkg;
3.77 + pkg.clear();
3.78 + }
3.79 for (SourceElement outbound : outbounds) {
3.80 if (arguments.isExcluded(outbound.qname().toString())) { // Ignore matches
3.81 continue;
3.82 @@ -181,24 +211,20 @@
3.83 if (!arguments.isSelfReferences() && sce.typeName().equals(outbound.typeName())) {
3.84 continue;
3.85 }
3.86 - if (outStream != null) {
3.87 + if (outStream != null || !arguments.isQuiet()) {
3.88 if (arguments.isShortNames()) {
3.89 mth.add(outbound.shortName());
3.90 } else {
3.91 mth.add(outbound.qname());
3.92 }
3.93 + if (arguments.isExtendedProperties()) {
3.94 + mth.add(outbound.isAbstract());
3.95 + }
3.96 }
3.97 // Build the package graph output if necessary
3.98 if (packageStream != null) {
3.99 - CharSequence pkg1 = sce.packageName();
3.100 - CharSequence pkg2 = outbound.packageName();
3.101 - if (!pkg1.equals(pkg2)) {
3.102 -// CharSequence pkgLine = '"' + pkg1.toString() + "\" \"" + pkg2.toString() + '"';
3.103 - CharSequence pkgLine = info.strings.concat(info.strings.QUOTE, pkg1, info.strings.CLOSE_OPEN_QUOTE, pkg2, info.strings.QUOTE);
3.104 - if (!emittedPackageLines.contains(pkgLine)) {
3.105 - emittedPackageLines.add(pkgLine);
3.106 - packageStream.println(pkgLine);
3.107 - }
3.108 + if (!outbound.packageName().equals(currPkg) || arguments.isSelfReferences()) {
3.109 + pkg.add(outbound.packageName());
3.110 }
3.111 }
3.112 // Build the class graph output if necessary
3.113 @@ -206,22 +232,24 @@
3.114 CharSequence type1 = sce.typeName();
3.115 CharSequence type2 = outbound.typeName();
3.116 if (!arguments.isShortNames()) {
3.117 - type1 = info.strings.concat(sce.packageName(), info.strings.DOT, type1);
3.118 +// type1 = info.strings.concat(sce.packageName(), info.strings.DOT, type1);
3.119 type2 = info.strings.concat(outbound.packageName(), info.strings.DOT, type2);
3.120 }
3.121 - if (!type1.equals(type2)) {
3.122 - CharSequence classLine = info.strings.concat(info.strings.QUOTE, type1, info.strings.CLOSE_OPEN_QUOTE, type2, info.strings.QUOTE);
3.123 - if (!emittedClassLines.contains(classLine)) {
3.124 - emittedClassLines.add(classLine);
3.125 - classStream.println(classLine);
3.126 + if (!type1.equals(type2) && !clazz.contains(type2)) {
3.127 + clazz.add(type2);
3.128 + if (arguments.isExtendedProperties()) {
3.129 + clazz.add(outbound.isAbstract());
3.130 }
3.131 }
3.132 }
3.133 }
3.134 - if ((!arguments.isQuiet() || outStream != null)) {
3.135 + if (!arguments.isQuiet() || outStream != null) {
3.136 if (!mth.isEmpty()) {
3.137 CharSequence nm = arguments.isShortNames() ? sce.shortName() : sce.qname();
3.138 - List<CharSequence> l = new ArrayList<>(mth);
3.139 + List<Object> l = mth;
3.140 + if (arguments.isExtendedProperties()) {
3.141 + mth.add(0, sce.isAbstract());
3.142 + }
3.143 l.add(0, nm);
3.144 CharSequence line = info.strings.concatQuoted(l);
3.145 if (!arguments.isQuiet()) {
3.146 @@ -233,6 +261,12 @@
3.147 }
3.148 }
3.149 }
3.150 + if (classStream != null && !clazz.isEmpty()) {
3.151 + writeLine(clazz, info, emittedClassLines, classStream);
3.152 + }
3.153 + if (packageStream != null && !pkg.isEmpty()) {
3.154 + writeLine(pkg, info, emittedPackageLines, packageStream);
3.155 + }
3.156 } finally {
3.157 for (PrintStream ps : new PrintStream[]{outStream, packageStream, classStream}) {
3.158 if (ps != null) {
3.159 @@ -243,6 +277,15 @@
3.160 }
3.161 return all;
3.162 }
3.163 + private static void writeLine(List<Object> clazz, SourcesInfo info, Set<CharSequence> emittedClassLines, PrintStream classStream) {
3.164 + if (!clazz.isEmpty()) {
3.165 + CharSequence cs = info.strings.concatQuoted(clazz);
3.166 + if (!emittedClassLines.contains(cs)) {
3.167 + classStream.println(cs);
3.168 + emittedClassLines.add(cs);
3.169 + }
3.170 + }
3.171 + }
3.172
3.173 private static PrintStream createPrintStreamIfNotNull(File outputFile) throws IOException {
3.174 PrintStream outStream = null;
4.1 --- a/callgraph/src/main/java/org/netbeans/lib/callgraph/CallgraphControl.java Mon Aug 29 13:00:53 2016 -0400
4.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/CallgraphControl.java Sat Sep 03 02:41:36 2016 -0400
4.3 @@ -1,4 +1,4 @@
4.4 -/*
4.5 +/*
4.6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.7 *
4.8 * Copyright (C) 1997-2015 Oracle and/or its affiliates. All rights reserved.
4.9 @@ -57,8 +57,11 @@
4.10
4.11 static final String CMD_NOSELF = "noself";
4.12 static final String CMD_SIMPLE = "simple";
4.13 + static final String CMD_ANT = "ant";
4.14 static final String CMD_MAVEN = "maven";
4.15 static final String CMD_GRADLE = "gradle";
4.16 + static final String CMD_EXTENDED_PROPERTIES = "extensions";
4.17 + static final String CMD_AGGRESSIVE_MEMORY = "aggressive";
4.18 static final String CMD_IGNORE = "ignore";
4.19 static final String CMD_PACKAGEGRAPH = "packagegraph";
4.20 static final String CMD_METHODGRAPH = "methodgraph";
4.21 @@ -80,6 +83,14 @@
4.22
4.23 boolean isMaven();
4.24
4.25 + boolean isGradle();
4.26 +
4.27 + boolean isAnt();
4.28 +
4.29 + boolean isExtendedProperties();
4.30 +
4.31 + boolean isAggressive();
4.32 +
4.33 boolean isQuiet();
4.34
4.35 boolean isSelfReferences();
5.1 --- a/callgraph/src/main/java/org/netbeans/lib/callgraph/javac/SourcesInfo.java Mon Aug 29 13:00:53 2016 -0400
5.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/javac/SourcesInfo.java Sat Sep 03 02:41:36 2016 -0400
5.3 @@ -75,8 +75,8 @@
5.4
5.5 public final EightBitStrings strings;
5.6
5.7 - public SourcesInfo(boolean eightBitStringsDisabled) {
5.8 - this.strings = new EightBitStrings(eightBitStringsDisabled);
5.9 + public SourcesInfo(boolean eightBitStringsDisabled, boolean aggressive) {
5.10 + this.strings = new EightBitStrings(eightBitStringsDisabled, aggressive);
5.11 }
5.12
5.13 // XXX rewrite to not hold references to ClassTree, just names,
6.1 --- a/callgraph/src/main/java/org/netbeans/lib/callgraph/util/EightBitStrings.java Mon Aug 29 13:00:53 2016 -0400
6.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/util/EightBitStrings.java Sat Sep 03 02:41:36 2016 -0400
6.3 @@ -70,14 +70,22 @@
6.4 private final InternTable INTERN_TABLE = new InternTable();
6.5 public final CharSequence DOT = create(".");
6.6 public final CharSequence QUOTE = create("\"");
6.7 + public final CharSequence SPACE = create(" ");
6.8 + public final CharSequence QUOTE_SPACE = create("\" ");
6.9 public final CharSequence CLOSE_OPEN_QUOTE = create("\" \"");
6.10
6.11 - private boolean disabled;
6.12 + private final boolean disabled;
6.13 + private final boolean aggressive;
6.14
6.15 public EightBitStrings(boolean disabled) {
6.16 - this.disabled = disabled;
6.17 + this (disabled, false);
6.18 }
6.19
6.20 + public EightBitStrings(boolean disabled, boolean aggressive) {
6.21 + this.disabled = disabled;
6.22 + this.aggressive = aggressive;
6.23 + }
6.24 +
6.25 public void clear() {
6.26 INTERN_TABLE.dispose();
6.27 }
6.28 @@ -87,6 +95,9 @@
6.29 return string instanceof ComparableCharSequence ? (ComparableCharSequence) string
6.30 : new StringWrapper(string.toString());
6.31 }
6.32 + if (aggressive) {
6.33 + return concat(string);
6.34 + }
6.35 return INTERN_TABLE.intern(string);
6.36 }
6.37
6.38 @@ -100,32 +111,66 @@
6.39 sb.append(c);
6.40 }
6.41 return new StringWrapper(sb.toString());
6.42 + } else if (aggressive) {
6.43 + List<CharSequence> nue = new ArrayList<>(seqs.length + (seqs.length / 2));
6.44 + for (CharSequence seq : seqs) {
6.45 + int ln = seq.length();
6.46 + StringBuilder sb = new StringBuilder();
6.47 + for(int i=0; i < ln; i++) {
6.48 + char c = seq.charAt(i);
6.49 + if (Character.isLetter(c) || Character.isDigit(c)) {
6.50 + sb.append(c);
6.51 + } else {
6.52 + nue.add(sb.toString());
6.53 + sb = new StringBuilder();
6.54 + nue.add(new String(new char[] { c }));
6.55 + }
6.56 + }
6.57 + if (sb.length() > 0) {
6.58 + nue.add(sb.toString());
6.59 + }
6.60 + }
6.61 + if (nue.size() != seqs.length) {
6.62 + seqs = nue.toArray(new CharSequence[nue.size()]);
6.63 + }
6.64 }
6.65 return new Concatenation(seqs);
6.66 }
6.67
6.68 - public ComparableCharSequence concatQuoted(Collection<CharSequence> seqs) {
6.69 + public ComparableCharSequence concatQuoted(Collection<Object> seqs) {
6.70 if (disabled) {
6.71 StringBuilder sb = new StringBuilder("\"");
6.72 - for (Iterator<CharSequence> it = seqs.iterator(); it.hasNext();) {
6.73 - CharSequence c = it.next();
6.74 + boolean first = true;
6.75 + for (Iterator<Object> it = seqs.iterator(); it.hasNext();) {
6.76 + Object c = it.next();
6.77 + if (!first) {
6.78 + sb.append(SPACE);
6.79 + }
6.80 + if (c instanceof CharSequence) {
6.81 + sb.append(QUOTE);
6.82 + }
6.83 sb.append(c);
6.84 - if (it.hasNext()) {
6.85 - sb.append("\" \"");
6.86 - } else {
6.87 - sb.append("\"");
6.88 + if (c instanceof CharSequence) {
6.89 + sb.append(QUOTE);
6.90 }
6.91 + first = false;
6.92 }
6.93 return new StringWrapper(sb.toString());
6.94 } else {
6.95 - List<CharSequence> quoted = new ArrayList<>((seqs.size() * 2) + 1);
6.96 - quoted.add(this.QUOTE);
6.97 - for (Iterator<CharSequence> it = seqs.iterator(); it.hasNext();) {
6.98 - quoted.add(it.next());
6.99 - if (it.hasNext()) {
6.100 - quoted.add(CLOSE_OPEN_QUOTE);
6.101 + List<CharSequence> quoted = new ArrayList<>((seqs.size() * 3) + 1);
6.102 + for (Iterator<Object> it = seqs.iterator(); it.hasNext();) {
6.103 + Object c = it.next();
6.104 + if (c instanceof CharSequence) {
6.105 + quoted.add(QUOTE);
6.106 + quoted.add((CharSequence)c);
6.107 + if (it.hasNext()) {
6.108 + quoted.add(QUOTE_SPACE);
6.109 + } else {
6.110 + quoted.add(QUOTE);
6.111 + }
6.112 } else {
6.113 - quoted.add(QUOTE);
6.114 + quoted.add(create(c.toString()));
6.115 + quoted.add(SPACE);
6.116 }
6.117 }
6.118 return new Concatenation(quoted.toArray(new CharSequence[quoted.size()]));
6.119 @@ -153,6 +198,10 @@
6.120 int internTableSize() {
6.121 return INTERN_TABLE.last + 1;
6.122 }
6.123 +
6.124 + List<CharSequence> dumpInternTable() {
6.125 + return INTERN_TABLE.dumpInternTable();
6.126 + }
6.127
6.128 static class InternTable {
6.129
6.130 @@ -187,6 +236,10 @@
6.131 Arrays.sort(entries, 0, last + 1);
6.132 return entry;
6.133 }
6.134 +
6.135 + List<CharSequence> dumpInternTable() {
6.136 + return Arrays.asList(entries);
6.137 + }
6.138
6.139 private static final class Entry implements ComparableCharSequence {
6.140
6.141 @@ -316,10 +369,16 @@
6.142 private final InternTable.Entry[] entries;
6.143
6.144 Concatenation(CharSequence... entries) {
6.145 - this.entries = new InternTable.Entry[entries.length];
6.146 - for (int i = 0; i < entries.length; i++) {
6.147 - this.entries[i] = INTERN_TABLE.intern(entries[i]);
6.148 + List<InternTable.Entry> l = new ArrayList<>(entries.length);
6.149 + for (CharSequence cs : entries) {
6.150 + if (cs instanceof Concatenation) {
6.151 + Concatenation c1 = (Concatenation) cs;
6.152 + l.addAll(Arrays.asList(c1.entries));
6.153 + } else {
6.154 + l.add(INTERN_TABLE.intern(cs));
6.155 + }
6.156 }
6.157 + this.entries = l.toArray(new InternTable.Entry[l.size()]);
6.158 }
6.159
6.160 @Override
6.161 @@ -358,7 +417,7 @@
6.162 sb.append(e);
6.163 }
6.164 if (debug) {
6.165 - sb.append (" - " + Arrays.asList(entries));
6.166 + sb.append(" - ").append (Arrays.asList(entries));
6.167 }
6.168 return sb.toString();
6.169 }
7.1 --- a/callgraph/src/test/java/org/netbeans/lib/callgraph/ArgumentsTest.java Mon Aug 29 13:00:53 2016 -0400
7.2 +++ b/callgraph/src/test/java/org/netbeans/lib/callgraph/ArgumentsTest.java Sat Sep 03 02:41:36 2016 -0400
7.3 @@ -175,4 +175,59 @@
7.4 }
7.5 }
7.6
7.7 +
7.8 + @Test
7.9 + public void testAntScan() throws IOException {
7.10 + File tmp = new File(System.getProperty("java.io.tmpdir"));
7.11 + File dir = new File(tmp, ArgumentsTest.class.getSimpleName() + "_" + System.currentTimeMillis());
7.12 + File project1 = new File(dir, "prj");
7.13 + File project2 = new File(dir, "prj2");
7.14 + File pom1 = new File(project1, "build.xml");
7.15 + File pom2 = new File(project2, "build.xml");
7.16 +
7.17 + File java1 = new File(project1, "src");
7.18 + File java2 = new File(project2, "src");
7.19 +
7.20 + assertTrue(java1.mkdirs());
7.21 + assertTrue(java2.mkdirs());
7.22 + pom1.createNewFile();
7.23 + pom2.createNewFile();
7.24 + dir = dir.getCanonicalFile();
7.25 + java1 = java1.getCanonicalFile();
7.26 + java2 = java2.getCanonicalFile();
7.27 +
7.28 + Arguments a = new Arguments("-v", dir.getAbsolutePath());
7.29 + assertEquals(1, a.folders().size());
7.30 + assertEquals(dir, a.folders().iterator().next());
7.31 + List<String> errors = new ArrayList<>();
7.32 + a.findAntSubfolders(errors);
7.33 + assertTrue(errors.isEmpty());
7.34 + System.out.println("FLDS: ");
7.35 + for (File f : a.folders()) {
7.36 + System.out.println(" " + f.getAbsolutePath());
7.37 + }
7.38 + assertEquals(2, a.folders().size());
7.39 + assertFalse(a.folders().isEmpty());
7.40 + assertTrue(a.folders().contains(java1));
7.41 + assertTrue(a.folders().contains(java2));
7.42 + try {
7.43 +
7.44 + Arguments args = new Arguments("--ant", "-s", dir.getAbsolutePath());
7.45 + assertTrue(args.isAnt());
7.46 + assertTrue(args.isShortNames());
7.47 + assertTrue(args.isSelfReferences());
7.48 + assertTrue(args.folders().contains(java1));
7.49 + assertTrue(args.folders().contains(java2));
7.50 + } finally {
7.51 + // Clean up
7.52 + assertTrue(pom1.delete());
7.53 + assertTrue(pom2.delete());
7.54 + assertTrue(java1.delete());
7.55 + assertTrue(java2.delete());
7.56 + assertTrue(project1.delete());
7.57 + assertTrue(project2.delete());
7.58 + assertTrue(dir.delete());
7.59 + }
7.60 + }
7.61 +
7.62 }
8.1 --- a/callgraph/src/test/java/org/netbeans/lib/callgraph/util/SmallStringTest.java Mon Aug 29 13:00:53 2016 -0400
8.2 +++ b/callgraph/src/test/java/org/netbeans/lib/callgraph/util/SmallStringTest.java Sat Sep 03 02:41:36 2016 -0400
8.3 @@ -9,6 +9,7 @@
8.4 import java.util.Set;
8.5 import org.junit.Test;
8.6 import static org.junit.Assert.*;
8.7 +import org.netbeans.lib.callgraph.util.EightBitStrings.Concatenation;
8.8
8.9 /**
8.10 *
8.11 @@ -120,7 +121,51 @@
8.12 Collections.sort(l);
8.13 assertEquals(l, Arrays.asList(a, b, c, d, e));
8.14 }
8.15 +
8.16 + List<String> stringsOf(List<CharSequence> cs) {
8.17 + List<String> result = new ArrayList<>();
8.18 + for (CharSequence c : cs) {
8.19 + if (c == null) {
8.20 + break;
8.21 + }
8.22 + result.add(c.toString());
8.23 + }
8.24 + return result;
8.25 + }
8.26 +
8.27 + @Test
8.28 + public void testAggressive() {
8.29 + EightBitStrings strings = new EightBitStrings(false, true);
8.30 + ComparableCharSequence c = strings.concat("com.foo.", "bar.baz.", "Hey$You");
8.31 + assertEquals("com.foo.bar.baz.Hey$You", c.toString());
8.32 + ComparableCharSequence c2 = strings.concat("com.foo.", "bar.whoodle.", "Hey$You");
8.33 + List<String> interned = stringsOf(strings.dumpInternTable());
8.34 + for (String cs : interned) {
8.35 + if (cs == null) {
8.36 + break;
8.37 + }
8.38 + System.out.println(" " + cs);
8.39 + }
8.40 + assertTrue(interned.contains("com"));
8.41 + assertTrue(interned.contains("foo"));
8.42 + assertTrue(interned.contains("bar"));
8.43 + assertTrue(interned.contains("baz"));
8.44 + assertTrue(interned.contains("Hey"));
8.45 + assertTrue(interned.contains("You"));
8.46 + assertTrue(interned.contains("whoodle"));
8.47 + assertTrue(interned.contains("."));
8.48 + assertTrue(interned.contains("$"));
8.49 + assertTrue(interned.contains("\""));
8.50 + }
8.51
8.52 + @Test
8.53 + public void testConcatQuoted() {
8.54 + EightBitStrings strings = new EightBitStrings(false);
8.55 + List<Object> l = Arrays.asList(strings.create("hey"), false, 23, strings.create("bar"), "baz");
8.56 + CharSequence cc = strings.concatQuoted(l);
8.57 + assertEquals("\"hey\" false 23 \"bar\" \"baz\"", cc.toString());
8.58 + }
8.59 +
8.60 private static String randomString(int len) {
8.61 char[] c = new char[len];
8.62 for (int i = 0; i < c.length; i++) {