/*******************************************************************************
* Copyright (c) 2014 Bruno Medeiros and other Contributors.
* 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:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package mmrnmhrm.ui.actions;
import static melnorme.utilbox.core.CoreUtil.areEqual;
import java.util.List;
import java.util.function.Function;
import org.eclipse.core.resources.IProject;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.texteditor.ITextEditor;
import dtool.engine.operations.FindDefinitionResult;
import dtool.engine.operations.FindDefinitionResult.FindDefinitionResultEntry;
import melnorme.lang.ide.core.LangCore;
import melnorme.lang.ide.core.utils.EclipseUtils;
import melnorme.lang.ide.ui.EditorSettings_Actual;
import melnorme.lang.ide.ui.editor.EditorUtils;
import melnorme.lang.ide.ui.editor.EditorUtils.OpenNewEditorMode;
import melnorme.lang.ide.ui.utils.UIOperationsStatusHandler;
import melnorme.lang.ide.ui.utils.operations.AbstractEditorOperation2;
import melnorme.lang.tooling.ast.SourceRange;
import melnorme.lang.tooling.common.ops.IOperationMonitor;
import melnorme.utilbox.concurrency.OperationCancellation;
import melnorme.utilbox.core.CommonException;
import melnorme.utilbox.misc.Location;
import melnorme.utilbox.misc.StringUtil;
import melnorme.utilbox.status.Severity;
import mmrnmhrm.core.engine.DeeLanguageEngine;
public class DeeOpenDefinitionOperation extends AbstractEditorOperation2<FindDefinitionResult> {
protected static final String OPEN_DEFINITION_OPNAME = "Open Definition";
protected final OpenNewEditorMode openNewEditorMode;
protected final int offset;
public DeeOpenDefinitionOperation(ITextEditor editor) {
this(editor, OpenNewEditorMode.TRY_REUSING_EXISTING);
}
public DeeOpenDefinitionOperation(ITextEditor editor, OpenNewEditorMode openNewEditorMode) {
this(editor, openNewEditorMode, EditorUtils.getSelectionSR(editor).getOffset());
}
public DeeOpenDefinitionOperation(ITextEditor editor, OpenNewEditorMode openNewEditorMode, int offset) {
super(OPEN_DEFINITION_OPNAME, editor);
this.openNewEditorMode = openNewEditorMode;
this.offset = offset;
}
protected IProject getAssociatedProject() {
return EditorUtils.getAssociatedProject(editor.getEditorInput());
}
@Override
protected FindDefinitionResult doBackgroundValueComputation(IOperationMonitor monitor)
throws CommonException, OperationCancellation {
IProject associatedProject = getAssociatedProject();
String dubPath = LangCore.settings().SDK_LOCATION.getValue(associatedProject).toString();
return DeeLanguageEngine.getDefault().
new FindDefinitionOperation(getInputLocation(), offset, -1, dubPath).runEngineOperation(monitor);
}
@Override
protected void handleComputationResult(FindDefinitionResult openDefResult) throws CommonException {
List<FindDefinitionResultEntry> results = openDefResult.results;
if(openDefResult.errorMessage != null) {
statusDialog(Severity.ERROR, openDefResult.errorMessage);
return;
}
if(results.size() > 1) {
statusDialog(Severity.INFO, "Multiple definitions found: \n"
+ namedResultsToString(results, "\n") + "\nOpening the first one.");
}
FindDefinitionResultEntry fdResultEntry = results.get(0);
if(fdResultEntry == null || fdResultEntry.isLanguageIntrinsic()) {
statusDialog(Severity.INFO, "Cannot open definition, "
+ "symbol \"" +fdResultEntry.extendedName + "\" is a language intrinsic.");
return;
}
final SourceRange sourceRange = fdResultEntry.sourceRange;
if(sourceRange == null) {
String msg = "Symbol " + fdResultEntry.extendedName + " has no source range info!";
throw new CommonException(msg);
}
Location newEditorFileLoc = fdResultEntry.modulePath;
if(newEditorFileLoc == null) {
throw new CommonException("no file path provided");
}
if(!newEditorFileLoc.toFile().exists()) {
throw new CommonException("File does not exist.");
}
IEditorInput newInput;
if(areEqual(newEditorFileLoc, getInputLocation())) {
newInput = editor.getEditorInput();
} else {
newInput = EditorUtils.getBestEditorInputForLoc(newEditorFileLoc);
}
EclipseUtils.run(() ->
EditorUtils.openTextEditorAndSetSelection(editor, EditorSettings_Actual.EDITOR_ID, newInput,
openNewEditorMode, sourceRange));
}
protected void statusDialog(Severity severity, String message) {
UIOperationsStatusHandler.displayStatusMessage(operationName, severity, message);
}
public static String namedResultsToString(Iterable<? extends FindDefinitionResultEntry> nodes, String sep) {
return StringUtil.toString(nodes, sep, new Function<FindDefinitionResultEntry, String>() {
@Override
public String apply(FindDefinitionResultEntry obj) {
return obj.extendedName;
}
});
}
}