Skip to content

Commit

Permalink
Call Hierarchy Provider
Browse files Browse the repository at this point in the history
  • Loading branch information
nixel2007 committed Mar 26, 2021
1 parent 47ff1f2 commit 93cae31
Show file tree
Hide file tree
Showing 5 changed files with 489 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.github._1c_syntax.bsl.languageserver.providers.DocumentSymbolProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.lsp4j.CallHierarchyRegistrationOptions;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionOptions;
import org.eclipse.lsp4j.CodeLensOptions;
Expand Down Expand Up @@ -93,6 +94,7 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
capabilities.setHoverProvider(getHoverProvider());
capabilities.setReferencesProvider(getReferencesProvider());
capabilities.setDefinitionProvider(getDefinitionProvider());
capabilities.setCallHierarchyProvider(getCallHierarchyProvider());

InitializeResult result = new InitializeResult(capabilities, serverInfo);

Expand Down Expand Up @@ -243,6 +245,13 @@ private static ReferenceOptions getReferencesProvider() {
return referenceOptions;
}

private CallHierarchyRegistrationOptions getCallHierarchyProvider() {
var callHierarchyRegistrationOptions = new CallHierarchyRegistrationOptions();
callHierarchyRegistrationOptions.setWorkDoneProgress(Boolean.FALSE);
callHierarchyRegistrationOptions.setDocumentSelector(documentSelector.asList());
return callHierarchyRegistrationOptions;
}

private static WorkspaceSymbolOptions getWorkspaceProvider() {
var workspaceSymbolOptions = new WorkspaceSymbolOptions();
workspaceSymbolOptions.setWorkDoneProgress(Boolean.FALSE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.github._1c_syntax.bsl.languageserver.jsonrpc.DiagnosticParams;
import com.github._1c_syntax.bsl.languageserver.jsonrpc.Diagnostics;
import com.github._1c_syntax.bsl.languageserver.jsonrpc.ProtocolExtension;
import com.github._1c_syntax.bsl.languageserver.providers.CallHierarchyProvider;
import com.github._1c_syntax.bsl.languageserver.providers.CodeActionProvider;
import com.github._1c_syntax.bsl.languageserver.providers.CodeLensProvider;
import com.github._1c_syntax.bsl.languageserver.providers.DefinitionProvider;
Expand All @@ -40,6 +41,12 @@
import com.github._1c_syntax.bsl.languageserver.providers.ReferencesProvider;
import com.github._1c_syntax.bsl.languageserver.utils.Ranges;
import lombok.RequiredArgsConstructor;
import org.eclipse.lsp4j.CallHierarchyIncomingCall;
import org.eclipse.lsp4j.CallHierarchyIncomingCallsParams;
import org.eclipse.lsp4j.CallHierarchyItem;
import org.eclipse.lsp4j.CallHierarchyOutgoingCall;
import org.eclipse.lsp4j.CallHierarchyOutgoingCallsParams;
import org.eclipse.lsp4j.CallHierarchyPrepareParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionParams;
import org.eclipse.lsp4j.CodeLens;
Expand Down Expand Up @@ -90,6 +97,7 @@ public class BSLTextDocumentService implements TextDocumentService, ProtocolExte
private final HoverProvider hoverProvider;
private final ReferencesProvider referencesProvider;
private final DefinitionProvider definitionProvider;
private final CallHierarchyProvider callHierarchyProvider;

@Override
public CompletableFuture<Hover> hover(HoverParams params) {
Expand Down Expand Up @@ -190,6 +198,47 @@ public CompletableFuture<List<FoldingRange>> foldingRange(FoldingRangeRequestPar
return CompletableFuture.supplyAsync(() -> foldingRangeProvider.getFoldingRange(documentContext));
}

@Override
public CompletableFuture<List<CallHierarchyItem>> prepareCallHierarchy(CallHierarchyPrepareParams params) {
// При возврате пустого списка VSCode падает. По протоколу разрешен возврат null.
DocumentContext documentContext = context.getDocument(params.getTextDocument().getUri());
if (documentContext == null) {
return CompletableFuture.completedFuture(null);
}

return CompletableFuture.supplyAsync(() -> {
List<CallHierarchyItem> callHierarchyItems = callHierarchyProvider.prepareCallHierarchy(documentContext, params);
if (callHierarchyItems.isEmpty()) {
return null;
}
return callHierarchyItems;
});
}

@Override
public CompletableFuture<List<CallHierarchyIncomingCall>> callHierarchyIncomingCalls(
CallHierarchyIncomingCallsParams params
) {
DocumentContext documentContext = context.getDocument(params.getItem().getUri());
if (documentContext == null) {
return CompletableFuture.completedFuture(Collections.emptyList());
}

return CompletableFuture.supplyAsync(() -> callHierarchyProvider.incomingCalls(documentContext, params));
}

@Override
public CompletableFuture<List<CallHierarchyOutgoingCall>> callHierarchyOutgoingCalls(
CallHierarchyOutgoingCallsParams params
) {
DocumentContext documentContext = context.getDocument(params.getItem().getUri());
if (documentContext == null) {
return CompletableFuture.completedFuture(Collections.emptyList());
}

return CompletableFuture.supplyAsync(() -> callHierarchyProvider.outgoingCalls(documentContext, params));
}

@Override
public void didOpen(DidOpenTextDocumentParams params) {
DocumentContext documentContext = context.addDocument(params.getTextDocument());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* 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.providers;

import com.github._1c_syntax.bsl.languageserver.context.DocumentContext;
import com.github._1c_syntax.bsl.languageserver.references.ReferenceIndex;
import com.github._1c_syntax.bsl.languageserver.context.symbol.SourceDefinedSymbol;
import com.github._1c_syntax.bsl.languageserver.references.Reference;
import com.github._1c_syntax.bsl.languageserver.references.ReferenceResolver;
import com.github._1c_syntax.bsl.languageserver.utils.MdoRefBuilder;
import lombok.RequiredArgsConstructor;
import org.eclipse.lsp4j.CallHierarchyIncomingCall;
import org.eclipse.lsp4j.CallHierarchyIncomingCallsParams;
import org.eclipse.lsp4j.CallHierarchyItem;
import org.eclipse.lsp4j.CallHierarchyOutgoingCall;
import org.eclipse.lsp4j.CallHierarchyOutgoingCallsParams;
import org.eclipse.lsp4j.CallHierarchyPrepareParams;
import org.eclipse.lsp4j.Position;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toCollection;

@Component
@RequiredArgsConstructor
public class CallHierarchyProvider {

private final ReferenceResolver referenceResolver;
private final ReferenceIndex referenceIndex;

public List<CallHierarchyItem> prepareCallHierarchy(
DocumentContext documentContext,
CallHierarchyPrepareParams params
) {
Position position = params.getPosition();

return referenceResolver.findReference(documentContext.getUri(), position)
.flatMap(Reference::getSourceDefinedSymbol)
.map(CallHierarchyProvider::getCallHierarchyItem)
.map(Collections::singletonList)
.orElse(Collections.emptyList())
;
}

public List<CallHierarchyIncomingCall> incomingCalls(
DocumentContext documentContext,
CallHierarchyIncomingCallsParams params
) {

URI uri = documentContext.getUri();
CallHierarchyItem item = params.getItem();
Position position = item.getSelectionRange().getStart();

return referenceResolver.findReference(uri, position)
.flatMap(Reference::getSourceDefinedSymbol)
.stream()
.map(referenceIndex::getReferencesTo)
.flatMap(Collection::stream)
.collect(groupingBy(
Reference::getFrom,
mapping(Reference::getSelectionRange, toCollection(ArrayList::new)))
)
.entrySet()
.stream()
.map(entry -> new CallHierarchyIncomingCall(getCallHierarchyItem(entry.getKey()), entry.getValue()))
.collect(Collectors.toList());

}

public List<CallHierarchyOutgoingCall> outgoingCalls(
DocumentContext documentContext,
CallHierarchyOutgoingCallsParams params
) {

URI uri = documentContext.getUri();
Position position = params.getItem().getSelectionRange().getStart();

return referenceResolver.findReference(uri, position)
.flatMap(Reference::getSourceDefinedSymbol)
.stream()
.map(referenceIndex::getReferencesFrom)
.flatMap(Collection::stream)
.filter(Reference::isSourceDefinedSymbolReference)
.collect(groupingBy(
reference -> reference.getSourceDefinedSymbol().orElseThrow(),
mapping(Reference::getSelectionRange, toCollection(ArrayList::new)))
)
.entrySet()
.stream()
.map(entry -> new CallHierarchyOutgoingCall(getCallHierarchyItem(entry.getKey()), entry.getValue()))
.collect(Collectors.toList());

}

private static CallHierarchyItem getCallHierarchyItem(SourceDefinedSymbol sourceDefinedSymbol) {
String detail = MdoRefBuilder.getMdoRef(sourceDefinedSymbol.getOwner());

CallHierarchyItem item = new CallHierarchyItem();
item.setName(sourceDefinedSymbol.getName());
item.setDetail(detail);
item.setKind(sourceDefinedSymbol.getSymbolKind());
item.setTags(sourceDefinedSymbol.getTags());
item.setUri(sourceDefinedSymbol.getOwner().getUri().toString());
item.setRange(sourceDefinedSymbol.getRange());
item.setSelectionRange(sourceDefinedSymbol.getSelectionRange());

return item;
}
}
Loading

0 comments on commit 93cae31

Please sign in to comment.