web-dev-qa-db-ja.com

libclangに基づくC / C ++リファクタリングツール(最も単純な「おもちゃの例」でも)

私が指摘したように- ここ -Clangのlibclangは、C/C++コードの分析と変更であるハードタスクの実装に最適であるようです( ビデオプレゼンテーションとスライドをチェックしてください =)。

Libclangに基づくany C/C++リファクタリングツールを知っていますか?

「すべて」には、1つのリファクタリング手法をサポートする、単純なアルファ状態プロジェクトさえ含まれます。プリプロセッサのサポートがなくてもかまいません。私が話している機能的な例として、メソッド名の変更、それが複数のファイルをサポートするか、一度に1つのファイルのみをサポートするか。あなたは小さな実用的な例でも尋ねることの目的が何であるか疑問に思うかもしれません私の考えは、1つの場所にあるコード例と小さなツールのリストを作成すると、実装方法を学ぶためのより良いリソースを提供することですlibclangによるリファクタリング。単純なプロジェクトからは、適切なオープンソースの方法で、より大きなプロジェクトが成長する可能性があると私は信じています:)。

47

Clangには、IDEでコード補完を行うために開発された「CIndex」と呼ばれるライブラリが含まれています。 C++の解析とASTのウォークにも使用できますが、リファクタリングの方法には何もありません。 Eli Benderskyの記事 here を参照してください。

私は最近そのようなプロジェクトを始めました: cmonster 。これはPythonベースのAPIで、C++を解析し(libclangを使用)、ASTを分析し、「書き換え」(つまり、ソース範囲を挿入/削除/変更)するためのインターフェースを備えています。関数名を変更したり、それをソース変更に変換したりするための(まだ)良い方法はありませんが、それを行うことはそれほど難しくありません。

Llvm/clang 3.0がリリースされるのを待っているので、この機能を備えたリリースはまだ作成していません(githubリポジトリにあります)。

また、いくつかのことを指摘しておきます。

  • コードは非常にラフで、アルファと呼ぶのはおそらく寛大でしょう。
  • 私は決してこのテーマの専門家ではありません(たとえば、そこにいるアイラバクスター博士とは異なります)。

期待を適切に調整します。

更新:cmonster 0.2がリリースされました。これには、説明されている機能が含まれています。確認してください Githubで

23
axw

GoogleはClangのツールライブラリに取り組んでいます。 .2リリース以降 。 ASTMatchersライブラリが含まれているため、クエリを作成するだけで、ASTを歩く必要はありません。

簡単な名前変更の例を紹介する件名に 素晴らしいビデオトーク があります。 (これは上記の MapReduceトーク と同じ人からのものですが、内部設計やGoogleが行っているエンタープライズ規模のものではなく、単純で実用的な実装についてより新しいものです)。

メソッドの名前を変更するその例のソースは tooling branch にあります。トランクのどこかにあるかもしれませんが見つかりません。また、getDeclAs関数の名前をgetNodesAsに変更します。他の関数は 明らかに非推奨 です。)。さらに 重複したc_str呼び出しを削除する高度な例 (これはトランク内にあり、上記の誰かが投稿しています)です。

LibASTMatchers および LibTooling のドキュメントを以下に示します。

編集:ASTMatcherのいくつかのより良いドキュメント。 ここ および ここ

編集: Googleは現在、Clangdと呼ばれるものに取り組んでいます これは、リファクタリングのためのある種のClangサーバーになることを目的としています。

15
David C. Bishop

GoogleはC++コードベース用にClangベースのリファクタリングツールを作成し、それをリリースする予定です。プロジェクトの現在の状態はわかりませんが、2011年のLLVM開発者ミーティング https://www.youtube.com/watch?v=mVbDzTM21BQ でこのデモをご覧いただけます。

また、XCodeの(4+)組み込みのオートコンプリートおよびリファクタリング関数はlibclangに基づいています。

8
Reuben Morais

これは少し「メタ」かもしれませんが、clangで実行するツールとしてclangで記述された例があります(ただし、それだけではありません。

RemoveCStrCalls.cpp

//  This file implements a tool that prints replacements that remove redundant
//  calls of c_str() on strings.
//
//  Usage:
//  remove-cstr-calls <cmake-output-dir> <file1> <file2> ...
//
//  Where <cmake-output-dir> is a CMake build directory in which a file named
//  compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
//  CMake to get this output).
//
//  <file1> ... specify the paths of files in the CMake source tree. This path
//  is looked up in the compile command database. If the path of a file is
//  absolute, it needs to point into CMake's source tree. If the path is
//  relative, the current working directory needs to be in the CMake source
//  tree and the file must be in a subdirectory of the current working
//  directory. "./" prefixes in the relative files will be automatically
//  removed, but the rest of a relative path must be a suffix of a path in
//  the compile command line database.
//
//  For example, to use remove-cstr-calls on all files in a subtree of the
//  source tree, use:
//
//    /path/in/subtree $ find . -name '*.cpp'|
//        xargs remove-cstr-calls /path/to/source
6

オープンソースではありませんが、非常におもちゃではない C++プログラムの大規模な自動リファクタリング を実行するために使用されています DMSソフトウェアリエンジニアリングツールキット 。 DMSは、解析や自動翻訳を実現するために構成できる機能の「ライブラリ」(「ツールキット」と呼びます)です。

C++に関連して、DMSは現時点で以下を提供します。

  • 完全なC++ 11パーサー、ASTを構築し、完全なプリプロセッサーを使用して、コメントを含むソースコードを正確に再生成できます
  • C++の名前と型の解決を伴う完全なC++パーサー(ANSI、GNU、MS Visual C++)
  • C++の制御フロー分析
  • ソースからソースへの変換
  • 部分的に完全な「名前変更」機構(以下の説明を参照)

経験から言えることは、C++は変換する言語の雌犬だということです。

私たちは引き続き取り組み、信頼できる名前変更ツールを完成させています。これでも難しいです。重要な問題は、名前のシャドウイングの問題です。ローカル変数Xと、そのスコープ内のYへの参照があります。 Yの名前をXに変更して、ローカル変数がアクセスを「キャプチャ」していることを発見したとします。 C++で心配する必要がある名前空間とキャプチャタイプの数は驚くべきものです。そして、これは他の多くのリファクタリングの基盤として必要です。

EDIT 2014年2月:完​​全なC++ 14パーサー、制御フロー分析、ローカルデータフロー分析

5
Ira Baxter

https://github.com/lukhnos/refactorial はclangとクレームに基づいています

提供される変換

アクセサー:指定されたメンバー変数のゲッターとセッターの合成

MethodMove:インライン化されたメンバー関数の本体を実装ファイルに移動する

ExtractParameter:関数変数をその関数のパラメーターに昇格します

TypeRename:タグ名(列挙型、構造体、共用体、クラス)、テンプレートクラス、Objective-C型(クラスとプロトコル)、typedef、さらにはブリットイン型(例:unint32_tへの未署名)を含む、名前の変更

RecordFieldRename:C++メンバー変数を含む、レコード(構造体、共用体)フィールドの名前を変更します

FunctionRename:C++メンバー関数を含む関数の名前変更

YAML構成ファイルの仕様を介して機能します。まだ試していません。

5
mabraham

もう1つの可能性は、GCC用の独自のプラグインを開発すること、または GCC MELT 拡張を開発してタスクを実行することです。ただし、GCC(またはClang)を拡張するには、これらのコンパイラーの内部表現(GCCのGimple&Tree)を理解する必要があり、これにはいくつかの作業が必要です。 MELTは、GCCを拡張するための高レベルのドメイン固有言語です。

これはリファクタリングではなく完了ですが、役に立つかもしれません: