blob: 01d22a710c695b390c60ffc48a2919ad27b767eb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2012 Wind River Systems, Inc. and others.
* 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
*
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
* IBM Corporation
******************************************************************************/
/* -- ST-Origin --
* Source folder: org.eclipse.cdt.ui/src
* Class: org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsJob
* Version: 1.16
*/
package org.eclipse.ptp.internal.rdt.ui.search.actions;
import java.net.URI;
import java.text.MessageFormat;
import org.eclipse.cdt.core.EFSExtensionProvider;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ISourceRange;
import org.eclipse.cdt.core.model.ISourceReference;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.util.CElementBaseLabels;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
import org.eclipse.cdt.internal.ui.actions.OpenActionUtil;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
import org.eclipse.cdt.internal.ui.search.CSearchMessages;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.utils.EFSExtensionManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ptp.internal.rdt.core.model.ModelAdapter;
import org.eclipse.ptp.internal.rdt.core.model.Scope;
import org.eclipse.ptp.internal.rdt.core.model.WorkingCopy;
import org.eclipse.ptp.internal.rdt.core.navigation.OpenDeclarationResult;
import org.eclipse.ptp.internal.rdt.ui.navigation.INavigationService;
import org.eclipse.ptp.rdt.core.RDTLog;
import org.eclipse.ptp.rdt.core.services.IRDTServiceConstants;
import org.eclipse.ptp.rdt.ui.serviceproviders.IIndexServiceProvider2;
import org.eclipse.ptp.services.core.IService;
import org.eclipse.ptp.services.core.IServiceConfiguration;
import org.eclipse.ptp.services.core.IServiceModelManager;
import org.eclipse.ptp.services.core.IServiceProvider;
import org.eclipse.ptp.services.core.ServiceModelManager;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.ITextEditor;
class OpenDeclarationsJob extends Job{
private final SelectionParseAction fAction;
private final ITranslationUnit fTranslationUnit;
private final ITextSelection fTextSelection;
private final String fSelectedText;
private CEditor fEditor;
OpenDeclarationsJob(SelectionParseAction action, ITranslationUnit editorInput, ITextSelection textSelection, String text, CEditor editor) {
super(CEditorMessages.OpenDeclarations_dialog_title);
fAction= action;
fTranslationUnit= editorInput;
fTextSelection= textSelection;
fSelectedText= text;
fEditor = editor;
}
private INavigationService getNavigationService(IProject project) {
IServiceModelManager smm = ServiceModelManager.getInstance();
IServiceConfiguration serviceConfig = smm.getActiveConfiguration(project);
IService indexingService = smm.getService(IRDTServiceConstants.SERVICE_C_INDEX);
IServiceProvider serviceProvider = serviceConfig.getServiceProvider(indexingService);
if (!(serviceProvider instanceof IIndexServiceProvider2)) {
return null;
}
INavigationService service = ((IIndexServiceProvider2) serviceProvider).getNavigationService();
return service;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
return performNavigation(monitor);
} catch (CoreException e) {
return e.getStatus();
}
}
IStatus performNavigation(IProgressMonitor monitor) throws CoreException {
ITranslationUnit workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
if (workingCopy == null)
return Status.CANCEL_STATUS;
ICProject project = workingCopy.getCProject();
int selectionStart = fTextSelection.getOffset();
int selectionLength = fTextSelection.getLength();
INavigationService service = getNavigationService(project.getProject());
OpenDeclarationResult result = service.openDeclaration(fEditor, fSelectedText, selectionStart, selectionLength, monitor);
if(result == null) // can happen when using the null service provider
return Status.OK_STATUS;
// check for cancellation... don't navigate if we cancelled
if(monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
switch(result.getResultType()) {
case RESULT_NAMES:
IName[] names = (IName[]) result.getResult();
navigateOneLocation(names, project);
break;
case RESULT_C_ELEMENTS:
ICElement[] elements = (ICElement[]) result.getResult();
navigateCElements(elements, project);
break;
case RESULT_INCLUDE_PATH:
String path = (String) result.getResult();
open(project.getProject(), path, project);
break;
case RESULT_NAME:
IName name = (IName) result.getResult();
navigateToName(name, project);
break;
case RESULT_LOCATION:
IASTFileLocation location = (IASTFileLocation) result.getResult();
navigateToLocation(location, project);
break;
case FAILURE_SYMBOL_LOOKUP:
String symbol = (String) result.getResult();
fAction.reportSymbolLookupFailure(symbol);
break;
case FAILURE_INCLUDE_LOOKUP:
String includedPath = (String) result.getResult();
fAction.reportIncludeLookupFailure(includedPath);
break;
default:
fAction.reportSelectionMatchFailure();
break;
}
return Status.OK_STATUS;
}
/**
* Replaces the path portion of the given URI.
*/
private URI replacePath(IProject project, URI u, String path) {
// TODO: PATHFIX this is a HACK, fix EFSExtensionProvider please!
if("org.eclipse.cdt.core.fastIndexer".equals(IndexerPreferences.get(project, IndexerPreferences.KEY_INDEXER_ID, null))) { // //$NON-NLS-1$
return new EFSExtensionProvider(){}.createNewURIFromPath(u, path);
}
return EFSExtensionManager.getDefault().createNewURIFromPath(u, path);
}
private void open(IProject project, String path, ICElement element) {
open(project, path, element, -1, -1);
}
private void open(IProject project, String path, final ICElement element, final int offset, final int length) {
final URI uri = replacePath(project, element.getLocationURI(), path);
if(uri == null)
return;
open(uri, element, offset, length);
}
/**
* Opens the editor.
*/
private void open(final URI uri, final ICElement element, final int offset, final int length) {
runInUIThread(new Runnable() {
public void run() {
try {
fAction.clearStatusLine();
IEditorPart editor = EditorUtility.openInEditor(uri, element);
if (editor instanceof ITextEditor) {
ITextEditor textEditor = (ITextEditor)editor;
if(offset >=0 && length >= 0)
textEditor.selectAndReveal(offset, length);
} else {
reportSourceFileOpenFailure(uri.toString());
}
} catch (CoreException e) {
RDTLog.logError(e);
}
}
});
}
private void navigateCElements(final ICElement[] elements, final ICProject project) {
if (elements == null || elements.length == 0)
return;
runInUIThread(new Runnable() {
public void run() {
ICElement target;
if (elements.length == 1) {
target= elements[0];
}
else {
target = OpenActionUtil.selectCElement(elements, fAction.getSite().getShell(),
CEditorMessages.OpenDeclarationsAction_dialog_title, CEditorMessages.OpenDeclarationsAction_selectMessage,
CElementBaseLabels.ALL_DEFAULT | CElementBaseLabels.ALL_FULLY_QUALIFIED | CElementBaseLabels.MF_POST_FILE_QUALIFIED, 0);
}
if (target instanceof ISourceReference) {
try {
ISourceRange sourceRange = ((ISourceReference) target).getSourceRange();
URI uri = replacePath(project.getProject(), target.getLocationURI(), target.getPath().toString());
open(uri, project, sourceRange.getIdStartPos(), sourceRange.getIdLength());
} catch (CoreException e) {
RDTLog.logError(e);
}
}
}
});
}
protected void reportSourceFileOpenFailure(String path) {
fAction.showStatusLineMessage(MessageFormat.format(
CSearchMessages.SelectionParseAction_FileOpenFailure_format,
path));
}
/**
* Opens the editor on the first name in the array that has
* location information.
*/
private void navigateOneLocation(IName[] declNames, ICProject project) {
for(IName name : declNames) {
IASTFileLocation fileloc = name.getFileLocation();
if(fileloc != null) {
String filePath = fileloc.getFileName();
int offset = fileloc.getNodeOffset();
int length = fileloc.getNodeLength();
open(project.getProject(), filePath, project, offset, length);
return;
}
}
}
private void navigateToName(IName name, ICProject project) {
navigateToLocation(name.getFileLocation(), project);
}
private void navigateToLocation(IASTFileLocation fileloc, ICProject project) {
if (fileloc != null) {
String filePath = fileloc.getFileName();
int offset = fileloc.getNodeOffset();
int length = fileloc.getNodeLength();
open(project.getProject(), filePath, project, offset, length);
}
}
private void runInUIThread(Runnable runnable) {
if (Display.getCurrent() != null) {
runnable.run();
}
else {
Display.getDefault().asyncExec(runnable);
}
}
}