Fixed: [Issue 94] Importing "google/protobuf/descriptor.proto" does not
work.
Now we pass the path to descriptor.proto to protoc. Code cleanup.
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder_findRootOf_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder_findRootOf_Test.java
new file mode 100644
index 0000000..3e8fab7
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder_findRootOf_Test.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 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.builder;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.rules.ExpectedException.none;
+
+import org.junit.*;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Tests for <code>{@link ProtoDescriptorPathFinder#findRootOf(String)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProtoDescriptorPathFinder_findRootOf_Test {
+
+ private static ProtoDescriptorPathFinder finder;
+
+ @BeforeClass public static void setUpOnce() {
+ finder = new ProtoDescriptorPathFinder();
+ }
+
+ @Rule public ExpectedException thrown = none();
+
+ @Test public void should_return_null_if_path_is_null() {
+ assertThat(finder.findRootOf(null), nullValue());
+ }
+
+ @Test public void should_throw_error_if_path_does_not_contain_descriptor_FQN() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Path '/usr/local/include' does not contain '/google/protobuf/descriptor.proto'");
+ finder.findRootOf("/usr/local/include");
+ }
+
+ @Test public void should_find_import_root_of_descriptor() {
+ String filePath = "/usr/local/include/google/protobuf/descriptor.proto";
+ assertThat(finder.findRootOf(filePath), equalTo("/usr/local/include"));
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder.java
new file mode 100644
index 0000000..9fa8783
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtoDescriptorPathFinder.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011 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.builder;
+
+import static com.google.eclipse.protobuf.scoping.ProtoDescriptor.DESCRIPTOR_IMPORT_URI;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class ProtoDescriptorPathFinder {
+
+ private static final String DESCRIPTOR_FQN = "/" + DESCRIPTOR_IMPORT_URI;
+
+ public String findRootOf(String descriptorFilePath) {
+ if (descriptorFilePath == null) return null;
+ int indexOfDescriptorFqn = descriptorFilePath.indexOf(DESCRIPTOR_FQN);
+ if (indexOfDescriptorFqn == -1) {
+ String format = "Path '%s' does not contain '%s'";
+ throw new IllegalArgumentException(String.format(format, descriptorFilePath, DESCRIPTOR_FQN));
+ }
+ return descriptorFilePath.substring(0, indexOfDescriptorFqn);
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtobufBuildParticipant.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtobufBuildParticipant.java
index 3dffc5e..e70f5d0 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtobufBuildParticipant.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtobufBuildParticipant.java
@@ -19,7 +19,6 @@
import java.util.ArrayList;
import java.util.List;
-import org.eclipse.core.filesystem.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.emf.common.util.URI;
@@ -42,6 +41,7 @@
@Inject private ProtocCommandFactory commandFactory;
@Inject private CompilerPreferencesFactory compilerPreferencesFactory;
@Inject private PathsPreferencesFactory pathsPreferencesFactory;
+ @Inject private ProtoDescriptorPathFinder protoDescriptorPathFinder;
public void build(IBuildContext context, IProgressMonitor monitor) throws CoreException {
IProject project = context.getBuiltProject();
@@ -50,25 +50,28 @@
List<Delta> deltas = context.getDeltas();
if (deltas.isEmpty()) return;
OutputDirectories outputDirectories = findOrCreateOutputDirectories(project, preferences.codeGenerationSettings());
+ String descriptorPath = descriptorPath(preferences);
List<String> importRoots = importRoots(project);
for (Delta d : deltas) {
- IResourceDescription newResource = d.getNew();
- String path = filePathIfIsProtoFile(newResource);
- if (path == null) continue;
- IFile source = project.getWorkspace().getRoot().getFile(new Path(path));
+ IFile source = protoFile(d.getNew(), project);
+ if (source == null) continue;
if (importRoots.isEmpty()) importRoots = singleImportRoot(source);
- generateSingleProto(source, preferences.protocPath(), importRoots, outputDirectories);
+ generateSingleProto(source, preferences.protocPath(), importRoots, descriptorPath, outputDirectories);
}
if (preferences.shouldRefreshResources()) refresh(project, outputDirectories, preferences.refreshTarget(), monitor);
}
+ private String descriptorPath(CompilerPreferences preferences) {
+ return protoDescriptorPathFinder.findRootOf(preferences.descriptorPath());
+ }
+
private List<String> importRoots(IProject project) {
List<String> paths = new ArrayList<String>();
PathsPreferences preferences = pathsPreferencesFactory.preferences(project);
if (MULTIPLE_DIRECTORIES.equals(preferences.pathResolutionType())) {
List<DirectoryPath> directoryPaths = preferences.importRoots();
for (DirectoryPath path : directoryPaths) {
- String location = locationOfDirectory(path, project);
+ String location = path.location(project);
if (location != null) paths.add(location);
}
return unmodifiableList(paths);
@@ -76,22 +79,9 @@
return emptyList();
}
- private String locationOfDirectory(DirectoryPath path, IProject project) {
- if (path.isWorkspacePath()) return locationOfWorkspaceDirectory(path, project);
- return locationOfFileSystemDirectory(path);
- }
-
- private String locationOfWorkspaceDirectory(DirectoryPath path, IProject project) {
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- IFolder folder = root.getFolder(new Path(path.value()));
- return folder.getLocation().toOSString();
- }
-
- private String locationOfFileSystemDirectory(DirectoryPath path) {
- IFileSystem fileSystem = EFS.getLocalFileSystem();
- IFileInfo fileInfo = fileSystem.getStore(new Path(path.value())).fetchInfo();
- if (!fileInfo.isDirectory()) return null;
- return path.value();
+ private static IFile protoFile(IResourceDescription r, IProject project) {
+ String path = filePathIfIsProtoFile(r);
+ return (path == null) ? null : project.getWorkspace().getRoot().getFile(new Path(path));
}
private static String filePathIfIsProtoFile(IResourceDescription r) {
@@ -116,9 +106,9 @@
return singletonList(current.toString());
}
- private void generateSingleProto(IFile source, String protocPath, List<String> importRoots,
+ private void generateSingleProto(IFile source, String protocPath, List<String> importRoots, String descriptorPath,
OutputDirectories outputDirectories) throws CoreException {
- String command = commandFactory.protocCommand(source, protocPath, importRoots, outputDirectories);
+ String command = commandFactory.protocCommand(source, protocPath, importRoots, descriptorPath, outputDirectories);
System.out.println(command);
try {
Process process = Runtime.getRuntime().exec(command);
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
index ec2694d..32ab772 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocCommandFactory.java
@@ -10,12 +10,14 @@
import static com.google.eclipse.protobuf.util.CommonWords.space;
-import com.google.eclipse.protobuf.ui.preferences.pages.compiler.SupportedLanguage;
-
-import org.eclipse.core.resources.*;
-
import java.util.*;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.xtext.util.Strings;
+
+import com.google.eclipse.protobuf.ui.preferences.pages.compiler.SupportedLanguage;
+
/**
* @author alruiz@google.com (Alex Ruiz)
*/
@@ -28,13 +30,16 @@
LANG_OUT_FLAG.put(lang, "--" + lang.code() + "_out=");
}
- String protocCommand(IFile protoFile, String protocPath, List<String> importRoots,
+ String protocCommand(IFile protoFile, String protocPath, List<String> importRoots, String descriptorPath,
OutputDirectories outputDirectories) {
StringBuilder command = new StringBuilder();
command.append(protocPath).append(space());
for (String importRoot : importRoots) {
command.append("-I=").append(importRoot).append(space());
}
+ if (!Strings.isEmpty(descriptorPath)) {
+ command.append("--proto_path=").append(descriptorPath).append(space());
+ }
for (SupportedLanguage language : SupportedLanguage.values()) {
IFolder outputDirectory = outputDirectories.outputDirectoryFor(language);
if (outputDirectory == null) continue;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/paths/DirectoryPath.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/paths/DirectoryPath.java
index 51a5886..1aeb5bb 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/paths/DirectoryPath.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/paths/DirectoryPath.java
@@ -10,17 +10,22 @@
import static com.google.eclipse.protobuf.ui.preferences.pages.paths.ProjectVariable.useProjectName;
-import org.eclipse.core.resources.IProject;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
-import java.util.regex.*;
+import org.eclipse.core.filesystem.*;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.Path;
/**
+ * Represents the path of a directory.
+ *
* @author alruiz@google.com (Alex Ruiz)
*/
public class DirectoryPath {
private static final Pattern WORKSPACE_PATH_PATTERN = Pattern.compile("\\$\\{workspace_loc:(.*)\\}");
-
+
private final String value;
private final boolean isWorkspacePath;
@@ -37,23 +42,54 @@
}
return new DirectoryPath(path, false);
}
-
+
DirectoryPath(String path, boolean isWorkspacePath) {
this.value = path;
this.isWorkspacePath = isWorkspacePath;
}
-
+
/** {@inheritDoc} */
@Override public String toString() {
if (!isWorkspacePath) return value;
return "${workspace_loc:" + value + "}";
}
+ /**
+ * Returns the textual value of this path.
+ * @return the textual value of this path.
+ */
public String value() {
return value;
}
+ /**
+ * Indicates whether this path belongs to a workspace resource.
+ * @return {@code true} if this path belongs to a workspace resource, {@code false} otherwise.
+ */
public boolean isWorkspacePath() {
return isWorkspacePath;
}
+
+ /**
+ * Returns the absolute path in the local file system, or {@code null} if no path can be determined.
+ * @param project used if this path belongs to a workspace resource.
+ * @return the absolute path in the local file system, or {@code null} if no path can be determined.
+ */
+ public String location(IProject project) {
+ if (isWorkspacePath()) return locationOfWorkspaceDirectory(project);
+ return locationOfFileSystemDirectory();
+ }
+
+ private String locationOfWorkspaceDirectory(IProject project) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IFolder folder = root.getFolder(new Path(value()));
+ return folder.getLocation().toOSString();
+ }
+
+ private String locationOfFileSystemDirectory() {
+ IFileSystem fileSystem = EFS.getLocalFileSystem();
+ IFileInfo fileInfo = fileSystem.getStore(new Path(value())).fetchInfo();
+ if (!fileInfo.isDirectory()) return null;
+ return value();
+ }
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
index f83be37..b27a2cf 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
@@ -38,6 +38,11 @@
*/
public class ProtoDescriptor {
+ /**
+ * The URI to use when importing descriptor.proto.
+ */
+ public static String DESCRIPTOR_IMPORT_URI = "google/protobuf/descriptor.proto";
+
private static final Map<String, OptionType> OPTION_DEFINITION_BY_NAME = new HashMap<String, OptionType>();
static {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Imports.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Imports.java
index ac9b01b..ea34fd0 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Imports.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Imports.java
@@ -8,6 +8,8 @@
*/
package com.google.eclipse.protobuf.util;
+import static com.google.eclipse.protobuf.scoping.ProtoDescriptor.DESCRIPTOR_IMPORT_URI;
+
import com.google.eclipse.protobuf.protobuf.Import;
import com.google.inject.Singleton;
@@ -38,6 +40,6 @@
* @return {@code true} if the given import URI is equal to the path of descriptor.proto, {@code false} otherwise.
*/
public boolean isUnresolvedDescriptorUri(String uri) {
- return "google/protobuf/descriptor.proto".equals(uri);
+ return DESCRIPTOR_IMPORT_URI.equals(uri);
}
}