HintsController и EventQueue в NetBeans

Мы создаем приложение на основе платформы Netbeans, и одной его частью является редактор для определенного языка, который мы используем.

У нас есть следующий класс для выделения ошибок в синтаксисе:

class SyntaxErrorsHighlightingTask extends org.netbeans.modules.parsing.spi.ParserResultTask {

public SyntaxErrorsHighlightingTask () {
}

@Override
public void run (org.netbeans.modules.parsing.spi.Parser.Result result, org.netbeans.modules.parsing.spi.SchedulerEvent event) {
    try {
        final javax.swing.text.Document document = result.getSnapshot().getSource ().getDocument(false);
        final List<ErrorDescription> errors = new ArrayList<ErrorDescription> ();
        // finds errors on the document and add them to 'errors' list
        }

        /***
        OFFENDING CODE GOES HERE
        ***/

    } catch (javax.swing.text.BadLocationException ex1) {
        org.openide.util.Exceptions.printStackTrace (ex1);
    } catch (org.netbeans.modules.parsing.spi.ParseException ex1) {
        Exceptions.printStackTrace (ex1);
    }
}

@Override
public int getPriority () {
    return 100;
}

@Override
public Class<? extends Scheduler> getSchedulerClass () {
    return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER;
}

@Override
public void cancel () {
}

}

Код нарушения, который выдает исключение, таков:

org.netbeans.spi.editor.hints.HintsController.setErrors (document, "testsequence", errors);

По результатам поиска он был изменен на следующее:

SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                     System.err.println("is EDT? " + SwingUtilities.isEventDispatchThread());
                     HintsController.setErrors (document, "testsequence", errors);
                }
           });

Вот что происходит, когда в редакторе возникает синтаксическая ошибка:

is EDT? true
SEVERE [org.openide.util.RequestProcessor]: Error in RequestProcessor org.netbeans.spi.editor.hints.HintsController$1
java.lang.IllegalStateException: Must be run in EQ
    at org.netbeans.editor.Annotations.addAnnotation(Annotations.java:195)
    at org.netbeans.modules.editor.NbEditorDocument.addAnnotation(NbEditorDocument.java:251)
    at org.openide.text.NbDocument.addAnnotation(NbDocument.java:504)
    at org.netbeans.modules.editor.hints.AnnotationHolder$NbDocumentAttacher.attachAnnotation(AnnotationHolder.java:235)
    at org.netbeans.modules.editor.hints.AnnotationHolder.attachAnnotation(AnnotationHolder.java:208)
    at org.netbeans.modules.editor.hints.AnnotationHolder.updateAnnotationOnLine(AnnotationHolder.java:674)
    at org.netbeans.modules.editor.hints.AnnotationHolder.setErrorDescriptionsImpl(AnnotationHolder.java:899)
    at org.netbeans.modules.editor.hints.AnnotationHolder.access$1300(AnnotationHolder.java:113)
    at org.netbeans.modules.editor.hints.AnnotationHolder$4.run(AnnotationHolder.java:812)
    at org.netbeans.editor.BaseDocument.render(BaseDocument.java:1409)
    at org.netbeans.modules.editor.hints.AnnotationHolder.setErrorDescriptions(AnnotationHolder.java:809)
    at org.netbeans.modules.editor.hints.HintsControllerImpl.setErrorsImpl(HintsControllerImpl.java:111)
    at org.netbeans.modules.editor.hints.HintsControllerImpl.setErrors(HintsControllerImpl.java:93)
    at org.netbeans.spi.editor.hints.HintsController$1.run(HintsController.java:79)
    at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1424)
    at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:1968)
Caused: org.openide.util.RequestProcessor$SlowItem: task failed due to
    at org.openide.util.RequestProcessor.post(RequestProcessor.java:425)
    at org.netbeans.spi.editor.hints.HintsController.setErrors(HintsController.java:77)
    at com.#.#.#.editor.parser.SyntaxErrorsHighlightingTask$1.run(SyntaxErrorsHighlightingTask.java:74)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:641)
    at java.awt.EventQueue.access$000(EventQueue.java:84)
    at java.awt.EventQueue$1.run(EventQueue.java:602)
    at java.awt.EventQueue$1.run(EventQueue.java:600)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:611)
    at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:148)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
[catch] at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Что происходит, так это то, что вызов HintsController выполняется в EDT (поток EventDispatch). Однако Annotations.addAnnotation() выполняется в другом потоке — иногда в потоке «Синхронизатор системного буфера обмена», иногда в потоке «Неактивный процессор запросов». Поскольку он проверяет, выполняется ли он в EDT, он всегда выдает исключение IllegalStateException.

Я не эксперт в использовании платформы Netbeans, и я новичок в этом конкретном приложении в компании, поэтому я могу упустить что-то действительно очевидное. Гугл не сильно помог. У кого-нибудь есть совет?


person Marcelo    schedule 25.01.2012    source источник
comment
Просто в качестве комментария: этот класс был создан с использованием руководства, доступного в Netbeans Wiki.   -  person Marcelo    schedule 25.01.2012
comment
Проверьте эту ссылку netbeans-org.1045718.n5 .nabble.com/. Проблема решена в этом посте, может вам поможет.   -  person alain.janinm    schedule 28.01.2012
comment
Спасибо за ссылку alain.janinm, но решение там мало помогло. Тема в списке разработчиков netbeans: netbeans-org. 1045718.n5.nabble.com/   -  person Marcelo    schedule 30.01.2012


Ответы (2)


Оказывается, дело было вовсе не в коде.

Как указано в списке NetBeans-dev :

HintsController.setErrors можно вызывать из любого потока — он использует свой собственный рабочий поток и при необходимости переназначает поток AWT.

Требование вызывать Annotations.addAnnotation в потоке AWT было удалено довольно давно: http://hg.netbeans.org/main-silver/rev/db82e4e0fbcc

Тот же набор изменений также удалил автоматическое перепланирование в поток AWT в NbDocument.addAnnotation. Таким образом, кажется, что используемая вами сборка имеет вторую часть набора изменений, но не первую часть (...)

После тщательного просмотра файлов pom.xml maven я понял, что приложение загружает более новые версии библиотек, в то время как модуль загружает более старые версии, поэтому он будет запускать неправильный код. Связанный с этим вопрос SO об этом здесь.

person Marcelo    schedule 02.02.2012

Возможно, вам следует попытаться обновить свои ошибки с помощью такого метода:

private void updateError(javax.swing.text.Document document, List<ErrorDescription> errors) {
    if(javax.swing.SwingUtilities.isEventDispatchThread()) {
        HintsController.setErrors (document, "testsequence", errors);
    }
    else {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                 HintsController.setErrors (document, "testsequence", errors);
            }
       });
    }    
}
person alain.janinm    schedule 30.01.2012