diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 7855cad769..ac33bd296f 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -822,6 +822,12 @@ def main() -> None: "REC_CATCH_EXCEPTION", "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE", "RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT", + "INT_VACUOUS_COMPARISON", + "DM_STRING_TOSTRING", + "HE_HASHCODE_USE_OBJECT_EQUALS", + "IM_BAD_CHECK_FOR_ODD", + "IT_NO_SUCH_ELEMENT", + "FL_FLOATS_AS_LOOP_COUNTERS", "UI_INHERITANCE_UNSAFE_GETRESOURCE", "URF_UNREAD_FIELD", "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", diff --git a/CodenameOne/src/com/codename1/charts/views/PieSegment.java b/CodenameOne/src/com/codename1/charts/views/PieSegment.java index caf8bee97e..756bba6087 100644 --- a/CodenameOne/src/com/codename1/charts/views/PieSegment.java +++ b/CodenameOne/src/com/codename1/charts/views/PieSegment.java @@ -52,9 +52,10 @@ public boolean isInSegment(double angle) { double cAngle = angle % 360; double startAngle = mStartAngle; double stopAngle = mEndAngle; - while (stopAngle > 360) { - startAngle -= 360; - stopAngle -= 360; + if (stopAngle > 360) { + int rotations = (int) Math.floor(stopAngle / 360d); + startAngle -= 360 * rotations; + stopAngle -= 360 * rotations; } return cAngle >= startAngle && cAngle <= stopAngle; } diff --git a/CodenameOne/src/com/codename1/charts/views/RadarChart.java b/CodenameOne/src/com/codename1/charts/views/RadarChart.java index 7adb92969e..7bc8de3671 100644 --- a/CodenameOne/src/com/codename1/charts/views/RadarChart.java +++ b/CodenameOne/src/com/codename1/charts/views/RadarChart.java @@ -112,8 +112,9 @@ public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint paint.setColor(ColorUtil.GRAY); float thisRad = (float) Math.toRadians(90 - currentAngle); float nextRad = (float) Math.toRadians(90 - (currentAngle + angle)); - for (double level = 0; level <= 1d; level += decCoef) { // PMD Fix: DontUseFloatTypeForLoopIndices switched to double - float levelFactor = (float) level; + int levelSteps = (int) Math.round(1d / decCoef); + for (int level = 0; level <= levelSteps; level++) { + float levelFactor = (float) (level * decCoef); float thisX = (float) (centerX - Math.sin(thisRad) * radius * levelFactor); float thisY = (float) (centerY - Math.cos(thisRad) * radius * levelFactor); float nextX = (float) (centerX - Math.sin(nextRad) * radius * levelFactor); diff --git a/CodenameOne/src/com/codename1/io/MultipartRequest.java b/CodenameOne/src/com/codename1/io/MultipartRequest.java index 7a383cd34a..ff026cc1ef 100644 --- a/CodenameOne/src/com/codename1/io/MultipartRequest.java +++ b/CodenameOne/src/com/codename1/io/MultipartRequest.java @@ -269,9 +269,9 @@ protected long calculateContentLength() { length += key.length(); if (ignoreEncoding.contains(key)) { try { - length += value.toString().getBytes("UTF-8").length; + length += ((String) value).getBytes("UTF-8").length; } catch (UnsupportedEncodingException ex) { - length += StringUtil.getBytes(value.toString()).length; + length += StringUtil.getBytes((String) value).length; } } else { if (base64Binaries) { @@ -287,9 +287,9 @@ protected long calculateContentLength() { length += key.length(); if (ignoreEncoding.contains(key)) { try { - length += s.toString().getBytes("UTF-8").length; + length += s.getBytes("UTF-8").length; } catch (UnsupportedEncodingException ex) { - length += StringUtil.getBytes(value.toString()).length; + length += StringUtil.getBytes(s).length; } } else { if (base64Binaries) { @@ -534,4 +534,4 @@ public int hashCode() { result = 31 * result + (args != null ? args.hashCode() : 0); return result; } -} \ No newline at end of file +} diff --git a/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java b/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java index a143338ed6..4294da0491 100644 --- a/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java +++ b/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java @@ -48,6 +48,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; /** * This class is used to build, invoke the http request and to get the http @@ -249,8 +250,8 @@ public RequestBuilder queryParam(String key, String[] values) { */ public RequestBuilder header(String key, String value) { checkFetched(); - // .toString() is used to trigger an NPE early for null headers - headers.put(key.toString(), value.toString()); + headers.put(Objects.requireNonNull(key, "Header key cannot be null"), + Objects.requireNonNull(value, "Header value cannot be null")); return this; } diff --git a/CodenameOne/src/com/codename1/properties/PropertyIndex.java b/CodenameOne/src/com/codename1/properties/PropertyIndex.java index 9ed9fe4770..1956334faf 100644 --- a/CodenameOne/src/com/codename1/properties/PropertyIndex.java +++ b/CodenameOne/src/com/codename1/properties/PropertyIndex.java @@ -55,6 +55,7 @@ import java.util.List; import java.util.Map; import java.util.Enumeration; +import java.util.NoSuchElementException; /** * Maps the properties that are in a class/object and provides access to them so tools such as ORM @@ -198,9 +199,10 @@ public void remove() { } public PropertyBase next() { - int i = off; - off++; - return properties[i]; + if (!hasNext()) { + throw new NoSuchElementException(); + } + return properties[off++]; } }; } diff --git a/CodenameOne/src/com/codename1/properties/PropertyXMLElement.java b/CodenameOne/src/com/codename1/properties/PropertyXMLElement.java index 54601eed8f..d885a27ae6 100644 --- a/CodenameOne/src/com/codename1/properties/PropertyXMLElement.java +++ b/CodenameOne/src/com/codename1/properties/PropertyXMLElement.java @@ -29,6 +29,8 @@ import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Vector; /** @@ -295,7 +297,21 @@ public boolean isEmpty() { @Override public int hashCode() { - return parent.hashCode(); + return Objects.hash(parent, parentElement, index); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof PropertyXMLElement)) { + return false; + } + PropertyXMLElement other = (PropertyXMLElement) obj; + return index == other.index + && Objects.equals(parent, other.parent) + && Objects.equals(parentElement, other.parentElement); } @Override @@ -330,8 +346,10 @@ public boolean hasNext() { @Override public Element next() { - offset++; - return getChildAt(index); + if (!hasNext()) { + throw new NoSuchElementException(); + } + return getChildAt(offset++); } @Override diff --git a/CodenameOne/src/com/codename1/ui/geom/Rectangle.java b/CodenameOne/src/com/codename1/ui/geom/Rectangle.java index 292db87755..b84a036fa9 100644 --- a/CodenameOne/src/com/codename1/ui/geom/Rectangle.java +++ b/CodenameOne/src/com/codename1/ui/geom/Rectangle.java @@ -188,16 +188,6 @@ public static void intersection(int rrX, int rrY, int rrW, int rrH, int rtx1, in tx2 -= tx1; ty2 -= ty1; - // tx2,ty2 will never overflow (they will never be - // larger than the smallest of the two source w,h) - // they might underflow, though... - if (tx2 < Integer.MIN_VALUE) { - tx2 = Integer.MIN_VALUE; - } - if (ty2 < Integer.MIN_VALUE) { - ty2 = Integer.MIN_VALUE; - } - dest.x = tx1; dest.y = ty1; dest.size.setWidth(tx2); @@ -422,16 +412,6 @@ public Rectangle intersection(int rX, int rY, int rW, int rH) { } tx2 -= tx1; ty2 -= ty1; - // tx2,ty2 will never overflow (they will never be - // larger than the smallest of the two source w,h) - // they might underflow, though... - if (tx2 < Integer.MIN_VALUE) { - tx2 = Integer.MIN_VALUE; - } - if (ty2 < Integer.MIN_VALUE) { - ty2 = Integer.MIN_VALUE; - } - return new Rectangle(tx1, ty1, tx2, ty2); } @@ -462,15 +442,6 @@ public void intersection(Rectangle input, Rectangle output) { } tx2 -= tx1; ty2 -= ty1; - // tx2,ty2 will never overflow (they will never be - // larger than the smallest of the two source w,h) - // they might underflow, though... - if (tx2 < Integer.MIN_VALUE) { - tx2 = Integer.MIN_VALUE; - } - if (ty2 < Integer.MIN_VALUE) { - ty2 = Integer.MIN_VALUE; - } tx2 = Math.max(0, tx2); ty2 = Math.max(0, ty2); output.setBounds(tx1, ty1, tx2, ty2); diff --git a/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java b/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java index c6128d94f1..3c3313e7f7 100644 --- a/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java +++ b/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java @@ -969,7 +969,7 @@ public static UnitValue[] parseInsets(String s, boolean acceptPanel) { String[] insS = toTrimmedTokens(s, ' '); UnitValue[] ins = new UnitValue[4]; for (int j = 0; j < 4; j++) { - UnitValue insSz = parseUnitValue(insS[j < insS.length ? j : insS.length - 1], UnitValue.ZERO, j % 2 == 1); + UnitValue insSz = parseUnitValue(insS[j < insS.length ? j : insS.length - 1], UnitValue.ZERO, (j & 1) != 0); ins[j] = insSz != null ? insSz : PlatformDefaults.getPanelInsets(j); } return ins; diff --git a/CodenameOne/src/com/codename1/ui/layouts/mig/UnitValue.java b/CodenameOne/src/com/codename1/ui/layouts/mig/UnitValue.java index ef83274fff..cb1e34268f 100644 --- a/CodenameOne/src/com/codename1/ui/layouts/mig/UnitValue.java +++ b/CodenameOne/src/com/codename1/ui/layouts/mig/UnitValue.java @@ -35,8 +35,10 @@ import com.codename1.util.MathUtil; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Objects; public final class UnitValue { /** @@ -617,7 +619,33 @@ public String getConstraintString() { return LayoutUtil.getCCString(this); } - public int hashCode() { - return (int) (value * 12345) + (oper >>> 5) + unit >>> 17; - } -} + public int hashCode() { + int result = 17; + result = 31 * result + Float.floatToIntBits(value); + result = 31 * result + unit; + result = 31 * result + oper; + result = 31 * result + (isHor ? 1 : 0); + result = 31 * result + (unitStr != null ? unitStr.hashCode() : 0); + result = 31 * result + (linkId != null ? linkId.hashCode() : 0); + result = 31 * result + Arrays.hashCode(subUnits); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof UnitValue)) { + return false; + } + UnitValue other = (UnitValue) obj; + return Float.compare(value, other.value) == 0 + && unit == other.unit + && oper == other.oper + && isHor == other.isHor + && Objects.equals(unitStr, other.unitStr) + && Objects.equals(linkId, other.linkId) + && Arrays.equals(subUnits, other.subUnits); + } +} diff --git a/CodenameOne/src/com/codename1/ui/plaf/RoundRectBorder.java b/CodenameOne/src/com/codename1/ui/plaf/RoundRectBorder.java index 91d3b46ba0..4d22101d86 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/RoundRectBorder.java +++ b/CodenameOne/src/com/codename1/ui/plaf/RoundRectBorder.java @@ -886,7 +886,7 @@ private GeneralPath createShape(int shapeW, int shapeH) { x += strokePx / 2f; y += strokePx / 2f; - if (strokePx % 2 == 1) { + if ((strokePx & 1) != 0) { x += 0.5f; y += 0.5f; }