From 4b58cfce2f14cc55a5981a66d1b3a8eca8450e9a Mon Sep 17 00:00:00 2001 From: Nikita Gryzlov Date: Mon, 14 Jun 2021 17:54:35 +0300 Subject: [PATCH 1/2] wip --- build.gradle.kts | 1 + ...lobalSourceDefinedSymbolContextEngine.java | 41 ++++++++++++++++++ .../languageserver/context/ServerContext.java | 29 +++++++++++++ .../BSLEngineConfiguration.java | 42 +++++++++++++++++++ .../references/ReferenceIndex.java | 2 + .../references/ReferenceIndexFiller.java | 20 ++++++--- .../references/ReferenceIndexTest.java | 21 ++++++++++ .../resources/references/ReferenceIndex.bsl | 2 + 8 files changed, 152 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/github/_1c_syntax/bsl/languageserver/context/GlobalSourceDefinedSymbolContextEngine.java create mode 100644 src/main/java/com/github/_1c_syntax/bsl/languageserver/infrastructure/BSLEngineConfiguration.java diff --git a/build.gradle.kts b/build.gradle.kts index 888699322bf..26de098dc5c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -68,6 +68,7 @@ dependencies { } api("com.github.1c-syntax", "utils", "0.3.1") api("com.github.1c-syntax", "mdclasses", "v0.9.1") + api("com.github.1c-syntax", "bsl-context", "431fb370f478eec9e7ad36bded53a65f913c77e7") // JLanguageTool implementation("org.languagetool", "languagetool-core", languageToolVersion) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/GlobalSourceDefinedSymbolContextEngine.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/GlobalSourceDefinedSymbolContextEngine.java new file mode 100644 index 00000000000..348a01b102d --- /dev/null +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/GlobalSourceDefinedSymbolContextEngine.java @@ -0,0 +1,41 @@ +/* + * This file is a part of BSL Language Server. + * + * Copyright © 2018-2021 + * Alexey Sosnoviy , Nikita Gryzlov and contributors + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * BSL Language Server is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * BSL Language Server is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with BSL Language Server. + */ +package com.github._1c_syntax.bsl.languageserver.context; + +import com.github._1c_syntax.bsl.context.BSLEngine; +import com.github._1c_syntax.bsl.context.component.Method; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Component +public class GlobalSourceDefinedSymbolContextEngine implements BSLEngine { + + private Map globalMethods = new HashMap<>(); + + @Override + public Map getGlobalMethods() { + return Collections.unmodifiableMap(globalMethods); + } +} diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContext.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContext.java index 0aebef029b0..1db41cc85d0 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContext.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContext.java @@ -23,6 +23,9 @@ import com.github._1c_syntax.bsl.languageserver.utils.MdoRefBuilder; import com.github._1c_syntax.mdclasses.Configuration; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; +import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; +import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; import com.github._1c_syntax.mdclasses.mdo.support.ModuleType; import com.github._1c_syntax.utils.Absolute; import com.github._1c_syntax.utils.Lazy; @@ -43,12 +46,16 @@ import java.util.Collection; import java.util.Collections; import java.util.EnumMap; +import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; @Slf4j @Component @@ -159,6 +166,28 @@ public Configuration getConfiguration() { return configurationMetadata.getOrCompute(); } + public Set getGlobalModules() { + + Set globalModules = new HashSet<>(); + + getConfiguration().getCommonModules().values().stream() + .filter(MDCommonModule::isGlobal) + .collect(Collectors.toCollection(() -> globalModules)); + + var globalClientModuleModuleTypes = EnumSet.of( + ModuleType.ApplicationModule, + ModuleType.ManagedApplicationModule, + ModuleType.OrdinaryApplicationModule + ); + + getConfiguration().getModules().stream() + .filter(mdoModule -> globalClientModuleModuleTypes.contains(mdoModule.getModuleType())) + .map(MDOModule::getOwner) + .collect(Collectors.toCollection(() -> globalModules)); + + return globalModules; + } + @Lookup protected abstract DocumentContext lookupDocumentContext(URI absoluteURI); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/infrastructure/BSLEngineConfiguration.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/infrastructure/BSLEngineConfiguration.java new file mode 100644 index 00000000000..724cd17c26f --- /dev/null +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/infrastructure/BSLEngineConfiguration.java @@ -0,0 +1,42 @@ +/* + * This file is a part of BSL Language Server. + * + * Copyright © 2018-2021 + * Alexey Sosnoviy , Nikita Gryzlov and contributors + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * BSL Language Server is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * BSL Language Server is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with BSL Language Server. + */ +package com.github._1c_syntax.bsl.languageserver.infrastructure; + +import com.github._1c_syntax.bsl.context.BSLEngine; +import com.github._1c_syntax.bsl.context.ContextStorage; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +@Configuration +public class BSLEngineConfiguration { + + @Bean + public ContextStorage contextStorage(List engines) { + var contextStorage = new ContextStorage(); + engines.forEach(contextStorage::registerEngine); + + return contextStorage; + } + +} diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndex.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndex.java index e7fcbbf16ad..ed910d602cf 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndex.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndex.java @@ -55,6 +55,8 @@ @RequiredArgsConstructor public class ReferenceIndex { + public static final String GLOBAL_METHOD_MDO_REF = "Global.Method"; + private final ServerContext serverContext; /** diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexFiller.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexFiller.java index c2c315116a0..0770d4cd484 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexFiller.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexFiller.java @@ -21,6 +21,7 @@ */ package com.github._1c_syntax.bsl.languageserver.references; +import com.github._1c_syntax.bsl.context.ContextStorage; import com.github._1c_syntax.bsl.languageserver.context.DocumentContext; import com.github._1c_syntax.bsl.languageserver.context.events.DocumentContextContentChangedEvent; import com.github._1c_syntax.bsl.languageserver.utils.MdoRefBuilder; @@ -43,17 +44,19 @@ import java.util.Optional; import java.util.Set; +import static com.github._1c_syntax.bsl.languageserver.references.ReferenceIndex.GLOBAL_METHOD_MDO_REF; + @Component @RequiredArgsConstructor public class ReferenceIndexFiller { - - private static final Set DEFAULT_MODULE_TYPES = EnumSet.of( + private static final Set DEFAULT_MODULE_TYPES = EnumSet.of( ModuleType.ManagerModule, ModuleType.CommonModule, ModuleType.UNKNOWN ); private final ReferenceIndex index; + private final ContextStorage contextStorage; @EventListener public void handleEvent(DocumentContextContentChangedEvent event) { @@ -108,11 +111,16 @@ public BSLParserRuleContext visitGlobalMethodCall(BSLParser.GlobalMethodCallCont var moduleType = documentContext.getModuleType(); var methodName = ctx.methodName().getStart(); var methodNameText = methodName.getText(); + var range = Ranges.create(methodName); + + var isLocalMethod = documentContext.getSymbolTree().getMethods().stream() + .anyMatch(methodSymbol -> methodSymbol.getName().equalsIgnoreCase(methodNameText)); - documentContext.getSymbolTree().getMethods().stream() - .filter(methodSymbol -> methodSymbol.getName().equalsIgnoreCase(methodNameText)) - .findAny() - .ifPresent(methodSymbol -> addMethodCall(mdoRef, moduleType, methodNameText, Ranges.create(methodName))); + if (isLocalMethod) { + addMethodCall(mdoRef, moduleType, methodNameText, range); + } else { + addMethodCall(GLOBAL_METHOD_MDO_REF, ModuleType.UNKNOWN, methodNameText, range); + } return super.visitGlobalMethodCall(ctx); } diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexTest.java index 92d7009cde1..d983cedd163 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexTest.java @@ -157,6 +157,27 @@ void testGetReferenceToCommonModuleMethod() { assertThat(reference.getUri()).isEqualTo(uri); } + @Test + void testGetReferenceToGlobalMethodFromApplicationModule() { + // given + var documentContext = TestUtils.getDocumentContextFromFile(PATH_TO_FILE); + var methodSymbol = documentContext.getSymbolTree().getMethodSymbol("ИмяПроцедуры").orElseThrow(); + var applicationModuleContext = serverContext.getDocument("Configuration.Конфигурация", ModuleType.ManagedApplicationModule).orElseThrow(); + var calledMethodSymbol = applicationModuleContext.getSymbolTree().getMethodSymbol("ПроцедураМодуляПриложения").orElseThrow(); + + var uri = documentContext.getUri(); + var position = new Position(5, 20); + + // when + var reference = referenceIndex.getReference(uri, position).orElseThrow(); + + // then + assertThat(reference.getFrom()).isEqualTo(methodSymbol); + assertThat(reference.getSymbol()).isEqualTo(calledMethodSymbol); + assertThat(reference.getSelectionRange()).isEqualTo(Ranges.create(5, 4, 41)); + assertThat(reference.getUri()).isEqualTo(uri); + } + @Test void testCantGetReferenceToNonExportCommonModuleMethod() { // given diff --git a/src/test/resources/references/ReferenceIndex.bsl b/src/test/resources/references/ReferenceIndex.bsl index 3ffbbc1d206..4141602fcac 100644 --- a/src/test/resources/references/ReferenceIndex.bsl +++ b/src/test/resources/references/ReferenceIndex.bsl @@ -3,4 +3,6 @@ ПервыйОбщийМодуль.УстаревшаяПроцедура(); РегистрыСведений.РегистрСведений1.УстаревшаяПроцедура(); ПервыйОбщийМодуль.Тест(); + ПроцедураМодуляПриложения(); + ГлобальнаяСервернаяПроцедура(); КонецПроцедуры From 9f8d05bd5d1a710cf8c877c1d593c11a46c6d8ac Mon Sep 17 00:00:00 2001 From: Nikita Gryzlov Date: Fri, 9 Jul 2021 12:50:58 +0300 Subject: [PATCH 2/2] wip --- .../languageserver/context/ServerContext.java | 6 +++--- .../references/ReferenceIndex.java | 19 +++++++++++++++---- .../references/ReferenceIndexTest.java | 4 ++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContext.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContext.java index 1db41cc85d0..8e9d875e7a4 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContext.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContext.java @@ -23,7 +23,7 @@ import com.github._1c_syntax.bsl.languageserver.utils.MdoRefBuilder; import com.github._1c_syntax.mdclasses.Configuration; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; import com.github._1c_syntax.mdclasses.mdo.support.ModuleType; @@ -166,9 +166,9 @@ public Configuration getConfiguration() { return configurationMetadata.getOrCompute(); } - public Set getGlobalModules() { + public Set getGlobalModules() { - Set globalModules = new HashSet<>(); + Set globalModules = new HashSet<>(); getConfiguration().getCommonModules().values().stream() .filter(MDCommonModule::isGlobal) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndex.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndex.java index ed910d602cf..606936143aa 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndex.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndex.java @@ -28,6 +28,8 @@ import com.github._1c_syntax.bsl.languageserver.context.symbol.SymbolTree; import com.github._1c_syntax.bsl.languageserver.utils.MdoRefBuilder; import com.github._1c_syntax.bsl.languageserver.utils.Ranges; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; +import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; import com.github._1c_syntax.mdclasses.mdo.support.ModuleType; import lombok.RequiredArgsConstructor; import lombok.Synchronized; @@ -50,6 +52,7 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; @Component @RequiredArgsConstructor @@ -204,11 +207,19 @@ private Optional getSourceDefinedSymbol(MultiKey mu ModuleType moduleType = ModuleType.valueOf(multikey.getKey(1)); String symbolName = multikey.getKey(2); - return serverContext.getDocument(mdoRef, moduleType) + Stream reffedModules = serverContext.getDocument(mdoRef, moduleType).stream(); + Stream globalModules = serverContext.getGlobalModules().stream() + .map(AbstractMDObjectBSL::getModules) + .flatMap(Collection::stream) + .map(MDOModule::getUri) + .map(serverContext::getDocument); + + return Stream.concat(reffedModules, globalModules) .map(DocumentContext::getSymbolTree) - // TODO: SymbolTree#getSymbol(Position)? - // Для поиска не только методов, но и переменных, которые могут иметь одинаковые имена - .flatMap(symbolTree -> symbolTree.getMethodSymbol(symbolName)); + .flatMap(symbolTree -> symbolTree.getMethodSymbol(symbolName).stream()) + .map(SourceDefinedSymbol.class::cast) + .findAny(); + } private SourceDefinedSymbol getFromSymbol(URI uri, Position position) { diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexTest.java index d983cedd163..18342d1b878 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexTest.java @@ -174,7 +174,7 @@ void testGetReferenceToGlobalMethodFromApplicationModule() { // then assertThat(reference.getFrom()).isEqualTo(methodSymbol); assertThat(reference.getSymbol()).isEqualTo(calledMethodSymbol); - assertThat(reference.getSelectionRange()).isEqualTo(Ranges.create(5, 4, 41)); + assertThat(reference.getSelectionRange()).isEqualTo(Ranges.create(5, 4, 29)); assertThat(reference.getUri()).isEqualTo(uri); } @@ -215,7 +215,7 @@ void testGetReferencesFromLocalMethodSymbol() { // then assertThat(references) - .hasSize(3) + .hasSize(5) .contains(Reference.of(localMethodSymbol, localMethodSymbol, locationLocal)) .contains(Reference.of(localMethodSymbol, commonModuleMethodSymbol, locationCommonModule)) .contains(Reference.of(localMethodSymbol, managerModuleMethodSymbol, locationManagerModule))