All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.smithy.lsp.project.SmithyFileDependenciesIndex Maven / Gradle / Ivy

There is a newer version: 0.5.0
Show newest version
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

package software.amazon.smithy.lsp.project;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.ToShapeId;
import software.amazon.smithy.model.traits.Trait;
import software.amazon.smithy.model.validation.ValidatedResult;

/**
 * An index that caches rebuild dependency relationships between Smithy files,
 * shapes, and traits.
 *
 * 

This is specifically for the following scenarios: *

*
A file applies traits to shapes in other files
*
If that file changes, the applied traits need to be removed before the * file is reloaded, so there aren't duplicate traits.
*
A file has shapes with traits applied in other files
*
If that file changes, the traits need to be re-applied when the model is * re-assembled, so they aren't lost.
*
Either 1 or 2, but specifically with list traits
*
List traits are merged via * trait conflict resolution . For these traits, all files that contain * parts of the list trait must be fully reloaded, since we can only remove * the whole trait, not parts of it.
*
*/ final class SmithyFileDependenciesIndex { private final Map> filesToDependentFiles; private final Map> shapeIdsToDependenciesFiles; private final Map>> filesToTraitsTheyApply; private final Map> shapesToAppliedTraitsInOtherFiles; SmithyFileDependenciesIndex() { this.filesToDependentFiles = new HashMap<>(0); this.shapeIdsToDependenciesFiles = new HashMap<>(0); this.filesToTraitsTheyApply = new HashMap<>(0); this.shapesToAppliedTraitsInOtherFiles = new HashMap<>(0); } private SmithyFileDependenciesIndex( Map> filesToDependentFiles, Map> shapeIdsToDependenciesFiles, Map>> filesToTraitsTheyApply, Map> shapesToAppliedTraitsInOtherFiles ) { this.filesToDependentFiles = filesToDependentFiles; this.shapeIdsToDependenciesFiles = shapeIdsToDependenciesFiles; this.filesToTraitsTheyApply = filesToTraitsTheyApply; this.shapesToAppliedTraitsInOtherFiles = shapesToAppliedTraitsInOtherFiles; } Set getDependentFiles(String path) { return filesToDependentFiles.getOrDefault(path, Collections.emptySet()); } Set getDependenciesFiles(ToShapeId toShapeId) { return shapeIdsToDependenciesFiles.getOrDefault(toShapeId.toShapeId(), Collections.emptySet()); } Map> getAppliedTraitsInFile(String path) { return filesToTraitsTheyApply.getOrDefault(path, Collections.emptyMap()); } List getTraitsAppliedInOtherFiles(ToShapeId toShapeId) { return shapesToAppliedTraitsInOtherFiles.getOrDefault(toShapeId.toShapeId(), Collections.emptyList()); } // TODO: Make this take care of metadata too static SmithyFileDependenciesIndex compute(ValidatedResult modelResult) { if (modelResult.getResult().isEmpty()) { return new SmithyFileDependenciesIndex(); } SmithyFileDependenciesIndex index = new SmithyFileDependenciesIndex( new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>()); Model model = modelResult.getResult().get(); for (Shape shape : model.toSet()) { String shapeSourceFilename = shape.getSourceLocation().getFilename(); for (Trait traitApplication : shape.getAllTraits().values()) { // We only care about trait applications in the source files if (traitApplication.isSynthetic()) { continue; } Node traitNode = traitApplication.toNode(); if (traitNode.isArrayNode()) { for (Node element : traitNode.expectArrayNode()) { String elementSourceFilename = element.getSourceLocation().getFilename(); if (!elementSourceFilename.equals(shapeSourceFilename)) { index.filesToDependentFiles.computeIfAbsent(elementSourceFilename, (k) -> new HashSet<>()) .add(shapeSourceFilename); index.shapeIdsToDependenciesFiles.computeIfAbsent(shape.getId(), (k) -> new HashSet<>()) .add(elementSourceFilename); } } } else { String traitSourceFilename = traitApplication.getSourceLocation().getFilename(); if (!traitSourceFilename.equals(shapeSourceFilename)) { index.shapesToAppliedTraitsInOtherFiles.computeIfAbsent(shape.getId(), (k) -> new ArrayList<>()) .add(traitApplication); index.filesToTraitsTheyApply.computeIfAbsent(traitSourceFilename, (k) -> new HashMap<>()) .computeIfAbsent(shape.getId(), (k) -> new ArrayList<>()) .add(traitApplication); } } } } return index; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy