Adding Gutter Icon depending on line highlight/console output

已回答

Hello, currently I managed to highlight lines of code programatically. I would like to add custom gutter icon for highlighted lines. Is there any way to verify if certain PsiElement is placed on highlighted line? I highlight lines depending on console output, so maybe there is a way to reach console output within LineMarkerProvide and then add gutter icon if PsiElement text would appear in console.

0

Hi Patryk,

Please share more information. What does it mean to highlight lines of code programmatically? What APIs do you use? How is the information provided by the console output and how do you use it currently? Please share your current code.

The first thought that came to my mind was storing the required information from console output in a service that could be used in other extensions.

0

Hi Karol,

At the moment I am using custom implementation of OutputToGeneralTestEventsConverter with given processServiceMessages() method:

@Override
protected boolean processServiceMessages(final String text, final Key outputType,
        final ServiceMessageVisitor visitor) {

    this.visitor = visitor;
    String logLine = text.trim();

    Matcher metadataMatcher = METADATA_PATTERN.matcher(logLine);

    if (metadataMatcher.matches()) {
        ApplicationManager.getApplication().invokeLater(() -> {
            String stepStatus = metadataMatcher.group(2);

            this.resolveStepOffset(Optional.ofNullable(metadataMatcher.group(4))
                            .map(this.scenariosOffsetsMap::get)
                            .orElse(this.backgroundOffset), Integer.parseInt(metadataMatcher.group(5)))
                    .ifPresent(stepOffset -> this.addScenarioLineHighlighting(stepOffset, stepStatus));
        });

        return false;
    }
    return true;
}

 

Below is the code of addScenarioLineHighlighting() and mapStepStatusToBackgroundColor():

private void addScenarioLineHighlighting(int lineNumber, String stepStatus) {
    JBColor color = this.mapStepStatusToBackgroundColor(stepStatus);

    if (color != null) {
        TextAttributes textAttributes = new TextAttributes();
        textAttributes.setBackgroundColor(color);

        Optional.ofNullable(this.highlighters.get(lineNumber)).ifPresent(this.markupModel::removeHighlighter);
        this.highlighters.put(lineNumber,
                this.markupModel.addLineHighlighter(lineNumber, HighlighterLayer.SELECTION, textAttributes));
    }
}

private JBColor mapStepStatusToBackgroundColor(String stepStatus) {
    return switch (stepStatus) {
        case "before" -> new JBColor(Color.YELLOW, new Color(252, 249, 145, 255));
        case "pending" -> new JBColor(Color.CYAN, new Color(27, 222, 222, 255));
        case "failed" -> new JBColor(Color.RED, new Color(236, 47, 47, 255));
        case "successful" -> new JBColor(Color.GREEN, new Color(84, 248, 107, 255));
        default -> null;
    };
}

What I want to achieve is to add gutter icon to the line that has been highlighted by mapStepStatusToBackgroundColor() as failed.

0

Hi Patryk,

Thanks for the details. If you need to add a gutter icon to a specific line number, then probably it would be easier to use `com.intellij.openapi.editor.RangeMarker`?
 

RangeMarker highlighter = LazyRangeMarkerFactory.getInstance(getProject()).createRangeMarker(file, line, 0, true);
highlighter.setGutterIconRenderer(new FailedGutterIconRenderer(file, line));


  private static class FailedGutterIconRenderer extends GutterIconRenderer {

    private final VirtualFile myFile;
    private final int myLine;

    private FailedGutterIconRenderer(@NotNull VirtualFile file, int line) {
      myFile = file;
      myLine = line;
    }

    @Override
    public @NotNull Icon getIcon() {
      return AllIcons.RunConfigurations.TestFailed;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      FailedGutterIconRenderer renderer2 = (FailedGutterIconRenderer)o;
      return myLine == renderer2.myLine && Objects.equals(myFile, renderer2.myFile);
    }

    @Override
    public int hashCode() {
      return Objects.hash(myFile, myLine);
    }
  }
0

Hello Sergey,

Sorry for my late response but I had to refactor my code and test everything thoroughly in case of any problems I could consult here. Seems like your solution works perfectly, thank you for your help.

1

请先登录再写评论。