페이지

2012년 12월 13일 목요일

Manipulating Texts in Eclipse

Manipulating texts in Eclipse

History

revisionchangesauthor
0.1initial version 2012-12-05 수 Darren Ha
0.2textBuffer.commit 2012-12-13 목 Darren Ha

Introduction

manipulating texts in Eclipse way can be hard for initial Eclipse plugin developers. I couldn't find any structured tutorial or articles. So this articles is born. any comments about the contets are welcomed! I hope it helps you too.

Getting IDocument form a IPath

A FileBuffer represents a file that is being modified over time. Fille buffers for text files provide IDocument(a content model) and IAnnotationModel(a marker model). so IDdocument is essential for manipulating texts.
ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager();
IPath path = new Path("/sample/test.h");
try{
    bufferManager.connect(path, LocationKind.IFILE, monitor);
    ITextFileBuffer textBuffer = bufferManager.getTextFileBuffer(path, LocationKind.IFILE);
    IDocument document = textBuffer.getDocument();
}finally{
    bufferManager.disconnect(path, LocationKind.IFILE, monitor);
}  

Creating and applying TextEdit

We can modify IDocument using TextEdit subclasses: e.g. ReplaceEdit, InsertEdit, DeleteEdit to apply those changed multiple times in a file, you should use MultiTextEdit which is tree container of TextEdits. MultiTextEdit::apply can produce an error if the changes made at the same location at multiple times.
MultiTextEdit::apply doesn't change file contetns immediately. to change file content you must call ITextFileBuffer::commit.
ITextFileBuffer textBuffer = ...;
IDocument document = ..;

FindReplaceDocumentAdapter finder = new FindReplaceDocumentAdapter(document);
IRegion regionReplace = finder.find(0, "textTobeReplaced", true, true, false, false);
IRegion regionInsert = finder.find(0, "//TODO", true, true, false, false);

MultiTextEdit multiEdit = new MultiTextEdit();
multiEdit.addChild( new ReplaceEdit(regionReplace.getOffset(), regionReplace.getLength(), "ReplacedText"));
multiEdit.addChild( new InsertEdit(regionInsert.getOffset(), regionInsert.getLength()));
multiEdit.apply(document);
textBuffer.commit(monitor, true);

using CDT refactoring mechanism

You can use CDT built-in refactoring framework to change texts more elegant way. the following codes demonstrate invoking rename refactoring of CDT programtically. You can invoke this by clicking Alt+Shift+R in eclipse source editor. It's cool!
If the indexer has unresolved symbols , when build is broken, the refactoring operation can fail.
IFile file = new File("/sample/test.h");
IRegion region = ...;
CRefactoringArgument arg = new CRefactoringArgument(file, region.getOffset(), region.getLength());
CRenameProcessor proc = new CRenameProcessor(CRefactory.getInstance(), arg);
proc.setReplacementText("ReplacedText");
proc.setSelectedOptions(-1);
proc.setScope(TextSearchWrapper.SCOPE_SINGLE_PROJECT);
CRenameRefactoring refactor = new CRenameRefactoring(proc);

((CRenameProcessor)refactor.getProcessor()) .lockIndex();
try{
    RefactoringStatus rs = refactor.checkInitialConditions(monitor);
    if (rs.hasFatalError()) {
        throw new Exception("checkInitialcondtion fail");
    }
    rs = refactor.checkFinalConditions(monitor);
    if (rs.hasError()) {
        throw new Exception("checkFinalcondtion fail");
    }
    Change change = refactor.createChange(monitor);
    change.perform(monitor);
}finally{
    ((CRenameProcessor)refactor.getProcessor()).unlockIndex();
}