페이지

레이블이 refactoring인 게시물을 표시합니다. 모든 게시물 표시
레이블이 refactoring인 게시물을 표시합니다. 모든 게시물 표시

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();
}