首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

擴展 NetBeans IDE 6.0 C/C++ 編輯器:實作標記實例高亮外掛

     編輯:關於C++

教學目標

建立 NetBeans 模組,為 C/C++ 編輯器新增「標記實例高亮」功能:游標停留在變數/函式名稱上時,自動高亮同一文件中所有相同識別項出現處。

前置需求

  • NetBeans 6.0 (含 C/C++ 與 Java SE 支援,建議「下載全部」安裝)。
  • 基本 Java 程式設計與 NetBeans 模組開發概念。

專案建立

  1. 模組專案:File → New Project → NetBeans Modules → Module,名稱 MarkOccurrences,代碼名稱基底 org.netbeans.modules.markoccurrences。
  2. 加入模組依賴:右鍵 Libraries → Add Module Dependency,勾選「Show Non-API Modules」,加入所有 C/C++ 相關模組 (CND Model, Editor, CND Editor 等),並將各 C/C++ 模組設為「Implementation Version」。
  3. 測試專案:File → New Project → Samples → C/C++ → Args,開啟 arg.c 供測試。

核心類別實作

1. MarkOccurrencesHighlighter (高亮提供者)

package org.netbeans.modules.markoccurrences;

import java.awt.Color;
import java.lang.ref.WeakReference;
import javax.swing.JEditorPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.*;
import org.netbeans.api.editor.settings.AttributesUtilities;
import org.netbeans.modules.cnd.modelutil.CsmUtilities;
import org.netbeans.modules.editor.NbEditorUtilities;
import org.netbeans.spi.editor.highlighting.support.OffsetsBag;
import org.openide.cookies.EditorCookie;
import org.openide.loaders.DataObject;

public class MarkOccurrencesHighlighter implements CaretListener {
    private static final AttributeSet DEFAULT_COLORS = 
        AttributesUtilities.createImmutable(StyleConstants.Background, new Color(236, 235, 163));

    private final WeakReference<Document> weakDoc;
    private final OffsetsBag bag;
    private int lastCaret;
    private RequestProcessor.Task task = null;
    private static final int DELAY = 300; // ms

    public MarkOccurrencesHighlighter(Document doc) {
        this.weakDoc = new WeakReference<>(doc);
        this.bag = new OffsetsBag(doc);
        registerCaretListener(doc);
    }

    private void registerCaretListener(Document doc) {
        DataObject dobj = NbEditorUtilities.getDataObject(doc);
        JEditorPane[] panes = CsmUtilities.getOpenedPanesInEQ(dobj.getCookie(EditorCookie.class));
        if (panes != null && panes.length > 0) panes[0].addCaretListener(this);
    }

    @Override
    public void caretUpdate(CaretEvent e) {
        lastCaret = e.getDot();
        scheduleUpdate();
    }

    private void scheduleUpdate() {
        if (task == null) {
            task = RequestProcessor.getDefault().create(() -> {
                CsmFile file = getCsmFile();
                if (file != null) {
                    CsmReference ref = CsmReferenceResolver.getDefault().findReference(file, lastCaret);
                    if (ref != null && ref.getReferencedObject() != null) {
                        Collection<CsmReference> refs = CsmReferenceRepository.getDefault()
                            .getReferences(ref.getReferencedObject(), file, true);
                        for (CsmReference r : refs) {
                            bag.addHighlight(r.getStartOffset(), r.getEndOffset(), DEFAULT_COLORS);
                        }
                    }
                }
            }, true);
            task.setPriority(Thread.MIN_PRIORITY);
        }
        task.cancel();
        task.schedule(DELAY);
    }

    private CsmFile getCsmFile() {
        Document doc = weakDoc.get();
        if (doc == null) return null;
        DataObject dobj = NbEditorUtilities.getDataObject(doc);
        CsmFile file = CsmUtilities.getCsmFile(dobj, false);
        return file;
    }

    public OffsetsBag getHighlightsBag() { return bag; }
}

2. MarkOccurrencesHighlightsLayerFactory (圖層工廠)

package org.netbeans.modules.markoccurrences;

import javax.swing.text.Document;
import org.netbeans.spi.editor.highlighting.*;
import org.netbeans.spi.editor.highlighting.ZOrder;

public class MarkOccurrencesHighlightsLayerFactory implements HighlightsLayerFactory {
    public static MarkOccurrencesHighlighter getMarkOccurrencesHighlighter(Document doc) {
        MarkOccurrencesHighlighter h = (MarkOccurrencesHighlighter) doc.getProperty(MarkOccurrencesHighlighter.class);
        if (h == null) doc.putProperty(MarkOccurrencesHighlighter.class, h = new MarkOccurrencesHighlighter(doc));
        return h;
    }

    @Override
    public HighlightsLayer[] createLayers(Context context) {
        return new HighlightsLayer[] {
            HighlightsLayer.create(
                MarkOccurrencesHighlighter.class.getName(),
                ZOrder.CARET_RACK.forPosition(2000),
                true,
                getMarkOccurrencesHighlighter(context.getDocument()).getHighlightsBag()
            )
        };
    }
}

3. 註冊圖層工廠 (layer.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" 
  "https://www.netbeans.org/dtds/filesystem-1_1.dtd">
<filesystem>
  <folder name="Editors">
    <folder name="text">
      <folder name="x-c++">
        <file name="org-netbeans-modules-markoccurrences-MarkOccurrencesHighlightsLayerFactory.instance"/>
      </folder>
      <folder name="x-c">
        <file name="org-netbeans-modules-markoccurrences-MarkOccurrencesHighlightsLayerFactory.instance"/>
      </folder>
    </folder>
  </folder>
</filesystem>

效能優化關鍵

  • WeakReference:避免長期持有 Document/CsmFile 導致記憶體洩漏。
  • RequestProcessor + 延遲排程:游標移動時取消前一任務,300ms 後才分析,避免輸入時卡頓。
  • 最低優先權執行緒:不阻塞 UI 執行緒。

測試驗證

  1. 建置模組專案 (Build)。
  2. Run (啟動新 NetBeans 實例)。
  3. 開啟測試專案 arg.c,點擊變數名稱 (如 argc),同一文件所有 argc 即高亮顯示。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved