// 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.ui.actions; import org.chromium.debug.core.model.ConnectedTargetData; import org.chromium.debug.core.model.Value; import org.chromium.debug.core.model.VmResourceId; import org.chromium.debug.core.sourcemap.SourcePosition; import org.chromium.debug.core.sourcemap.SourcePositionMap; import org.chromium.debug.core.sourcemap.SourcePositionMap.TranslateDirection; import org.chromium.sdk.JsFunction; import org.chromium.sdk.JsObject; import org.chromium.sdk.JsValue; import org.chromium.sdk.Script; import org.chromium.sdk.TextStreamPosition; import org.eclipse.core.resources.IFile; import org.eclipse.debug.core.model.ISourceLocator; import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; /** * The action for context menu in Variable/Expression views that opens selected * function source text in editor. */ public abstract class OpenFunctionAction extends VariableBasedAction { public static class ForVariable extends OpenFunctionAction { public ForVariable() { super(VARIABLE_VIEW_ELEMENT_HANDLER); } } public static class ForExpression extends OpenFunctionAction { public ForExpression() { super(EXPRESSION_VIEW_ELEMENT_HANDLER); } } protected OpenFunctionAction(ElementHandler elementHandler) { super(elementHandler); } protected Runnable createRunnable(VariableWrapper wrapper) { if (wrapper == null) { return null; } final ConnectedTargetData connectedTargetData = wrapper.getConnectedTargetData(); if (connectedTargetData == null) { return null; } final JsFunction jsFunction = getJsFunctionFromElement(wrapper); if (jsFunction == null) { return null; } return new Runnable() { public void run() { // This works in UI thread. IWorkbench workbench = PlatformUI.getWorkbench(); final IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow(); ISourceLocator sourceLocator = connectedTargetData.getDebugTarget().getLaunch().getSourceLocator(); if (sourceLocator instanceof ISourceLookupDirector == false) { return; } ISourceLookupDirector director = (ISourceLookupDirector) sourceLocator; SourcePositionMap positionMap = connectedTargetData.getSourcePositionMap(); SourcePosition userPosition; { // First get VM positions. Script script = jsFunction.getScript(); if (script == null) { return; } TextStreamPosition functionOpenParenPosition = jsFunction.getOpenParenPosition(); if (functionOpenParenPosition == null) { return; } // Convert them to user positions. userPosition = positionMap.translatePosition( VmResourceId.forScript(script), functionOpenParenPosition.getLine(), functionOpenParenPosition.getColumn(), TranslateDirection.VM_TO_USER); } Object sourceObject = director.getSourceElement(userPosition.getId()); if (sourceObject instanceof IFile == false) { return; } IFile resource = (IFile) sourceObject; IEditorPart editor; try { editor= IDE.openEditor(activeWorkbenchWindow.getActivePage(), resource, true); } catch (PartInitException e) { throw new RuntimeException(e); } if (editor instanceof ITextEditor == false) { return; } ITextEditor textEditor = (ITextEditor) editor; int offset = calculateOffset(textEditor, userPosition); textEditor.selectAndReveal(offset, 0); } private int calculateOffset(ITextEditor editor, SourcePosition userPosition) { IDocumentProvider provider = editor.getDocumentProvider(); IDocument document = provider.getDocument(editor.getEditorInput()); int lineStartOffset; try { lineStartOffset = document.getLineOffset(userPosition.getLine()); } catch (BadLocationException e) { throw new RuntimeException(e); } return lineStartOffset + userPosition.getColumn(); } }; } private JsFunction getJsFunctionFromElement(VariableWrapper wrapper) { if (wrapper == null) { return null; } final Value uiValue = wrapper.getValue(); if (uiValue == null) { // Probably hasn't got result yet. return null; } JsValue jsValue = uiValue.getJsValue(); if (jsValue == null) { return null; } JsObject jsObject = jsValue.asObject(); if (jsObject == null) { return null; } return jsObject.asFunction(); } }