use of nl.ramsolutions.sw.magik.analysis.Range in project magik-tools by StevenLooman.
the class CompletionProvider method provideGlobalCompletion.
/**
* Provide global completion.
* @param magikFile MagikFile.
* @param position Position in source.
* @param tokenNode Current node.
* @return Completions items.
*/
@SuppressWarnings("checkstyle:NestedIfDepth")
private List<CompletionItem> provideGlobalCompletion(final MagikTypedFile magikFile, final Position position, @Nullable final AstNode tokenNode) {
final List<CompletionItem> items = new ArrayList<>();
// Keyword entries.
Stream.of(MagikKeyword.values()).map(magikKeyword -> {
final String name = magikKeyword.toString().toLowerCase();
final CompletionItem item = new CompletionItem(name);
item.setKind(CompletionItemKind.Keyword);
item.setInsertText(magikKeyword.getValue());
return item;
}).forEach(items::add);
// Scope entries.
final AstNode topNode = magikFile.getTopNode();
AstNode scopeNode = AstQuery.nodeSurrounding(topNode, Lsp4jConversion.positionFromLsp4j(position));
if (scopeNode != null) {
if (scopeNode.getFirstChild(MagikGrammar.BODY) != null) {
scopeNode = scopeNode.getFirstChild(MagikGrammar.BODY);
}
final GlobalScope globalScope = magikFile.getGlobalScope();
final Scope scopeForNode = globalScope.getScopeForNode(scopeNode);
if (scopeForNode != null) {
scopeForNode.getSelfAndAncestorScopes().stream().flatMap(scope -> scope.getScopeEntriesInScope().stream()).filter(scopeEntry -> {
final AstNode definingNode = scopeEntry.getNode();
final Range range = new Range(definingNode);
return Lsp4jConversion.positionFromLsp4j(position).isAfterRange(range);
}).map(scopeEntry -> {
final CompletionItem item = new CompletionItem(scopeEntry.getIdentifier());
item.setInsertText(scopeEntry.getIdentifier());
item.setDetail(scopeEntry.getIdentifier());
item.setKind(CompletionItemKind.Variable);
return item;
}).forEach(items::add);
}
}
// Slots.
final ITypeKeeper typeKeeper = magikFile.getTypeKeeper();
if (scopeNode != null) {
final AstNode methodDefinitionNode = scopeNode.getFirstAncestor(MagikGrammar.METHOD_DEFINITION);
if (methodDefinitionNode != null) {
final MethodDefinitionNodeHelper helper = new MethodDefinitionNodeHelper(methodDefinitionNode);
final GlobalReference globalRef = helper.getTypeGlobalReference();
final AbstractType type = typeKeeper.getType(globalRef);
type.getSlots().stream().map(slot -> {
final String slotName = slot.getName();
final String fullSlotName = slot.getOwner().getFullName() + "." + slot.getName();
final CompletionItem item = new CompletionItem(slotName);
item.setInsertText(slotName);
item.setDetail(fullSlotName);
item.setKind(CompletionItemKind.Property);
return item;
}).forEach(items::add);
}
}
// Global types.
final String identifierPart = tokenNode != null ? tokenNode.getTokenValue() : "";
typeKeeper.getTypes().stream().filter(type -> type.getFullName().indexOf(identifierPart) != -1).map(type -> {
final CompletionItem item = new CompletionItem(type.getFullName());
// TODO: if visible from current package, don't prefix package.
item.setInsertText(type.getFullName());
item.setDetail(type.getFullName());
item.setDocumentation(type.getDoc());
item.setKind(CompletionItemKind.Class);
return item;
}).forEach(items::add);
return items;
}
use of nl.ramsolutions.sw.magik.analysis.Range in project magik-tools by StevenLooman.
the class DocumentSymbolProvider method convertDefinition.
private DocumentSymbol convertDefinition(final Definition definition) {
final SymbolKind symbolKind = this.symbolKindForDefinition(definition);
final DocumentSymbol documentSymbol = new DocumentSymbol(definition.getName(), symbolKind, Lsp4jConversion.rangeToLsp4j(new Range(definition.getNode())), Lsp4jConversion.rangeToLsp4j(new Range(definition.getNode())));
if (definition instanceof SlottedExemplarDefinition) {
final SlottedExemplarDefinition exemplarDefinition = (SlottedExemplarDefinition) definition;
final List<DocumentSymbol> slotSymbols = this.convertedSlotsFromDefinition(exemplarDefinition);
documentSymbol.setChildren(slotSymbols);
}
return documentSymbol;
}
use of nl.ramsolutions.sw.magik.analysis.Range in project magik-tools by StevenLooman.
the class RenameProvider method provideRename.
/**
* Provide rename.
* @param magikFile Magik file.
* @param position Position in magik source.
* @param newName New name.
* @return Edits to workspace.
*/
public WorkspaceEdit provideRename(final MagikTypedFile magikFile, final Position position, final String newName) {
// Parse magik.
final AstNode topNode = magikFile.getTopNode();
// Should always be on an identifier.
final AstNode node = AstQuery.nodeAt(topNode, Lsp4jConversion.positionFromLsp4j(position), MagikGrammar.IDENTIFIER);
if (node == null) {
return null;
}
// Set up scope.
final ScopeEntry scopeEntry = this.findScopeEntry(magikFile, node);
if (scopeEntry == null || scopeEntry.isType(ScopeEntry.Type.GLOBAL) || scopeEntry.isType(ScopeEntry.Type.DYNAMIC) || scopeEntry.isType(ScopeEntry.Type.IMPORT)) {
return null;
}
// Provide edits.
final String uri = magikFile.getUri().toString();
final AstNode definitionNode = scopeEntry.getNode();
final List<TextEdit> textEdits = Stream.concat(Stream.of(definitionNode), scopeEntry.getUsages().stream()).map(renameNode -> renameNode.isNot(MagikGrammar.IDENTIFIER) ? renameNode.getFirstChild(MagikGrammar.IDENTIFIER) : renameNode).map(Range::new).map(Lsp4jConversion::rangeToLsp4j).map(range -> new TextEdit(range, newName)).collect(Collectors.toList());
return new WorkspaceEdit(Map.of(uri, textEdits));
}
Aggregations