SlideShare a Scribd company logo
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
朝木卓見
Qt Creatorを拡張する

" C++ Editor: リファクタリング機能編
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
Qt Creatorのアーキテクチャ
• プラグインアーキテクチャ"
– 固定機能は最小限"
– プラグインの追加で拡張可能
2
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
リファクタリング機能
• エディタの文脈を考慮した簡易編集機能"
– http://qt-project.org/doc/qtcreator-3.2/creator-
editor-refactoring.html"
– 使いこなすことでより楽にコーディング可能"
– ex."
• メソッドの宣言に対する定義の作成"
• 選択範囲のコードから関数を作成"
• 基底クラスの仮想関数のオーバーライドの作成"
• etc.
3
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
エディタに機能を追加する
• TextEditorのアシスト用クラス"
– TextEditor::IAssistProcessor"
• http://doc.qt.digia.com/qtcreator-extending/texteditor-
iassistprocessor.html"
• Acts as an interface that actually computes an assist proposal"
• アシストの実行用クラス"
– TextEditor::IAssistProvider"
• http://doc.qt.digia.com/qtcreator-extending/texteditor-
iassistprovider.html"
• Acts as an interface for providing code assist"
• IAssistProcessor生成用クラス"
• 今回はC++特化のため上記を直接扱わない
4
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
C++エディタのリファクタリング機能
• cppeditorプラグイン"
– src/plugins/cppeditor/"
• C++エディタ専用の以下のクラスを利用"
– CppQuickFixOperation"
• リファクタリングを実行する"
– CppQuickFixFactory"
• コードモデルからリファクタリング用に
CppQuickFixOperationのインスタンスを作成する
5
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
実装する機能
• 文字列リテラルのエスケープ/アンエスケープ"
– ex."
• “あい” “xe3x81x82xe3x81x84”"
"
• 詳細は"
– https://codereview.qt-project.org/90103"
– Qt Creator 3.3 から利用可能"
– スライドは一部省略
6
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixFactory(1)
• cppquickfixes.hに宣言を追加"
"
"
"
– interface: コードモデルへのインターフェース"
• コードの構造やカーソル位置の情報など"
– result: リファクタリング用インスタンスのリスト"
• 実行用クラスのインスタンスをここに登録する
7
class EscapeStringLiteral : public CppQuickFixFactory"
{"
public:"
void match(const CppQuickFixInterface &interface,"
TextEditor::QuickFixOperations &result); // virtual"
}
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixFactory(2)
• cppquickfixes.cppに定義を追加"
"
"
"
"
"
"
– AST: 抽象構文木"
• http://ja.wikipedia.org/wiki/%E6%8A%BD
%E8%B1%A1%E6%A7%8B%E6%96%87%E6%9C%A8
8
void EscapeStringLiteral::match(const CppQuickFixInterface &interface,"
QuickFixOperations &result)"
{"
// カーソル位置のASTの取得"
const QList<AST *> &path = interface->path();"
AST * const lastAst = path.last();"
"
// 文字列リテラルの取得"
ExpressionAST *literal = lastAst->asStringLiteral();"
if (!literal)"
return;"" "
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixFactory(3)
• cppquickfixes.cppに定義を追加
9
// 文字列リテラルの取得"
StringLiteralAST *stringLiteral = literal->asStringLiteral();"
CppRefactoringFilePtr file = interface->currentFile();"
const QByteArray"
" contents(file->tokenAt(stringLiteral->literal_token).identifier->chars());"
"
// エスケープ可能かどうか確認"
bool canEscape = false;"
for (int i = 0; i < contents.length(); ++i) {"
" quint8 c = contents.at(i);"
" if (!isascii(c) || !isprint(c)) {"
" " canEscape = true;"
" " break;"
" }"
}
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixFactory(3)
• cppquickfixes.cppに定義を追加
10
// プライオリティの決定"
const int priority = path.size() - 1;"
"
// Operationの作成と登録"
if (canEscape) {"
" QuickFixOperation::Ptr op("
" " new EscapeStringLiteralOperation(interface, priority, literal));"
" result.append(op);"
}
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixOperation(1)
• cppquickfixes.cppに宣言を追加
11
class EscapeStringLiteralOperation : public CppQuickFixOperation"
{"
public:"
" EscapeStringLiteralOperation(const CppQuickFixInterface &interface,"
" " " int priority, ExpressionAST *literal);"
" void perform(); // virtual"
private:"
" ExpressionAST *m_literal;"
}; " " "
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixOperation(2)
• cppquickfixes.cppに定義を追加
12
EscapeStringLiteralOperation::EscapeStringLiteralOperation("
" " " const CppQuickFixInterface &interface,"
" " " int priority, ExpressionAST *literal) :"
" CppQuickFixOperation(interface, priority),"
" m_literal(literal)"
{"
" // コンテキストメニューの文字列"
" setDescription(QApplication::translate("CppTools::QuickFix", " "
" " " "Escape String Literal"));"
}
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixOperation(3)
• cppquickfixes.cppに定義を追加
13
// リファクタリング実行時の処理"
void EscapeStringLiteralOperation::perform()"
{"
" // 対象ファイルや位置の取得"
" CppRefactoringChanges refactoring(snapshot());"
" CppRefactoringFilePtr currentFile = refactoring.file(fileName());" "
" const int startPos = currentFile->startOf(m_literal);"
" const int endPos = currentFile->endOf(m_literal);"
"
" // 文字列リテラルの取得"
" StringLiteralAST *stringLiteral = m_literal->asStringLiteral();"
" QTC_ASSERT(stringLiteral, return ;);"
" const QByteArray oldContents(currentFile->"
" " tokenAt(stringLiteral->literal_token).identifier->chars());
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixOperation(4)
• cppquickfixes.cppに定義を追加
14
" // エスケープ処理"
" QByteArray newContents;"
" for (int i = 0; i < oldContents.length(); ++i) {"
" " quint8 c = oldContents.at(i);"
" " if (isascii(c) && isprint(c))"
" " " newContents += c;"
" " else {"
" " " newContents += QByteArray("x");"
" " " QByteArray buf;"
" " " buf.setNum(c, 16);"
" " " newContents += buf;"
" " }"
" }
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppQuickFixOperation(5)
• cppquickfixes.cppに定義を追加
15
" // エスケープの変更を反映"
" if (oldContents != newContents) {"
" " ChangeSet changes;"
" " changes.replace(startPos + 1, endPos - 1,"
" " " " QString::fromUtf8(newContents));"
" " currentFile->setChangeSet(changes);"
" " currentFile->apply();"
" }"
}
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
CppEditor::Internal::registerQuickFixes()
• EscapeStringLiteralを登録
16
void CppEditor::Internal::registerQuickFixes(ExtensionSystem::IPlugin *plugin)"
{"
" :"
" :"
"
" plugIn->addAutoReleasedObject(new EscapeStringLiteral);"
}
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
プラグイン化
• Qt Creator自体を変更せずに機能を拡張"
– Qt Creator プラグインプロジェクト"
• Qt Creatorの「ライブラリ」プロジェクト内"
– Doc: Creating Plugins"
• http://doc.qt.digia.com/qtcreator-extending/creating-
plugins.html"
– 依存関係の設定"
– Core::EditorManager"
• http://doc.qt.digia.com/qtcreator-extending/core-
editormanager.html"
• 今回は行わず
17
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
注意点
• ASTからのコード取得: char *"
– UTF-8(ファイルのエンコーディングとは無関係)"
• ChangeSetに設定するのはQString
18
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
まとめ
• Qt Creatorの拡張は難しくない"
– 多数の機能・仕組みが用意済み"
– (十分ではないが)開発者向けドキュメント"
• コードモデル"
– 比較的簡単にコードの構造を活用可能
19
Copyright (c)2014 Software Research Associates, Inc. All Right Reserved
参考文献
• Extending Qt Creator Manual!
– http://doc.qt.digia.com/qtcreator-extending/!
• Extending Qt Creator - Qt Developer Days 2014
Europe!
– http://devdays.kdab.com/wp-content/uploads/2014/11/
tobiashunger-extending-qtc.pdf!
• Qt Creator Plugin Development - Qt Developer Days
2014 Europe!
– http://devdays.kdab.com/wp-content/uploads/2014/11/
tobiashunger-qtc-plugins.pdf
20

More Related Content

PDF
qmake入門
PDF
QtとC++でGUIプログラミング
PDF
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
PDF
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
PPTX
UniRxことはじめ
PDF
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
PDF
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
PDF
NextGen Server/Client Architecture - gRPC + Unity + C#
qmake入門
QtとC++でGUIプログラミング
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
UniRxことはじめ
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
NextGen Server/Client Architecture - gRPC + Unity + C#

What's hot (20)

PDF
How to Make Own Framework built on OWIN
PPTX
Javaで簡単にgpgpu aparapi
PPTX
RuntimeUnitTestToolkit for Unity
PDF
Qt5 の新機能 2012/12/15
PDF
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
PDF
UniRx - Reactive Extensions for Unity
PDF
Unityで覚えるC#
KEY
PyOpenCLによるGPGPU入門
PDF
Reactive Extensionsで非同期処理を簡単に
PDF
linq.js - Linq to Objects for JavaScript
PDF
A Framework for LightUp Applications of Grani
PDF
An Internal of LINQ to Objects
PPTX
async/await のしくみ
PDF
AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践
PDF
Qt5 の Input Method
PDF
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る
PDF
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
PDF
Custom Scan API - PostgreSQL Unconference #3 (18-Jan-2014)
PDF
【Unite Tokyo 2019】Understanding C# Struct All Things
PPTX
Open modeler
How to Make Own Framework built on OWIN
Javaで簡単にgpgpu aparapi
RuntimeUnitTestToolkit for Unity
Qt5 の新機能 2012/12/15
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
UniRx - Reactive Extensions for Unity
Unityで覚えるC#
PyOpenCLによるGPGPU入門
Reactive Extensionsで非同期処理を簡単に
linq.js - Linq to Objects for JavaScript
A Framework for LightUp Applications of Grani
An Internal of LINQ to Objects
async/await のしくみ
AWS + Windows(C#)で構築する.NET最先端技術によるハイパフォーマンスウェブアプリケーション開発実践
Qt5 の Input Method
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
Custom Scan API - PostgreSQL Unconference #3 (18-Jan-2014)
【Unite Tokyo 2019】Understanding C# Struct All Things
Open modeler
Ad

Viewers also liked (7)

PDF
Qt creatorでremote_debug
PPTX
slide for #raytracingcamp3
PDF
QtでC++開発環境構築
PPTX
レイトレ合宿2!! 3分間アピールプレゼン―Pocol
PDF
Color Science for Games(JP)
PDF
(旧版) オープンソースライセンスの基礎と実務
PDF
PyQtではじめるGUIプログラミング
Qt creatorでremote_debug
slide for #raytracingcamp3
QtでC++開発環境構築
レイトレ合宿2!! 3分間アピールプレゼン―Pocol
Color Science for Games(JP)
(旧版) オープンソースライセンスの基礎と実務
PyQtではじめるGUIプログラミング
Ad

Similar to Qt Creator を拡張する (16)

PDF
C++コミュニティーの中心でC++をDISる
PDF
2011.12.10 関数型都市忘年会 発表資料「最近書いた、関数型言語と関連する?C++プログラムの紹介」
PDF
C++11概要 ライブラリ編
PDF
バッチリネーマーの制作
PDF
中3女子でもわかる constexpr
PDF
C++14 Overview
PDF
Boost Tour 1_58_0 merge
PDF
boost tour 1.48.0 all
PDF
Replace Output Iterator and Extend Range JP
PDF
Boost Tour 1.50.0 All
PPTX
Visual C++で使えるC++11
DOCX
Boost勉強会 #10 ディスカッションまとめ
PPTX
C++ tips1 #include編
PDF
Constexpr 中3女子テクニック
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
PPTX
Lambda in template_final
C++コミュニティーの中心でC++をDISる
2011.12.10 関数型都市忘年会 発表資料「最近書いた、関数型言語と関連する?C++プログラムの紹介」
C++11概要 ライブラリ編
バッチリネーマーの制作
中3女子でもわかる constexpr
C++14 Overview
Boost Tour 1_58_0 merge
boost tour 1.48.0 all
Replace Output Iterator and Extend Range JP
Boost Tour 1.50.0 All
Visual C++で使えるC++11
Boost勉強会 #10 ディスカッションまとめ
C++ tips1 #include編
Constexpr 中3女子テクニック
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Lambda in template_final

Qt Creator を拡張する

  • 1. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved 朝木卓見 Qt Creatorを拡張する
 " C++ Editor: リファクタリング機能編
  • 2. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved Qt Creatorのアーキテクチャ • プラグインアーキテクチャ" – 固定機能は最小限" – プラグインの追加で拡張可能 2
  • 3. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved リファクタリング機能 • エディタの文脈を考慮した簡易編集機能" – http://qt-project.org/doc/qtcreator-3.2/creator- editor-refactoring.html" – 使いこなすことでより楽にコーディング可能" – ex." • メソッドの宣言に対する定義の作成" • 選択範囲のコードから関数を作成" • 基底クラスの仮想関数のオーバーライドの作成" • etc. 3
  • 4. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved エディタに機能を追加する • TextEditorのアシスト用クラス" – TextEditor::IAssistProcessor" • http://doc.qt.digia.com/qtcreator-extending/texteditor- iassistprocessor.html" • Acts as an interface that actually computes an assist proposal" • アシストの実行用クラス" – TextEditor::IAssistProvider" • http://doc.qt.digia.com/qtcreator-extending/texteditor- iassistprovider.html" • Acts as an interface for providing code assist" • IAssistProcessor生成用クラス" • 今回はC++特化のため上記を直接扱わない 4
  • 5. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved C++エディタのリファクタリング機能 • cppeditorプラグイン" – src/plugins/cppeditor/" • C++エディタ専用の以下のクラスを利用" – CppQuickFixOperation" • リファクタリングを実行する" – CppQuickFixFactory" • コードモデルからリファクタリング用に CppQuickFixOperationのインスタンスを作成する 5
  • 6. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved 実装する機能 • 文字列リテラルのエスケープ/アンエスケープ" – ex." • “あい” “xe3x81x82xe3x81x84”" " • 詳細は" – https://codereview.qt-project.org/90103" – Qt Creator 3.3 から利用可能" – スライドは一部省略 6
  • 7. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixFactory(1) • cppquickfixes.hに宣言を追加" " " " – interface: コードモデルへのインターフェース" • コードの構造やカーソル位置の情報など" – result: リファクタリング用インスタンスのリスト" • 実行用クラスのインスタンスをここに登録する 7 class EscapeStringLiteral : public CppQuickFixFactory" {" public:" void match(const CppQuickFixInterface &interface," TextEditor::QuickFixOperations &result); // virtual" }
  • 8. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixFactory(2) • cppquickfixes.cppに定義を追加" " " " " " " – AST: 抽象構文木" • http://ja.wikipedia.org/wiki/%E6%8A%BD %E8%B1%A1%E6%A7%8B%E6%96%87%E6%9C%A8 8 void EscapeStringLiteral::match(const CppQuickFixInterface &interface," QuickFixOperations &result)" {" // カーソル位置のASTの取得" const QList<AST *> &path = interface->path();" AST * const lastAst = path.last();" " // 文字列リテラルの取得" ExpressionAST *literal = lastAst->asStringLiteral();" if (!literal)" return;"" "
  • 9. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixFactory(3) • cppquickfixes.cppに定義を追加 9 // 文字列リテラルの取得" StringLiteralAST *stringLiteral = literal->asStringLiteral();" CppRefactoringFilePtr file = interface->currentFile();" const QByteArray" " contents(file->tokenAt(stringLiteral->literal_token).identifier->chars());" " // エスケープ可能かどうか確認" bool canEscape = false;" for (int i = 0; i < contents.length(); ++i) {" " quint8 c = contents.at(i);" " if (!isascii(c) || !isprint(c)) {" " " canEscape = true;" " " break;" " }" }
  • 10. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixFactory(3) • cppquickfixes.cppに定義を追加 10 // プライオリティの決定" const int priority = path.size() - 1;" " // Operationの作成と登録" if (canEscape) {" " QuickFixOperation::Ptr op(" " " new EscapeStringLiteralOperation(interface, priority, literal));" " result.append(op);" }
  • 11. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixOperation(1) • cppquickfixes.cppに宣言を追加 11 class EscapeStringLiteralOperation : public CppQuickFixOperation" {" public:" " EscapeStringLiteralOperation(const CppQuickFixInterface &interface," " " " int priority, ExpressionAST *literal);" " void perform(); // virtual" private:" " ExpressionAST *m_literal;" }; " " "
  • 12. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixOperation(2) • cppquickfixes.cppに定義を追加 12 EscapeStringLiteralOperation::EscapeStringLiteralOperation(" " " " const CppQuickFixInterface &interface," " " " int priority, ExpressionAST *literal) :" " CppQuickFixOperation(interface, priority)," " m_literal(literal)" {" " // コンテキストメニューの文字列" " setDescription(QApplication::translate("CppTools::QuickFix", " " " " " "Escape String Literal"));" }
  • 13. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixOperation(3) • cppquickfixes.cppに定義を追加 13 // リファクタリング実行時の処理" void EscapeStringLiteralOperation::perform()" {" " // 対象ファイルや位置の取得" " CppRefactoringChanges refactoring(snapshot());" " CppRefactoringFilePtr currentFile = refactoring.file(fileName());" " " const int startPos = currentFile->startOf(m_literal);" " const int endPos = currentFile->endOf(m_literal);" " " // 文字列リテラルの取得" " StringLiteralAST *stringLiteral = m_literal->asStringLiteral();" " QTC_ASSERT(stringLiteral, return ;);" " const QByteArray oldContents(currentFile->" " " tokenAt(stringLiteral->literal_token).identifier->chars());
  • 14. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixOperation(4) • cppquickfixes.cppに定義を追加 14 " // エスケープ処理" " QByteArray newContents;" " for (int i = 0; i < oldContents.length(); ++i) {" " " quint8 c = oldContents.at(i);" " " if (isascii(c) && isprint(c))" " " " newContents += c;" " " else {" " " " newContents += QByteArray("x");" " " " QByteArray buf;" " " " buf.setNum(c, 16);" " " " newContents += buf;" " " }" " }
  • 15. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppQuickFixOperation(5) • cppquickfixes.cppに定義を追加 15 " // エスケープの変更を反映" " if (oldContents != newContents) {" " " ChangeSet changes;" " " changes.replace(startPos + 1, endPos - 1," " " " " QString::fromUtf8(newContents));" " " currentFile->setChangeSet(changes);" " " currentFile->apply();" " }" }
  • 16. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved CppEditor::Internal::registerQuickFixes() • EscapeStringLiteralを登録 16 void CppEditor::Internal::registerQuickFixes(ExtensionSystem::IPlugin *plugin)" {" " :" " :" " " plugIn->addAutoReleasedObject(new EscapeStringLiteral);" }
  • 17. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved プラグイン化 • Qt Creator自体を変更せずに機能を拡張" – Qt Creator プラグインプロジェクト" • Qt Creatorの「ライブラリ」プロジェクト内" – Doc: Creating Plugins" • http://doc.qt.digia.com/qtcreator-extending/creating- plugins.html" – 依存関係の設定" – Core::EditorManager" • http://doc.qt.digia.com/qtcreator-extending/core- editormanager.html" • 今回は行わず 17
  • 18. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved 注意点 • ASTからのコード取得: char *" – UTF-8(ファイルのエンコーディングとは無関係)" • ChangeSetに設定するのはQString 18
  • 19. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved まとめ • Qt Creatorの拡張は難しくない" – 多数の機能・仕組みが用意済み" – (十分ではないが)開発者向けドキュメント" • コードモデル" – 比較的簡単にコードの構造を活用可能 19
  • 20. Copyright (c)2014 Software Research Associates, Inc. All Right Reserved 参考文献 • Extending Qt Creator Manual! – http://doc.qt.digia.com/qtcreator-extending/! • Extending Qt Creator - Qt Developer Days 2014 Europe! – http://devdays.kdab.com/wp-content/uploads/2014/11/ tobiashunger-extending-qtc.pdf! • Qt Creator Plugin Development - Qt Developer Days 2014 Europe! – http://devdays.kdab.com/wp-content/uploads/2014/11/ tobiashunger-qtc-plugins.pdf 20