Best way to implement code highlighting/annotation by file+line number?

Is there a way to highlight code given line and filename, using the plugin API.

Such that a small snippet of information is displayed in conjunction with that line, ( from an external source.)

I have looked into the available methods, and it seems to be based on parsing rather than arbitrary line numbers.

thanks

0

It seems com.intellij.lang.annotation.ExternalAnnotator might be suitable here. You can then register highlighting without PSI using com.intellij.lang.annotation.AnnotationHolder with TextRange parameter, which can be calculated to match certain line(s) in editor.

0

Thanks for the reply @yannc76, will investigate.

0
Avatar
Permanently deleted user

I have the same requirements. Could you provide some more details?

The documentation seems out of date, com.intellij.lang.annotation.ExternalAnnotator is no longer an interface. How can I use the com.intellij.lang.annotation.AnnotationHolder for this? Is there any documentation beside the source code?

My plugin loads information from a server. The information contains the exact position of the text (line number/character), which has to be annotated. How would I do that?

0

Thanks for noting, we're going to update this part.

Still using ExternalAnnotator seems a solution for your problem here. Unfortunately there are not too many examples in Community Edition sources.

You'll have to map line/col information from server to a TextRange (full line or specific elements at that position) to map the results to the current file.

See DartAnalysisServerAnnotator.java in contrib repository.

0
Avatar
Permanently deleted user

I can't find any file called DartAnalysisServerAnnotator.java. Could you provide me with a link?

0
Avatar
Permanently deleted user

When I extend ExternalAnnotator, a PluginException is thrown, which says: "No key specified for extension of class FindingsAnnotator"

 
<externalAnnotator
    implementationClass="FindingsAnnotator">
</externalAnnotator>


Do I have to declare a language like it is done in the plugin.xml for DartAnalysisServerAnnotator? My plugin is independent of the used language.

0

Currently you'll have to register your annotator for every supported language explicitly. What kind of data do you provide that language/filetype does not matter at all?

0
Avatar
Permanently deleted user

The data holds information about the code, which should be displayed at the according line. Several languages are currently supported, but constantly extended on the server-side. Therefore, it would be best, if the plugin was language independent, so it would not have to be maintained for that matter.

1
Avatar
Permanently deleted user

Hi! I'm having the same problem that @Benedikt had. I need to annotate a specific line in the document but it must be language agnostic, I just want to highlight it and have a tooltip with some information about the Warning/Error on the UI. How can I do this?

0
Avatar
Permanently deleted user

@Bmibferreira I am using a SideBarFactory to create a sidebar with annotations:

 

public class MySideBarFactory implements SideBarFactory {

Implement the createSideBar method and determine the open file:

 @Override
public JComponent createSideBar(JTextComponent editor) {
TopComponent tc = TopComponent.getRegistry().getActivated();
if (tc == null) {
LOGGER.info("No active TopComponent");
return null;
}

FileObject fileObject = tc.getLookup().lookup(FileObject.class);
if (fileObject == null) {
LOGGER.info("FileObject of current TopComponent is null");
return null;
}

MyData data = getDataForFile(fileObject);
return new MySidebarComponent(editor, data);
}

Do the painting in MySideBarComponent:

public class MySideBarComponent extends JPanel {
public MySideBarComponent(JTextComponent target, MyData data) {
// constructor stuff
}

@Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);

// Do paint action on g
}
}

//EDIT:

Don't forget to register the SideBarFactory in your layer.xml:


<filesystem>
...
<folder name="Editors">
<folder name="SideBar">
<!-- See: https://blogs.oracle.com/geertjan/orgnetbeanseditorsidebarfactory-part-1 -->
<file name="com-my-package-MySideBarFactory.instance">
<attr name="position" intvalue="1580"/>
</file>
</folder>
</folder>
</filesystem>

 

1
Avatar
Permanently deleted user

Hi @Benedikt, thanks for your answer. I searched for SideBarFactory but I didn't found it. Is your example valid for IntelliJ? Because it seems that SideBarFactory is from Netbeans (http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-editor-lib2/org/netbeans/spi/editor/SideBarFactory.html?is-external=true)

0
Avatar
Permanently deleted user

@BmiBferreira You are totally right... I completely mixed it up. So if you plan to develop your plugin for Netbeans as well, you already know how to do it ;)

For Intellij IDEA, you can use an ActionGutterRenderer:

First you need to implement a FileEditorManagerListener and register it to the MessageBus, in order to get notified, when the file of the editor is changed:

public class MyFileManagerListener implements FileEditorManagerListener {
public MyFileManagerListener() {
MessageBus bus = ApplicationManager.getApplication().getMessageBus();
MessageBusConnection connection = bus.connect();
connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, this);
}

@Override
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
MyData data = getDataForFile(file);
ApplicationManager.getApplication().invokeLater(() -> {
Editor selectedEditor = manager.getSelectedTextEditor();
if (selectedEditor != null && selectedEditor instanceof EditorEx) {
EditorEx editor = (EditorEx) selectedEditor;
MarkupModel model = editor.getMarkupModel();
RangeHighlighter highlighter = model.addRangeHighlighter(data.lineStartOffset, data.lineEndOffset, 1, null, HighlighterTargetArea.LINES_IN_RANGE);
highlighter.setLineMarkerRenderer(new MyGutterRenderer(editor, myData));
}
}
}
}

Second you need to implement your renderer:

public class MyGutterRenderer implements ActiveGutterRenderer {

Implement the required methods:

@Override
public void paint(Editor editor, Graphics g, Rectangle r) {
g.setColor(new JBColor(new Color(255, 255, 255), new Color(200, 200, 200)));
g.fillRect(r.x, r.y, 3, r.height);
}

@Override
public void doAction(Editor editor, MouseEvent e) {
e.consume();
// react on mouse events on the gutter
}

@Override
public boolean canDoAction(MouseEvent e) {
// return true, when the mouse event is valid for an action. This will then call doAction.
}

Now you need to register both classes as ProjectComponents in your plugin.xml:

<project-components>
<component>
<implementation-class>
com.mycompany.MyRenderer
</implementation-class>
</component>
<component>
<implementation-class>
com.mycompany.MyFileManagerListener
</implementation-class>
</component>
...

Hope this helps.

1

请先登录再写评论。