--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/ReverseSourceLookup.java Mon Jun 07 16:51:19 2010 -0700
@@ -0,0 +1,100 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.debug.core;
+
+import org.chromium.debug.core.model.VmResourceId;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
+import org.eclipse.debug.core.sourcelookup.containers.ContainerSourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer;
+
+/**
+ * Eclipse has a standard facility for looking up source file for a debug artifact.
+ * LiveEdit feature has an opposite problem: find script in remote VM for a particular js file.
+ * This class implements some approach to this problem. An instance of this class corresponds
+ * to a particular debug launch.
+ */
+public class ReverseSourceLookup {
+ private final ISourceLookupDirector sourceDirector;
+
+ public ReverseSourceLookup(ISourceLookupDirector sourceDirector) {
+ this.sourceDirector = sourceDirector;
+ }
+
+ /**
+ * Tries to find a corresponding script for a file from a user workspace. The method uses
+ * the file name and current source lookup rules to retrieve a resource id, regardless of
+ * whether the resource has actually been loaded into the VM (you may want to set a breakpoint
+ * on resource before it is actually loaded).
+ */
+ public VmResourceId findVmResource(IFile sourceFile) throws CoreException {
+ for (ISourceContainer container : sourceDirector.getSourceContainers()) {
+ VmResourceId scriptName = tryForContainer(sourceFile, container);
+ if (scriptName != null) {
+ return scriptName;
+ }
+ }
+ return null;
+ }
+
+ private VmResourceId tryForContainer(IFile sourceFile, ISourceContainer container)
+ throws CoreException {
+ if (container.isComposite() && isSupportedCompositeContainer(container)) {
+ ISourceContainer[] subContainers = container.getSourceContainers();
+ for (ISourceContainer subContainer : subContainers) {
+ VmResourceId res = tryForContainer(sourceFile, subContainer);
+ if (res != null) {
+ return res;
+ }
+ }
+ return null;
+ } else if (container instanceof VProjectSourceContainer) {
+ VProjectSourceContainer projectSourceContainer = (VProjectSourceContainer) container;
+ return projectSourceContainer.findScriptId(sourceFile);
+ } else {
+ String name = tryForNonVirtualContainer(sourceFile, container);
+ if (name == null) {
+ return null;
+ }
+ return VmResourceId.forName(name);
+ }
+ }
+
+ /**
+ * We use {@link ISourceContainer#getSourceContainers()} method to unwrap internal containers.
+ * However it doesn't make sense for all composite containers (some of them may return their
+ * subdirectories as containers, which is not what we need).
+ */
+ private boolean isSupportedCompositeContainer(ISourceContainer container) {
+ return container instanceof DefaultSourceContainer;
+ }
+
+ /**
+ * @param container that may not wrap VProjectSourceContainer
+ */
+ private String tryForNonVirtualContainer(IFile resource, ISourceContainer container) {
+ if (container instanceof ContainerSourceContainer) {
+ ContainerSourceContainer containerSourceContainer = (ContainerSourceContainer) container;
+ IContainer resourceContainer = containerSourceContainer.getContainer();
+ if (resourceContainer.getFullPath().isPrefixOf(resource.getFullPath())) {
+ String name = resource.getFullPath().makeRelativeTo(
+ resourceContainer.getFullPath()).toPortableString();
+ return name;
+ }
+ } else if (container instanceof SourceNameMapperContainer) {
+ SourceNameMapperContainer mappingContainer =
+ (SourceNameMapperContainer) container;
+ String subResult = tryForNonVirtualContainer(resource, mappingContainer.getTargetContainer());
+ if (subResult != null) {
+ return mappingContainer.getPrefix() + subResult;
+ }
+ }
+
+ return null;
+ }
+}