Skip to content

Commit

Permalink
Рефакторинг, кэширование
Browse files Browse the repository at this point in the history
  • Loading branch information
nixel2007 committed Dec 27, 2024
1 parent 6e0a2aa commit bd1e564
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,69 @@
import com.github._1c_syntax.bsl.languageserver.context.DocumentContext;
import com.github._1c_syntax.bsl.languageserver.context.FileType;
import com.github._1c_syntax.bsl.languageserver.context.ServerContext;
import com.github._1c_syntax.bsl.languageserver.context.events.DocumentContextContentChangedEvent;
import com.github._1c_syntax.bsl.languageserver.context.events.ServerContextPopulatedEvent;
import com.github._1c_syntax.bsl.languageserver.context.symbol.AnnotationSymbol;
import com.github._1c_syntax.bsl.languageserver.context.symbol.MethodSymbol;
import com.github._1c_syntax.bsl.languageserver.context.symbol.SymbolTree;
import com.github._1c_syntax.bsl.languageserver.context.symbol.annotations.Annotation;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import com.github._1c_syntax.bsl.languageserver.utils.Methods;
import com.github._1c_syntax.bsl.languageserver.utils.Ranges;
import com.github._1c_syntax.bsl.languageserver.utils.Trees;
import com.github._1c_syntax.bsl.parser.BSLParser;
import lombok.RequiredArgsConstructor;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import org.apache.commons.lang3.tuple.Pair;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class AnnotationReferenceFinder implements ReferenceFinder {

private final ServerContext serverContext;
private final Map<String, AnnotationSymbol> registeredAnnotations = new CaseInsensitiveMap<>();

@EventListener
public void handleContextRefresh(ServerContextPopulatedEvent event) {
registeredAnnotations.clear();
serverContext.getDocuments()
.values()
.forEach(this::findAndRegisterAnnotation);
}

@EventListener
public void handleDocumentContextChange(DocumentContextContentChangedEvent event) {
DocumentContext documentContext = event.getSource();
var uri = documentContext.getUri();

registeredAnnotations.values().stream()
.filter(annotationSymbol -> annotationSymbol.getOwner().getUri().equals(uri))
.forEach(annotationSymbol -> registeredAnnotations.remove(annotationSymbol.getName()));

findAndRegisterAnnotation(documentContext);
}

private void findAndRegisterAnnotation(DocumentContext documentContext) {
if (documentContext.getFileType() != FileType.OS) {
return;
}

var symbolTree = documentContext.getSymbolTree();

Methods.getOscriptClassConstructor(symbolTree)
.flatMap(AnnotationReferenceFinder::findAnnotation)
.map(methodSymbolAnnotationPair -> AnnotationSymbol.from(getAnnotationName(methodSymbolAnnotationPair.getRight()), methodSymbolAnnotationPair.getLeft()))
.ifPresent(annotationSymbol -> registeredAnnotations.put(annotationSymbol.getName(), annotationSymbol));
}

@Override
public Optional<Reference> findReference(URI uri, Position position) {
Expand All @@ -53,27 +95,30 @@ public Optional<Reference> findReference(URI uri, Position position) {
return Optional.empty();
}

var registeredAnnotations = serverContext.getDocuments().values().stream()
.filter(documentContext -> documentContext.getFileType() == FileType.OS)
.map(DocumentContext::getSymbolTree)
.flatMap(symbolTree -> symbolTree.getMethodSymbol("ПриСозданииОбъекта").stream())
.filter(methodSymbol -> methodSymbol.getAnnotations().stream().anyMatch(annotation -> annotation.getName().equals("Аннотация")))
.map(methodSymbol -> Pair.of(methodSymbol, methodSymbol.getAnnotations().stream().filter(annotation -> annotation.getName().equals("Аннотация")).findFirst().get()))
.collect(Collectors.toMap(methodSymbolAnnotationPair -> methodSymbolAnnotationPair.getRight().getParameters().get(0).getValue(), Pair::getLeft));

return Trees.findTerminalNodeContainsPosition(document.getAst(), position)
.filter(node -> node.getParent().getRuleContext().getRuleIndex() == BSLParser.RULE_annotationName)
.flatMap((TerminalNode annotationNode) -> {
var annotationName = annotationNode.getText();
var foundAnnotationDeclaration = registeredAnnotations.get(annotationName);
if (foundAnnotationDeclaration == null) {
var annotationSymbol = registeredAnnotations.get(annotationName);
if (annotationSymbol == null) {
return Optional.empty();
}
return Optional.of(Reference.of(
document.getSymbolTree().getModule(),
AnnotationSymbol.from(annotationName, foundAnnotationDeclaration),
annotationSymbol,
new Location(uri.toString(), Ranges.create(annotationNode.getParent().getParent()))
));
});
}

private static Optional<Pair<MethodSymbol, Annotation>> findAnnotation(MethodSymbol methodSymbol) {
return methodSymbol.getAnnotations().stream()
.filter(annotation -> annotation.getName().equalsIgnoreCase("Аннотация"))
.findFirst()
.map(annotation -> Pair.of(methodSymbol, annotation));
}

private static String getAnnotationName(Annotation annotation) {
return annotation.getParameters().get(0).getValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
*/
package com.github._1c_syntax.bsl.languageserver.utils;

import com.github._1c_syntax.bsl.languageserver.context.symbol.MethodSymbol;
import com.github._1c_syntax.bsl.languageserver.context.symbol.SymbolTree;
import com.github._1c_syntax.bsl.parser.BSLParser;
import lombok.experimental.UtilityClass;
import org.antlr.v4.runtime.Token;
Expand Down Expand Up @@ -82,4 +84,9 @@ public static Optional<Token> getMethodName(BSLParser.LValueContext lValueContex
.flatMap(Methods::getMethodName);
}

public static Optional<MethodSymbol> getOscriptClassConstructor(SymbolTree symbolTree) {
return symbolTree.getMethodSymbol("ПриСозданииОбъекта")
.or(() -> symbolTree.getMethodSymbol("OnObjectCreate"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.github._1c_syntax.bsl.languageserver.context;

import com.github._1c_syntax.utils.Absolute;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.PostConstruct;
import java.nio.file.Path;

@SpringBootTest
public abstract class AbstractServerContextAwareTest {
@Autowired
protected ServerContext context;

@PostConstruct
public void init() {
context.clear();
}

protected void initServerContext(String path) {
var configurationRoot = Absolute.path(path);
initServerContext(configurationRoot);
}

protected void initServerContext(Path configurationRoot) {
context.setConfigurationRoot(configurationRoot);
context.populateContext();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
package com.github._1c_syntax.bsl.languageserver.diagnostics;

import com.github._1c_syntax.bsl.languageserver.configuration.LanguageServerConfiguration;
import com.github._1c_syntax.bsl.languageserver.context.AbstractServerContextAwareTest;
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.diagnostics.infrastructure.DiagnosticObjectProvider;
Expand All @@ -46,13 +47,11 @@
import java.util.List;

@SpringBootTest
abstract class AbstractDiagnosticTest<T extends BSLDiagnostic> {
abstract class AbstractDiagnosticTest<T extends BSLDiagnostic> extends AbstractServerContextAwareTest {

@Autowired
private DiagnosticObjectProvider diagnosticObjectProvider;
@Autowired
protected ServerContext context;
@Autowired
protected LanguageServerConfiguration configuration;

private final Class<T> diagnosticClass;
Expand All @@ -65,20 +64,9 @@ abstract class AbstractDiagnosticTest<T extends BSLDiagnostic> {
@PostConstruct
public void init() {
diagnosticInstance = diagnosticObjectProvider.get(diagnosticClass);
context.clear();
configuration.reset();
}

protected void initServerContext(String path) {
var configurationRoot = Absolute.path(path);
initServerContext(configurationRoot);
}

protected void initServerContext(Path configurationRoot) {
context.setConfigurationRoot(configurationRoot);
context.populateContext();
}

protected List<Diagnostic> getDiagnostics(DocumentContext documentContext) {
return diagnosticInstance.getDiagnostics(documentContext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
*/
package com.github._1c_syntax.bsl.languageserver.references;

import com.github._1c_syntax.bsl.languageserver.context.AbstractServerContextAwareTest;
import com.github._1c_syntax.bsl.languageserver.util.CleanupContextBeforeClassAndAfterClass;
import com.github._1c_syntax.bsl.languageserver.util.TestUtils;
import com.github._1c_syntax.bsl.languageserver.utils.Ranges;
import org.eclipse.lsp4j.Position;
Expand All @@ -32,15 +34,18 @@
import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
class AnnotationReferenceFinderTest {
@CleanupContextBeforeClassAndAfterClass
class AnnotationReferenceFinderTest extends AbstractServerContextAwareTest {

@Autowired
private AnnotationReferenceFinder referenceFinder;

@Test
void findReference() {
// given
initServerContext(TestUtils.PATH_TO_METADATA);
var documentContext = TestUtils.getDocumentContextFromFile("./src/test/resources/references/AnnotationReferenceFinder.os");

var module = documentContext.getSymbolTree().getModule();
var method = documentContext.getSymbolTree().getMethods().get(0);

Expand Down

0 comments on commit bd1e564

Please sign in to comment.