void (@NotNull final Editor editor, @NotNull final Project project, @NotNull final FileAnnotation fileAnnotation, @NotNull final AbstractVcs vcs, @NotNull final UpToDateLineNumberProvider upToDateLineNumbers, final boolean warnAboutSuspiciousAnnotations) { ThreadingAssertions.assertEventDispatchThread(); if (project.isDisposed() || editor.isDisposed()) return; if (warnAboutSuspiciousAnnotations) { int expectedLines = Math.max(upToDateLineNumbers.getLineCount(), 1); int actualLines = Math.max(fileAnnotation.getLineCount(), 1); if (Math.abs(expectedLines - actualLines) > 1) { // 1 - for different conventions about files ending with line separator LOG.warn("Unexpected annotation lines number. Expected: " + expectedLines + ", actual: " + actualLines); editor.setHeaderComponent(new MyEditorNotificationPanel(editor, vcs, () -> { doAnnotate(editor, project, fileAnnotation, vcs, upToDateLineNumbers, false); })); return; } } fileAnnotation.setCloser(() -> UIUtil.invokeLaterIfNeeded(() -> { if (project.isDisposed()) return; closeVcsAnnotations(editor); })); fileAnnotation.setReloader(newFileAnnotation -> { if (project.isDisposed()) return; if (hasVcsAnnotations(editor)) { if (newFileAnnotation != null) { assert Comparing.equal(fileAnnotation.getFile(), newFileAnnotation.getFile()); doAnnotate(editor, project, newFileAnnotation, vcs, upToDateLineNumbers, false); } else { DataContext dataContext = DataManager.getInstance().getDataContext(editor.getComponent()); AnActionEvent event = AnActionEvent.createFromDataContext(ActionPlaces.UNKNOWN, null, dataContext); Provider provider = getProvider(event); if (provider != null && provider.isEnabled(event) && !provider.isSuspended(event)) { provider.perform(event, true); } else { closeVcsAnnotations(editor); } } } }); if (fileAnnotation.isClosed()) return; Disposable disposable = new Disposable() { @Override public void dispose() { fileAnnotation.dispose(); } }; VcsAnnotationLocalChangesListener changesListener = ProjectLevelVcsManager.getInstance(project).getAnnotationLocalChangesListener(); changesListener.registerAnnotation(fileAnnotation); Disposer.register(disposable, new Disposable() { @Override public void dispose() { changesListener.unregisterAnnotation(fileAnnotation); } }); closeVcsAnnotations(editor); final List<AnnotationFieldGutter> gutters = new ArrayList<>(); final AnnotationSourceSwitcher switcher = fileAnnotation.getAnnotationSourceSwitcher(); final AnnotationPresentation presentation = new AnnotationPresentation(fileAnnotation, upToDateLineNumbers, switcher, disposable); presentation.addAction(new ShowDiffFromAnnotation(project, fileAnnotation)); presentation.addAction(new CopyRevisionNumberFromAnnotateAction(fileAnnotation)); presentation.addAction(Separator.getInstance()); final Couple<Map<VcsRevisionNumber, Color>> bgColorMap = computeBgColors(fileAnnotation, editor); final Map<VcsRevisionNumber, Integer> historyIds = computeLineNumbers(fileAnnotation); gutters.add(new FillerColumn(fileAnnotation, presentation, bgColorMap)); if (switcher != null) { switcher.switchTo(switcher.getDefaultSource()); final LineAnnotationAspect revisionAspect = switcher.getRevisionAspect(); final CurrentRevisionAnnotationFieldGutter currentRevisionGutter = new CurrentRevisionAnnotationFieldGutter(fileAnnotation, revisionAspect, presentation, bgColorMap); final MergeSourceAvailableMarkerGutter mergeSourceGutter = new MergeSourceAvailableMarkerGutter(fileAnnotation, presentation, bgColorMap); SwitchAnnotationSourceAction switchAction = new SwitchAnnotationSourceAction(switcher); presentation.addAction(switchAction); switchAction.addSourceSwitchListener(currentRevisionGutter); switchAction.addSourceSwitchListener(mergeSourceGutter); currentRevisionGutter.accept(switcher.getDefaultSource()); mergeSourceGutter.accept(switcher.getDefaultSource()); gutters.add(currentRevisionGutter); gutters.add(mergeSourceGutter); } List<LineAnnotationAspect> aspects = Arrays.asList(fileAnnotation.getAspects()); List<LineAnnotationAspect> fromExt = ContainerUtil.mapNotNull(AnnotationGutterColumnProvider.EP_NAME.getExtensions(), extension -> extension.createColumn(fileAnnotation)); for (LineAnnotationAspect aspect : ContainerUtil.concat(aspects, fromExt)) { gutters.add(new AspectAnnotationFieldGutter(fileAnnotation, aspect, presentation, bgColorMap)); } if (historyIds != null) { gutters.add(new HistoryIdColumn(fileAnnotation, presentation, bgColorMap, historyIds)); } if (!ExperimentalUI.isNewUI()) { gutters.add(new HighlightedAdditionalColumn(fileAnnotation, presentation, bgColorMap)); } final AnnotateActionGroup actionGroup = new AnnotateActionGroup(fileAnnotation, gutters, bgColorMap); presentation.addAction(actionGroup, 1); gutters.add(new ExtraFieldGutter(fileAnnotation, presentation, bgColorMap, actionGroup)); presentation.addAction(new AnnotateCurrentRevisionAction(fileAnnotation, vcs)); presentation.addAction(new AnnotatePreviousRevisionAction(fileAnnotation, vcs)); addActionsFromExtensions(presentation, fileAnnotation); for (AnnotationFieldGutter gutter : gutters) { final AnnotationGutterLineConvertorProxy proxy = gutter instanceof TextAnnotationGutterProvider.Filler ? new AnnotationGutterLineConvertorProxy.Filler(upToDateLineNumbers, gutter) : new AnnotationGutterLineConvertorProxy(upToDateLineNumbers, gutter); if (gutter.isGutterAction()) { editor.getGutter().registerTextAnnotation(proxy, proxy); } else { editor.getGutter().registerTextAnnotation(proxy); } } InlineDiffFromAnnotation.showDiffOnHover(editor, fileAnnotation, presentation, disposable); }