/plugins/org.chromium.debug.core/src/org/chromium/debug/core/ChromiumSourceDirector.java
Java | 513 lines | 422 code | 61 blank | 30 comment | 64 complexity | e9a78985097ca96c851fcc72618a6b23 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
- // 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 java.util.ArrayList;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.Iterator;
- import java.util.List;
- import org.chromium.debug.core.ScriptNameManipulator.ScriptNamePattern;
- import org.chromium.debug.core.model.JavascriptVmEmbedder;
- import org.chromium.debug.core.model.LaunchParams;
- import org.chromium.debug.core.model.LaunchParams.LookupMode;
- import org.chromium.debug.core.model.ResourceManager;
- import org.chromium.debug.core.model.StackFrame;
- import org.chromium.debug.core.model.VmResource;
- import org.chromium.debug.core.model.VmResourceId;
- import org.chromium.debug.core.model.VmResourceRef;
- import org.chromium.debug.core.util.AccuratenessProperty;
- import org.chromium.sdk.Breakpoint;
- import org.chromium.sdk.BreakpointTypeExtension;
- import org.chromium.sdk.Script;
- import org.eclipse.core.resources.IFile;
- import org.eclipse.core.resources.IProject;
- import org.eclipse.core.runtime.CoreException;
- import org.eclipse.core.runtime.IPath;
- import org.eclipse.debug.core.ILaunchConfiguration;
- import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
- import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
- import org.eclipse.debug.core.sourcelookup.ISourceContainer;
- import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
- import org.eclipse.osgi.util.NLS;
- import org.eclipse.swt.SWT;
- import org.eclipse.swt.widgets.Display;
- import org.eclipse.swt.widgets.MessageBox;
- /**
- * A source lookup director implementation that provides a simple participant and
- * accepts instance of virtual project once it is created.
- */
- public class ChromiumSourceDirector extends AbstractSourceLookupDirector {
- private volatile ResourceManager resourceManager = null;
- private volatile IProject project = null;
- private volatile ReverseSourceLookup reverseSourceLookup = null;
- private volatile JavascriptVmEmbedder javascriptVmEmbedder = null;
- /**
- * Contains 'true' if we have already shown the warning about unsupported look-up mode.
- * However this should be reset when user switches from one mode to another.
- */
- private volatile boolean lookupWarningShown = false;
- public void initializeParticipants() {
- ISourceLookupParticipant participant = new LookupParticipant(this);
- addParticipants(new ISourceLookupParticipant[] { participant } );
- // Check mode post factum.
- checkSupportedLookupMode();
- }
- public VmResourceRef findVmResourceRef(IFile file) throws CoreException {
- return getLookupModeHandler().findVmResourceRef(file);
- }
- public static LookupMode readLookupMode(ILaunchConfiguration launchConfiguration)
- throws CoreException {
- String lookupStringValue = launchConfiguration.getAttribute(
- LaunchParams.SOURCE_LOOKUP_MODE, (String) null);
- LookupMode value;
- if (lookupStringValue == null) {
- value = LookupMode.DEFAULT_VALUE;
- } else {
- value = LookupMode.STRING_CONVERTER.decode(lookupStringValue);
- }
- return value;
- }
- private LookupModeHandler getLookupModeHandler() {
- LookupMode mode;
- try {
- mode = readLookupMode(getLaunchConfiguration());
- } catch (CoreException e) {
- ChromiumDebugPlugin.log(e);
- mode = LookupMode.DEFAULT_VALUE;
- }
- return mode.accept(MODE_TO_HANDLER_VISITOR);
- }
- private final LookupMode.Visitor<LookupModeHandler> MODE_TO_HANDLER_VISITOR =
- new LookupMode.Visitor<LookupModeHandler>() {
- @Override
- public LookupModeHandler visitExactMatch() {
- return exactMatchLookupMode;
- }
- @Override
- public LookupModeHandler visitAutoDetect() {
- return autoDetectLookupMode;
- }
- };
- @Override
- public boolean isFindDuplicates() {
- return getLookupModeHandler().forceFindDuplicates() || super.isFindDuplicates();
- }
- /**
- * A single implementation of look participant. This way the participant may decide to become
- * exact match/auto-detect after it is created, because javascriptVm instances comes too late
- * after everything is created.
- */
- private static class LookupParticipant extends AbstractSourceLookupParticipant {
- private final SuperClassAccess superClassAccess = new SuperClassAccess();
- private final ChromiumSourceDirector chromiumSourceDirector;
- LookupParticipant(ChromiumSourceDirector chromiumSourceDirector) {
- this.chromiumSourceDirector = chromiumSourceDirector;
- }
- public String getSourceName(Object object) throws CoreException {
- return getSourceNameImpl(object);
- }
- @Override
- public Object[] findSourceElements(Object object) throws CoreException {
- Delegate delegate = chromiumSourceDirector.getLookupModeHandler().getDelegate();
- return delegate.findSourceElements(object, superClassAccess);
- }
- private Object[] findSourceElementsSuper(Object object) throws CoreException {
- return super.findSourceElements(object);
- }
- static abstract class Delegate {
- abstract Object[] findSourceElements(Object object, SuperClassAccess superClass)
- throws CoreException;
- }
- class SuperClassAccess {
- Object[] findSourceElements(Object object) throws CoreException {
- return findSourceElementsSuper(object);
- }
- ISourceContainer[] getSourceContainers() {
- return LookupParticipant.this.getSourceContainers();
- }
- ChromiumSourceDirector getChromiumSourceDirector() {
- return chromiumSourceDirector;
- }
- }
- }
- private static final LookupParticipant.Delegate EXACT_MATCH_DELEGATE =
- new LookupParticipant.Delegate() {
- @Override
- Object[] findSourceElements(Object object, LookupParticipant.SuperClassAccess superClass)
- throws CoreException {
- Object[] result = superClass.findSourceElements(object);
- if (result.length > 0) {
- ArrayList<Object> filtered = new ArrayList<Object>(result.length);
- for (Object obj : result) {
- if (obj instanceof VProjectSourceContainer.LookupResult) {
- VProjectSourceContainer.LookupResult vprojectResult =
- (VProjectSourceContainer.LookupResult) obj;
- expandVProjectResult(vprojectResult, object, filtered);
- } else {
- filtered.add(obj);
- }
- }
- result = filtered.toArray();
- }
- return result;
- }
- };
- private static final LookupParticipant.Delegate AUTO_DETECT_DELEGATE =
- new LookupParticipant.Delegate() {
- @Override
- Object[] findSourceElements(Object object, LookupParticipant.SuperClassAccess superClass)
- throws CoreException {
- ArrayList<Object> result = new ArrayList<Object>();
- JavascriptVmEmbedder vmEmbedder =
- superClass.getChromiumSourceDirector().javascriptVmEmbedder;
- ScriptNameManipulator.FilePath scriptName =
- getParsedScriptFileName(object, vmEmbedder.getScriptNameManipulator());
- if (scriptName != null) {
- for (ISourceContainer container : superClass.getSourceContainers()) {
- try {
- findSourceElements(container, object, scriptName, result);
- } catch (CoreException e) {
- ChromiumDebugPlugin.log(e);
- continue;
- }
- // If one container returned one file -- that's a single uncompromised result.
- IFile oneFile = getSimpleResult(result);
- if (oneFile != null) {
- return new Object[] { oneFile };
- }
- }
- }
- return result.toArray();
- }
- private void findSourceElements(ISourceContainer container, Object object,
- ScriptNameManipulator.FilePath scriptName, ArrayList<Object> output)
- throws CoreException {
- Object[] objects = container.findSourceElements(scriptName.getLastComponent());
- if (objects.length == 0) {
- return;
- }
- int outputStartPos = output.size();
- for (Object obj : objects) {
- if (obj instanceof IFile) {
- IFile file = (IFile) obj;
- if (matchFileAccurateness(file, scriptName)) {
- output.add(obj);
- }
- } else if (obj instanceof VProjectSourceContainer.LookupResult) {
- VProjectSourceContainer.LookupResult vprojectResult =
- (VProjectSourceContainer.LookupResult) obj;
- expandVProjectResult(vprojectResult, object, output);
- } else {
- output.add(obj);
- }
- }
- int outputEndPos = output.size();
- if (outputEndPos - outputStartPos > 1) {
- // Put short name last. They cannot be filtered out by our rules, so they may
- // be parasite.
- Collections.sort(output.subList(outputStartPos, outputEndPos), SHORT_NAME_LAST);
- }
- }
- private IFile getSimpleResult(List<Object> objects) {
- if (objects.size() != 1) {
- return null;
- }
- Object oneObject = objects.get(0);
- if (oneObject instanceof IFile == false) {
- return null;
- }
- IFile file = (IFile) oneObject;
- return file;
- }
- private boolean matchFileAccurateness(IFile file,
- ScriptNameManipulator.FilePath scriptName) throws CoreException {
- int accurateness = AccuratenessProperty.read(file);
- if (accurateness > AccuratenessProperty.BASE_VALUE) {
- IPath path = file.getFullPath();
- int pathPos = path.segmentCount() - AccuratenessProperty.BASE_VALUE -1;
- Iterator<String> scriptIterator = scriptName.iterator();
- while (accurateness > AccuratenessProperty.BASE_VALUE) {
- if (pathPos < 0 || !scriptIterator.hasNext()) {
- return false;
- }
- String scriptComponent = scriptIterator.next();
- String pathComponent = path.segment(pathPos--);
- if (!scriptComponent.equals(pathComponent)) {
- return false;
- }
- accurateness--;
- }
- }
- return true;
- }
- private ScriptNameManipulator.FilePath getParsedScriptFileName(Object object,
- ScriptNameManipulator nameManipulator) throws CoreException {
- VmResourceId vmResourceId = getVmResourceId(object);
- if (vmResourceId == null) {
- return null;
- }
- final String scriptName = vmResourceId.getName();
- if (scriptName == null) {
- return UNKNOWN_NAME;
- }
- return nameManipulator.getFileName(scriptName);
- }
- };
- private static String getSourceNameImpl(Object object) throws CoreException {
- VmResourceId vmResourceId = getVmResourceId(object);
- if (vmResourceId == null) {
- return null;
- }
- String name = vmResourceId.getName();
- if (name == null) {
- // Do not return null, this will cancel look-up.
- // Return empty string. Virtual project container will pass us some data.
- name = ""; //$NON-NLS-1$
- }
- return name;
- }
- private static final ScriptNameManipulator.FilePath UNKNOWN_NAME =
- new ScriptNameManipulator.FilePath() {
- @Override
- public String getLastComponent() {
- return "<unknonwn source>"; //$NON-NLS-1$
- }
- @Override
- public Iterator<String> iterator() {
- return Collections.<String>emptyList().iterator();
- }
- };
- private static final Comparator<Object> SHORT_NAME_LAST = new Comparator<Object>() {
- @Override
- public int compare(Object o1, Object o2) {
- int len1 = getPathLength(o1);
- int len2 = getPathLength(o2);
- return len2 - len1;
- }
- private int getPathLength(Object obj) {
- if (obj instanceof IFile == false) {
- return Integer.MIN_VALUE;
- }
- IFile file = (IFile) obj;
- return file.getFullPath().segmentCount();
- }
- };
- private static VmResourceId getVmResourceId(Object object) throws CoreException {
- if (object instanceof Script) {
- Script script = (Script) object;
- return VmResourceId.forScript(script);
- } else if (object instanceof StackFrame) {
- StackFrame jsStackFrame = (StackFrame) object;
- return jsStackFrame.getVmResourceId();
- } else if (object instanceof Breakpoint) {
- Breakpoint breakpoint = (Breakpoint) object;
- return breakpoint.getTarget().accept(BREAKPOINT_RESOURCE_VISITOR);
- } else if (object instanceof VmResourceId) {
- VmResourceId resourceId = (VmResourceId) object;
- return resourceId;
- } else {
- return null;
- }
- }
- /**
- * Virtual project container cannot properly resolve from a sting name. Instead it returns
- * {@link ResourceManager} object that can be processed here, where we have full
- * {@link VmResourceId}.
- */
- private static void expandVProjectResult(VProjectSourceContainer.LookupResult lookupResult,
- Object object, ArrayList<Object> output) throws CoreException {
- VmResourceId resourceId = getVmResourceId(object);
- if (resourceId.getId() != null) {
- VmResource vmResource = lookupResult.getVmResource(resourceId);
- if (vmResource != null) {
- output.add(vmResource.getVProjectFile());
- }
- }
- }
- private static final Breakpoint.Target.Visitor<VmResourceId> BREAKPOINT_RESOURCE_VISITOR =
- new BreakpointTypeExtension.ScriptRegExpSupport.Visitor<VmResourceId>() {
- @Override public VmResourceId visitScriptName(String scriptName) {
- return new VmResourceId(scriptName, null);
- }
- @Override public VmResourceId visitScriptId(Object scriptId) {
- return new VmResourceId(null, scriptId);
- }
- @Override public VmResourceId visitRegExp(String regExp) {
- // RegExp cannot be converted into VmResourceId without additional context.
- return null;
- }
- @Override public VmResourceId visitUnknown(Breakpoint.Target target) {
- return null;
- }
- };
- public void initializeVProjectContainers(IProject project, ResourceManager resourceManager,
- JavascriptVmEmbedder javascriptVmEmbedder) {
- this.resourceManager = resourceManager;
- this.project = project;
- this.javascriptVmEmbedder = javascriptVmEmbedder;
- this.reverseSourceLookup = new ReverseSourceLookup(this);
- checkSupportedLookupMode();
- }
- public ReverseSourceLookup getReverseSourceLookup() {
- return reverseSourceLookup;
- }
- public ResourceManager getResourceManager() {
- return resourceManager;
- }
- IProject getProject() {
- return project;
- }
- private void checkSupportedLookupMode() {
- LookupModeHandler lookupMode = getLookupModeHandler();
- if (javascriptVmEmbedder != null) {
- lookupMode.showUnsupportedWarning(javascriptVmEmbedder);
- }
- }
- private static abstract class LookupModeHandler {
- abstract LookupParticipant.Delegate getDelegate();
- abstract void showUnsupportedWarning(JavascriptVmEmbedder javascriptVmEmbedder);
- abstract boolean forceFindDuplicates();
- abstract VmResourceRef findVmResourceRef(IFile file) throws CoreException;
- }
- private final LookupModeHandler exactMatchLookupMode = new LookupModeHandler() {
- @Override LookupParticipant.Delegate getDelegate() {
- return EXACT_MATCH_DELEGATE;
- }
- @Override void showUnsupportedWarning(JavascriptVmEmbedder javascriptVmEmbedder) {
- // 'Exact match' is chosen. Enable warning again.
- lookupWarningShown = false;
- }
- @Override boolean forceFindDuplicates() {
- return false;
- }
- @Override
- VmResourceRef findVmResourceRef(IFile file) throws CoreException {
- VmResourceId vmResourceId = reverseSourceLookup.findVmResource(file);
- if (vmResourceId == null) {
- return null;
- }
- return VmResourceRef.forVmResourceId(vmResourceId);
- }
- };
- private final LookupModeHandler autoDetectLookupMode = new LookupModeHandler() {
- @Override LookupParticipant.Delegate getDelegate() {
- return AUTO_DETECT_DELEGATE;
- }
- @Override
- void showUnsupportedWarning(final JavascriptVmEmbedder javascriptVmEmbedder) {
- if (lookupWarningShown) {
- return;
- }
- BreakpointTypeExtension breakpointTypeExtension =
- javascriptVmEmbedder.getJavascriptVm().getBreakpointTypeExtension();
- BreakpointTypeExtension.ScriptRegExpSupport scriptRegExpSupport =
- breakpointTypeExtension.getScriptRegExpSupport();
- if (scriptRegExpSupport != null) {
- return;
- }
- lookupWarningShown = true;
- Display display = Display.getDefault();
- display.asyncExec(new Runnable() {
- @Override
- public void run() {
- Display display = Display.getDefault();
- MessageBox messageBox = new MessageBox(display.getActiveShell(), SWT.ICON_WARNING);
- messageBox.setText(Messages.ChromiumSourceDirector_WARNING_TITLE);
- String messagePattern = Messages.ChromiumSourceDirector_WARNING_TEXT_PATTERN;
- String message = NLS.bind(messagePattern,
- javascriptVmEmbedder.getJavascriptVm().getVersion());
- messageBox.setMessage(message);
- messageBox.open();
- }
- });
- }
- @Override boolean forceFindDuplicates() {
- return true;
- }
- @Override
- VmResourceRef findVmResourceRef(IFile file) throws CoreException {
- {
- // Try inside virtual project.
- VmResourceId resourceId = resourceManager.getResourceId(file);
- if (resourceId != null) {
- return VmResourceRef.forVmResourceId(resourceId);
- }
- }
- IPath path = file.getFullPath();
- int accurateness = AccuratenessProperty.read(file);
- if (accurateness > path.segmentCount()) {
- accurateness = path.segmentCount();
- }
- int offset = path.segmentCount() - accurateness;
- List<String> components = new ArrayList<String>(accurateness);
- for (int i = 0; i < accurateness; i++) {
- components.add(path.segment(i + offset));
- }
- ScriptNameManipulator scriptNameManipulator = javascriptVmEmbedder.getScriptNameManipulator();
- ScriptNamePattern pattern = scriptNameManipulator.createPattern(components);
- return VmResourceRef.forRegExpBased(pattern);
- }
- };
- }