Improved graph output
authorTim Boudreau <tboudreau@netbeans.org>
Mon, 29 Aug 2016 13:00:53 -0400
changeset 183733527a32a19f0
parent 18372 25e1d840480b
child 18374 04a79821e760
Improved graph output
callgraph/src/main/java/org/netbeans/lib/callgraph/Callgraph.java
callgraph/src/main/java/org/netbeans/lib/callgraph/javac/SourceElement.java
callgraph/src/main/java/org/netbeans/lib/callgraph/util/ComparableCharSequence.java
callgraph/src/main/java/org/netbeans/lib/callgraph/util/EightBitStrings.java
callgraph/src/test/java/org/netbeans/lib/callgraph/util/SmallStringTest.java
     1.1 --- a/callgraph/src/main/java/org/netbeans/lib/callgraph/Callgraph.java	Mon Aug 29 05:21:59 2016 -0400
     1.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/Callgraph.java	Mon Aug 29 13:00:53 2016 -0400
     1.3 @@ -41,7 +41,6 @@
     1.4   * Version 2 license, then the option applies only if the new code is
     1.5   * made subject to such option by the copyright holder.
     1.6   */
     1.7 -
     1.8  package org.netbeans.lib.callgraph;
     1.9  
    1.10  import org.netbeans.lib.callgraph.Arguments.InvalidArgumentsException;
    1.11 @@ -71,8 +70,10 @@
    1.12  import java.util.LinkedList;
    1.13  import java.util.List;
    1.14  import java.util.Set;
    1.15 +import java.util.TreeSet;
    1.16  import java.util.concurrent.atomic.AtomicReference;
    1.17  import java.util.function.Consumer;
    1.18 +import org.netbeans.lib.callgraph.util.ComparableCharSequence;
    1.19  
    1.20  /**
    1.21   * Scans a source folder and runs javac against any Java sources present, and
    1.22 @@ -166,6 +167,7 @@
    1.23                      List<SourceElement> outbounds = new ArrayList<>(arguments.isReverse() ? sce.getInboundReferences() : sce.getOutboundReferences());
    1.24                      Collections.sort(outbounds); // also sort connections
    1.25                      // Iterate the current method's connections
    1.26 +                    Set<ComparableCharSequence> mth = new TreeSet<>();
    1.27                      for (SourceElement outbound : outbounds) {
    1.28                          if (arguments.isExcluded(outbound.qname().toString())) { // Ignore matches
    1.29                              continue;
    1.30 @@ -179,20 +181,12 @@
    1.31                          if (!arguments.isSelfReferences() && sce.typeName().equals(outbound.typeName())) {
    1.32                              continue;
    1.33                          }
    1.34 -                        CharSequence line;
    1.35 -                        // Build our line for the method graph output
    1.36 -                        if (arguments.isShortNames()) {
    1.37 -                            line = info.strings.concat(info.strings.QUOTE, sce.shortName(), info.strings.CLOSE_OPEN_QUOTE, outbound.shortName(), info.strings.QUOTE);
    1.38 -                        } else {
    1.39 -                            line = info.strings.concat(info.strings.QUOTE, sce.qname(), info.strings.CLOSE_OPEN_QUOTE, outbound.qname(), info.strings.QUOTE);
    1.40 -                        }
    1.41 -                        // Print to stdout
    1.42 -                        if (!arguments.isQuiet()) {
    1.43 -                            System.out.println(line);
    1.44 -                        }
    1.45 -                        // Write to file if necessary
    1.46                          if (outStream != null) {
    1.47 -                            outStream.println(line);
    1.48 +                            if (arguments.isShortNames()) {
    1.49 +                                mth.add(outbound.shortName());
    1.50 +                            } else {
    1.51 +                                mth.add(outbound.qname());
    1.52 +                            }
    1.53                          }
    1.54                          // Build the package graph output if necessary
    1.55                          if (packageStream != null) {
    1.56 @@ -224,6 +218,20 @@
    1.57                              }
    1.58                          }
    1.59                      }
    1.60 +                    if ((!arguments.isQuiet() || outStream != null)) {
    1.61 +                        if (!mth.isEmpty()) {
    1.62 +                            CharSequence nm = arguments.isShortNames() ? sce.shortName() : sce.qname();
    1.63 +                            List<CharSequence> l = new ArrayList<>(mth);
    1.64 +                            l.add(0, nm);
    1.65 +                            CharSequence line = info.strings.concatQuoted(l);
    1.66 +                            if (!arguments.isQuiet()) {
    1.67 +                                System.out.println(line);
    1.68 +                            }
    1.69 +                            if (outStream != null) {
    1.70 +                                outStream.println(line);
    1.71 +                            }
    1.72 +                        }
    1.73 +                    }
    1.74                  }
    1.75              } finally {
    1.76                  for (PrintStream ps : new PrintStream[]{outStream, packageStream, classStream}) {
     2.1 --- a/callgraph/src/main/java/org/netbeans/lib/callgraph/javac/SourceElement.java	Mon Aug 29 05:21:59 2016 -0400
     2.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/javac/SourceElement.java	Mon Aug 29 13:00:53 2016 -0400
     2.3 @@ -44,11 +44,11 @@
     2.4  
     2.5  package org.netbeans.lib.callgraph.javac;
     2.6  
     2.7 -import org.netbeans.lib.callgraph.util.EightBitStrings;
     2.8  import com.sun.source.util.TreePath;
     2.9  import java.util.Collections;
    2.10  import java.util.HashSet;
    2.11  import java.util.Set;
    2.12 +import org.netbeans.lib.callgraph.util.ComparableCharSequence;
    2.13  
    2.14  /**
    2.15   * Represents a method or field and the things that it references and that
    2.16 @@ -58,16 +58,16 @@
    2.17   */
    2.18  public final class SourceElement implements Comparable<SourceElement> {
    2.19  
    2.20 -    private final CharSequence name;
    2.21 +    private final ComparableCharSequence name;
    2.22      private final Set<SourceElement> inbound = new HashSet<>();
    2.23      private final Set<SourceElement> outbound = new HashSet<>();
    2.24      private final SourceElementKind kind;
    2.25 -    private final CharSequence type;
    2.26 -    private final CharSequence typeName;
    2.27 -    private final CharSequence parameters;
    2.28 -    private final CharSequence packageName;
    2.29 -    private final CharSequence qname;
    2.30 -    private final CharSequence shortName;
    2.31 +    private final ComparableCharSequence type;
    2.32 +    private final ComparableCharSequence typeName;
    2.33 +    private final ComparableCharSequence parameters;
    2.34 +    private final ComparableCharSequence packageName;
    2.35 +    private final ComparableCharSequence qname;
    2.36 +    private final ComparableCharSequence shortName;
    2.37      private final boolean abstrakt;
    2.38  
    2.39      public SourceElement(SourceElementKind kind, TreePath handle, String name, String type, SourcesInfo info, boolean abstrakt) {
    2.40 @@ -84,11 +84,11 @@
    2.41          this.abstrakt = abstrakt;
    2.42      }
    2.43  
    2.44 -    public CharSequence getType() {
    2.45 +    public ComparableCharSequence getType() {
    2.46          return type;
    2.47      }
    2.48  
    2.49 -    public CharSequence getName() {
    2.50 +    public ComparableCharSequence getName() {
    2.51          return name;
    2.52      }
    2.53  
    2.54 @@ -116,15 +116,15 @@
    2.55          return kind;
    2.56      }
    2.57  
    2.58 -    public CharSequence typeName() {
    2.59 +    public ComparableCharSequence typeName() {
    2.60          return typeName;
    2.61      }
    2.62  
    2.63 -    public CharSequence packageName() {
    2.64 +    public ComparableCharSequence packageName() {
    2.65          return packageName;
    2.66      }
    2.67  
    2.68 -    public CharSequence parameters() {
    2.69 +    public ComparableCharSequence parameters() {
    2.70          return parameters;
    2.71      }
    2.72      
    2.73 @@ -137,11 +137,11 @@
    2.74          return qname().toString();
    2.75      }
    2.76  
    2.77 -    public CharSequence qname() {
    2.78 +    public ComparableCharSequence qname() {
    2.79          return qname;
    2.80      }
    2.81  
    2.82 -    public CharSequence shortName() {
    2.83 +    public ComparableCharSequence shortName() {
    2.84          return shortName;
    2.85      }
    2.86  
    2.87 @@ -168,6 +168,6 @@
    2.88  
    2.89      @Override
    2.90      public int compareTo(SourceElement o) {
    2.91 -        return toString().compareTo(o.toString());
    2.92 +        return qname.compareTo(o.qname);
    2.93      }
    2.94  }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/util/ComparableCharSequence.java	Mon Aug 29 13:00:53 2016 -0400
     3.3 @@ -0,0 +1,13 @@
     3.4 +package org.netbeans.lib.callgraph.util;
     3.5 +
     3.6 +/**
     3.7 + *
     3.8 + * @author Tim Boudreau
     3.9 + */
    3.10 +public interface ComparableCharSequence extends CharSequence, Comparable<CharSequence> {
    3.11 +
    3.12 +    @Override
    3.13 +    public default int compareTo(CharSequence o) {
    3.14 +        return EightBitStrings.compareCharSequences(this, o);
    3.15 +    }
    3.16 +}
     4.1 --- a/callgraph/src/main/java/org/netbeans/lib/callgraph/util/EightBitStrings.java	Mon Aug 29 05:21:59 2016 -0400
     4.2 +++ b/callgraph/src/main/java/org/netbeans/lib/callgraph/util/EightBitStrings.java	Mon Aug 29 13:00:53 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 @@ -41,15 +41,20 @@
    4.10   * Version 2 license, then the option applies only if the new code is
    4.11   * made subject to such option by the copyright holder.
    4.12   */
    4.13 -
    4.14  package org.netbeans.lib.callgraph.util;
    4.15  
    4.16  import java.io.ByteArrayOutputStream;
    4.17  import java.io.IOException;
    4.18 +import java.io.UnsupportedEncodingException;
    4.19  import java.nio.ByteBuffer;
    4.20  import java.nio.charset.CharacterCodingException;
    4.21  import java.nio.charset.Charset;
    4.22 +import java.util.ArrayList;
    4.23  import java.util.Arrays;
    4.24 +import java.util.Collection;
    4.25 +import java.util.Iterator;
    4.26 +import java.util.List;
    4.27 +import java.util.Locale;
    4.28  
    4.29  /**
    4.30   * byte[] backed string to cut memory consumption from Strings in half for most
    4.31 @@ -77,24 +82,56 @@
    4.32          INTERN_TABLE.dispose();
    4.33      }
    4.34  
    4.35 -    public CharSequence create(CharSequence string) {
    4.36 +    public ComparableCharSequence create(CharSequence string) {
    4.37          if (disabled) {
    4.38 -            return string;
    4.39 +            return string instanceof ComparableCharSequence ? (ComparableCharSequence) string
    4.40 +                    : new StringWrapper(string.toString());
    4.41          }
    4.42          return INTERN_TABLE.intern(string);
    4.43      }
    4.44  
    4.45 -    public CharSequence concat(CharSequence... seqs) {
    4.46 +    public ComparableCharSequence concat(CharSequence... seqs) {
    4.47 +        if (seqs.length == 1 && seqs[0] instanceof ComparableCharSequence) {
    4.48 +            return (ComparableCharSequence) seqs[0];
    4.49 +        }
    4.50          if (disabled) {
    4.51              StringBuilder sb = new StringBuilder();
    4.52              for (CharSequence c : seqs) {
    4.53                  sb.append(c);
    4.54              }
    4.55 -            return sb.toString();
    4.56 +            return new StringWrapper(sb.toString());
    4.57          }
    4.58          return new Concatenation(seqs);
    4.59      }
    4.60  
    4.61 +    public ComparableCharSequence concatQuoted(Collection<CharSequence> seqs) {
    4.62 +        if (disabled) {
    4.63 +            StringBuilder sb = new StringBuilder("\"");
    4.64 +            for (Iterator<CharSequence> it = seqs.iterator(); it.hasNext();) {
    4.65 +                CharSequence c = it.next();
    4.66 +                sb.append(c);
    4.67 +                if (it.hasNext()) {
    4.68 +                    sb.append("\" \"");
    4.69 +                } else {
    4.70 +                    sb.append("\"");
    4.71 +                }
    4.72 +            }
    4.73 +            return new StringWrapper(sb.toString());
    4.74 +        } else {
    4.75 +            List<CharSequence> quoted = new ArrayList<>((seqs.size() * 2) + 1);
    4.76 +            quoted.add(this.QUOTE);
    4.77 +            for (Iterator<CharSequence> it = seqs.iterator(); it.hasNext();) {
    4.78 +                quoted.add(it.next());
    4.79 +                if (it.hasNext()) {
    4.80 +                    quoted.add(CLOSE_OPEN_QUOTE);
    4.81 +                } else {
    4.82 +                    quoted.add(QUOTE);
    4.83 +                }
    4.84 +            }
    4.85 +            return new Concatenation(quoted.toArray(new CharSequence[quoted.size()]));
    4.86 +        }
    4.87 +    }
    4.88 +
    4.89      private static byte[] toBytes(CharSequence seq) {
    4.90          try {
    4.91              ByteArrayOutputStream out = new ByteArrayOutputStream();
    4.92 @@ -151,7 +188,7 @@
    4.93              return entry;
    4.94          }
    4.95  
    4.96 -        private static final class Entry implements Comparable<CharSequence>, CharSequence {
    4.97 +        private static final class Entry implements ComparableCharSequence {
    4.98  
    4.99              private final byte[] bytes;
   4.100              private final short length;
   4.101 @@ -216,6 +253,7 @@
   4.102                  }
   4.103              }
   4.104  
   4.105 +            @Override
   4.106              public String toString() {
   4.107                  return new String(bytes, UTF);
   4.108              }
   4.109 @@ -244,12 +282,36 @@
   4.110                  if (o instanceof Entry) {
   4.111                      return compare((Entry) o);
   4.112                  }
   4.113 -                return toString().compareTo(o.toString());
   4.114 +                return compareCharSequences(this, o);
   4.115              }
   4.116          }
   4.117      }
   4.118  
   4.119 -    class Concatenation implements CharSequence {
   4.120 +    static int compareCharSequences(CharSequence a, CharSequence b) {
   4.121 +        if (a == b) {
   4.122 +            return 0;
   4.123 +        }
   4.124 +        int aLength = a.length();
   4.125 +        int bLength = b.length();
   4.126 +        int max = Math.min(aLength, bLength);
   4.127 +        for (int i = 0; i < max; i++) {
   4.128 +            if (a.charAt(i) > b.charAt(i)) {
   4.129 +                return 1;
   4.130 +            } else if (a.charAt(i) < b.charAt(i)) {
   4.131 +                return -1;
   4.132 +            }
   4.133 +        }
   4.134 +        if (aLength == bLength) {
   4.135 +            return 0;
   4.136 +        } else if (aLength > bLength) {
   4.137 +            return 1;
   4.138 +        } else {
   4.139 +            return -1;
   4.140 +        }
   4.141 +    }
   4.142 +
   4.143 +    static boolean debug;
   4.144 +    class Concatenation implements ComparableCharSequence, Comparable<CharSequence> {
   4.145  
   4.146          private final InternTable.Entry[] entries;
   4.147  
   4.148 @@ -271,15 +333,18 @@
   4.149  
   4.150          @Override
   4.151          public char charAt(int index) {
   4.152 -            int offset = 0;
   4.153 +            if (entries.length == 0) {
   4.154 +                throw new IndexOutOfBoundsException("0 length but asked for " + index);
   4.155 +            }
   4.156              for (int i = 0; i < entries.length; i++) {
   4.157 -                if (index < offset + entries[i].length) {
   4.158 -                    offset += entries[i].length;
   4.159 -                    continue;
   4.160 +                InternTable.Entry e = entries[i];
   4.161 +                if (index >= e.length) {
   4.162 +                    index -= e.length;
   4.163 +                } else {
   4.164 +                    return e.charAt(index);
   4.165                  }
   4.166 -                return entries[i].charAt(index - offset);
   4.167              }
   4.168 -            throw new IndexOutOfBoundsException(index + " of " + length() + " in " + this);
   4.169 +            throw new IndexOutOfBoundsException(index + " of " + length() + " in " + this + " with entries " + Arrays.asList(entries));
   4.170          }
   4.171  
   4.172          @Override
   4.173 @@ -292,6 +357,9 @@
   4.174              for (InternTable.Entry e : entries) {
   4.175                  sb.append(e);
   4.176              }
   4.177 +            if (debug) {
   4.178 +                sb.append (" - " + Arrays.asList(entries));
   4.179 +            }
   4.180              return sb.toString();
   4.181          }
   4.182  
   4.183 @@ -313,6 +381,11 @@
   4.184          }
   4.185  
   4.186          public boolean equals(Object o) {
   4.187 +            if (true) {
   4.188 +                if (o instanceof CharSequence) {
   4.189 +                    return charSequencesEqual(this, (CharSequence) o);
   4.190 +                }
   4.191 +            }
   4.192              if (o == this) {
   4.193                  return true;
   4.194              } else if (o == null) {
   4.195 @@ -320,9 +393,12 @@
   4.196              } else if (o instanceof Concatenation) {
   4.197                  Concatenation c = (Concatenation) o;
   4.198                  if (c.entries.length != entries.length) {
   4.199 -                    return false;
   4.200 +                    return charSequencesEqual(this, c);
   4.201                  }
   4.202                  for (int i = 0; i < entries.length; i++) {
   4.203 +                    if (entries[i].length() != entries[i].length) {
   4.204 +                        return charSequencesEqual(this, c);
   4.205 +                    }
   4.206                      if (!entries[i].equals(c.entries[i])) {
   4.207                          return false;
   4.208                      }
   4.209 @@ -334,6 +410,11 @@
   4.210                  return false;
   4.211              }
   4.212          }
   4.213 +
   4.214 +        @Override
   4.215 +        public int compareTo(CharSequence o) {
   4.216 +            return compareCharSequences(this, o);
   4.217 +        }
   4.218      }
   4.219  
   4.220      private static boolean charSequencesEqual(CharSequence a, CharSequence b) {
   4.221 @@ -343,10 +424,300 @@
   4.222              return false;
   4.223          }
   4.224          for (int i = 0; i < maxA; i++) {
   4.225 -            if (a.charAt(i) != b.charAt(i)) {
   4.226 +            char aa = a.charAt(i);
   4.227 +            char bb = b.charAt(i);
   4.228 +            if (aa != bb) {
   4.229                  return false;
   4.230              }
   4.231          }
   4.232          return true;
   4.233      }
   4.234 +
   4.235 +    static class StringWrapper implements ComparableCharSequence {
   4.236 +
   4.237 +        private final String s;
   4.238 +
   4.239 +        public StringWrapper(String s) {
   4.240 +            this.s = s;
   4.241 +        }
   4.242 +
   4.243 +        public int length() {
   4.244 +            return s.length();
   4.245 +        }
   4.246 +
   4.247 +        public boolean isEmpty() {
   4.248 +            return s.isEmpty();
   4.249 +        }
   4.250 +
   4.251 +        public char charAt(int index) {
   4.252 +            return s.charAt(index);
   4.253 +        }
   4.254 +
   4.255 +        public int codePointAt(int index) {
   4.256 +            return s.codePointAt(index);
   4.257 +        }
   4.258 +
   4.259 +        public int codePointBefore(int index) {
   4.260 +            return s.codePointBefore(index);
   4.261 +        }
   4.262 +
   4.263 +        public int codePointCount(int beginIndex, int endIndex) {
   4.264 +            return s.codePointCount(beginIndex, endIndex);
   4.265 +        }
   4.266 +
   4.267 +        public int offsetByCodePoints(int index, int codePointOffset) {
   4.268 +            return s.offsetByCodePoints(index, codePointOffset);
   4.269 +        }
   4.270 +
   4.271 +        public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
   4.272 +            s.getChars(srcBegin, srcEnd, dst, dstBegin);
   4.273 +        }
   4.274 +
   4.275 +        public void getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) {
   4.276 +            s.getBytes(srcBegin, srcEnd, dst, dstBegin);
   4.277 +        }
   4.278 +
   4.279 +        public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
   4.280 +            return s.getBytes(charsetName);
   4.281 +        }
   4.282 +
   4.283 +        public byte[] getBytes(Charset charset) {
   4.284 +            return s.getBytes(charset);
   4.285 +        }
   4.286 +
   4.287 +        public byte[] getBytes() {
   4.288 +            return s.getBytes();
   4.289 +        }
   4.290 +
   4.291 +        public boolean equals(Object anObject) {
   4.292 +            if (anObject == this) {
   4.293 +                return true;
   4.294 +            }
   4.295 +            if (anObject == null) {
   4.296 +                return false;
   4.297 +            }
   4.298 +            if (!(anObject instanceof CharSequence)) {
   4.299 +                return false;
   4.300 +            }
   4.301 +            return charSequencesEqual(this, (CharSequence) anObject);
   4.302 +        }
   4.303 +
   4.304 +        public boolean contentEquals(StringBuffer sb) {
   4.305 +            return s.contentEquals(sb);
   4.306 +        }
   4.307 +
   4.308 +        public boolean contentEquals(CharSequence cs) {
   4.309 +            return s.contentEquals(cs);
   4.310 +        }
   4.311 +
   4.312 +        public boolean equalsIgnoreCase(String anotherString) {
   4.313 +            return s.equalsIgnoreCase(anotherString);
   4.314 +        }
   4.315 +
   4.316 +        public int compareTo(CharSequence anotherString) {
   4.317 +            return compareCharSequences(this, anotherString);
   4.318 +        }
   4.319 +
   4.320 +        public int compareToIgnoreCase(String str) {
   4.321 +            return s.compareToIgnoreCase(str);
   4.322 +        }
   4.323 +
   4.324 +        public boolean regionMatches(int toffset, String other, int ooffset, int len) {
   4.325 +            return s.regionMatches(toffset, other, ooffset, len);
   4.326 +        }
   4.327 +
   4.328 +        public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) {
   4.329 +            return s.regionMatches(ignoreCase, toffset, other, ooffset, len);
   4.330 +        }
   4.331 +
   4.332 +        public boolean startsWith(String prefix, int toffset) {
   4.333 +            return s.startsWith(prefix, toffset);
   4.334 +        }
   4.335 +
   4.336 +        public boolean startsWith(String prefix) {
   4.337 +            return s.startsWith(prefix);
   4.338 +        }
   4.339 +
   4.340 +        public boolean endsWith(String suffix) {
   4.341 +            return s.endsWith(suffix);
   4.342 +        }
   4.343 +
   4.344 +        @Override
   4.345 +        public int hashCode() {
   4.346 +            return s.hashCode();
   4.347 +        }
   4.348 +
   4.349 +        public int indexOf(int ch) {
   4.350 +            return s.indexOf(ch);
   4.351 +        }
   4.352 +
   4.353 +        public int indexOf(int ch, int fromIndex) {
   4.354 +            return s.indexOf(ch, fromIndex);
   4.355 +        }
   4.356 +
   4.357 +        public int lastIndexOf(int ch) {
   4.358 +            return s.lastIndexOf(ch);
   4.359 +        }
   4.360 +
   4.361 +        public int lastIndexOf(int ch, int fromIndex) {
   4.362 +            return s.lastIndexOf(ch, fromIndex);
   4.363 +        }
   4.364 +
   4.365 +        public int indexOf(String str) {
   4.366 +            return s.indexOf(str);
   4.367 +        }
   4.368 +
   4.369 +        public int indexOf(String str, int fromIndex) {
   4.370 +            return s.indexOf(str, fromIndex);
   4.371 +        }
   4.372 +
   4.373 +        public int lastIndexOf(String str) {
   4.374 +            return s.lastIndexOf(str);
   4.375 +        }
   4.376 +
   4.377 +        public int lastIndexOf(String str, int fromIndex) {
   4.378 +            return s.lastIndexOf(str, fromIndex);
   4.379 +        }
   4.380 +
   4.381 +        public String substring(int beginIndex) {
   4.382 +            return s.substring(beginIndex);
   4.383 +        }
   4.384 +
   4.385 +        public String substring(int beginIndex, int endIndex) {
   4.386 +            return s.substring(beginIndex, endIndex);
   4.387 +        }
   4.388 +
   4.389 +        public CharSequence subSequence(int beginIndex, int endIndex) {
   4.390 +            return s.subSequence(beginIndex, endIndex);
   4.391 +        }
   4.392 +
   4.393 +        public String concat(String str) {
   4.394 +            return s.concat(str);
   4.395 +        }
   4.396 +
   4.397 +        public String replace(char oldChar, char newChar) {
   4.398 +            return s.replace(oldChar, newChar);
   4.399 +        }
   4.400 +
   4.401 +        public boolean matches(String regex) {
   4.402 +            return s.matches(regex);
   4.403 +        }
   4.404 +
   4.405 +        public boolean contains(CharSequence s) {
   4.406 +            return this.s.contains(s);
   4.407 +        }
   4.408 +
   4.409 +        public String replaceFirst(String regex, String replacement) {
   4.410 +            return s.replaceFirst(regex, replacement);
   4.411 +        }
   4.412 +
   4.413 +        public String replaceAll(String regex, String replacement) {
   4.414 +            return s.replaceAll(regex, replacement);
   4.415 +        }
   4.416 +
   4.417 +        public String replace(CharSequence target, CharSequence replacement) {
   4.418 +            return s.replace(target, replacement);
   4.419 +        }
   4.420 +
   4.421 +        public String[] split(String regex, int limit) {
   4.422 +            return s.split(regex, limit);
   4.423 +        }
   4.424 +
   4.425 +        public String[] split(String regex) {
   4.426 +            return s.split(regex);
   4.427 +        }
   4.428 +
   4.429 +        public static String join(CharSequence delimiter, CharSequence... elements) {
   4.430 +            return String.join(delimiter, elements);
   4.431 +        }
   4.432 +
   4.433 +        public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements) {
   4.434 +            return String.join(delimiter, elements);
   4.435 +        }
   4.436 +
   4.437 +        public String toLowerCase(Locale locale) {
   4.438 +            return s.toLowerCase(locale);
   4.439 +        }
   4.440 +
   4.441 +        public String toLowerCase() {
   4.442 +            return s.toLowerCase();
   4.443 +        }
   4.444 +
   4.445 +        public String toUpperCase(Locale locale) {
   4.446 +            return s.toUpperCase(locale);
   4.447 +        }
   4.448 +
   4.449 +        public String toUpperCase() {
   4.450 +            return s.toUpperCase();
   4.451 +        }
   4.452 +
   4.453 +        public String trim() {
   4.454 +            return s.trim();
   4.455 +        }
   4.456 +
   4.457 +        public String toString() {
   4.458 +            return s.toString();
   4.459 +        }
   4.460 +
   4.461 +        public char[] toCharArray() {
   4.462 +            return s.toCharArray();
   4.463 +        }
   4.464 +
   4.465 +        public static String format(String format, Object... args) {
   4.466 +            return String.format(format, args);
   4.467 +        }
   4.468 +
   4.469 +        public static String format(Locale l, String format, Object... args) {
   4.470 +            return String.format(l, format, args);
   4.471 +        }
   4.472 +
   4.473 +        public static String valueOf(Object obj) {
   4.474 +            return String.valueOf(obj);
   4.475 +        }
   4.476 +
   4.477 +        public static String valueOf(char[] data) {
   4.478 +            return String.valueOf(data);
   4.479 +        }
   4.480 +
   4.481 +        public static String valueOf(char[] data, int offset, int count) {
   4.482 +            return String.valueOf(data, offset, count);
   4.483 +        }
   4.484 +
   4.485 +        public static String copyValueOf(char[] data, int offset, int count) {
   4.486 +            return String.copyValueOf(data, offset, count);
   4.487 +        }
   4.488 +
   4.489 +        public static String copyValueOf(char[] data) {
   4.490 +            return String.copyValueOf(data);
   4.491 +        }
   4.492 +
   4.493 +        public static String valueOf(boolean b) {
   4.494 +            return String.valueOf(b);
   4.495 +        }
   4.496 +
   4.497 +        public static String valueOf(char c) {
   4.498 +            return String.valueOf(c);
   4.499 +        }
   4.500 +
   4.501 +        public static String valueOf(int i) {
   4.502 +            return String.valueOf(i);
   4.503 +        }
   4.504 +
   4.505 +        public static String valueOf(long l) {
   4.506 +            return String.valueOf(l);
   4.507 +        }
   4.508 +
   4.509 +        public static String valueOf(float f) {
   4.510 +            return String.valueOf(f);
   4.511 +        }
   4.512 +
   4.513 +        public static String valueOf(double d) {
   4.514 +            return String.valueOf(d);
   4.515 +        }
   4.516 +
   4.517 +        public String intern() {
   4.518 +            return s.intern();
   4.519 +        }
   4.520 +
   4.521 +    }
   4.522  }
     5.1 --- a/callgraph/src/test/java/org/netbeans/lib/callgraph/util/SmallStringTest.java	Mon Aug 29 05:21:59 2016 -0400
     5.2 +++ b/callgraph/src/test/java/org/netbeans/lib/callgraph/util/SmallStringTest.java	Mon Aug 29 13:00:53 2016 -0400
     5.3 @@ -1,7 +1,8 @@
     5.4  package org.netbeans.lib.callgraph.util;
     5.5  
     5.6 -import org.netbeans.lib.callgraph.util.EightBitStrings;
     5.7  import java.util.ArrayList;
     5.8 +import java.util.Arrays;
     5.9 +import java.util.Collections;
    5.10  import java.util.HashSet;
    5.11  import java.util.List;
    5.12  import java.util.Random;
    5.13 @@ -66,7 +67,58 @@
    5.14          assertEquals("Hello there how are you?", concat.toString());
    5.15          assertEquals("Hello there how are you?".hashCode(), concat.toString().hashCode());
    5.16          assertEquals(concat, concat2);
    5.17 +    }
    5.18  
    5.19 +    @Test
    5.20 +    public void testSorting() {
    5.21 +        EightBitStrings strings = new EightBitStrings(false);
    5.22 +        ComparableCharSequence a = strings.concat(strings.create("a"), strings.create("b"), strings.create("c"), strings.create("d"));
    5.23 +        ComparableCharSequence b = strings.concat(strings.create("a"), strings.create("b"), strings.create("cd"));
    5.24 +        ComparableCharSequence c = strings.concat(strings.create("ab"), strings.create("cd"));
    5.25 +        ComparableCharSequence d = strings.concat(strings.create("a"), strings.create("bcd"));
    5.26 +        ComparableCharSequence e = strings.concat(strings.create("abcd"));
    5.27 +        assertEquals(4, a.length());
    5.28 +        assertEquals(4, b.length());
    5.29 +        assertEquals(4, c.length());
    5.30 +        assertEquals(4, d.length());
    5.31 +        assertEquals(4, e.length());
    5.32 +        for (ComparableCharSequence c1 : new ComparableCharSequence[]{a, b, c, d, e}) {
    5.33 +            for (ComparableCharSequence c2 : new ComparableCharSequence[]{a, b, c, d, e}) {
    5.34 +                assertEquals(c1, c2);
    5.35 +                assertEquals(0, c1.compareTo(c2));
    5.36 +            }
    5.37 +        }
    5.38 +
    5.39 +        ComparableCharSequence cs = strings.concatQuoted(Arrays.asList(strings.create("a"), strings.create("b"), strings.create("c"), strings.create("d")));
    5.40 +        assertEquals("\"a\" \"b\" \"c\" \"d\"", cs.toString());
    5.41 +
    5.42 +        strings = new EightBitStrings(true);
    5.43 +        a = strings.concat("a", "b", "c", "d");
    5.44 +        b = strings.concat("a", "b", "cd");
    5.45 +        c = strings.concat("ab", "cd");
    5.46 +        d = strings.concat("a", "bcd");
    5.47 +        e = strings.concat("abcd");
    5.48 +        assertEquals(4, a.length());
    5.49 +        assertEquals(4, b.length());
    5.50 +        assertEquals(4, c.length());
    5.51 +        assertEquals(4, d.length());
    5.52 +        assertEquals(4, e.length());
    5.53 +        for (ComparableCharSequence c1 : new ComparableCharSequence[]{a, b, c, d, e}) {
    5.54 +            for (ComparableCharSequence c2 : new ComparableCharSequence[]{a, b, c, d, e}) {
    5.55 +                assertEquals(c1, c2);
    5.56 +                assertEquals(0, c1.compareTo(c2));
    5.57 +            }
    5.58 +        }
    5.59 +
    5.60 +        strings = new EightBitStrings(false);
    5.61 +        a = strings.concat(strings.create("abc"), strings.create("def"));
    5.62 +        b = strings.concat("bcd", strings.create("efg"));
    5.63 +        c = strings.concat("cde", strings.create("fgh"));
    5.64 +        d = strings.create("defghi");
    5.65 +        e = strings.create("efghij");
    5.66 +        List<ComparableCharSequence> l = Arrays.asList(e, c, d, a, b);
    5.67 +        Collections.sort(l);
    5.68 +        assertEquals(l, Arrays.asList(a, b, c, d, e));
    5.69      }
    5.70  
    5.71      private static String randomString(int len) {