-
Notifications
You must be signed in to change notification settings - Fork 1
CodeLens Extension Point
Here a quick tutorial to implement your own CodeLens inside your own editor.
The first step is to create your own CodeLens class to register needed data used to resolve Codelens or implement action when the CodeLens is clicked:
package org.eclipse.codelens.samples;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.provisional.codelens.CodeLens;
import org.eclipse.swt.widgets.Display;
public class ClassCodeLens extends CodeLens {
private String className;
public ClassCodeLens(String className, int startLineNumber) {
super(startLineNumber);
this.className = className;
}
public String getClassName() {
return className;
}
@Override
public void open() {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
MessageDialog.openInformation(Display.getDefault().getActiveShell(), "Open class CodeLens", ClassCodeLens.this.className);
}
});
}
}
ICodeLensProvider API works with CompletableFuture:
package org.eclipse.jface.text.provisional.codelens;
import java.util.concurrent.CompletableFuture;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* A code lens provider adds [commands](#Command) to source text. The commands
* will be shown as dedicated horizontal lines in between the source text.
*/
public interface ICodeLensProvider {
/**
* Compute a list of [lenses](#CodeLens). This call should return as fast as
* possible and if computing the commands is expensive implementors should only
* return code lens objects with the range set and implement
* [resolve](#CodeLensProvider.resolveCodeLens).
*
* @param document
* The document in which the command was invoked.
* @param token
* A cancellation token.
* @return An array of code lenses or a thenable that resolves to such. The lack
* of a result can be signaled by returning `undefined`, `null`, or an
* empty array.
*/
CompletableFuture<ICodeLens[]> provideCodeLenses(ICodeLensContext context, IProgressMonitor monitor);
/**
* This function will be called for each visible code lens, usually when
* scrolling and after calls to
* [compute](#CodeLensProvider.provideCodeLenses)-lenses.
*
* @param codeLens
* code lens that must be resolved.
* @param token
* A cancellation token.
* @return The given, resolved code lens or thenable that resolves to such.
*/
CompletableFuture<ICodeLens> resolveCodeLens(ICodeLensContext context, ICodeLens codeLens,
IProgressMonitor monitor);
}
If you don't want to use CompletableFutire, you can AbstractSyncCodeLensProvider
At this step you can implement you own CodeLens Provider like this:
package org.eclipse.codelens.samples;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.provisional.codelens.AbstractSyncCodeLensProvider;
import org.eclipse.jface.text.provisional.codelens.Command;
import org.eclipse.jface.text.provisional.codelens.ICodeLens;
import org.eclipse.jface.text.provisional.codelens.ICodeLensContext;
public class ClassReferencesCodeLensProvider extends AbstractSyncCodeLensProvider {
@Override
public ICodeLens[] provideSyncCodeLenses(ICodeLensContext context, IProgressMonitor monitor) {
ITextViewer textViewer = context.getViewer();
IDocument document = textViewer.getDocument();
List<ICodeLens> lenses = new ArrayList<>();
int lineCount = document.getNumberOfLines();
for (int i = 0; i < lineCount; i++) {
String line = getLineText(document, i, false);
int index = line.indexOf("class ");
if (index != -1) {
String className = line.substring(index + "class ".length(), line.length());
index = className.indexOf(" ");
if (index != -1) {
className = className.substring(0, index);
}
if (className.length() > 0) {
lenses.add(new ClassCodeLens(className, i + 1));
}
}
}
return lenses.toArray(new ICodeLens[0]);
}
@Override
public ICodeLens resolveSyncCodeLens(ICodeLensContext context, ICodeLens codeLens, IProgressMonitor monitor) {
ITextViewer textViewer = context.getViewer();
IDocument document = textViewer.getDocument();
String className = ((ClassCodeLens) codeLens).getClassName();
int refCount = 0;
int lineCount = document.getNumberOfLines();
for (int i = 0; i < lineCount; i++) {
String line = getLineText(document, i, false);
refCount += line.contains("new " + className) ? 1 : 0;
}
((ClassCodeLens) codeLens).setCommand(new Command(refCount + " references", ""));
return codeLens;
}
private static String getLineText(IDocument document, int line, boolean withLineDelimiter) {
try {
int lo = document.getLineOffset(line);
int ll = document.getLineLength(line);
if (!withLineDelimiter) {
String delim = document.getLineDelimiter(line);
ll = ll - (delim != null ? delim.length() : 0);
}
return document.get(lo, ll);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
You can register your custom CodeLens provider with Extension Point.
The target mylanguage.codeLens
is used to define which Codelens provider should be executed with your editor:
<!-- "references" CodeLens -->
<extension
point="org.eclipse.codelens.codeLensProviders">
<codeLensProvider
name="References"
class="org.eclipse.codelens.samples.ClassReferencesCodeLensProvider"
targetId="mylanguage.codeLens">
</codeLensProvider>
</extension>
<!-- "implementations" CodeLens -->
<extension
point="org.eclipse.codelens.codeLensProviders">
<codeLensProvider
name="Implementations"
class="org.eclipse.codelens.samples.ClassImplementationsCodeLensProvider"
targetId="mylanguage.codeLens">
</codeLensProvider>
</extension>
Create an instance of CodeLensStrategy bound with the text viewer of your editor and target .
ITextViewer textViewer = ...
CodeLensStrategy codelens = new CodeLensStrategy(new DefaultCodeLensContext(textViewer), false);
codelensStategy.addTarget("mylanguage.codeLens");
When editor changed, codelens strategy should be updated. In a Thread background or other thing update codelensStategy when your editor changed:
codelensStategy.reconcile(null, null);