diff --git a/src/main/java/org/jsoup/helper/HttpConnection.java b/src/main/java/org/jsoup/helper/HttpConnection.java index db2877a7bb..425d77d0cf 100644 --- a/src/main/java/org/jsoup/helper/HttpConnection.java +++ b/src/main/java/org/jsoup/helper/HttpConnection.java @@ -465,7 +465,6 @@ public String header(String name) { @Override public T addHeader(String name, @Nullable String value) { Validate.notEmptyParam(name, "name"); - //noinspection ConstantConditions value = value == null ? "" : value; List values = headers(name); diff --git a/src/main/java/org/jsoup/nodes/Attributes.java b/src/main/java/org/jsoup/nodes/Attributes.java index 0de6a9b6b4..6a3c0b549e 100644 --- a/src/main/java/org/jsoup/nodes/Attributes.java +++ b/src/main/java/org/jsoup/nodes/Attributes.java @@ -58,8 +58,8 @@ public class Attributes implements Iterable, Cloneable { // the number of instance fields is kept as low as possible giving an object size of 24 bytes private int size = 0; // number of slots used (not total capacity, which is keys.length) - String[] keys = new String[InitialCapacity]; - Object[] vals = new Object[InitialCapacity]; // Genericish: all non-internal attribute values must be Strings and are cast on access. + @Nullable String[] keys = new String[InitialCapacity]; // keys is not null, but contents may be. Same for vals + @Nullable Object[] vals = new Object[InitialCapacity]; // Genericish: all non-internal attribute values must be Strings and are cast on access. // todo - make keys iterable without creating Attribute objects // check there's room for more @@ -119,7 +119,7 @@ public String get(String key) { @return the Attribute for this key, or null if not present. @since 1.17.2 */ - public Attribute attribute(String key) { + @Nullable Attribute attribute(String key) { int i = indexOfKey(key); return i == NotFound ? null : new Attribute(key, checkNotNull(vals[i]), this); } @@ -182,6 +182,7 @@ Map userData() { //noinspection unchecked userData = (Map) vals[i]; } + assert userData != null; return userData; } @@ -218,7 +219,9 @@ void putIgnoreCase(String key, @Nullable String value) { int i = indexOfKeyIgnoreCase(key); if (i != NotFound) { vals[i] = value; - if (!keys[i].equals(key)) // case changed, update + String old = keys[i]; + assert old != null; + if (!old.equals(key)) // case changed, update keys[i] = key; } else @@ -389,7 +392,8 @@ public Range.AttributeRange sourceRange(String key) { @Override public Iterator iterator() { - return new Iterator() { + //noinspection ReturnOfInnerClass + return new Iterator<>() { int expectedSize = size; int i = 0; @@ -397,7 +401,9 @@ public Iterator iterator() { public boolean hasNext() { checkModified(); while (i < size) { - if (isInternalKey(keys[i])) // skip over internal keys + String key = keys[i]; + assert key != null; + if (isInternalKey(key)) // skip over internal keys i++; else break; @@ -410,7 +416,9 @@ public boolean hasNext() { public Attribute next() { checkModified(); if (i >= size) throw new NoSuchElementException(); - final Attribute attr = new Attribute(keys[i], (String) vals[i], Attributes.this); + String key = keys[i]; + assert key != null; + final Attribute attr = new Attribute(key, (String) vals[i], Attributes.this); i++; return attr; } @@ -434,9 +442,11 @@ public void remove() { public List asList() { ArrayList list = new ArrayList<>(size); for (int i = 0; i < size; i++) { - if (isInternalKey(keys[i])) + String key = keys[i]; + assert key != null; + if (isInternalKey(key)) continue; // skip internal keys - Attribute attr = new Attribute(keys[i], (String) vals[i], Attributes.this); + Attribute attr = new Attribute(key, (String) vals[i], Attributes.this); list.add(attr); } return Collections.unmodifiableList(list); @@ -468,11 +478,13 @@ public String html() { final void html(final Appendable accum, final Document.OutputSettings out) throws IOException { final int sz = size; for (int i = 0; i < sz; i++) { - if (isInternalKey(keys[i])) + String key = keys[i]; + assert key != null; + if (isInternalKey(key)) continue; - final String key = Attribute.getValidKey(keys[i], out.syntax()); - if (key != null) - Attribute.htmlNoValidate(key, (String) vals[i], accum.append(' '), out); + final String validated = Attribute.getValidKey(key, out.syntax()); + if (validated != null) + Attribute.htmlNoValidate(validated, (String) vals[i], accum.append(' '), out); } } @@ -496,6 +508,7 @@ public boolean equals(@Nullable Object o) { if (size != that.size) return false; for (int i = 0; i < size; i++) { String key = keys[i]; + assert key != null; int thatI = that.indexOfKey(key); if (thatI == NotFound || !Objects.equals(vals[i], that.vals[thatI])) return false; @@ -534,8 +547,11 @@ public Attributes clone() { */ public void normalize() { for (int i = 0; i < size; i++) { - if (!isInternalKey(keys[i])) - keys[i] = lowerCase(keys[i]); + assert keys[i] != null; + String key = keys[i]; + assert key != null; + if (!isInternalKey(key)) + keys[i] = lowerCase(key); } } @@ -549,11 +565,11 @@ public int deduplicate(ParseSettings settings) { return 0; boolean preserve = settings.preserveAttributeCase(); int dupes = 0; - OUTER: for (int i = 0; i < keys.length; i++) { - for (int j = i + 1; j < keys.length; j++) { - if (keys[j] == null) - continue OUTER; // keys.length doesn't shrink when removing, so re-test - if ((preserve && keys[i].equals(keys[j])) || (!preserve && keys[i].equalsIgnoreCase(keys[j]))) { + for (int i = 0; i < size; i++) { + String keyI = keys[i]; + assert keyI != null; + for (int j = i + 1; j < size; j++) { + if ((preserve && keyI.equals(keys[j])) || (!preserve && keyI.equalsIgnoreCase(keys[j]))) { dupes++; remove(j); j--; @@ -593,7 +609,7 @@ public Iterator> iterator() { @Override public int size() { int count = 0; - Iterator iter = new DatasetIterator(); + Iterator> iter = new DatasetIterator(); while (iter.hasNext()) count++; return count; @@ -601,9 +617,9 @@ public int size() { } private class DatasetIterator implements Iterator> { - private Iterator attrIter = attributes.iterator(); + private final Iterator attrIter = attributes.iterator(); private Attribute attr; - public boolean hasNext() { + @Override public boolean hasNext() { while (attrIter.hasNext()) { attr = attrIter.next(); if (attr.isDataAttribute()) return true; @@ -611,11 +627,11 @@ public boolean hasNext() { return false; } - public Entry next() { + @Override public Entry next() { return new Attribute(attr.getKey().substring(dataPrefix.length()), attr.getValue()); } - public void remove() { + @Override public void remove() { attributes.remove(attr.getKey()); } } @@ -630,6 +646,6 @@ static String internalKey(String key) { } static boolean isInternalKey(String key) { - return key != null && key.length() > 1 && key.charAt(0) == InternalPrefix; + return key.length() > 1 && key.charAt(0) == InternalPrefix; } }