1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-01 06:05:24 +02:00

Bug 481126 - Add hyperlink support to open decl in QML editor.

Also moved the text package contents to the editor package.

Change-Id: I352f8cfa78e937fb4046f86df8c7767df6c5eff2
This commit is contained in:
Doug Schaefer 2015-12-08 10:22:33 -05:00 committed by Gerrit Code Review @ Eclipse.org
parent 48f520d54c
commit 6ba6157708
16 changed files with 311 additions and 25 deletions

View file

@ -39,7 +39,7 @@ public class CMakeBuilder extends IncrementalProjectBuilder {
// TODO assuming cmake is in the path here, probably need a
// preference in case it isn't.
List<String> command = Arrays.asList("cmake", //$NON-NLS-1$
new File(project.getLocationURI()).getAbsolutePath());
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", new File(project.getLocationURI()).getAbsolutePath());
ProcessBuilder processBuilder = new ProcessBuilder(command).directory(buildDir.toFile());
cmakeConfig.getToolChain().setEnvironment(processBuilder.environment());
Process process = processBuilder.start();

View file

@ -26,7 +26,6 @@ import javax.script.ScriptException;
import org.eclipse.cdt.internal.qt.core.Activator;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
@ -135,7 +134,7 @@ public class QMLAnalyzer {
@FunctionalInterface
public interface RequestCallback {
void callback(Object err, Bindings data);
void callback(Object err, Object data);
}
public void addFile(String fileName, String code) throws NoSuchMethodException, ScriptException {
@ -182,8 +181,9 @@ public class QMLAnalyzer {
throw new RuntimeException(err.toString());
} else {
try {
for (Bindings completion : (Bindings[]) invoke.invokeMethod(engine.get("Java"), "to",
data.get("completions"), "javax.script.Bindings[]")) {
Bindings comps = (Bindings) ((Bindings) data).get("completions");
for (Bindings completion : (Bindings[]) invoke.invokeMethod(engine.get("Java"), "to", comps,
"javax.script.Bindings[]")) {
completions.add(new QMLTernCompletion((String) completion.get("name"),
(String) completion.get("type"), (String) completion.get("origin")));
}
@ -198,4 +198,45 @@ public class QMLAnalyzer {
return completions;
}
public List<Bindings> getDefinition(String identifier, String fileName, String text, int pos)
throws NoSuchMethodException, ScriptException {
waitUntilLoaded();
Bindings file = engine.createBindings();
file.put("type", "full");
file.put("name", fileName);
file.put("text", text);
Bindings files = (Bindings) engine.eval("new Array()");
invoke.invokeMethod(files, "push", file);
Bindings query = engine.createBindings();
query.put("type", "definition");
query.put("file", fileName);
query.put("end", pos);
query.put("types", true);
query.put("docs", false);
query.put("urls", false);
query.put("origins", true);
query.put("caseInsensitive", true);
query.put("lineCharPositions", true);
query.put("expandWordForward", false);
query.put("includeKeywords", true);
query.put("guess", false);
Bindings request = engine.createBindings();
request.put("files", files);
request.put("query", query);
List<Bindings> definitions = new ArrayList<>();
RequestCallback callback = (err, data) -> {
if (err != null) {
throw new RuntimeException(err.toString());
} else {
definitions.add((Bindings) data);
}
};
invoke.invokeMethod(tern, "request", request, invoke.invokeFunction("requestCallback", callback));
return definitions;
}
}

View file

@ -140,4 +140,24 @@
name="Reload QML Analyzer">
</command>
</extension>
<extension
point="org.eclipse.ui.workbench.texteditor.hyperlinkDetectorTargets">
<target
id="org.eclipse.cdt.qt.ui.qml"
name="QML Hyperlink Target">
<context
type="org.eclipse.cdt.internal.qt.ui.editor.QMLEditor">
</context>
</target>
</extension>
<extension
point="org.eclipse.ui.workbench.texteditor.hyperlinkDetectors">
<hyperlinkDetector
activate="true"
class="org.eclipse.cdt.internal.qt.ui.editor.QMLHyperlinkDetector"
id="org.eclipse.cdt.qt.ui.hyperlinkDetector2"
name="QML Hyperlink Detector"
targetId="org.eclipse.cdt.qt.ui.qml">
</hyperlinkDetector>
</extension>
</plugin>

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems 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
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.actions;
import org.eclipse.jface.action.Action;
public class OpenDeclarationsAction extends Action {
public static final String ID = "OpenDeclarations"; //$NON-NLS-1$
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
}
}

View file

@ -0,0 +1,14 @@
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems 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
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.editor;
public interface IQMLEditorActionDefinitionIds {
public static final String OPEN_DECLARATION = "org.eclipse.cdt.qml.edit.opendecl"; //$NON-NLS-1$
}

View file

@ -8,9 +8,7 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.text;
import org.eclipse.cdt.internal.qt.ui.editor.QMLPartitionScanner;
package org.eclipse.cdt.internal.qt.ui.editor;
/**
* Constants for the various partitions created by {@link QMLPartitionScanner}.

View file

@ -5,14 +5,14 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.text;
package org.eclipse.cdt.internal.qt.ui.editor;
import java.io.File;
import java.util.Collection;
import javax.script.ScriptException;
import org.eclipse.cdt.internal.qt.ui.Activator;
import org.eclipse.cdt.internal.qt.ui.editor.QMLEditor;
import org.eclipse.cdt.qt.core.QMLAnalyzer;
import org.eclipse.cdt.qt.core.QMLTernCompletion;
import org.eclipse.jface.text.BadLocationException;
@ -42,7 +42,7 @@ public class QMLContentAssistProcessor implements IContentAssistProcessor {
String prefix = lastWord(document, offset);
// Save the file
IFileEditorInput fileInput = (IFileEditorInput) editor.getEditorInput();
String fileName = fileInput.getFile().getFullPath().toString().substring(1);// getLocation().toOSString().substring(1);
String fileName = new File(fileInput.getFile().getLocationURI()).getAbsolutePath().substring(1);
try {
String contents = document.get();

View file

@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.editor;
import org.eclipse.cdt.internal.qt.ui.text.IQMLPartitions;
import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;

View file

@ -13,12 +13,16 @@ package org.eclipse.cdt.internal.qt.ui.editor;
import javax.script.ScriptException;
import org.eclipse.cdt.internal.qt.ui.Activator;
import org.eclipse.cdt.internal.qt.ui.text.QMLSourceViewerConfiguration;
import org.eclipse.cdt.internal.qt.ui.actions.OpenDeclarationsAction;
import org.eclipse.cdt.qt.core.QMLAnalyzer;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;
import org.eclipse.jface.text.source.ICharacterPairMatcher;
import org.eclipse.ui.IFileEditorInput;
@ -39,8 +43,8 @@ public class QMLEditor extends TextEditor {
@Override
protected void initializeEditor() {
setPreferenceStore(Activator.getDefault().getPreferenceStore());
setSourceViewerConfiguration(new QMLSourceViewerConfiguration(this));
super.initializeEditor();
setSourceViewerConfiguration(new QMLSourceViewerConfiguration(this, getPreferenceStore()));
}
@Override
@ -76,4 +80,56 @@ public class QMLEditor extends TextEditor {
store.setDefault(BRACKET_MATCHING_COLOR_PREFERENCE, "155,155,155"); //$NON-NLS-1$
}
@Override
protected void createActions() {
super.createActions();
IAction action = new OpenDeclarationsAction();
action.setActionDefinitionId(IQMLEditorActionDefinitionIds.OPEN_DECLARATION);
setAction(OpenDeclarationsAction.ID, action);
}
public static IRegion findWord(IDocument document, int offset) {
int start = -2;
int end = -1;
try {
int pos = offset;
char c;
while (--pos >= 0) {
c = document.getChar(pos);
if (!Character.isJavaIdentifierPart(c)) {
break;
}
}
start = pos;
pos = offset;
int length = document.getLength();
while (pos < length) {
c = document.getChar(pos);
if (!Character.isJavaIdentifierPart(c))
break;
++pos;
}
end = pos;
} catch (BadLocationException x) {
}
if (start >= -1 && end > -1) {
if (start == offset && end == offset)
return new Region(offset, 0);
else if (start == offset)
return new Region(start, end - start);
else
return new Region(start + 1, end - start - 1);
}
return null;
}
}

View file

@ -0,0 +1,100 @@
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems 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
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.editor;
import java.io.File;
import java.util.List;
import javax.script.Bindings;
import javax.script.ScriptException;
import org.eclipse.cdt.internal.qt.core.Activator;
import org.eclipse.cdt.qt.core.QMLAnalyzer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.ITextEditor;
public class QMLHyperlink implements IHyperlink {
private final IRegion region;
private final ITextViewer viewer;
private final ITextEditor editor;
public QMLHyperlink(IRegion region, ITextViewer viewer, ITextEditor editor) {
this.region = region;
this.viewer = viewer;
this.editor = editor;
}
@Override
public IRegion getHyperlinkRegion() {
return region;
}
@Override
public String getTypeLabel() {
return null;
}
@Override
public String getHyperlinkText() {
return "Open Declaration";
}
@Override
public void open() {
QMLAnalyzer analyzer = Activator.getService(QMLAnalyzer.class);
try {
IDocument document = viewer.getDocument();
String selected = document.get(region.getOffset(), region.getLength());
IFileEditorInput fileInput = (IFileEditorInput) editor.getEditorInput();
String fileName = new File(fileInput.getFile().getLocationURI()).getAbsolutePath().substring(1);
List<Bindings> definitions = analyzer.getDefinition(selected, fileName, document.get(),
region.getOffset() + region.getLength());
if (!definitions.isEmpty()) {
Bindings definition = definitions.iterator().next();
Bindings start = (Bindings) definition.get("start"); //$NON-NLS-1$
if (start == null) {
return;
}
int startLine = (int) (double) start.get("line"); //$NON-NLS-1$
int startChar = (int) (double) start.get("ch"); //$NON-NLS-1$
int startOffset = document.getLineOffset(startLine) + startChar;
Bindings end = (Bindings) definition.get("end"); //$NON-NLS-1$
int endLine = (int) (double) end.get("line"); //$NON-NLS-1$
int endChar = (int) (double) end.get("ch"); //$NON-NLS-1$
int endOffset = document.getLineOffset(endLine) + endChar;
String target = (String) definition.get("file"); //$NON-NLS-1$
if (fileName.equals(target)) {
editor.selectAndReveal(startOffset, endOffset - startOffset);
} else {
IFile[] targetFiles = ResourcesPlugin.getWorkspace().getRoot()
.findFilesForLocationURI(new File("/" + target).toURI()); //$NON-NLS-1$
if (targetFiles.length > 0) {
IEditorPart part = IDE.openEditor(editor.getEditorSite().getPage(), targetFiles[0]);
if (part instanceof ITextEditor) {
((ITextEditor) part).selectAndReveal(startOffset, endOffset - startOffset);
}
}
}
}
} catch (BadLocationException | NoSuchMethodException | ScriptException | PartInitException e) {
Activator.log(e);
}
}
}

View file

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems 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
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.editor;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.texteditor.ITextEditor;
public class QMLHyperlinkDetector extends AbstractHyperlinkDetector {
@Override
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
// TODO is length of region ever > 0?
IRegion wordRegion = QMLEditor.findWord(textViewer.getDocument(), region.getOffset());
if (wordRegion != null) {
ITextEditor editor = (ITextEditor) getAdapter(ITextEditor.class);
return new IHyperlink[] { new QMLHyperlink(wordRegion, textViewer, editor) };
}
return null;
}
}

View file

@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.editor;
import org.eclipse.cdt.internal.qt.ui.text.IQMLPartitions;
import org.eclipse.jface.text.rules.EndOfLineRule;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.IToken;

View file

@ -8,10 +8,12 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.text;
package org.eclipse.cdt.internal.qt.ui.editor;
import org.eclipse.cdt.internal.qt.ui.editor.QMLEditor;
import org.eclipse.cdt.internal.qt.ui.editor.QMLKeywords;
import java.util.Map;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.contentassist.ContentAssistant;
@ -56,7 +58,8 @@ public class QMLSourceViewerConfiguration extends TextSourceViewerConfiguration
private final QMLEditor editor;
public QMLSourceViewerConfiguration(QMLEditor editor) {
public QMLSourceViewerConfiguration(QMLEditor editor, IPreferenceStore prefs) {
super(prefs);
this.editor = editor;
}
@ -160,4 +163,12 @@ public class QMLSourceViewerConfiguration extends TextSourceViewerConfiguration
return contentAssistant;
}
@Override
protected Map<String, IAdaptable> getHyperlinkDetectorTargets(ISourceViewer sourceViewer) {
@SuppressWarnings("unchecked")
Map<String, IAdaptable> targets = super.getHyperlinkDetectorTargets(sourceViewer);
targets.put("org.eclipse.cdt.qt.ui.qml", editor); //$NON-NLS-1$
return targets;
}
}

View file

@ -8,13 +8,12 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.text;
package org.eclipse.cdt.internal.qt.ui.editor;
import java.util.ArrayList;
import java.util.Locale;
import org.eclipse.cdt.internal.qt.ui.Activator;
import org.eclipse.cdt.internal.qt.ui.editor.QtProjectFileKeyword;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;

View file

@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.editor;
import org.eclipse.cdt.internal.qt.ui.text.QtProjectFileSourceViewerConfiguration;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;

View file

@ -8,9 +8,8 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.qt.ui.text;
package org.eclipse.cdt.internal.qt.ui.editor;
import org.eclipse.cdt.internal.qt.ui.editor.QtProjectFileKeyword;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.TextAttribute;