程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 擴展NetBeans IDE 6.0中的C/C++編輯器以提供標記實例的高亮

擴展NetBeans IDE 6.0中的C/C++編輯器以提供標記實例的高亮

編輯:關於C++

教程需求

在繼續前,請確保您重新檢查了本節的需求。

先決條件

本 教程假設您已經有一些使用 IDE 的基本知識和 Java 編程經驗。

本教程所需的軟 件

在開始前,您需要安裝 NetBeans 6.0。您將同時需要 C/C++ 和 Java SE 支持,所 以最佳選擇是選擇“下載全部”選項並在安裝時排除 Base IDE、Java SE 和 C/C++ 包之外的所有模塊。

准備項目

對本教程,我們需要兩個項目。一個是管 理我們的插件的源代碼的 NetBeans 模塊。另一個是用來測試它的 C++ 項目。

創 建 NetBeans 插件模塊

選擇“文件”>“新建項目”。在 “新建項目”向導中,選擇“類別”下的“NetBeans 模塊 ”和“項目”下的“模塊”。單擊“下一步”。

在“名稱和位置”頁,在“項目名稱”字段中鍵入 MarkOccurrences,並把“項目位置”設置到磁盤上一個適當的文件夾裡。請 選中“獨立模塊”和“設置為主項目”,如果沒有選中的話。單擊 “下一步”。

在“基本模塊配置”頁,在“代碼名稱 基”字段中鍵入 org.netbeans.modules.markoccurrences。單擊“完成 ”。

在本項目中,我們需要一些依賴關系。在“項目”窗口,右 鍵單擊“庫”節點並在“添加模塊依賴關系”對話框中選擇 “庫”,然後添加屏幕快照裡列出的各個庫。C/C++ 模塊 API 正處於開發中 ,所以您需要在對話框中選擇“顯示非-API 模塊”,以便在模塊列表中看到 它們。

右鍵 單擊各個 C/C++ 模塊,選擇“編輯”,然後選擇“實現版本”。

創建測試應用程序

選擇“文件”>“新建項目”。選 擇“樣例”>“C/C++”>“C/C++”類別下的 Args 項目。單擊“下一步”。

在“項目名稱和位置”頁, 把“項目位置”設置到磁盤上一個適當的文件夾裡。單擊“完成” 。

現已創建了 Args_1 項目。在編輯器中打開 arg.c 源文件。我們將使用這個文 件來測試我們的模塊。

創建高亮基礎結構

現在我們將使用 NetBeans API 來向 C/C++ 編輯器添加高亮顯示。

創建高亮提供者

在標記實例項目的“源包 ”節點中右鍵單擊包 org.netbeans.modules.markoccurrences,然後選擇“ 新建”>“Java 類”。

將新類命名為 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.AttributeSet;
import javax.swing.text.Document;
import javax.swing.text.StyleConstants;
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 defaultColors = AttributesUtilities.createImmutable(StyleConstants.Background, new Color(236, 235, 163));
  public void caretUpdate(CaretEvent e) {
    bag.clear();
    bag.addHighlight(0, 5, defaultColors);
  }

  private final WeakReference<Document> weakDoc;
  public MarkOccurrencesHighlighter(Document doc) {
    bag = new OffsetsBag(doc);
    weakDoc = new WeakReference<Document> ((Document) doc);
    DataObject dobj = NbEditorUtilities.getDataObject(weakDoc.get());
    JEditorPane[] panes = CsmUtilities.getOpenedPanesInEQ(dobj.getCookie (EditorCookie.class));
    if (panes != null && panes.length > 0) {
      panes[0].addCaretListener(this);
    }
  }
  private final OffsetsBag bag;
  public OffsetsBag getHighlightsBag() {
    return bag;
  }
}
本類尚未 提供任何智能功能。它只是向光標事件注冊了一個偵聽器,並高亮顯示文檔開頭的符號。

創建並注冊 HighlightsLayerFactory

現在我們創建 HighlightsLayerFactory ,來讓 NetBeans 知道我們的高亮顯示提供者。

向項目源文件添加一個新的 Java 類,並將其命名為 MarkOccurrencesHighlightsLayerFactory。

用下面的代碼替 換新類中的代碼:package org.netbeans.modules.markoccurrences;
import javax.swing.text.Document;
import org.netbeans.spi.editor.highlighting.HighlightsLayer;
import org.netbeans.spi.editor.highlighting.HighlightsLayerFactory;
import org.netbeans.spi.editor.highlighting.ZOrder;
public class MarkOccurrencesHighlightsLayerFactory implements HighlightsLayerFactory {

  public static MarkOccurrencesHighlighter getMarkOccurrencesHighlighter(Document doc) {
     MarkOccurrencesHighlighter highlighter = (MarkOccurrencesHighlighter) doc.getProperty(MarkOccurrencesHighlighter.class);
    if (highlighter == null) {
      doc.putProperty (MarkOccurrencesHighlighter.class, highlighter = new MarkOccurrencesHighlighter(doc));
    }
    return highlighter;
  }
  public HighlightsLayer[] createLayers(Context context) {
    return new HighlightsLayer[] {
       HighlightsLayer.create(
           MarkOccurrencesHighlighter.class.getName(),
           ZOrder.CARET_RACK.forPosition(2000),
          true,
           getMarkOccurrencesHighlighter(context.getDocument ()).getHighlightsBag())
    };
  }
}

我們已 經提供了一個 HighlightsLayerFactory 的實現,它用 MarkOccurrencesHighlighte類提 供的數據創建了一個高亮顯示層。現在我們需要在 layer.xml 中注冊這個類。打開 org.netbeans.modules.markoccurrences 包中的 layer.xml,並將其內容更改為以下內 容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://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>

現在我們已經准備好第一次 運行我們的高亮顯示器了。

生成項目。

項目成功生成後,運行它。

打開我們在前一節中創建的 Args 項目。

在編輯器中打開 args.c 文件, 並單擊文件中的任一位置。高亮顯示看起來就會像下面的例子一樣:

太棒 了。我們的高亮顯示工作了。現在我們來教它變得更有用。

從 C/C++ 語言模型收 集信息

在 MarkOccurrencesHighlighter.java 類中,刪除我們粗略實現的 caretUpdate() ,並添加以下代碼:private WeakReference<CsmFile> weakFile;
public void caretUpdate(CaretEvent e) {
  bag.clear ();
  CsmFile file = getCsmFile();
  if (file != null) {
     CsmReference ref = CsmReferenceResolver.getDefault().findReference(file, e.getDot());
    if (ref != null && ref.getReferencedObject() != null) {
      Collection<CsmReference> out = CsmReferenceRepository.getDefault().getReferences(ref.getReferencedObject(), file, true);
      for (CsmReference csmReference : out) {
         bag.addHighlight(csmReference.getStartOffset(), csmReference.getEndOffset(), defaultColors);
      }
     }
  }
}
private CsmFile getCsmFile() {
  if (weakFile == null || weakFile.get() == null) {
    if (weakDoc == null || weakDoc.get() == null) {
      return null;
    }
    DataObject dobj = NbEditorUtilities.getDataObject(weakDoc.get ());
    CsmFile file = CsmUtilities.getCsmFile(dobj, false);
     if (file != null) {
      weakFile = new WeakReference<CsmFile>(file);
    } else {
       return null;
    }
  }
  return weakFile.get();
}

在 caretUpdate() 方法中,我們使用 CsmReferenceResolver 來查找光標下對語 言實體的引用。如果存在有效的實體,我們就向 CsmReferenceRepository 詢問文件中所 有相同實體的出現位置並存儲它們的偏移量。getCsmFile() 方法是一段銜接代碼,用來 確保我們不保留任何語言模型數據。

按下 Ctrl-Shift-I 以修復導入(或者右鍵 單擊,然後選擇“修復導入”)。

生成並運行項目。

如果把鼠 標放到 main() 的 argc 參數上,您就將看到如下的高亮顯示:

單擊 文件的不同位置以查看標記實例是怎樣工作的。您也許想嘗試更復雜的項目中以查看它怎 樣與類、宏等等協同工作。

提高性能

對靜態文本來說,我們當前的代碼足夠好 了,但將在編輯文件的過程中產生嚴重的延遲。出現延遲的原因是我們每按下一個鍵,就 立即開始搜索。要解決這個問題,我們將推遲任務以分析代碼,如果鼠標位置在任務開始 前改變了,我們就取消並重新計劃任務。

在 MarkOccurrencesHighlighter.java 類中,把先前的 caretUpdate() 實現更改為以下代碼:

public void caretUpdate(CaretEvent e) {
  bag.clear();
  lastCaret = e.getDot();
  scheduleUpdate();
}
private int lastCaret;
private RequestProcessor.Task task = null;
private final static int DELAY = 1000;

public void scheduleUpdate() {
  if (task==null) {
    task = RequestProcessor.getDefault().create(new Runnable() {
      public void run() {
        CsmFile file = getCsmFile();
        if (file != null) {
           CsmReference ref = CsmReferenceResolver.getDefault().findReference (file, lastCaret);
          if (ref!=null && ref.getReferencedObject()!=null) {
             Collection<CsmReference> out = CsmReferenceRepository.getDefault ().getReferences(ref.getReferencedObject(), file, true);
             for (CsmReference csmReference : out) {
               bag.addHighlight(csmReference.getStartOffset(), csmReference.getEndOffset (), defaultColors);
            }
          }
        }
      }
    }, true);
     task.setPriority(Thread.MIN_PRIORITY);
  }
  task.cancel();
  task.schedule(DELAY);
}

在這個代碼塊中,我們使用 org.openide.util.RequestProcessor 來處理代碼分析任務。如果得到幾個光標更新,我 們就取消先前的任務,記住鼠標位置,然後在稍後的時間重新計劃任務。

修復導 入,然後生成並運行項目。

現在您將注意到,在鍵入大塊代碼時沒有延遲了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved