software.amazon.smithy.lsp.handler.DefinitionHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of smithy-language-server Show documentation
Show all versions of smithy-language-server Show documentation
Language Server Protocol implementation for Smithy
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package software.amazon.smithy.lsp.handler;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.eclipse.lsp4j.DefinitionParams;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import software.amazon.smithy.lsp.document.DocumentId;
import software.amazon.smithy.lsp.document.DocumentParser;
import software.amazon.smithy.lsp.document.DocumentPositionContext;
import software.amazon.smithy.lsp.project.Project;
import software.amazon.smithy.lsp.project.SmithyFile;
import software.amazon.smithy.lsp.protocol.LspAdapter;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.loader.Prelude;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.traits.MixinTrait;
import software.amazon.smithy.model.traits.TraitDefinition;
/**
* Handles go-to-definition requests.
*/
public final class DefinitionHandler {
private final Project project;
private final SmithyFile smithyFile;
public DefinitionHandler(Project project, SmithyFile smithyFile) {
this.project = project;
this.smithyFile = smithyFile;
}
/**
* @param params The request params
* @return A list of possible definition locations
*/
public List handle(DefinitionParams params) {
Position position = params.getPosition();
DocumentId id = smithyFile.document().copyDocumentId(position);
if (id == null || id.idSlice().isEmpty()) {
return Collections.emptyList();
}
Optional modelResult = project.modelResult().getResult();
if (modelResult.isEmpty()) {
return Collections.emptyList();
}
Model model = modelResult.get();
DocumentPositionContext context = DocumentParser.forDocument(smithyFile.document())
.determineContext(position);
return contextualShapes(model, context)
.filter(contextualMatcher(smithyFile, id))
.findFirst()
.map(Shape::getSourceLocation)
.map(LspAdapter::toLocation)
.map(Collections::singletonList)
.orElse(Collections.emptyList());
}
private static Predicate contextualMatcher(SmithyFile smithyFile, DocumentId id) {
String token = id.copyIdValue();
if (id.type() == DocumentId.Type.ABSOLUTE_ID) {
return (shape) -> shape.getId().toString().equals(token);
} else {
return (shape) -> (Prelude.isPublicPreludeShape(shape)
|| shape.getId().getNamespace().contentEquals(smithyFile.namespace())
|| smithyFile.hasImport(shape.getId().toString()))
&& shape.getId().getName().equals(token);
}
}
private static Stream contextualShapes(Model model, DocumentPositionContext context) {
return switch (context) {
case TRAIT -> model.getShapesWithTrait(TraitDefinition.class).stream();
case MEMBER_TARGET -> model.shapes()
.filter(shape -> !shape.isMemberShape())
.filter(shape -> !shape.hasTrait(TraitDefinition.class));
case MIXIN -> model.getShapesWithTrait(MixinTrait.class).stream();
default -> model.shapes().filter(shape -> !shape.isMemberShape());
};
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy