Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Глобальные методы в контексте #1720

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright © 2018-2021
* Alexey Sosnoviy <[email protected]>, Nikita Gryzlov <[email protected]> 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<String, Method> globalMethods = new HashMap<>();

@Override
public Map<String, Method> getGlobalMethods() {
return Collections.unmodifiableMap(globalMethods);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.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;
import com.github._1c_syntax.utils.Absolute;
import com.github._1c_syntax.utils.Lazy;
Expand All @@ -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
Expand Down Expand Up @@ -159,6 +166,28 @@ public Configuration getConfiguration() {
return configurationMetadata.getOrCompute();
}

public Set<AbstractMDObjectBSL> getGlobalModules() {

Set<AbstractMDObjectBSL> 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);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright © 2018-2021
* Alexey Sosnoviy <[email protected]>, Nikita Gryzlov <[email protected]> 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<BSLEngine> engines) {
var contextStorage = new ContextStorage();
engines.forEach(contextStorage::registerEngine);

return contextStorage;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -50,11 +52,14 @@
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component
@RequiredArgsConstructor
public class ReferenceIndex {

public static final String GLOBAL_METHOD_MDO_REF = "Global.Method";

private final ServerContext serverContext;

/**
Expand Down Expand Up @@ -202,11 +207,19 @@ private Optional<SourceDefinedSymbol> getSourceDefinedSymbol(MultiKey<String> mu
ModuleType moduleType = ModuleType.valueOf(multikey.getKey(1));
String symbolName = multikey.getKey(2);

return serverContext.getDocument(mdoRef, moduleType)
Stream<DocumentContext> reffedModules = serverContext.getDocument(mdoRef, moduleType).stream();
Stream<DocumentContext> 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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<ModuleType> DEFAULT_MODULE_TYPES = EnumSet.of(
private static final Set<ModuleType> 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) {
Expand Down Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, 29));
assertThat(reference.getUri()).isEqualTo(uri);
}

@Test
void testCantGetReferenceToNonExportCommonModuleMethod() {
// given
Expand Down Expand Up @@ -194,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))
Expand Down
2 changes: 2 additions & 0 deletions src/test/resources/references/ReferenceIndex.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
ПервыйОбщийМодуль.УстаревшаяПроцедура();
РегистрыСведений.РегистрСведений1.УстаревшаяПроцедура();
ПервыйОбщийМодуль.Тест();
ПроцедураМодуляПриложения();
ГлобальнаяСервернаяПроцедура();
КонецПроцедуры