In progress: [Issue 199] Add ability to navigate to proto element from
generated C++ code.

Initial project import.
diff --git a/com.google.eclipse.protobuf.cdt/.classpath b/com.google.eclipse.protobuf.cdt/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/com.google.eclipse.protobuf.cdt/.gitignore b/com.google.eclipse.protobuf.cdt/.gitignore
new file mode 100644
index 0000000..40a85ff
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/.gitignore
@@ -0,0 +1 @@
+/.settings
diff --git a/com.google.eclipse.protobuf.cdt/.project b/com.google.eclipse.protobuf.cdt/.project
new file mode 100644
index 0000000..130ae32
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.google.eclipse.protobuf.cdt</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/com.google.eclipse.protobuf.cdt/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.cdt/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..d989a9b
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/META-INF/MANIFEST.MF
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Protocol Buffer Editor: CDT Integration
+Bundle-SymbolicName: com.google.eclipse.protobuf.cdt;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: com.google.eclipse.protobuf.cdt.ProtobufCdtActivator
+Bundle-Vendor: Google, Inc.
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.cdt.core;bundle-version="5.3.1",
+ org.eclipse.cdt.ui;bundle-version="5.3.1",
+ com.google.eclipse.protobuf;bundle-version="1.2.1",
+ com.google.eclipse.protobuf.ui;bundle-version="1.2.1",
+ org.eclipse.core.resources;bundle-version="3.7.100",
+ org.eclipse.jface.text;bundle-version="3.7.1",
+ org.eclipse.xtext;bundle-version="2.2.1",
+ org.eclipse.xtext.ui;bundle-version="2.2.1"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
diff --git a/com.google.eclipse.protobuf.cdt/build.properties b/com.google.eclipse.protobuf.cdt/build.properties
new file mode 100644
index 0000000..e9863e2
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml
diff --git a/com.google.eclipse.protobuf.cdt/icons/pb.gif b/com.google.eclipse.protobuf.cdt/icons/pb.gif
new file mode 100644
index 0000000..762a318
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/icons/pb.gif
Binary files differ
diff --git a/com.google.eclipse.protobuf.cdt/plugin.xml b/com.google.eclipse.protobuf.cdt/plugin.xml
new file mode 100644
index 0000000..17864bd
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/plugin.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         point="org.eclipse.ui.popupMenus">
+      <viewerContribution
+            id="com.google.eclipse.protobuf.cdt.cEditorPopup"
+            targetID="#CEditorContext">
+         <action
+               class="com.google.eclipse.protobuf.cdt.ProtobufCdtExecutableExtensionFactory:com.google.eclipse.protobuf.cdt.actions.OpenProtoDeclarationAction"
+               icon="icons/pb.gif"
+               id="com.google.eclipse.protobuf.cdt.openProtoDeclaration"
+               label="Open Declaration in .proto File"
+               menubarPath="group.open"
+               style="push">
+         </action>
+      </viewerContribution>
+   </extension>
+
+</plugin>
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtActivator.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtActivator.java
new file mode 100644
index 0000000..caf3075
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtActivator.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 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.cdt;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+import com.google.inject.*;
+
+/**
+ * Controls the plug-in life cycle.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProtobufCdtActivator extends AbstractUIPlugin {
+  public static final String PLUGIN_ID = "com.google.eclipse.protobuf.cdt";
+
+  private static ProtobufCdtActivator plugin;
+
+  private final Injector injector;
+
+  public ProtobufCdtActivator() {
+    injector = Guice.createInjector(new ProtobufCdtModule());
+  }
+
+  /**
+   * Returns the singleton instance of this class.
+   * @return the singleton instance of this class.
+   */
+  public static ProtobufCdtActivator getInstance() {
+    return plugin;
+  }
+
+  @Override public void start(BundleContext context) throws Exception {
+    super.start(context);
+    plugin = this;
+  }
+
+  @Override public void stop(BundleContext context) throws Exception {
+    plugin = null;
+    super.stop(context);
+  }
+
+  public Injector getInjector() {
+    return injector;
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtExecutableExtensionFactory.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtExecutableExtensionFactory.java
new file mode 100644
index 0000000..76bcb0a
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtExecutableExtensionFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012 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.cdt;
+
+import org.eclipse.xtext.ui.guice.AbstractGuiceAwareExecutableExtensionFactory;
+import org.osgi.framework.Bundle;
+
+import com.google.inject.Injector;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProtobufCdtExecutableExtensionFactory extends AbstractGuiceAwareExecutableExtensionFactory {
+
+  @Override protected Bundle getBundle() {
+    return plugIn().getBundle();
+  }
+
+  @Override protected Injector getInjector() {
+    return plugIn().getInjector();
+  }
+
+  private ProtobufCdtActivator plugIn() {
+    return ProtobufCdtActivator.getInstance();
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtModule.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtModule.java
new file mode 100644
index 0000000..2774df5
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtModule.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 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.cdt;
+
+import static com.google.eclipse.protobuf.cdt.ProtobufObjectsProvider.getfromProtobufPlugin;
+
+import org.eclipse.xtext.service.AbstractGenericModule;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
+
+import com.google.eclipse.protobuf.ui.editor.ModelObjectDefinitionNavigator;
+import com.google.inject.Binder;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProtobufCdtModule extends AbstractGenericModule {
+  public void configureModelObjectDefinitionNavigator(Binder binder) {
+    bindToProtobufPluginObject(ModelObjectDefinitionNavigator.class, binder);
+    bindToProtobufPluginObject(IPreferenceStoreAccess.class, binder);
+  }
+
+  private <T> void bindToProtobufPluginObject(Class<T> type, Binder binder) {
+    binder.bind(type).toProvider(getfromProtobufPlugin(type));
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufObjectsProvider.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufObjectsProvider.java
new file mode 100644
index 0000000..0bdb758
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufObjectsProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012 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.cdt;
+
+import com.google.eclipse.protobuf.ui.util.ProtobufPlugIn;
+import com.google.inject.Provider;
+
+/**
+ * Obtains objects from the protobuf editor plug-in.
+ * @param <T> the type of object to obtain from the protobuf editor plug-in.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class ProtobufObjectsProvider<T> implements Provider<T> {
+  private final Class<T> type;
+
+  static <T> ProtobufObjectsProvider<T> getfromProtobufPlugin(Class<T> type) {
+    return new ProtobufObjectsProvider<T>(type);
+  }
+
+  private ProtobufObjectsProvider(Class<T> type) {
+    this.type = type;
+  }
+
+  @Override public T get() {
+    return ProtobufPlugIn.getInstance(type);
+  }
+}
\ No newline at end of file
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ClassTypeQualifiedNameBuilder.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ClassTypeQualifiedNameBuilder.java
new file mode 100644
index 0000000..b521a6a
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ClassTypeQualifiedNameBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012 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.cdt.actions;
+
+import static java.util.Collections.*;
+
+import java.util.Collection;
+
+import org.eclipse.cdt.core.dom.IName;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.*;
+import org.eclipse.xtext.naming.QualifiedName;
+
+import com.google.inject.Singleton;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@SuppressWarnings("restriction")
+@Singleton class ClassTypeQualifiedNameBuilder {
+  public Collection<QualifiedName> createQualifiedNamesFrom(CPPClassType classType) {
+    if (isMessage(classType)) {
+      String[] segments = classType.getQualifiedName();
+      return singletonList(QualifiedName.create(segments));
+    }
+    return emptyList();
+  }
+
+  private boolean isMessage(CPPClassType classType) {
+    ICPPBase[] bases = classType.getBases();
+    if (bases.length != 1) {
+      return false;
+    }
+    IName name = bases[0].getBaseClassSpecifierName();
+    if (!(name instanceof CPPASTQualifiedName)) {
+      return false;
+    }
+    CPPASTQualifiedName qualifiedName = (CPPASTQualifiedName) name;
+    if (!qualifiedName.isFullyQualified()) {
+      return false;
+    }
+    String rawSignature = qualifiedName.getRawSignature();
+    return "::google::protobuf::Message".equals(rawSignature);
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ModelObjectDefinitionQueryBuilder.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ModelObjectDefinitionQueryBuilder.java
new file mode 100644
index 0000000..dcb0e0e
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ModelObjectDefinitionQueryBuilder.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012 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.cdt.actions;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.eclipse.protobuf.ui.editor.ModelObjectDefinitionNavigator.Query.query;
+import static java.lang.Math.max;
+import static java.util.Collections.emptyList;
+import static org.eclipse.cdt.internal.ui.editor.ASTProvider.WAIT_NO;
+import static org.eclipse.core.runtime.Status.*;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.cdt.core.dom.ast.*;
+import org.eclipse.cdt.core.model.*;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
+import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
+import org.eclipse.cdt.internal.ui.editor.ASTProvider;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.xtext.naming.QualifiedName;
+
+import com.google.eclipse.protobuf.ui.editor.ModelObjectDefinitionNavigator.Query;
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@SuppressWarnings("restriction")
+class ModelObjectDefinitionQueryBuilder {
+  @Inject private ClassTypeQualifiedNameBuilder nameBuilder;
+  @Inject private ProtoFilePathFinder pathFinder;
+
+  Collection<Query> buildQueries(final IEditorPart editor, final ITextSelection selection) {
+    final IPath protoFilePath = pathFinder.findProtoFilePath(editor);
+    if (protoFilePath == null) {
+      return emptyList();
+    }
+    IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
+    if (workingCopy == null) {
+      return emptyList();
+    }
+    final AtomicReference<Collection<Query>> queriesReference = new AtomicReference<Collection<Query>>();
+    ASTProvider astProvider = ASTProvider.getASTProvider();
+    IStatus status = astProvider.runOnAST(workingCopy, WAIT_NO, null, new ASTRunnable() {
+      @Override public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
+        if (ast == null) {
+          return CANCEL_STATUS;
+        }
+        int offset = selection.getOffset();
+        int length = max(1, selection.getLength());
+        IASTNodeSelector nodeSelector= ast.getNodeSelector(null);
+        IASTName selectedName = nodeSelector.findEnclosingName(offset, length);
+        if (selectedName == null) {
+          return CANCEL_STATUS;
+        }
+        if (selectedName.isDefinition()) {
+          IBinding binding = selectedName.resolveBinding();
+          if (binding instanceof CPPClassType) {
+            Collection<QualifiedName> qualifiedNames = nameBuilder.createQualifiedNamesFrom((CPPClassType) binding);
+            if (qualifiedNames.isEmpty()) {
+              return CANCEL_STATUS;
+            }
+            List<Query> queries = newArrayList();
+            for (QualifiedName qualifiedName : qualifiedNames) {
+              queries.add(query(qualifiedName, protoFilePath));
+            }
+            queriesReference.set(queries);
+            return OK_STATUS;
+          }
+        }
+        return CANCEL_STATUS;
+      }
+    });
+    if (status == CANCEL_STATUS) {
+      return emptyList();
+    }
+    return queriesReference.get();
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/NavigationJobs.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/NavigationJobs.java
new file mode 100644
index 0000000..a46878c
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/NavigationJobs.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012 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.cdt.actions;
+
+import static org.eclipse.core.runtime.Status.OK_STATUS;
+
+import java.util.Collection;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.ui.progress.UIJob;
+
+import com.google.eclipse.protobuf.ui.editor.*;
+import com.google.eclipse.protobuf.ui.editor.ModelObjectDefinitionNavigator.Query;
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class NavigationJobs {
+  @Inject private ModelObjectDefinitionNavigator navigator;
+
+  void scheduleUsing(final Collection<Query> queries) {
+    UIJob job = new UIJob("Navigating to .proto file") {
+      @Override public IStatus runInUIThread(IProgressMonitor monitor) {
+        for (Query query : queries) {
+          IStatus result = navigator.navigateToDefinition(query);
+          if (result.equals(OK_STATUS)) {
+            break;
+          }
+        }
+        return OK_STATUS;
+      }
+    };
+    job.schedule();
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/OpenProtoDeclarationAction.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/OpenProtoDeclarationAction.java
new file mode 100644
index 0000000..0dd8c35
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/OpenProtoDeclarationAction.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 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.cdt.actions;
+
+import java.util.Collection;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.*;
+
+import com.google.eclipse.protobuf.ui.editor.ModelObjectDefinitionNavigator.Query;
+import com.google.inject.Inject;
+
+/**
+ * Opens the declaration of a C++ element in the corresponding .proto file.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class OpenProtoDeclarationAction implements IEditorActionDelegate {
+  private IEditorPart editor;
+  private ITextSelection selection;
+
+  @Inject private ModelObjectDefinitionQueryBuilder queryBuilder;
+  @Inject private NavigationJobs navigationJobs;
+
+  @Override public void run(IAction action) {
+    if (editor == null || selection == null) {
+      return;
+    }
+    Collection<Query> queries = queryBuilder.buildQueries(editor, selection);
+    if (!queries.isEmpty()) {
+      navigationJobs.scheduleUsing(queries);
+    }
+  }
+
+  @Override public void selectionChanged(IAction action, ISelection selection) {
+    if (selection instanceof ITextSelection) {
+      this.selection = (ITextSelection) selection;
+      return;
+    }
+    this.selection = null;
+  }
+
+  @Override public void setActiveEditor(IAction action, IEditorPart editor) {
+    this.editor = editor;
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ProtoFilePathFinder.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ProtoFilePathFinder.java
new file mode 100644
index 0000000..9ee947e
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ProtoFilePathFinder.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012 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.cdt.actions;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.eclipse.protobuf.ui.preferences.compiler.core.CompilerPreferences.compilerPreferences;
+import static org.eclipse.core.runtime.IPath.SEPARATOR;
+import static org.eclipse.xtext.util.Strings.*;
+
+import java.util.List;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
+
+import com.google.eclipse.protobuf.ui.preferences.compiler.core.CompilerPreferences;
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class ProtoFilePathFinder {
+  private static final String PATH_SEPARATOR = new String(new char[] { SEPARATOR });
+
+  @Inject private IPreferenceStoreAccess storeAccess;
+
+  IPath findProtoFilePath(IEditorPart editor) {
+    IFile file = (IFile) editor.getEditorInput().getAdapter(IFile.class);
+    IPath headerFilePath = file.getFullPath();
+    if (!"h".equals(headerFilePath.getFileExtension())) {
+      return null;
+    }
+    String cppOutputDirectory = cppOutputDirectory(file.getProject());
+    if (isEmpty(cppOutputDirectory)) {
+      return null;
+    }
+    List<String> segments = newArrayList(headerFilePath.segments());
+    for (int i = 0; i < headerFilePath.segmentCount() - 1; i++) {
+      segments.remove(0);
+      if (headerFilePath.segment(i).equals(cppOutputDirectory)) {
+        break;
+      }
+    }
+    String headerFileName = headerFilePath.lastSegment();
+    segments.set(segments.size() - 1, headerFileName.replace("pb.h", "proto"));
+    String protoFilePath = concat(PATH_SEPARATOR, segments);
+    return new Path(protoFilePath);
+  }
+
+  private String cppOutputDirectory(IProject project) {
+    CompilerPreferences preferences = compilerPreferences(storeAccess, project);
+    if (!preferences.compileProtoFiles().getValue() && !preferences.cppCodeGenerationEnabled().getValue()) {
+      return null;
+    }
+    return preferences.cppOutputDirectory().getValue();
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/QualifiedNameBuilder.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/QualifiedNameBuilder.java
new file mode 100644
index 0000000..2afab3e
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/QualifiedNameBuilder.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 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.cdt.actions;
+
+import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
+import org.eclipse.xtext.naming.QualifiedName;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@SuppressWarnings("restriction")
+interface QualifiedNameBuilder {
+  QualifiedName createQualifiedNameFrom(ASTNode node);
+}
diff --git a/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
index 95017c2..0166022 100644
--- a/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
@@ -27,5 +27,7 @@
 Export-Package: com.google.eclipse.protobuf.ui.contentassist,

  com.google.eclipse.protobuf.ui.contentassist.antlr,

  com.google.eclipse.protobuf.ui.editor,

+ com.google.eclipse.protobuf.ui.preferences,

+ com.google.eclipse.protobuf.ui.preferences.compiler.core,

  com.google.eclipse.protobuf.ui.util

 Bundle-Activator: com.google.eclipse.protobuf.ui.internal.ProtobufActivator