Skip to content

RC-350 Unify ruling expectation file locations. - #6103

Merged
romainbrenguier merged 7 commits into
masterfrom
romain/normalize-ruling-expectations
Sep 23, 2026
Merged

romainbrenguier merged 7 commits into
masterfrom
romain/normalize-ruling-expectations

Conversation

@romainbrenguier

@romainbrenguier romainbrenguier commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Normalize ruling expectation file locations so that it is consistent across all analyzers.

  • Move ruling expectation JSON files from its/ruling/src/test/resources/<project>/ to its/ruling/src/test/resources/expected/<project>/
  • Update JavaRulingTest to read expectations from the new path

Test plan

  • Verify ruling tests pass on CI with the new file locations

🤖 Generated with Claude Code

Agent workflow

Tool link: Tool link: https://github.com/SonarSource/languages-experimental-tooling/tree/romain/my-tickets/personal/romain-brenguier

Iterated on the PR with uv run ci_loop.py for 4 iterations.
✔️ The PR is now ready for review.

Iterated on the PR with uv run ci_loop.py for 0 iterations.
✔️ The PR is now ready for review.

Iterated on the PR with uv run ci_loop.py for 0 iterations.
✔️ The PR is now ready for review.

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

RC-350

Comment thread its/ruling/src/test/java/org/sonar/java/it/JavaRulingTest.java Outdated
@romainbrenguier
romainbrenguier force-pushed the romain/normalize-ruling-expectations branch from 7ca009e to caa2455 Compare September 16, 2026 08:12
@romainbrenguier romainbrenguier changed the title RC-350 Unify ruling expectation file locations RC-350 Unify ruling expectation file locations. Sep 16, 2026
@datadog-sonarsource

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

❌ Ruling needs updating. A fix PR has been created: #6170

Please review and merge it into your branch.

romainbrenguier pushed a commit that referenced this pull request Sep 16, 2026
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Ruling Diff Summary

Detected changes in 1252 rule files: 0 issues removed, 164136 issues added.

S103 (java) on commons-beanutils - 0 issues removed, 24 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/BeanPropertyValueChangeClosure.java (line 134)

       129 |      * object.
       130 |      * @param ignoreNull Determines whether <code>null</code> objects in the property path will
       131 |      * genenerate an <code>IllegalArgumentException</code> or not.
       132 |      * @throws IllegalArgumentException If the propertyName provided is null or empty.
       133 |      */
>>>    134 |     public BeanPropertyValueChangeClosure(final String propertyName, final Object propertyValue, final boolean ignoreNull) {
       135 |         super();
       136 | 
       137 |         if (propertyName != null && propertyName.length() > 0) {
       138 |             this.propertyName = propertyName;
       139 |             this.propertyValue = propertyValue;

Added src/main/java/org/apache/commons/beanutils2/BeanPropertyValueEqualsPredicate.java (line 164)

       159 |      * @param propertyValue The value to use in object evaluation.
       160 |      * @param ignoreNull Determines whether <code>null</code> objects in the property path will
       161 |      * genenerate an <code>IllegalArgumentException</code> or not.
       162 |      * @throws IllegalArgumentException If the property name provided is null or empty.
       163 |      */
>>>    164 |     public BeanPropertyValueEqualsPredicate(final String propertyName, final Object propertyValue, final boolean ignoreNull) {
       165 |         super();
       166 | 
       167 |         if (propertyName != null && propertyName.length() > 0) {
       168 |             this.propertyName = propertyName;
       169 |             this.propertyValue = propertyValue;

Added src/main/java/org/apache/commons/beanutils2/MethodUtils.java (line 1319)

      1314 |          * @param cls  the class to reflect, must not be null
      1315 |          * @param methodName  the method name to obtain
      1316 |          * @param paramTypes the array of classes representing the parameter types
      1317 |          * @param exact whether the match has to be exact.
      1318 |          */
>>>   1319 |         public MethodDescriptor(final Class<?> cls, final String methodName, Class<?>[] paramTypes, final boolean exact) {
      1320 |             if (cls == null) {
      1321 |                 throw new IllegalArgumentException("Class cannot be null");
      1322 |             }
      1323 |             if (methodName == null) {
      1324 |                 throw new IllegalArgumentException("Method Name cannot be null");

Added src/main/java/org/apache/commons/beanutils2/RowSetDynaClass.java (line 236)

       231 |      *  is <code>null</code>
       232 |      * @throws SQLException if the metadata for this result set
       233 |      *  cannot be introspected
       234 |      * @since 1.8.3
       235 |      */
>>>    236 |     public RowSetDynaClass(final ResultSet resultSet, final boolean lowerCase, final int limit, final boolean useColumnLabel)
       237 |                                                             throws SQLException {
       238 | 
       239 |         if (resultSet == null) {
       240 |             throw new NullPointerException();
       241 |         }

Added src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java (line 555)

       550 |      * @param format The DateFormat to parse the String value.
       551 |      *
       552 |      * @return The converted Calendar object.
       553 |      * @throws ConversionException if the String cannot be converted.
       554 |      */
>>>    555 |     private Calendar parse(final Class<?> sourceType, final Class<?> targetType, final String value, final DateFormat format) {
       556 |         logFormat("Parsing", format);
       557 |         format.setLenient(false);
       558 |         final ParsePosition pos = new ParsePosition(0);
       559 |         final Date parsedDate = format.parse(value, pos); // ignore the result (use the Calendar)
       560 |         if (pos.getErrorIndex() >= 0 || pos.getIndex() != value.length() || parsedDate == null) {

Added src/main/java/org/apache/commons/beanutils2/converters/NumberConverter.java (line 546)

       541 |      * @param format The NumberFormat to parse the String value.
       542 |      *
       543 |      * @return The converted Number object.
       544 |      * @throws ConversionException if the String cannot be converted.
       545 |      */
>>>    546 |     private Number parse(final Class<?> sourceType, final Class<?> targetType, final String value, final NumberFormat format) {
       547 |         final ParsePosition pos = new ParsePosition(0);
       548 |         final Number parsedNumber = format.parse(value, pos);
       549 |         if (pos.getErrorIndex() >= 0 || pos.getIndex() != value.length() || parsedNumber == null) {
       550 |             String msg = "Error converting from '" + toString(sourceType) + "' to '" + toString(targetType) + "'";
       551 |             if (format instanceof DecimalFormat) {

Added src/main/java/org/apache/commons/beanutils2/locale/BaseLocaleConverter.java (line 111)

       106 |      * @param defaultValue  The default value to be returned
       107 |      * @param locale        The locale
       108 |      * @param pattern       The convertion pattern
       109 |      * @param locPattern    Indicate whether the pattern is localized or not
       110 |      */
>>>    111 |     protected BaseLocaleConverter(final Object defaultValue, final Locale locale, final String pattern, final boolean locPattern) {
       112 | 
       113 |         this(defaultValue, locale, pattern, true, locPattern);
       114 |     }
       115 | 
       116 |     /**

Added src/main/java/org/apache/commons/beanutils2/locale/LocaleBeanUtils.java (line 618)

       613 |      * @throws InvocationTargetException if the property accessor method
       614 |      *  throws an exception
       615 |      *
       616 |      * @see LocaleBeanUtilsBean#invokeSetter(Object, String, String, int, Object)
       617 |      */
>>>    618 |     protected static void invokeSetter(final Object target, final String propName, final String key, final int index, final Object newValue)
       619 |             throws IllegalAccessException, InvocationTargetException {
       620 | 
       621 |        LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().invokeSetter(target, propName, key, index, newValue);
       622 |     }
       623 | }

Added src/main/java/org/apache/commons/beanutils2/locale/LocaleBeanUtilsBean.java (line 875)

       870 |      * @throws IllegalAccessException if the caller does not have
       871 |      *  access to the property accessor method
       872 |      * @throws InvocationTargetException if the property accessor method
       873 |      *  throws an exception
       874 |      */
>>>    875 |     protected void invokeSetter(final Object target, final String propName, final String key, final int index, final Object newValue)
       876 |             throws IllegalAccessException, InvocationTargetException {
       877 | 
       878 |         try {
       879 |             if (index >= 0) {
       880 |                 getPropertyUtils().setIndexedProperty(target, propName,

Added src/main/java/org/apache/commons/beanutils2/locale/LocaleConvertUtils.java (line 235)

       230 |      * @param locale The locale
       231 |      * @param pattern The convertion pattern
       232 |      * @return the converted value
       233 |      * @see LocaleConvertUtilsBean#convert(String[], Class, Locale, String)
       234 |      */
>>>    235 |     public static Object convert(final String[] values, final Class<?> clazz, final Locale locale, final String pattern) {
       236 | 
       237 |         return LocaleConvertUtilsBean.getInstance().convert(values, clazz, locale, pattern);
       238 |     }
       239 | 
       240 |     /**

Added src/main/java/org/apache/commons/beanutils2/locale/converters/BigDecimalLocaleConverter.java (line 197)

       192 |      * @param defaultValue  The default value to be returned
       193 |      * @param locale        The locale
       194 |      * @param pattern       The convertion pattern
       195 |      * @param locPattern    Indicate whether the pattern is localized or not
       196 |      */
>>>    197 |     public BigDecimalLocaleConverter(final Object defaultValue, final Locale locale, final String pattern, final boolean locPattern) {
       198 | 
       199 |         super(defaultValue, locale, pattern, locPattern);
       200 |     }
       201 | 
       202 |     /**

Added src/main/java/org/apache/commons/beanutils2/locale/converters/BigIntegerLocaleConverter.java (line 198)

       193 |      * @param defaultValue  The default value to be returned
       194 |      * @param locale        The locale
       195 |      * @param pattern       The convertion pattern
       196 |      * @param locPattern    Indicate whether the pattern is localized or not
       197 |      */
>>>    198 |     public BigIntegerLocaleConverter(final Object defaultValue, final Locale locale, final String pattern, final boolean locPattern) {
       199 | 
       200 |         super(defaultValue, locale, pattern, locPattern);
       201 |     }
       202 | 
       203 |     /**

Added src/main/java/org/apache/commons/beanutils2/locale/converters/ByteLocaleConverter.java (line 198)

       193 |      * @param defaultValue  The default value to be returned
       194 |      * @param locale        The locale
       195 |      * @param pattern       The convertion pattern
       196 |      * @param locPattern    Indicate whether the pattern is localized or not
       197 |      */
>>>    198 |     public ByteLocaleConverter(final Object defaultValue, final Locale locale, final String pattern, final boolean locPattern) {
       199 | 
       200 |         super(defaultValue, locale, pattern, locPattern);
       201 |     }
       202 | 
       203 |     /**

Added src/main/java/org/apache/commons/beanutils2/locale/converters/DateLocaleConverter.java (line 219)

       214 |      * @param defaultValue  The default value to be returned
       215 |      * @param locale        The locale
       216 |      * @param pattern       The convertion pattern
       217 |      * @param locPattern    Indicate whether the pattern is localized or not
       218 |      */
>>>    219 |     public DateLocaleConverter(final Object defaultValue, final Locale locale, final String pattern, final boolean locPattern) {
       220 | 
       221 |         super(defaultValue, locale, pattern, locPattern);
       222 |     }
       223 | 
       224 |     // --------------------------------------------------------- Methods

Added src/main/java/org/apache/commons/beanutils2/locale/converters/DecimalLocaleConverter.java (line 208)

       203 |      * @param defaultValue  The default value to be returned
       204 |      * @param locale        The locale
       205 |      * @param pattern       The convertion pattern
       206 |      * @param locPattern    Indicate whether the pattern is localized or not
       207 |      */
>>>    208 |     public DecimalLocaleConverter(final Object defaultValue, final Locale locale, final String pattern, final boolean locPattern) {
       209 | 
       210 |         super(defaultValue, locale, pattern, locPattern);
       211 | 
       212 |     }
       213 | 
S104 (java) on commons-beanutils - 0 issues removed, 1 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/PropertyUtilsBean.java (file-level)

>>> FILE-LEVEL ISSUE
         1 | /*
         2 |  * Licensed to the Apache Software Foundation (ASF) under one or more
         3 |  * contributor license agreements.  See the NOTICE file distributed with
         4 |  * this work for additional information regarding copyright ownership.
         5 |  * The ASF licenses this file to You under the Apache License, Version 2.0
         6 |  * (the "License"); you may not use this file except in compliance with
         7 |  * the License.  You may obtain a copy of the License at
         8 |  *
         9 |  *      http://www.apache.org/licenses/LICENSE-2.0
        10 |  *
        11 |  * Unless required by applicable law or agreed to in writing, software
S105 (java) on commons-beanutils - 0 issues removed, 2 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/BeanUtilsBean.java (file-level)

>>> FILE-LEVEL ISSUE
         1 | /*
         2 |  * Licensed to the Apache Software Foundation (ASF) under one or more
         3 |  * contributor license agreements.  See the NOTICE file distributed with
         4 |  * this work for additional information regarding copyright ownership.
         5 |  * The ASF licenses this file to You under the Apache License, Version 2.0
         6 |  * (the "License"); you may not use this file except in compliance with
         7 |  * the License.  You may obtain a copy of the License at
         8 |  *
         9 |  *      http://www.apache.org/licenses/LICENSE-2.0
        10 |  *
        11 |  * Unless required by applicable law or agreed to in writing, software

Added src/main/java/org/apache/commons/beanutils2/DynaProperty.java (file-level)

>>> FILE-LEVEL ISSUE
         1 | /*
         2 |  * Licensed to the Apache Software Foundation (ASF) under one or more
         3 |  * contributor license agreements.  See the NOTICE file distributed with
         4 |  * this work for additional information regarding copyright ownership.
         5 |  * The ASF licenses this file to You under the Apache License, Version 2.0
         6 |  * (the "License"); you may not use this file except in compliance with
         7 |  * the License.  You may obtain a copy of the License at
         8 |  *
         9 |  *      http://www.apache.org/licenses/LICENSE-2.0
        10 |  *
        11 |  * Unless required by applicable law or agreed to in writing, software
S106 (java) on commons-beanutils - 0 issues removed, 2 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/BeanMap.java (line 855)

       850 |      *
       851 |      * @param ex  the exception to log
       852 |      */
       853 |     protected void logInfo(final Exception ex) {
       854 |         // Deliberately do not use LOG4J or Commons Logging to avoid dependencies
>>>    855 |         System.out.println( "INFO: Exception: " + ex );
       856 |     }
       857 | 
       858 |     /**
       859 |      * Logs the given exception to <code>System.err</code>.  Used to display
       860 |      * errors while accessing/mutating the bean.

Added src/main/java/org/apache/commons/beanutils2/BeanMap.java (line 866)

       861 |      *
       862 |      * @param ex  the exception to log
       863 |      */
       864 |     protected void logWarn(final Exception ex) {
       865 |         // Deliberately do not use LOG4J or Commons Logging to avoid dependencies
>>>    866 |         System.out.println( "WARN: Exception: " + ex );
       867 |         ex.printStackTrace();
       868 |     }
       869 | }
S1066 (java) on commons-beanutils - 0 issues removed, 1 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/MethodUtils.java (line 1295)

      1290 |      * @param md The method descriptor
      1291 |      * @param method The method to cache
      1292 |      */
      1293 |     private static void cacheMethod(final MethodDescriptor md, final Method method) {
      1294 |         if (CACHE_METHODS) {
>>>   1295 |             if (method != null) {
      1296 |                 cache.put(md, new WeakReference<>(method));
      1297 |             }
      1298 |         }
      1299 |     }
      1300 | 
S1067 (java) on commons-beanutils - 0 issues removed, 5 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/BasicDynaBean.java (line 436)

       431 |      * @return <code>true</code> if the source class is assignable to the
       432 |      * destination class, otherwise <code>false</code>
       433 |      */
       434 |     protected boolean isAssignable(final Class<?> dest, final Class<?> source) {
       435 | 
>>>    436 |         if (dest.isAssignableFrom(source) ||
       437 |                 dest == Boolean.TYPE && source == Boolean.class ||
       438 |                 dest == Byte.TYPE && source == Byte.class ||
       439 |                 dest == Character.TYPE && source == Character.class ||
       440 |                 dest == Double.TYPE && source == Double.class ||
       441 |                 dest == Float.TYPE && source == Float.class ||

Added src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java (line 848)

       843 |      * @param type The class of the property
       844 |      * @return The new value
       845 |      */
       846 |     protected Object createOtherProperty(final String name, final Class<?> type) {
       847 | 
>>>    848 |         if (type == Object.class    ||
       849 |             type == String.class    ||
       850 |             type == Boolean.class   ||
       851 |             type == Character.class ||
       852 |             Date.class.isAssignableFrom(type)) {
       853 | 

Added src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java (line 929)

       924 |      * @return <code>true</code> if the source class is assignable to the
       925 |      * destination class, otherwise <code>false</code>
       926 |      */
       927 |     protected boolean isAssignable(final Class<?> dest, final Class<?> source) {
       928 | 
>>>    929 |         if (dest.isAssignableFrom(source) ||
       930 |                 dest == Boolean.TYPE && source == Boolean.class ||
       931 |                 dest == Byte.TYPE && source == Byte.class ||
       932 |                 dest == Character.TYPE && source == Character.class ||
       933 |                 dest == Double.TYPE && source == Double.class ||
       934 |                 dest == Float.TYPE && source == Float.class ||

Added src/main/java/org/apache/commons/beanutils2/MethodUtils.java (line 1067)

      1062 |             final Log log = LogFactory.getLog(MethodUtils.class);
      1063 |             if (!loggedAccessibleWarning) {
      1064 |                 boolean vulnerableJVM = false;
      1065 |                 try {
      1066 |                     final String specVersion = System.getProperty("java.specification.version");
>>>   1067 |                     if (specVersion.charAt(0) == '1' &&
      1068 |                             (specVersion.charAt(2) == '0' ||
      1069 |                              specVersion.charAt(2) == '1' ||
      1070 |                              specVersion.charAt(2) == '2' ||
      1071 |                              specVersion.charAt(2) == '3')) {
      1072 | 

Added src/main/java/org/apache/commons/beanutils2/locale/converters/StringLocaleConverter.java (line 236)

       231 |     @Override
       232 |     protected Object parse(final Object value, final String pattern) throws ParseException {
       233 | 
       234 |         String result = null;
       235 | 
>>>    236 |         if (value instanceof Integer ||
       237 |                 value instanceof Long ||
       238 |                 value instanceof BigInteger ||
       239 |                 value instanceof Byte ||
       240 |                 value instanceof Short) {
       241 | 
S108 (java) on commons-beanutils - 0 issues removed, 3 issues added - new ruling file

Added src/test/java/org/apache/commons/beanutils2/MappedPropertyTestCase.java (line 290)

       285 |         final String property = "protectedMapped";
       286 |         final Class<?> clazz = MappedPropertyChildBean.class;
       287 |         try {
       288 |             new MappedPropertyDescriptor(property, clazz);
       289 |             fail("Property '" + property + "' found in " + clazz.getName());
>>>    290 |         } catch (final Exception ex) {
       291 |         }
       292 |     }
       293 | 
       294 | 
       295 |     /**

Added src/test/java/org/apache/commons/beanutils2/MappedPropertyTestCase.java (line 320)

       315 |         final String property = "XXXXXX";
       316 |         final Class<?> clazz = MappedPropertyTestInterface.class;
       317 |         try {
       318 |             new MappedPropertyDescriptor(property, clazz);
       319 |             fail("Property '" + property + "' found in " + clazz.getName());
>>>    320 |         } catch (final Exception ex) {
       321 |         }
       322 |     }
       323 | 
       324 |     /**
       325 |      * Test Interface Inherited mapped property

Added src/test/java/org/apache/commons/beanutils2/bugs/Jira347TestCase.java (line 114)

       109 |             try {
       110 |                 long i = 0;
       111 |                 while (true && ref.get() != null) {
       112 |                     list.add("A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String A Big String " + i++);
       113 |                 }
>>>    114 |             } catch (final Throwable ignored) {
       115 |             }
       116 |             list.clear();
       117 |             list = null;
       118 |             // System.out.println("Count " + count + " : " + getMemoryStats());
       119 |             System.gc();
S109 (java) on commons-beanutils - 0 issues removed, 19 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java (line 119)

       114 |              */
       115 |         }
       116 | 
       117 |         // If there's no read method, then look for just a write method
       118 |         if (mappedReadMethod == null) {
>>>    119 |             mappedWriteMethod = getMethod(beanClass, "set" + base, 2);
       120 |         }
       121 | 
       122 |         if (mappedReadMethod == null && mappedWriteMethod == null) {
       123 |             throw new IntrospectionException("Property '" + propertyName +
       124 |                     "' not found on " +

Added src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java (line 175)

       170 |             final Class<?>[] params = { String.class, mappedReadMethod.getReturnType() };
       171 |             mappedWriteMethod =
       172 |                 getMethod(beanClass, mappedSetterName, params);
       173 |         } else {
       174 |             mappedWriteMethod =
>>>    175 |                 getMethod(beanClass, mappedSetterName, 2);
       176 |         }
       177 |         mappedReadMethodRef  = new MappedMethodReference(mappedReadMethod);
       178 |         mappedWriteMethodRef = new MappedMethodReference(mappedWriteMethod);
       179 | 
       180 |         findMappedPropertyType();

Added src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java (line 302)

       297 |                 }
       298 |             }
       299 | 
       300 |             if (mappedWriteMethod != null) {
       301 |                 final Class<?>[] params = mappedWriteMethod.getParameterTypes();
>>>    302 |                 if (params.length != 2) {
       303 |                     throw new IntrospectionException
       304 |                             ("bad mapped write method arg count");
       305 |                 }
       306 |                 if (mappedPropertyType != null &&
       307 |                         mappedPropertyType != params[1]) {

Added src/main/java/org/apache/commons/beanutils2/MethodUtils.java (line 1068)

      1063 |             if (!loggedAccessibleWarning) {
      1064 |                 boolean vulnerableJVM = false;
      1065 |                 try {
      1066 |                     final String specVersion = System.getProperty("java.specification.version");
      1067 |                     if (specVersion.charAt(0) == '1' &&
>>>   1068 |                             (specVersion.charAt(2) == '0' ||
      1069 |                              specVersion.charAt(2) == '1' ||
      1070 |                              specVersion.charAt(2) == '2' ||
      1071 |                              specVersion.charAt(2) == '3')) {
      1072 | 
      1073 |                         vulnerableJVM = true;

Added src/main/java/org/apache/commons/beanutils2/MethodUtils.java (line 1069)

      1064 |                 boolean vulnerableJVM = false;
      1065 |                 try {
      1066 |                     final String specVersion = System.getProperty("java.specification.version");
      1067 |                     if (specVersion.charAt(0) == '1' &&
      1068 |                             (specVersion.charAt(2) == '0' ||
>>>   1069 |                              specVersion.charAt(2) == '1' ||
      1070 |                              specVersion.charAt(2) == '2' ||
      1071 |                              specVersion.charAt(2) == '3')) {
      1072 | 
      1073 |                         vulnerableJVM = true;
      1074 |                     }

Added src/main/java/org/apache/commons/beanutils2/MethodUtils.java (line 1070)

      1065 |                 try {
      1066 |                     final String specVersion = System.getProperty("java.specification.version");
      1067 |                     if (specVersion.charAt(0) == '1' &&
      1068 |                             (specVersion.charAt(2) == '0' ||
      1069 |                              specVersion.charAt(2) == '1' ||
>>>   1070 |                              specVersion.charAt(2) == '2' ||
      1071 |                              specVersion.charAt(2) == '3')) {
      1072 | 
      1073 |                         vulnerableJVM = true;
      1074 |                     }
      1075 |                 } catch (final SecurityException e) {

Added src/main/java/org/apache/commons/beanutils2/PropertyUtilsBean.java (line 1619)

      1614 |         if (descriptor instanceof IndexedPropertyDescriptor) {
      1615 |             Method writeMethod = ((IndexedPropertyDescriptor) descriptor).
      1616 |                     getIndexedWriteMethod();
      1617 |             writeMethod = MethodUtils.getAccessibleMethod(bean.getClass(), writeMethod);
      1618 |             if (writeMethod != null) {
>>>   1619 |                 final Object[] subscript = new Object[2];
      1620 |                 subscript[0] = Integer.valueOf(index);
      1621 |                 subscript[1] = value;
      1622 |                 try {
      1623 |                     if (log.isTraceEnabled()) {
      1624 |                         final String valueClassName =

Added src/main/java/org/apache/commons/beanutils2/PropertyUtilsBean.java (line 1787)

      1782 |             Method mappedWriteMethod =
      1783 |                     ((MappedPropertyDescriptor) descriptor).
      1784 |                     getMappedWriteMethod();
      1785 |             mappedWriteMethod = MethodUtils.getAccessibleMethod(bean.getClass(), mappedWriteMethod);
      1786 |             if (mappedWriteMethod != null) {
>>>   1787 |                 final Object[] params = new Object[2];
      1788 |                 params[0] = key;
      1789 |                 params[1] = value;
      1790 |                 if (log.isTraceEnabled()) {
      1791 |                     final String valueClassName =
      1792 |                         value == null ? "<null>" : value.getClass().getName();

Added src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java (line 303)

       298 |             // ---------------------- JDK 1.3 Fix ----------------------
       299 |             // N.B. Prior to JDK 1.4 the Timestamp's getTime() method
       300 |             //      didn't include the milliseconds. The following code
       301 |             //      ensures it works consistently accross JDK versions
       302 |             final java.sql.Timestamp timestamp = (java.sql.Timestamp)value;
>>>    303 |             long timeInMillis = ((timestamp.getTime() / 1000) * 1000);
       304 |             timeInMillis += timestamp.getNanos() / 1000000;
       305 |             // ---------------------- JDK 1.3 Fix ----------------------
       306 |             return toDate(targetType, timeInMillis);
       307 |         }
       308 | 

Added src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java (line 304)

       299 |             // N.B. Prior to JDK 1.4 the Timestamp's getTime() method
       300 |             //      didn't include the milliseconds. The following code
       301 |             //      ensures it works consistently accross JDK versions
       302 |             final java.sql.Timestamp timestamp = (java.sql.Timestamp)value;
       303 |             long timeInMillis = ((timestamp.getTime() / 1000) * 1000);
>>>    304 |             timeInMillis += timestamp.getNanos() / 1000000;
       305 |             // ---------------------- JDK 1.3 Fix ----------------------
       306 |             return toDate(targetType, timeInMillis);
       307 |         }
       308 | 
       309 |         // Handle Date (includes java.sql.Date & java.sql.Time)

Added src/main/java/org/apache/commons/beanutils2/expression/DefaultResolver.java (line 98)

        93 |                 if (value.length() == 0) {
        94 |                     throw new IllegalArgumentException("No Index Value");
        95 |                 }
        96 |                 int index = 0;
        97 |                 try {
>>>     98 |                     index = Integer.parseInt(value, 10);
        99 |                 } catch (final Exception e) {
       100 |                     throw new IllegalArgumentException("Invalid index value '"
       101 |                             + value + "'");
       102 |                 }
       103 |                 return index;
S110 (java) on commons-beanutils - 0 issues removed, 1 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/NestedNullException.java (line 27)

        22 |  * against given bean since a nested bean referenced is null.
        23 |  *
        24 |  * @since 1.7
        25 |  */
        26 | 
>>>     27 | public class NestedNullException extends BeanAccessLanguageException {
        28 | 
        29 |     private static final long serialVersionUID = 1L;
        30 | 
        31 |     // --------------------------------------------------------- Constuctors
        32 | 
S1105 (java) on commons-beanutils - 0 issues removed, 2 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/BeanComparator.java (line 201)

       196 | 
       197 |         if (!comparator.equals(beanComparator.comparator)) {
       198 |             return false;
       199 |         }
       200 |         if (property != null)
>>>    201 |         {
       202 |             if (!property.equals(beanComparator.property)) {
       203 |                 return false;
       204 |             }
       205 |         }
       206 |         else

Added src/main/java/org/apache/commons/beanutils2/BeanComparator.java (line 207)

       202 |             if (!property.equals(beanComparator.property)) {
       203 |                 return false;
       204 |             }
       205 |         }
       206 |         else
>>>    207 |         {
       208 |             return beanComparator.property == null;
       209 |         }
       210 | 
       211 |         return true;
       212 |     }
S1107 (java) on commons-beanutils - 0 issues removed, 53 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/BeanComparator.java (line 168)

       163 |         try {
       164 |             final Object value1 = PropertyUtils.getProperty( o1, property );
       165 |             final Object value2 = PropertyUtils.getProperty( o2, property );
       166 |             return internalCompare( value1, value2 );
       167 |         }
>>>    168 |         catch ( final IllegalAccessException iae ) {
       169 |             throw new RuntimeException( "IllegalAccessException: " + iae.toString() );
       170 |         }
       171 |         catch ( final InvocationTargetException ite ) {
       172 |             throw new RuntimeException( "InvocationTargetException: " + ite.toString() );
       173 |         }

Added src/main/java/org/apache/commons/beanutils2/BeanComparator.java (line 171)

       166 |             return internalCompare( value1, value2 );
       167 |         }
       168 |         catch ( final IllegalAccessException iae ) {
       169 |             throw new RuntimeException( "IllegalAccessException: " + iae.toString() );
       170 |         }
>>>    171 |         catch ( final InvocationTargetException ite ) {
       172 |             throw new RuntimeException( "InvocationTargetException: " + ite.toString() );
       173 |         }
       174 |         catch ( final NoSuchMethodException nsme ) {
       175 |             throw new RuntimeException( "NoSuchMethodException: " + nsme.toString() );
       176 |         }

Added src/main/java/org/apache/commons/beanutils2/BeanComparator.java (line 174)

       169 |             throw new RuntimeException( "IllegalAccessException: " + iae.toString() );
       170 |         }
       171 |         catch ( final InvocationTargetException ite ) {
       172 |             throw new RuntimeException( "InvocationTargetException: " + ite.toString() );
       173 |         }
>>>    174 |         catch ( final NoSuchMethodException nsme ) {
       175 |             throw new RuntimeException( "NoSuchMethodException: " + nsme.toString() );
       176 |         }
       177 |     }
       178 | 
       179 |     /**

Added src/main/java/org/apache/commons/beanutils2/BeanMap.java (line 295)

       290 |         Class<? extends Object> beanClass = null;
       291 |         try {
       292 |             beanClass = bean.getClass();
       293 |             bean = beanClass.newInstance();
       294 |         }
>>>    295 |         catch (final Exception e) {
       296 |             final UnsupportedOperationException uoe =
       297 |                 new UnsupportedOperationException("Could not create new instance of class: " + beanClass);
       298 |             BeanUtils.initCause(uoe, e);
       299 |             throw uoe;
       300 |         }

Added src/main/java/org/apache/commons/beanutils2/BeanMap.java (line 361)

       356 |             final Method method = getReadMethod( name );
       357 |             if ( method != null ) {
       358 |                 try {
       359 |                     return method.invoke( bean, NULL_ARGUMENTS );
       360 |                 }
>>>    361 |                 catch (  final IllegalAccessException e ) {
       362 |                     logWarn( e );
       363 |                 }
       364 |                 catch ( final IllegalArgumentException e ) {
       365 |                     logWarn(  e );
       366 |                 }

Added src/main/java/org/apache/commons/beanutils2/BeanMap.java (line 364)

       359 |                     return method.invoke( bean, NULL_ARGUMENTS );
       360 |                 }
       361 |                 catch (  final IllegalAccessException e ) {
       362 |                     logWarn( e );
       363 |                 }
>>>    364 |                 catch ( final IllegalArgumentException e ) {
       365 |                     logWarn(  e );
       366 |                 }
       367 |                 catch ( final InvocationTargetException e ) {
       368 |                     logWarn(  e );
       369 |                 }

Added src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java (line 725)

       720 |                 indexedProperty = defaultIndexedProperty(name);
       721 |             } else {
       722 |                 try {
       723 |                     indexedProperty = type.newInstance();
       724 |                 }
>>>    725 |                 catch (final Exception ex) {
       726 |                     throw new IllegalArgumentException
       727 |                         ("Error instantiating indexed property of type '" +
       728 |                                    type.getName() + "' for '" + name + "' " + ex);
       729 |                 }
       730 |             }

Added src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java (line 764)

       759 | 
       760 |         } else if (Map.class.isAssignableFrom(type)) {
       761 |             try {
       762 |                 mappedProperty = type.newInstance();
       763 |             }
>>>    764 |             catch (final Exception ex) {
       765 |                 throw new IllegalArgumentException
       766 |                     ("Error instantiating mapped property of type '" +
       767 |                             type.getName() + "' for '" + name + "' " + ex);
       768 |             }
       769 |         } else {

Added src/main/java/org/apache/commons/beanutils2/LazyDynaBean.java (line 789)

       784 |      */
       785 |     protected Object createDynaBeanProperty(final String name, final Class<?> type) {
       786 |         try {
       787 |             return type.newInstance();
       788 |         }
>>>    789 |         catch (final Exception ex) {
       790 |             if (logger().isWarnEnabled()) {
       791 |                 logger().warn("Error instantiating DynaBean property of type '" +
       792 |                         type.getName() + "' for '" + name + "' " + ex);
       793 |             }
       794 |             return null;

Added src/main/java/org/apache/commons/beanutils2/ResultSetDynaClass.java (line 243)

       238 |     protected Class<?> loadClass(final String className) throws SQLException {
       239 | 
       240 |         try {
       241 |             return getClass().getClassLoader().loadClass(className);
       242 |         }
>>>    243 |         catch (final Exception e) {
       244 |             throw new SQLException("Cannot load column class '" +
       245 |                                    className + "': " + e);
       246 |         }
       247 |     }
       248 | }

Added src/main/java/org/apache/commons/beanutils2/locale/LocaleBeanUtilsBean.java (line 647)

       642 |             sb.append(name);
       643 |             sb.append(", ");
       644 |             if (value == null) {
       645 |                 sb.append("<NULL>");
       646 |             }
>>>    647 |             else if (value instanceof String) {
       648 |                 sb.append((String) value);
       649 |             }
       650 |             else if (value instanceof String[]) {
       651 |                 final String[] values = (String[]) value;
       652 |                 sb.append('[');

Added src/main/java/org/apache/commons/beanutils2/locale/LocaleBeanUtilsBean.java (line 650)

       645 |                 sb.append("<NULL>");
       646 |             }
       647 |             else if (value instanceof String) {
       648 |                 sb.append((String) value);
       649 |             }
>>>    650 |             else if (value instanceof String[]) {
       651 |                 final String[] values = (String[]) value;
       652 |                 sb.append('[');
       653 |                 for (int i = 0; i < values.length; i++) {
       654 |                     if (i > 0) {
       655 |                         sb.append(',');

Added src/main/java/org/apache/commons/beanutils2/locale/LocaleBeanUtilsBean.java (line 661)

       656 |                     }
       657 |                     sb.append(values[i]);
       658 |                 }
       659 |                 sb.append(']');
       660 |             }
>>>    661 |             else {
       662 |                 sb.append(value.toString());
       663 |             }
       664 |             sb.append(')');
       665 |             log.trace(sb.toString());
       666 |         }

Added src/main/java/org/apache/commons/beanutils2/locale/LocaleConvertUtilsBean.java (line 144)

       139 |     public void setDefaultLocale(final Locale locale) {
       140 | 
       141 |         if (locale == null) {
       142 |             defaultLocale = Locale.getDefault();
       143 |         }
>>>    144 |         else {
       145 |             defaultLocale = locale;
       146 |         }
       147 |     }
       148 | 
       149 |     /**

Added src/main/java/org/apache/commons/beanutils2/locale/LocaleConvertUtilsBean.java (line 440)

       435 |         Map<Class<?>, LocaleConverter> localeConverters;
       436 | 
       437 |         if (locale == null) {
       438 |             localeConverters = (Map<Class<?>, LocaleConverter>) mapConverters.get(defaultLocale);
       439 |         }
>>>    440 |         else {
       441 |             localeConverters = (Map<Class<?>, LocaleConverter>) mapConverters.get(locale);
       442 | 
       443 |             if (localeConverters == null) {
       444 |                 localeConverters = create(locale);
       445 |                 mapConverters.put(locale, localeConverters);
S1108 (java) on commons-beanutils - 0 issues removed, 367 issues added - new ruling file

Added src/main/java/org/apache/commons/beanutils2/BaseDynaBeanMapDecorator.java (line 146)

       141 |             final Object prop = getDynaBean().get(key);
       142 |             if (value == null) {
       143 |                 if (prop == null) {
       144 |                     return true;
       145 |                 }
>>>    146 |             } else {
       147 |                 if (value.equals(prop)) {
       148 |                     return true;
       149 |                 }
       150 |             }
       151 |         }

Added src/main/java/org/apache/commons/beanutils2/BasicDynaBean.java (line 123)

       118 | 
       119 |         final Object value = values.get(name);
       120 |         if (value == null) {
       121 |             throw new NullPointerException
       122 |                     ("No mapped value for '" + name + "(" + key + ")'");
>>>    123 |         } else if (value instanceof Map) {
       124 |             return ((Map<?, ?>) value).containsKey(key);
       125 |         } else {
       126 |             throw new IllegalArgumentException
       127 |                     ("Non-mapped property for '" + name + "(" + key + ")'");
       128 |         }

Added src/main/java/org/apache/commons/beanutils2/BasicDynaBean.java (line 125)

       120 |         if (value == null) {
       121 |             throw new NullPointerException
       122 |                     ("No mapped value for '" + name + "(" + key + ")'");
       123 |         } else if (value instanceof Map) {
       124 |             return ((Map<?, ?>) value).containsKey(key);
>>>    125 |         } else {
       126 |             throw new IllegalArgumentException
       127 |                     ("Non-mapped property for '" + name + "(" + key + ")'");
       128 |         }
       129 | 
       130 |     }

Added src/main/java/org/apache/commons/beanutils2/BasicDynaBean.java (line 160)

       155 |         }
       156 | 
       157 |         // Manufacture default values for primitive properties
       158 |         if (type == Boolean.TYPE) {
       159 |             return Boolean.FALSE;
>>>    160 |         } else if (type == Byte.TYPE) {
       161 |             return Byte.valueOf((byte) 0);
       162 |         } else if (type == Character.TYPE) {
       163 |             return Character.valueOf((char) 0);
       164 |         } else if (type == Double.TYPE) {
       165 |             return Double.valueOf(0.0);

Added src/main/java/org/apache/commons/beanutils2/BasicDynaClass.java (line 226)

       221 |             if (constructor == null) {
       222 |                 setDynaBeanClass(this.dynaBeanClass);
       223 |             }
       224 |             // Invoke the constructor to create a new bean instance
       225 |             return (DynaBean) constructor.newInstance(constructorValues);
>>>    226 |         } catch (final InvocationTargetException e) {
       227 |             throw new InstantiationException
       228 |                     (e.getTargetException().getMessage());
       229 |         }
       230 | 
       231 |     }

Added src/main/java/org/apache/commons/beanutils2/BasicDynaClass.java (line 281)

       276 |         }
       277 | 
       278 |         // Identify the Constructor we will use in newInstance()
       279 |         try {
       280 |             this.constructor = dynaBeanClass.getConstructor(constructorTypes);
>>>    281 |         } catch (final NoSuchMethodException e) {
       282 |             throw new IllegalArgumentException
       283 |                     ("Class " + dynaBeanClass.getName() +
       284 |                     " does not have an appropriate constructor");
       285 |         }
       286 |         this.dynaBeanClass = dynaBeanClass;

Added src/main/java/org/apache/commons/beanutils2/BeanComparator.java (line 110)

       105 |      */
       106 |     public BeanComparator( final String property, final Comparator<?> comparator ) {
       107 |         setProperty( property );
       108 |         if (comparator != null) {
       109 |             this.comparator = comparator;
>>>    110 |         } else {
       111 |             this.comparator = ComparableComparator.INSTANCE;
       112 |         }
       113 |     }
       114 | 
       115 |     /**

Added src/main/java/org/apache/commons/beanutils2/BeanIntrospectionData.java (line 121)

       116 |                 method = MethodUtils.getAccessibleMethod(beanCls, methodName,
       117 |                         desc.getPropertyType());
       118 |                 if (method != null) {
       119 |                     try {
       120 |                         desc.setWriteMethod(method);
>>>    121 |                     } catch (final IntrospectionException e) {
       122 |                         // ignore, in this case the method is not cached
       123 |                     }
       124 |                 }
       125 |             }
       126 |         }

Added src/main/java/org/apache/commons/beanutils2/BeanMap.java (line 222)

       217 | 
       218 |         Object newBean = null;
       219 |         final Class<? extends Object> beanClass = bean.getClass(); // Cannot throw Exception
       220 |         try {
       221 |             newBean = beanClass.newInstance();
>>>    222 |         } catch (final Exception e) {
       223 |             // unable to instantiate
       224 |             final CloneNotSupportedException cnse = new CloneNotSupportedException
       225 |                 ("Unable to instantiate the underlying bean \"" +
       226 |                  beanClass.getName() + "\": " + e);
       227 |             BeanUtils.initCause(cnse, e);

Added src/main/java/org/apache/commons/beanutils2/BeanMap.java (line 233)

       228 |             throw cnse;
       229 |         }
       230 | 
       231 |         try {
       232 |             newMap.setBean(newBean);
>>>    233 |         } catch (final Exception exception) {
       234 |             final CloneNotSupportedException cnse = new CloneNotSupportedException
       235 |                 ("Unable to set bean in the cloned bean map: " +
       236 |                  exception);
       237 |             BeanUtils.initCause(cnse, exception);
       238 |             throw cnse;

Added src/main/java/org/apache/commons/beanutils2/BeanMap.java (line 250)

       245 |             for (final Object key : readMethods.keySet()) {
       246 |                 if(getWriteMethod(key) != null) {
       247 |                     newMap.put(key, get(key));
       248 |                 }
       249 |             }
>>>    250 |         } catch (final Exception exception) {
       251 |             final CloneNotSupportedException cnse = new CloneNotSupportedException
       252 |                 ("Unable to copy bean values to cloned bean map: " +
       253 |                  exception);
       254 |             BeanUtils.initCause(cnse, exception);
       255 |             throw cnse;

Added src/main/java/org/apache/commons/beanutils2/BeanPredicate.java (line 70)

        65 |         boolean evaluation = false;
        66 | 
        67 |         try {
        68 |             final Object propValue = PropertyUtils.getProperty( object, propertyName );
        69 |             evaluation = predicate.evaluate(propValue);
>>>     70 |         } catch (final IllegalArgumentException e) {
        71 |             final String errorMsg = "Problem during evaluation.";
        72 |             log.error("ERROR: " + errorMsg, e);
        73 |             throw e;
        74 |         } catch (final IllegalAccessException e) {
        75 |             final String errorMsg = "Unable to access the property provided.";

Added src/main/java/org/apache/commons/beanutils2/BeanPredicate.java (line 74)

        69 |             evaluation = predicate.evaluate(propValue);
        70 |         } catch (final IllegalArgumentException e) {
        71 |             final String errorMsg = "Problem during evaluation.";
        72 |             log.error("ERROR: " + errorMsg, e);
        73 |             throw e;
>>>     74 |         } catch (final IllegalAccessException e) {
        75 |             final String errorMsg = "Unable to access the property provided.";
        76 |             log.error(errorMsg, e);
        77 |             throw new IllegalArgumentException(errorMsg);
        78 |         } catch (final InvocationTargetException e) {
        79 |             final String errorMsg = "Exception occurred in property's getter";

Added src/main/java/org/apache/commons/beanutils2/BeanPredicate.java (line 78)

        73 |             throw e;
        74 |         } catch (final IllegalAccessException e) {
        75 |             final String errorMsg = "Unable to access the property provided.";
        76 |             log.error(errorMsg, e);
        77 |             throw new IllegalArgumentException(errorMsg);
>>>     78 |         } catch (final InvocationTargetException e) {
        79 |             final String errorMsg = "Exception occurred in property's getter";
        80 |             log.error(errorMsg, e);
        81 |             throw new IllegalArgumentException(errorMsg);
        82 |         } catch (final NoSuchMethodException e) {
        83 |             final String errorMsg = "Property not found.";

Added src/main/java/org/apache/commons/beanutils2/BeanPropertyValueChangeClosure.java (line 141)

       136 | 
       137 |         if (propertyName != null && propertyName.length() > 0) {
       138 |             this.propertyName = propertyName;
       139 |             this.propertyValue = propertyValue;
       140 |             this.ignoreNull = ignoreNull;
>>>    141 |         } else {
       142 |             throw new IllegalArgumentException("propertyName cannot be null or empty");
       143 |         }
       144 |     }
       145 | 
       146 |     /**

... and 1240 more rules with changes (diff too large to display fully)

@github-actions

Copy link
Copy Markdown
Contributor

❌ Ruling needs updating. A fix PR has been created: #6177

Please review and merge it into your branch.

romainbrenguier pushed a commit that referenced this pull request Sep 16, 2026
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

❌ Ruling needs updating. A fix PR has been created: #6180

Please review and merge it into your branch.

romainbrenguier pushed a commit that referenced this pull request Sep 16, 2026
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@romainbrenguier
romainbrenguier marked this pull request as ready for review September 16, 2026 14:32
@github-actions

Copy link
Copy Markdown
Contributor

❌ Ruling needs updating. A fix PR has been created: #6204

Please review and merge it into your branch.

romainbrenguier pushed a commit that referenced this pull request Sep 21, 2026
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Comment thread its/ruling/src/test/java/org/sonar/java/it/JavaRulingTest.java
@github-actions

Copy link
Copy Markdown
Contributor

❌ Ruling needs updating. A fix PR has been created: #6207

Please review and merge it into your branch.

2 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

❌ Ruling needs updating. A fix PR has been created: #6207

Please review and merge it into your branch.

@github-actions

Copy link
Copy Markdown
Contributor

❌ Ruling needs updating. A fix PR has been created: #6207

Please review and merge it into your branch.

romainbrenguier and others added 5 commits September 23, 2026 09:47
Move ruling expectation JSON files from
its/ruling/src/test/resources/<project>/
to its/ruling/src/test/resources/expected/java/<project>/
for consistency across analyzers. Update JavaRulingTest to
read expectations from the new path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
…y structure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…erences

Remove duplicated ruling expectation directories that were left at
its/ruling/src/test/resources/<project>/ after the move to
expected/java/<project>/. Also update the upload-actual expected-dir
in CI and the README instructions to reference the new path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@romainbrenguier
romainbrenguier force-pushed the romain/normalize-ruling-expectations branch from 26a1432 to e15d5db Compare September 23, 2026 07:49
Comment thread README.md Outdated
Co-authored-by: Romain Brenguier <11854194+romainbrenguier@users.noreply.github.com>
nathsou

This comment was marked as duplicate.

@nathsou

nathsou commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Minor finding: AGENTS.md line 264 still documents the old ruling expectation path (its/ruling/src/test/resources/<project>/java-<RULE_ID>.json). It should be updated to its/ruling/src/test/resources/expected/<project>/java-<RULE_ID>.json so contributors and agents do not create expectation files where the tests no longer read them.

nathsou

This comment was marked as duplicate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gitar-bot

gitar-bot Bot commented Sep 23, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 4 closed / 4 findings

🟡 Medium risk · Ruling tests and CI now resolve 1,257 baselines from a new directory.

Normalizes ruling expectation file locations to its/ruling/src/test/resources/expected/<project>/ for consistency across analyzers. Resolved CI ruling-root inputs, master branch file migration, documentation references, and path inconsistencies between PR description and implementation.

✅ 4 closed
✅ Bug: CI ruling-root inputs still point at the old expectation root

📄 its/ruling/src/test/java/org/sonar/java/it/JavaRulingTest.java:160
ruling-update-and-notify copies the merged actual_* artifacts straight into ruling-root (cp -rv "$TEMP_DIR"/* "${ruling-root}/" in SonarSource/core-languages-tooling-public/ruling-update-and-notify/action.yml:302), and the artifacts are laid out as <project>/java-SXXXX.json. With ruling-root: 'its/ruling/src/test/resources' unchanged, the auto-update job will recreate the pre-PR its/ruling/src/test/resources/<project>/ tree instead of updating expected/java/<project>/, so the generated update PR never fixes the ruling failure that JavaRulingTest reads from src/test/resources/expected/java. Likewise ruling-diff-comment parses each changed path with parse_ruling_relative_path, which requires exactly <project>/<repo>-<rule>.json after stripping ruling-root; the new paths yield expected/java/<project>/java-SXXXX.json (4 parts), so every ruling file is dropped with "Skipping unrecognized ruling path" and no diff comment is ever posted again. Point both ruling-root inputs at its/ruling/src/test/resources/expected/java.

✅ Bug: Master's new ruling files still land at the old path and are left behind on merge

📄 its/ruling/src/test/resources/expected/eclipse-jetty/java-S9398.json:1 📄 its/ruling/src/test/resources/expected/guava/java-S9395.json:1 📄 its/ruling/src/test/java/org/sonar/java/it/JavaRulingTest.java:160
Since the merge base (218ea99), origin/master has added 21 expectation files at the old location its/ruling/src/test/resources/<project>/java-S93xx.json. This PR deletes the old directories, but that deletion does not cover files master added later, so a merge would bring all of them back as orphans outside expected/. This delta copies S9395, S9398 and S9404 to the new path, and several others (S9386, S9390, S9391) already exist there. The S9396 files (eclipse-jetty, guava, sonar-server, eclipse-jetty-similar-to-main) and eclipse-jetty-similar-to-main/java-S9398.json are still missing from expected/<project>/. After merge, JavaRulingTest reads only src/test/resources/expected (line 160), so those expectations would be ignored and the ruling would report new/unexpected issues. Also, the files that were copied would then exist twice, at both paths. To fix this, merge or rebase onto current master, git mv every file master added under its/ruling/src/test/resources/<project>/ into expected/<project>/, and delete the old copies.

✅ Quality: PR description names expected/java/<project>/, but the code uses expected/<project>/

📄 its/ruling/src/test/java/org/sonar/java/it/JavaRulingTest.java:160
The PR description says expectations move to its/ruling/src/test/resources/expected/java/<project>/. Commit 2075b16 later dropped the java/ level, so the test, CI inputs (build.yml, ruling-diff-comment.yml) and the files in this delta all use expected/<project>/. Update the description so it matches the layout that will actually be merged.

✅ Quality: Docs still point at expected/java/ and old per-project ruling paths

📄 README.md:171 📄 README.md:175
The latest commit (e15d5db) moved the ruling expectations from its/ruling/src/test/resources/expected/java/<project>/ up to expected/<project>/. JavaRulingTest and the CI inputs now use src/test/resources/expected. README.md lines 171 and 175 were not updated and still point at expected/java/. That directory no longer exists, so anyone following the README's cp its/ruling/target/actual/* its/ruling/src/test/resources/expected/java/ step puts files where the test never reads them. AGENTS.md line 264 still gives the pre-PR location its/ruling/src/test/resources/<project>/java-<RULE_ID>.json, which also misleads contributors and agents. Point both docs at its/ruling/src/test/resources/expected/.

Review coverage

🧪 Functional validation No results

📋 Rules No rules evaluated

🤖 Auto-approval Not enabled · Set up

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Counting what did not apply, without listing it.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqube-next

Copy link
Copy Markdown
Contributor

@romainbrenguier
romainbrenguier merged commit af7f7ec into master Sep 23, 2026
17 checks passed
@romainbrenguier
romainbrenguier deleted the romain/normalize-ruling-expectations branch September 23, 2026 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants