Skip to content

Commit

Permalink
Работа с ховером переведена на reference-api. Исправлено возможное NP…
Browse files Browse the repository at this point in the history
…E на получении типа по символу.
  • Loading branch information
nixel2007 committed Apr 25, 2024
1 parent 872b84e commit 7b21327
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
package com.github._1c_syntax.bsl.languageserver.hover;

import com.github._1c_syntax.bsl.languageserver.context.symbol.Symbol;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.SymbolKind;

Expand All @@ -34,10 +35,11 @@ public interface MarkupContentBuilder<T extends Symbol> {
/**
* Возвращает контент для всплывающего окна на основе символа.
*
* @param symbol Символ, для которого нужно построить контент.
* @param reference Ссылка на символ, для которого нужно построить контент.
* @param symbol Символ с приведенным типом, для которого нужно построить контент.
* @return Сконструированный контент.
*/
MarkupContent getContent(T symbol);
MarkupContent getContent(Reference reference, T symbol);

/**
* Тип символа, на основе которого работает данный построитель.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.github._1c_syntax.bsl.languageserver.context.symbol.description.MethodDescription;
import com.github._1c_syntax.bsl.languageserver.context.symbol.description.ParameterDescription;
import com.github._1c_syntax.bsl.languageserver.context.symbol.description.TypeDescription;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import com.github._1c_syntax.bsl.languageserver.utils.MdoRefBuilder;
import com.github._1c_syntax.bsl.languageserver.utils.Resources;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -63,7 +64,7 @@ public class MethodSymbolMarkupContentBuilder implements MarkupContentBuilder<Me
private final LanguageServerConfiguration configuration;

@Override
public MarkupContent getContent(MethodSymbol symbol) {
public MarkupContent getContent(Reference reference, MethodSymbol symbol) {
var markupBuilder = new StringJoiner("\n");

// сигнатура
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.github._1c_syntax.bsl.languageserver.configuration.LanguageServerConfiguration;
import com.github._1c_syntax.bsl.languageserver.context.symbol.VariableSymbol;
import com.github._1c_syntax.bsl.languageserver.context.symbol.variable.VariableDescription;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import com.github._1c_syntax.bsl.languageserver.types.Type;
import com.github._1c_syntax.bsl.languageserver.types.TypeResolver;
import com.github._1c_syntax.bsl.languageserver.utils.MdoRefBuilder;
Expand All @@ -49,7 +50,7 @@ public class VariableSymbolMarkupContentBuilder implements MarkupContentBuilder<
private final LanguageServerConfiguration configuration;

@Override
public MarkupContent getContent(VariableSymbol symbol) {
public MarkupContent getContent(Reference reference, VariableSymbol symbol) {
var markupBuilder = new StringJoiner("\n");

// сигнатура
Expand All @@ -74,7 +75,7 @@ public MarkupContent getContent(VariableSymbol symbol) {
.map(VariableDescription::getPurposeDescription)
.ifPresent(trailingDescription -> addSectionIfNotEmpty(markupBuilder, trailingDescription));

var types = typeResolver.findTypes(symbol);
var types = typeResolver.findTypes(reference);
var typeDescription = getTypeDescription(types);
addSectionIfNotEmpty(markupBuilder, typeDescription);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public Optional<Hover> getHover(DocumentContext documentContext, HoverParams par
var range = reference.getSelectionRange();

return Optional.ofNullable(markupContentBuilders.get(symbol.getSymbolKind()))
.map(markupContentBuilder -> markupContentBuilder.getContent(symbol))
.map(markupContentBuilder -> markupContentBuilder.getContent(reference, symbol))
.map(content -> new Hover(content, range));
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.github._1c_syntax.bsl.languageserver.context.ServerContext;
import com.github._1c_syntax.bsl.languageserver.context.symbol.Describable;
import com.github._1c_syntax.bsl.languageserver.context.symbol.SourceDefinedSymbol;
import com.github._1c_syntax.bsl.languageserver.context.symbol.Symbol;
import com.github._1c_syntax.bsl.languageserver.context.symbol.description.MethodDescription;
import com.github._1c_syntax.bsl.languageserver.context.symbol.description.TypeDescription;
import com.github._1c_syntax.bsl.languageserver.context.symbol.variable.VariableDescription;
Expand Down Expand Up @@ -58,20 +59,26 @@ public class TypeResolver {

// TODO: Create LRU cache for calculated types.

// TODO: Use reference instead of symbol. Refactor hover provider to pass references to markup content builders.
public List<Type> findTypes(SourceDefinedSymbol symbol) {
return calculateTypes(symbol);
public List<Type> findTypes(Reference reference) {
return calculateTypes(reference.getUri(), reference.getSymbol());
}

public List<Type> findTypes(URI uri, Position position) {
return referenceResolver.findReference(uri, position)
.stream()
.flatMap(reference -> calculateTypes(uri, reference).stream())
.flatMap(reference -> calculateTypes(reference).stream())
.distinct()
.toList();
}

private List<Type> calculateTypes(SourceDefinedSymbol symbol) {
private List<Type> calculateTypes(URI uri, Symbol symbol) {
if (symbol instanceof SourceDefinedSymbol sourceDefinedSymbol) {
return calculateTypes(uri, sourceDefinedSymbol);
}
return Collections.emptyList();
}

private List<Type> calculateTypes(URI uri, SourceDefinedSymbol symbol) {

// variable description resolver
if (symbol instanceof Describable describableSymbol) {
Expand All @@ -94,7 +101,9 @@ private List<Type> calculateTypes(SourceDefinedSymbol symbol) {
}

// reference-based type resolver
var uri = symbol.getOwner().getUri();
if (symbol.getOwner().getContent() == null) {
return Collections.emptyList();
}
var ast = symbol.getOwner().getAst();
if (ast == null) {
return Collections.emptyList();
Expand All @@ -115,13 +124,16 @@ private List<Type> calculateTypes(SourceDefinedSymbol symbol) {
.toList();
}

private List<Type> calculateTypes(URI uri, Reference reference) {
private List<Type> calculateTypes(Reference reference) {

var uri = reference.getUri();

// source defined symbol resolver
if (reference.isSourceDefinedSymbolReference()) {
return calculateTypes(reference.getSourceDefinedSymbol().orElseThrow());
return calculateTypes(uri, reference.getSourceDefinedSymbol().orElseThrow());
}


// expression tree resolver
if (reference.getOccurrenceType() == OccurrenceType.DEFINITION) {
var document = serverContext.getDocument(uri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
*/
package com.github._1c_syntax.bsl.languageserver.hover;

import com.github._1c_syntax.bsl.languageserver.context.DocumentContext;
import com.github._1c_syntax.bsl.languageserver.context.ServerContext;
import com.github._1c_syntax.bsl.languageserver.context.symbol.MethodSymbol;
import com.github._1c_syntax.bsl.languageserver.references.model.OccurrenceType;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import com.github._1c_syntax.bsl.languageserver.util.CleanupContextBeforeClassAndAfterClass;
import com.github._1c_syntax.bsl.languageserver.util.TestUtils;
import com.github._1c_syntax.bsl.types.ModuleType;
import jakarta.annotation.PostConstruct;
import org.eclipse.lsp4j.Location;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down Expand Up @@ -59,9 +64,10 @@ void testContentFromDirectFile() {
// given
var documentContext = TestUtils.getDocumentContextFromFile(PATH_TO_FILE);
var methodSymbol = documentContext.getSymbolTree().getMethodSymbol("ИмяФункции").orElseThrow();
var reference = getReference(documentContext, methodSymbol);

// when
var content = markupContentBuilder.getContent(methodSymbol).getValue();
var content = markupContentBuilder.getContent(reference, methodSymbol).getValue();

assertThat(content).isNotEmpty();

Expand Down Expand Up @@ -122,9 +128,10 @@ void testContentFromManagerModule() {
// given
var documentContext = serverContext.getDocument("Catalog.Справочник1", ModuleType.ManagerModule).orElseThrow();
var methodSymbol = documentContext.getSymbolTree().getMethodSymbol("ТестЭкспортная").orElseThrow();
var reference = getReference(documentContext, methodSymbol);

// when
var content = markupContentBuilder.getContent(methodSymbol).getValue();
var content = markupContentBuilder.getContent(reference, methodSymbol).getValue();

// then
assertThat(content).isNotEmpty();
Expand All @@ -146,9 +153,10 @@ void testMethodsFromCommonModule() {
// given
var documentContext = serverContext.getDocument("CommonModule.ПервыйОбщийМодуль", ModuleType.CommonModule).orElseThrow();
var methodSymbol = documentContext.getSymbolTree().getMethodSymbol("УстаревшаяПроцедура").orElseThrow();
var reference = getReference(documentContext, methodSymbol);

// when
var content = markupContentBuilder.getContent(methodSymbol).getValue();
var content = markupContentBuilder.getContent(reference, methodSymbol).getValue();

// then
assertThat(content).isNotEmpty();
Expand All @@ -166,4 +174,12 @@ void testMethodsFromCommonModule() {
assertThat(blocks.get(2)).isEqualTo("Процедура - Устаревшая процедура\n\n");
}

private static Reference getReference(DocumentContext documentContext, MethodSymbol methodSymbol) {
return Reference.of(
documentContext.getSymbolTree().getModule(),
methodSymbol,
new Location(documentContext.getUri().toString(), methodSymbol.getSelectionRange()),
OccurrenceType.DEFINITION
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
*/
package com.github._1c_syntax.bsl.languageserver.hover;

import com.github._1c_syntax.bsl.languageserver.context.DocumentContext;
import com.github._1c_syntax.bsl.languageserver.context.ServerContext;
import com.github._1c_syntax.bsl.languageserver.context.symbol.VariableSymbol;
import com.github._1c_syntax.bsl.languageserver.references.model.OccurrenceType;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import com.github._1c_syntax.bsl.languageserver.util.CleanupContextBeforeClassAndAfterClass;
import com.github._1c_syntax.bsl.languageserver.util.TestUtils;
import com.github._1c_syntax.bsl.types.ModuleType;
import jakarta.annotation.PostConstruct;
import org.eclipse.lsp4j.Location;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down Expand Up @@ -60,9 +65,10 @@ void testFileVarContentFromDirectFile_NoComments() {
var documentContext = TestUtils.getDocumentContextFromFile(PATH_TO_FILE);
final var symbolTree = documentContext.getSymbolTree();
var varSymbol = symbolTree.getVariableSymbol("ИмяБезОписания", symbolTree.getModule()).orElseThrow();
var reference = getReference(documentContext, varSymbol);

// when
var content = markupContentBuilder.getContent(varSymbol).getValue();
var content = markupContentBuilder.getContent(reference, varSymbol).getValue();

assertThat(content).isNotEmpty();

Expand All @@ -87,9 +93,10 @@ void testFileVarContentFromDirectFile_OneCommentsStringFromRight() {
var documentContext = TestUtils.getDocumentContextFromFile(PATH_TO_FILE);
final var symbolTree = documentContext.getSymbolTree();
var varSymbol = symbolTree.getVariableSymbol("Имя_ОписаниеСправаОднойСтрокой", symbolTree.getModule()).orElseThrow();
var reference = getReference(documentContext, varSymbol);

// when
var content = markupContentBuilder.getContent(varSymbol).getValue();
var content = markupContentBuilder.getContent(reference, varSymbol).getValue();

assertThat(content).isNotEmpty();

Expand Down Expand Up @@ -119,9 +126,10 @@ void testMethodVarContentFromDirectFile_2_comments_strings() {
final var symbolTree = documentContext.getSymbolTree();
var methodSymbol = symbolTree.getMethodSymbol("ИмяФункции").orElseThrow();
var varSymbol = symbolTree.getVariableSymbol("Имя_ОписаниеСверхуДвеСтроки_Функция", methodSymbol).orElseThrow();
var reference = getReference(documentContext, varSymbol);

// when
var content = markupContentBuilder.getContent(varSymbol).getValue();
var content = markupContentBuilder.getContent(reference, varSymbol).getValue();

assertThat(content).isNotEmpty();

Expand Down Expand Up @@ -153,9 +161,10 @@ void testMethodVarContentFromDirectFile_3_comments_strings() {
final var symbolTree = documentContext.getSymbolTree();
var methodSymbol = symbolTree.getMethodSymbol("ИмяФункции").orElseThrow();
var varSymbol = symbolTree.getVariableSymbol("Имя_ОписаниеСверхуТриСтрокиПоследняяПустая_Функция", methodSymbol).orElseThrow();
var reference = getReference(documentContext, varSymbol);

// when
var content = markupContentBuilder.getContent(varSymbol).getValue();
var content = markupContentBuilder.getContent(reference, varSymbol).getValue();

assertThat(content).isNotEmpty();

Expand Down Expand Up @@ -186,9 +195,10 @@ void testContentFromObjectModule() {
var documentContext = serverContext.getDocument("Catalog.Справочник1", ModuleType.ObjectModule).orElseThrow();
final var symbolTree = documentContext.getSymbolTree();
var varSymbol = symbolTree.getVariableSymbol("ВалютаУчета", symbolTree.getModule()).orElseThrow();
var reference = getReference(documentContext, varSymbol);

// when
var content = markupContentBuilder.getContent(varSymbol).getValue();
var content = markupContentBuilder.getContent(reference, varSymbol).getValue();

// then
assertThat(content).isNotEmpty();
Expand All @@ -205,4 +215,12 @@ void testContentFromObjectModule() {
assertThat(blocks.get(1)).matches("\\[Catalog.Справочник1]\\(.*Catalogs/.*/Ext/ObjectModule.bsl#\\d+\\)\n\n");
}

private static Reference getReference(DocumentContext documentContext, VariableSymbol variableSymbol) {
return Reference.of(
documentContext.getSymbolTree().getModule(),
variableSymbol,
new Location(documentContext.getUri().toString(), variableSymbol.getSelectionRange()),
OccurrenceType.DEFINITION
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
*/
package com.github._1c_syntax.bsl.languageserver.types;

import com.github._1c_syntax.bsl.languageserver.context.DocumentContext;
import com.github._1c_syntax.bsl.languageserver.context.symbol.VariableSymbol;
import com.github._1c_syntax.bsl.languageserver.references.model.OccurrenceType;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import com.github._1c_syntax.bsl.languageserver.util.TestUtils;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -35,6 +40,8 @@ class TypeResolverTest {
@Autowired
private TypeResolver typeResolver;

public static final String PATH_TO_FILE = "./src/test/resources/types/TypeResolver.os";

@Test
void simpleType() {
// given
Expand Down Expand Up @@ -76,9 +83,10 @@ void twoTypesFromSymbol() {
// given
var documentContext = TestUtils.getDocumentContextFromFile("./src/test/resources/types/TypeResolver.os");
var variableSymbol = documentContext.getSymbolTree().getVariableSymbol("ДваТипа", documentContext.getSymbolTree().getModule()).orElseThrow();
var reference = getReference(documentContext, variableSymbol);

// when
var types = typeResolver.findTypes(variableSymbol);
var types = typeResolver.findTypes(reference);

// then
assertThat(types).hasSize(2);
Expand All @@ -89,9 +97,10 @@ void twoAssignments() {
// given
var documentContext = TestUtils.getDocumentContextFromFile("./src/test/resources/types/TypeResolver.os");
var variableSymbol = documentContext.getSymbolTree().getVariableSymbol("Переприсваивание", documentContext.getSymbolTree().getModule()).orElseThrow();
var reference = getReference(documentContext, variableSymbol);

// when
var types = typeResolver.findTypes(variableSymbol);
var types = typeResolver.findTypes(reference);

// then
assertThat(types).hasSize(1);
Expand All @@ -102,9 +111,10 @@ void newArray() {
// given
var documentContext = TestUtils.getDocumentContextFromFile("./src/test/resources/types/TypeResolver.os");
var variableSymbol = documentContext.getSymbolTree().getVariableSymbol("ДругоеИмяМассива", documentContext.getSymbolTree().getModule()).orElseThrow();
var reference = getReference(documentContext, variableSymbol);

// when
var types = typeResolver.findTypes(variableSymbol);
var types = typeResolver.findTypes(reference);

// then
assertThat(types).hasSize(1);
Expand All @@ -116,9 +126,10 @@ void globalMethodCall() {
// given
var documentContext = TestUtils.getDocumentContextFromFile("./src/test/resources/types/TypeResolver.os");
var variableSymbol = documentContext.getSymbolTree().getVariableSymbol("РезультатФункции", documentContext.getSymbolTree().getModule()).orElseThrow();
var reference = getReference(documentContext, variableSymbol);

// when
var types = typeResolver.findTypes(variableSymbol);
var types = typeResolver.findTypes(reference);

// then
assertThat(types).hasSize(1);
Expand All @@ -128,15 +139,24 @@ void globalMethodCall() {
@Test
void varWithDescription() {
// given
var documentContext = TestUtils.getDocumentContextFromFile("./src/test/resources/types/TypeResolver.os");
var documentContext = TestUtils.getDocumentContextFromFile(PATH_TO_FILE);
var variableSymbol = documentContext.getSymbolTree().getVariableSymbol("ПеременнаяСОписанием", documentContext.getSymbolTree().getModule()).orElseThrow();
var reference = getReference(documentContext, variableSymbol);

// when
var types = typeResolver.findTypes(variableSymbol);
var types = typeResolver.findTypes(reference);

// then
assertThat(types).hasSize(1);
assertThat(types.get(0).getName()).isEqualTo("Строка");
}

private static Reference getReference(DocumentContext documentContext, VariableSymbol variableSymbol) {
return Reference.of(
documentContext.getSymbolTree().getModule(),
variableSymbol,
new Location(documentContext.getUri().toString(), variableSymbol.getSelectionRange()),
OccurrenceType.DEFINITION
);
}
}

0 comments on commit 7b21327

Please sign in to comment.