org.chromium.debug.core/src/org/chromium/debug/core/ReverseSourceLookup.java
changeset 355 8726e95bcbba
equal deleted inserted replaced
354:0bceeb415e7f 355:8726e95bcbba
       
     1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.debug.core;
       
     6 
       
     7 import org.chromium.debug.core.model.VmResourceId;
       
     8 import org.eclipse.core.resources.IContainer;
       
     9 import org.eclipse.core.resources.IFile;
       
    10 import org.eclipse.core.runtime.CoreException;
       
    11 import org.eclipse.debug.core.sourcelookup.ISourceContainer;
       
    12 import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
       
    13 import org.eclipse.debug.core.sourcelookup.containers.ContainerSourceContainer;
       
    14 import org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer;
       
    15 
       
    16 /**
       
    17  * Eclipse has a standard facility for looking up source file for a debug artifact.
       
    18  * LiveEdit feature has an opposite problem: find script in remote VM for a particular js file.
       
    19  * This class implements some approach to this problem. An instance of this class corresponds
       
    20  * to a particular debug launch.
       
    21  */
       
    22 public class ReverseSourceLookup {
       
    23   private final ISourceLookupDirector sourceDirector;
       
    24 
       
    25   public ReverseSourceLookup(ISourceLookupDirector sourceDirector) {
       
    26     this.sourceDirector = sourceDirector;
       
    27   }
       
    28 
       
    29   /**
       
    30    * Tries to find a corresponding script for a file from a user workspace. The method uses
       
    31    * the file name and current source lookup rules to retrieve a resource id, regardless of
       
    32    * whether the resource has actually been loaded into the VM (you may want to set a breakpoint
       
    33    * on resource before it is actually loaded).
       
    34    */
       
    35   public VmResourceId findVmResource(IFile sourceFile) throws CoreException {
       
    36     for (ISourceContainer container : sourceDirector.getSourceContainers()) {
       
    37       VmResourceId scriptName = tryForContainer(sourceFile, container);
       
    38       if (scriptName != null) {
       
    39         return scriptName;
       
    40       }
       
    41     }
       
    42     return null;
       
    43   }
       
    44 
       
    45   private VmResourceId tryForContainer(IFile sourceFile, ISourceContainer container)
       
    46       throws CoreException {
       
    47     if (container.isComposite() && isSupportedCompositeContainer(container)) {
       
    48       ISourceContainer[] subContainers = container.getSourceContainers();
       
    49       for (ISourceContainer subContainer : subContainers) {
       
    50         VmResourceId res = tryForContainer(sourceFile, subContainer);
       
    51         if (res != null) {
       
    52           return res;
       
    53         }
       
    54       }
       
    55       return null;
       
    56     } else if (container instanceof VProjectSourceContainer) {
       
    57       VProjectSourceContainer projectSourceContainer = (VProjectSourceContainer) container;
       
    58       return projectSourceContainer.findScriptId(sourceFile);
       
    59     } else {
       
    60       String name = tryForNonVirtualContainer(sourceFile, container);
       
    61       if (name == null) {
       
    62         return null;
       
    63       }
       
    64       return VmResourceId.forName(name);
       
    65     }
       
    66   }
       
    67 
       
    68   /**
       
    69    * We use {@link ISourceContainer#getSourceContainers()} method to unwrap internal containers.
       
    70    * However it doesn't make sense for all composite containers (some of them may return their
       
    71    * subdirectories as containers, which is not what we need).
       
    72    */
       
    73   private boolean isSupportedCompositeContainer(ISourceContainer container) {
       
    74     return container instanceof DefaultSourceContainer;
       
    75   }
       
    76 
       
    77   /**
       
    78    * @param container that may not wrap VProjectSourceContainer
       
    79    */
       
    80   private String tryForNonVirtualContainer(IFile resource, ISourceContainer container) {
       
    81     if (container instanceof ContainerSourceContainer) {
       
    82       ContainerSourceContainer containerSourceContainer = (ContainerSourceContainer) container;
       
    83       IContainer resourceContainer = containerSourceContainer.getContainer();
       
    84       if (resourceContainer.getFullPath().isPrefixOf(resource.getFullPath())) {
       
    85         String name = resource.getFullPath().makeRelativeTo(
       
    86             resourceContainer.getFullPath()).toPortableString();
       
    87         return name;
       
    88       }
       
    89     } else if (container instanceof SourceNameMapperContainer) {
       
    90       SourceNameMapperContainer mappingContainer =
       
    91           (SourceNameMapperContainer) container;
       
    92       String subResult = tryForNonVirtualContainer(resource, mappingContainer.getTargetContainer());
       
    93       if (subResult != null) {
       
    94         return mappingContainer.getPrefix() + subResult;
       
    95       }
       
    96     }
       
    97 
       
    98     return null;
       
    99   }
       
   100 }