blob: f9d2a74fcc088cc822a33a994f64ceb7dd9c2a74 [file] [log] [blame]
/*
* Copyright (c) 2014 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.ui.scoping;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.eclipse.protobuf.model.util.Imports;
import com.google.eclipse.protobuf.protobuf.Import;
import com.google.eclipse.protobuf.scoping.IImportResolver;
import com.google.eclipse.protobuf.scoping.IUriResolver;
import com.google.eclipse.protobuf.scoping.ProtoDescriptorProvider;
import com.google.eclipse.protobuf.util.EResources;
import com.google.eclipse.protobuf.util.Uris;
import com.google.inject.Inject;
import org.eclipse.core.resources.IProject;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import java.util.concurrent.ExecutionException;
/**
* Resolves "import" URIs.
*
* @author alruiz@google.com (Alex Ruiz)
*/
public class ImportResolver implements IImportResolver {
@Inject private ProtoDescriptorProvider descriptorProvider;
@Inject private Imports imports;
@Inject private IUriResolver resolver;
@Inject private Uris uris;
private LoadingCache<Import, String> cache =
CacheBuilder.newBuilder().build(new CacheLoader<Import, String>() {
@Override
public String load(Import key) throws Exception {
String result = internalResolveUri(key);
if (result == null) {
throw new Exception("Unable to resolve import: " + imports.getPath(key));
}
return result;
}
});
/*
* The import URI is relative to the file where the import is. Protoc works fine, but the editor doesn't.
* In order for the editor to see the import, we need to add to the import URI "platform:resource" and the parent
* folder of the file containing the import.
*
* For example: given the following file hierarchy:
*
* - protobuf-test (project)
* - folder
* - proto2.proto
* - proto1.proto
*
* If we import "folder/proto2.proto" into proto1.proto, proto1.proto will compile fine, but the editor will complain.
* We need to have the import URI as "platform:/resource/protobuf-test/folder/proto2.proto" for the editor to see it.
*/
@Override public String resolve(Import anImport) {
try {
return cache.get(anImport);
} catch (ExecutionException e) {
return null;
}
}
private String internalResolveUri(Import anImport) {
return resolveUri(imports.getPath(anImport), anImport.eResource());
}
private String resolveUri(String importUri, Resource resource) {
URI location =
descriptorProvider.descriptorLocation(EResources.getProjectOf(resource), importUri);
if (location != null) {
return location.toString();
}
URI resourceUri = resource.getURI();
IProject project = uris.projectOfReferredFile(resourceUri);
return resolver.resolveUri(importUri, resourceUri, project);
}
@Override
public void invalidateCacheFor(Import anImport) {
cache.invalidate(anImport);
}
}