Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@
@Slf4j
public class BSLTextDocumentService implements TextDocumentService, ProtocolExtension {

private static final long AWAIT_CLOSE = 30;

private final ServerContext context;
private final LanguageServerConfiguration configuration;
private final DiagnosticProvider diagnosticProvider;
Expand Down Expand Up @@ -488,7 +490,7 @@ public void didClose(DidCloseTextDocumentParams params) {
docExecutor.shutdown();
try {
// Wait for all queued changes to complete (with timeout to avoid hanging)
if (!docExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
if (!docExecutor.awaitTermination(AWAIT_CLOSE, TimeUnit.SECONDS)) {
docExecutor.shutdownNow();
}
} catch (InterruptedException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import org.aspectj.lang.annotation.Aspect;
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.services.LanguageServer;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
@Autowired
@Lazy
@Getter
@SuppressWarnings("NullAway.Init")

Check warning on line 66 in src/main/java/com/github/_1c_syntax/bsl/languageserver/codelenses/RunTestCodeLensSupplier.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Suppressing warnings is not allowed

See more on https://sonarcloud.io/project/issues?id=1c-syntax_bsl-language-server&issues=AZsRqZ42PonS3uYeTslO&open=AZsRqZ42PonS3uYeTslO&pullRequest=3659
private RunTestCodeLensSupplier self;

public RunTestCodeLensSupplier(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ private void runWorker() {
*/
private CompletableFuture<Void> registerWaiter(int version) {
var future = new CompletableFuture<Void>();
versionWaiters.compute(version, (key, futures) -> {
versionWaiters.compute(version, (Integer key, CopyOnWriteArrayList<CompletableFuture<Void>> futures) -> {
var list = futures;
if (list == null) {
list = new CopyOnWriteArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.github._1c_syntax.bsl.types.MDOType;
import com.github._1c_syntax.bsl.types.ModuleType;
import org.eclipse.lsp4j.Range;
import org.jspecify.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -56,7 +57,7 @@ public abstract class AbstractMetadataDiagnostic extends AbstractDiagnostic {
/**
* Область для регистрации замечания
*/
private Range diagnosticRange;
private @Nullable Range diagnosticRange;

/**
* Конструктор с указанием типов объектов метаданных для проверки.
Expand Down Expand Up @@ -118,6 +119,7 @@ protected boolean computeDiagnosticRange() {
* @param message Сообщение об ошибке
*/
protected void addDiagnostic(String message) {
assert diagnosticRange != null;
diagnosticStorage.addDiagnostic(diagnosticRange, message);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void configure(Map<String, Object> configuration) {
}

private Set<String> makeWordsToIgnore() {
char delimiter = ',';
var delimiter = ',';
var exceptions = SPACES_PATTERN.matcher(info.getResourceString("diagnosticExceptions")).replaceAll("");
if (!userWordsToIgnore.isEmpty()) {
exceptions += delimiter + SPACES_PATTERN.matcher(userWordsToIgnore).replaceAll("");
Expand Down Expand Up @@ -180,11 +180,11 @@ private Map<String, List<Token>> getTokensMap(
@Override
protected void check() {

String lang = info.getResourceString("diagnosticLanguage");
Map<String, List<Token>> tokensMap = getTokensMap(documentContext);
var lang = info.getResourceString("diagnosticLanguage");
var tokensMap = getTokensMap(documentContext);

// build string of unchecked words
Set<String> uncheckedWords = tokensMap.keySet().stream()
var uncheckedWords = tokensMap.keySet().stream()
.filter(word -> checkedWordsHolder.getWordStatus(lang, word) == WordStatus.MISSING)
.collect(Collectors.toSet());

Expand All @@ -195,9 +195,9 @@ protected void check() {

// Join with double \n to force LT make paragraph after each word.
// Otherwise results may be flaky cause of sort order of words in file.
String uncheckedWordsString = String.join("\n\n", uncheckedWords);
var uncheckedWordsString = String.join("\n\n", uncheckedWords);

JLanguageTool languageTool = acquireLanguageTool(lang);
var languageTool = acquireLanguageTool(lang);

List<RuleMatch> matches = Collections.emptyList();
try {
Expand Down Expand Up @@ -228,7 +228,7 @@ protected void check() {
private void fireDiagnosticOnCheckedWordsWithErrors(
Map<String, List<Token>> tokensMap
) {
String lang = info.getResourceString("diagnosticLanguage");
var lang = info.getResourceString("diagnosticLanguage");

tokensMap.entrySet().stream()
.filter(entry -> checkedWordsHolder.getWordStatus(lang, entry.getKey()) == WordStatus.HAS_ERROR)
Expand All @@ -239,5 +239,4 @@ private void fireDiagnosticOnCheckedWordsWithErrors(
tokens.forEach(token -> diagnosticStorage.addDiagnostic(token, info.getMessage(word)));
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,27 @@
public class UselessTernaryOperatorDiagnostic extends AbstractVisitorDiagnostic implements QuickFixProvider {

private static final int SKIPPED_RULE_INDEX = 0;
private static final int COUNT_EXPRESSIONS = 3;
private static final int INDEX_CONDITION = 0;
private static final int INDEX_TRUE_BRANCH = 1;
private static final int INDEX_FALSE_BRANCH = 2;

@Override
public ParseTree visitTernaryOperator(BSLParser.TernaryOperatorContext ctx) {
var exp = ctx.expression();

if (exp != null && exp.size() >= 3) {
var condition = getBooleanToken(exp.get(0));
var trueBranch = getBooleanToken(exp.get(1));
var falseBranch = getBooleanToken(exp.get(2));
if (exp != null && exp.size() >= COUNT_EXPRESSIONS) {
var condition = getBooleanToken(exp.get(INDEX_CONDITION));
var trueBranch = getBooleanToken(exp.get(INDEX_TRUE_BRANCH));
var falseBranch = getBooleanToken(exp.get(INDEX_FALSE_BRANCH));
Comment on lines +64 to +67
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Harden null-safety: getBooleanToken(Optional.of(expCtx)) will NPE if any exp.get(i) is null.

If ctx.expression() can’t contain null items, it’s fine today, but given the PR’s general null-safety direction, it’d be safer to make getBooleanToken tolerate null inputs (or explicitly assert non-null at call sites).

-  private static int getBooleanToken(BSLParser.ExpressionContext expCtx) {
+  private static int getBooleanToken(@org.jetbrains.annotations.Nullable BSLParser.ExpressionContext expCtx) {
     var tmpCtx = Optional.of(expCtx)
+      // or: Optional.ofNullable(expCtx)
       .filter(ctx -> ctx.children.size() == 1)
       .map(ctx -> ctx.member(0))
       .map(ctx -> ctx.getChild(0))
       .filter(BSLParser.ConstValueContext.class::isInstance)
       .map(BSLParser.ConstValueContext.class::cast);

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UselessTernaryOperatorDiagnostic.java
around lines 64 to 67, calling getBooleanToken(exp.get(...)) can NPE if any
exp.get(i) returns null; either guard each exp.get(INDEX_...) with a null check
and only call getBooleanToken when non-null (e.g., use
Optional.ofNullable(exp.get(i)) or skip/handle missing entries), or change
getBooleanToken to accept a possibly-null parameter (or Optional) and handle
null internally; update the callsite to pass a nullable/Optional value and
adjust downstream logic accordingly so no NPE occurs.


if (condition != SKIPPED_RULE_INDEX) {
diagnosticStorage.addDiagnostic(ctx);
} else if (trueBranch == BSLParser.TRUE && falseBranch == BSLParser.FALSE) {
diagnosticStorage.addDiagnostic(ctx, DiagnosticStorage.createAdditionalData(exp.get(0).getText()));
diagnosticStorage.addDiagnostic(ctx, DiagnosticStorage.createAdditionalData(exp.get(INDEX_CONDITION).getText()));
} else if (trueBranch == BSLParser.FALSE && falseBranch == BSLParser.TRUE) {
diagnosticStorage.addDiagnostic(ctx,
DiagnosticStorage.createAdditionalData(getAdaptedText(exp.get(0).getText())));
DiagnosticStorage.createAdditionalData(getAdaptedText(exp.get(INDEX_CONDITION).getText())));
} else if (trueBranch != SKIPPED_RULE_INDEX || falseBranch != SKIPPED_RULE_INDEX) {
diagnosticStorage.addDiagnostic(ctx);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ public MarkupContent getContent(AnnotationParamSymbol symbol) {
var parameterDefinition = maybeParameterDefinition.get();

// описание параметра аннотации
String parameter = descriptionFormatter.parameterToString(parameterDefinition);
var parameter = descriptionFormatter.parameterToString(parameterDefinition);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, parameter);

String content = markupBuilder.toString();
var content = markupBuilder.toString();

return new MarkupContent(MarkupKind.MARKDOWN, content);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ public MarkupContent getContent(AnnotationSymbol symbol) {
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, examplesSection);

// варианты вызова
String callOptionsSection = descriptionFormatter.getCallOptionsSection(methodSymbol);
var callOptionsSection = descriptionFormatter.getCallOptionsSection(methodSymbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, callOptionsSection);

String content = markupBuilder.toString();
var content = markupBuilder.toString();

return new MarkupContent(MarkupKind.MARKDOWN, content);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,6 @@
@Component
@RequiredArgsConstructor
public class MethodSymbolMarkupContentBuilder implements MarkupContentBuilder<MethodSymbol> {

private static final String PROCEDURE_KEY = "procedure";
private static final String FUNCTION_KEY = "function";
private static final String EXPORT_KEY = "export";
private static final String VAL_KEY = "val";
private static final String PARAMETERS_KEY = "parameters";
private static final String RETURNED_VALUE_KEY = "returnedValue";
private static final String EXAMPLES_KEY = "examples";
private static final String CALL_OPTIONS_KEY = "callOptions";
private static final String PARAMETER_TEMPLATE = "* **%s**: %s";

private final DescriptionFormatter descriptionFormatter;

@Override
Expand All @@ -62,34 +51,34 @@ public MarkupContent getContent(MethodSymbol symbol) {
// варианты вызова

// сигнатура
String signature = descriptionFormatter.getSignature(symbol);
var signature = descriptionFormatter.getSignature(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, signature);

// местоположение метода
String methodLocation = descriptionFormatter.getLocation(symbol);
var methodLocation = descriptionFormatter.getLocation(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, methodLocation);

// описание метода
String purposeSection = descriptionFormatter.getPurposeSection(symbol);
var purposeSection = descriptionFormatter.getPurposeSection(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, purposeSection);

// параметры
String parametersSection = descriptionFormatter.getParametersSection(symbol);
var parametersSection = descriptionFormatter.getParametersSection(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, parametersSection);

// возвращаемое значение
String returnedValueSection = descriptionFormatter.getReturnedValueSection(symbol);
var returnedValueSection = descriptionFormatter.getReturnedValueSection(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, returnedValueSection);

// примеры
String examplesSection = descriptionFormatter.getExamplesSection(symbol);
var examplesSection = descriptionFormatter.getExamplesSection(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, examplesSection);

// варианты вызова
String callOptionsSection = descriptionFormatter.getCallOptionsSection(symbol);
var callOptionsSection = descriptionFormatter.getCallOptionsSection(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, callOptionsSection);

String content = markupBuilder.toString();
var content = markupBuilder.toString();

return new MarkupContent(MarkupKind.MARKDOWN, content);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ public MarkupContent getContent(ModuleSymbol symbol) {
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, moduleLocation);

// Информация о модуле из метаданных
String moduleInfo = getModuleInfo(symbol);
var moduleInfo = getModuleInfo(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, moduleInfo);

String content = markupBuilder.toString();
var content = markupBuilder.toString();
return new MarkupContent(MarkupKind.MARKDOWN, content);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public MarkupContent getContent(VariableSymbol symbol) {
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, signature);

// местоположение переменной
String location = descriptionFormatter.getLocation(symbol);
var location = descriptionFormatter.getLocation(symbol);
descriptionFormatter.addSectionIfNotEmpty(markupBuilder, location);

// описание переменной
Expand All @@ -68,7 +68,7 @@ public MarkupContent getContent(VariableSymbol symbol) {
.map(VariableDescription::getPurposeDescription)
.ifPresent(trailingDescription -> descriptionFormatter.addSectionIfNotEmpty(markupBuilder, trailingDescription));

String content = markupBuilder.toString();
var content = markupBuilder.toString();

return new MarkupContent(MarkupKind.MARKDOWN, content);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
public class CacheConfiguration {
private static final String TYPO_CACHE_NAME = "typoCache";
private static final int MAX_CACHE_INSTANCES = 10;
private static final long HEAP_ENTRIES_COUNT = 125_000;
private static final long DISK_SIZE_MB = 50;

/**
* Основной менеджер кэша, использующий Caffeine для кэширования в памяти.
Expand Down Expand Up @@ -108,12 +110,12 @@ public org.ehcache.CacheManager ehcacheManager(
* @param fullPath полный путь (если задан)
* @return менеджер EhCache
*/
private org.ehcache.CacheManager createEhcacheManagerWithRetry(
private static org.ehcache.CacheManager createEhcacheManagerWithRetry(
CachePathProvider cachePathProvider,
String basePath,
String fullPath
) {
for (int instanceNumber = 0; instanceNumber < MAX_CACHE_INSTANCES; instanceNumber++) {
for (var instanceNumber = 0; instanceNumber < MAX_CACHE_INSTANCES; instanceNumber++) {
try {
var cacheDir = cachePathProvider.getCachePath(basePath, fullPath, instanceNumber);
return createEhcacheManager(cacheDir);
Expand All @@ -133,11 +135,11 @@ private org.ehcache.CacheManager createEhcacheManagerWithRetry(
* @param cacheDir каталог для персистентного хранилища
* @return менеджер EhCache
*/
private org.ehcache.CacheManager createEhcacheManager(java.nio.file.Path cacheDir) {
private static org.ehcache.CacheManager createEhcacheManager(java.nio.file.Path cacheDir) {
// Build resource pools with disk persistence
var resourcePools = ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(125_000, EntryUnit.ENTRIES)
.disk(50, MemoryUnit.MB, true);
.heap(HEAP_ENTRIES_COUNT, EntryUnit.ENTRIES)
.disk(DISK_SIZE_MB, MemoryUnit.MB, true);

var cacheConfig = createTypoCacheConfig(resourcePools);

Expand All @@ -156,10 +158,10 @@ private org.ehcache.CacheManager createEhcacheManager(java.nio.file.Path cacheDi
*
* @return менеджер EhCache с in-memory хранилищем
*/
private org.ehcache.CacheManager createInMemoryEhcacheManager() {
private static org.ehcache.CacheManager createInMemoryEhcacheManager() {
// Build resource pools with heap-only storage
var resourcePools = ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(125_000, EntryUnit.ENTRIES);
.heap(HEAP_ENTRIES_COUNT, EntryUnit.ENTRIES);

var cacheConfig = createTypoCacheConfig(resourcePools);

Expand All @@ -175,7 +177,7 @@ private org.ehcache.CacheManager createInMemoryEhcacheManager() {
* @param resourcePoolsBuilder построитель пулов ресурсов (heap, disk и т.д.)
* @return конфигурация кэша
*/
private org.ehcache.config.CacheConfiguration<String, WordStatus> createTypoCacheConfig(
private static org.ehcache.config.CacheConfiguration<String, WordStatus> createTypoCacheConfig(
ResourcePoolsBuilder resourcePoolsBuilder
) {
return CacheConfigurationBuilder
Expand Down
Loading
Loading