/* * Copyright (c) 2016 Google Inc. * * All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package com.google.eclipse.protobuf.scoping; import com.google.common.base.Predicate; import com.google.eclipse.protobuf.model.util.Imports; import com.google.eclipse.protobuf.model.util.Protobufs; import com.google.eclipse.protobuf.model.util.Resources; import com.google.eclipse.protobuf.protobuf.Import; import com.google.eclipse.protobuf.protobuf.Protobuf; import com.google.eclipse.protobuf.util.EResources; import com.google.inject.Inject; import com.google.inject.Provider; import org.eclipse.core.resources.IProject; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.xtext.resource.IEObjectDescription; import org.eclipse.xtext.resource.IResourceDescription; import org.eclipse.xtext.resource.IResourceDescriptions; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.impl.ImportUriGlobalScopeProvider; import org.eclipse.xtext.util.IResourceScopeCache; import java.util.LinkedHashSet; /** * A global scope provider that reads each {@link Import} in the protobuf file, resolves it, and * caches the result. */ public class ProtobufImportUriGlobalScopeProvider extends ImportUriGlobalScopeProvider { @Override protected IScope createLazyResourceScope( IScope parent, URI uri, IResourceDescriptions descriptions, EClass type, Predicate<IEObjectDescription> filter, boolean ignoreCase) { IResourceDescription description = descriptions.getResourceDescription(uri); return ProtobufSelectableBasedScope.createScope(parent, description, filter, type, ignoreCase); } @Inject private Protobufs protobufs; @Inject private Resources resources; @Inject private Imports imports; @Inject private IResourceScopeCache cache; @Inject private ProtoDescriptorProvider descriptorProvider; @Override protected LinkedHashSet<URI> getImportedUris(final Resource resource) { return cache.get( ProtobufImportUriGlobalScopeProvider.class.getName(), resource, new Provider<LinkedHashSet<URI>>() { @Override public LinkedHashSet<URI> get() { LinkedHashSet<URI> importedUris = new LinkedHashSet<>(); Protobuf protobuf = resources.rootOf(resource); if (protobuf == null) { return importedUris; } for (Import singleImport : protobufs.importsIn(protobuf)) { resolveImport(importedUris, singleImport); } return importedUris; } private void addPublicImportedUris(Protobuf protobuf, LinkedHashSet<URI> importedUris) { for (Import singleImport : protobufs.publicImportsIn(protobuf)) { if (!importedUris.contains(imports.resolvedUriOf(singleImport))) { resolveImport(importedUris, singleImport); } } } private void resolveImport(LinkedHashSet<URI> importedUris, Import singleImport) { if (imports.isResolved(singleImport)) { Protobuf root = resources.rootOf(imports.importedResource(singleImport)); if (root != null) { importedUris.add(imports.resolvedUriOf(singleImport)); addPublicImportedUris(root, importedUris); } } else if (imports.hasUnresolvedDescriptorUri(singleImport)) { IProject project = EResources.getProjectOf(singleImport.eResource()); importedUris.add( descriptorProvider.descriptorLocation(project, imports.getPath(singleImport))); } } }); } }