Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
import org.antlr.v4.runtime.tree.ParseTree;
import org.jspecify.annotations.Nullable;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
Expand Down Expand Up @@ -122,6 +125,7 @@ public static void configureDiagnostic(BSLDiagnostic diagnostic, @Nullable Map<S
types.add(Boolean.class);
types.add(Float.class);
types.add(String.class);
types.add(List.class);

diagnostic.getInfo().getParameters().stream()
.filter(diagnosticParameterInfo -> configuration.containsKey(diagnosticParameterInfo.getName())
Expand All @@ -130,14 +134,36 @@ public static void configureDiagnostic(BSLDiagnostic diagnostic, @Nullable Map<S
try {
var field = diagnostic.getClass().getDeclaredField(diagnosticParameterInfo.getName());
if (field.trySetAccessible()) {
field.set(diagnostic, configuration.get(field.getName()));
field.set(diagnostic, castParameterValue(field, configuration.get(field.getName())));
}
} catch (NoSuchFieldException | IllegalAccessException e) {
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
LOGGER.error("Can't set param.", e);
}
});
}

/**
* Приводит значение параметра из конфигурации к типу целевого поля диагностики.
* <p>
* Для полей типа {@link List} значение может прийти как строка (элементы через запятую —
* например, из SonarQube UI) либо как JSON-массив (десериализуется Jackson в {@link List}).
* В обоих случаях возвращается {@code List<String>}. Для остальных полей значение
* возвращается без изменений.
*
* @param field Целевое поле диагностики
* @param value Значение из конфигурации ({@code String}, {@code List} и т.п.)
* @return Значение, пригодное для присвоения полю
*/
private static Object castParameterValue(Field field, Object value) {
if (List.class.isAssignableFrom(field.getType())) {
if (value instanceof List<?> list) {
return list.stream().map(String::valueOf).toList();
}
return asStringList(String.valueOf(value));
}
return value;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

/**
* Настроить параметры диагностики с фильтрацией по именам параметров.
*
Expand All @@ -158,6 +184,23 @@ public static void configureDiagnostic(BSLDiagnostic diagnostic,
configureDiagnostic(diagnostic, newConfiguration);
}

/**
* Разбирает строку с элементами через запятую в список строк.
* <p>
* Используется как для значения параметра-списка из конфигурации в строковой форме
* (SonarQube UI, «старые» конфиги), так и для инициализации поля значением по умолчанию.
* Элементы обрезаются по краям от пробелов; пустые элементы отбрасываются.
*
* @param value Строка с элементами через запятую
* @return Список строк без пустых элементов
*/
public static List<String> asStringList(String value) {
return Arrays.stream(value.split(","))
.map(String::trim)
.filter(element -> !element.isEmpty())
.toList();
}

/**
* Создает PATTERN из строки со словами с разделителем ',' (запятая) (используется в параметрах диагностики).
* При создании паттерна удаляются концевые пробелы слов
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ public class TypoDiagnostic extends AbstractDiagnostic {
private int minWordLength = DEFAULT_MIN_WORD_LENGTH;

@DiagnosticParameter(
type = String.class
type = List.class
)
private String userWordsToIgnore = DEFAULT_USER_WORDS_TO_IGNORE;
private List<String> userWordsToIgnore = DiagnosticHelper.asStringList(DEFAULT_USER_WORDS_TO_IGNORE);

/**
* Готовый список слов для игнорирования
Expand All @@ -130,8 +130,9 @@ public void configure(Map<String, Object> configuration) {
private Set<String> makeWordsToIgnore() {
var delimiter = ',';
var exceptions = SPACES_PATTERN.matcher(info.getResourceString("diagnosticExceptions")).replaceAll("");
if (!userWordsToIgnore.isEmpty()) {
exceptions += delimiter + SPACES_PATTERN.matcher(userWordsToIgnore).replaceAll("");
var userWords = String.join(String.valueOf(delimiter), userWordsToIgnore);
if (!userWords.isEmpty()) {
exceptions += delimiter + SPACES_PATTERN.matcher(userWords).replaceAll("");
}

// добавим к переданным строки в разных регистрах
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ private Object castDiagnosticParameterValue(String valueToCast) {
value = Float.parseFloat(valueToCast);
} else if (type == String.class) {
value = valueToCast;
} else if (type == List.class) {
// Параметр-список: внешнее (config/SonarQube) представление по умолчанию — строка через запятую.
// В List значение разбирается при применении конфигурации (см. DiagnosticHelper).
value = valueToCast;
} else {
throw new IllegalArgumentException("Unsupported diagnostic parameter type " + type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,18 @@ void testConfigureUserWordsToIgnoreWithSpaces() {
assertThat(diagnostics, true)
.hasRange(8, 13, 8, 18);
}

@Test
void testConfigureUserWordsToIgnoreAsList() {

Map<String, Object> configuration = diagnosticInstance.getInfo().getDefaultConfiguration();
configuration.put("userWordsToIgnore", List.of("Варинаты", "Атмена"));
diagnosticInstance.configure(configuration);

List<Diagnostic> diagnostics = getDiagnostics();

assertThat(diagnostics).hasSize(1);
assertThat(diagnostics, true)
.hasRange(8, 13, 8, 18);
}
}
Loading