summaryrefslogtreecommitdiffstats
path: root/tools/clang-format
diff options
context:
space:
mode:
Diffstat (limited to 'tools/clang-format')
-rw-r--r--tools/clang-format/CMakeLists.txt6
-rw-r--r--tools/clang-format/ClangFormat.cpp65
-rw-r--r--tools/clang-format/Makefile2
-rwxr-xr-xtools/clang-format/clang-format-diff.py32
-rw-r--r--tools/clang-format/clang-format.py83
-rwxr-xr-xtools/clang-format/git-clang-format3
6 files changed, 122 insertions, 69 deletions
diff --git a/tools/clang-format/CMakeLists.txt b/tools/clang-format/CMakeLists.txt
index 7bb3fbf..f80a3ec 100644
--- a/tools/clang-format/CMakeLists.txt
+++ b/tools/clang-format/CMakeLists.txt
@@ -1,15 +1,15 @@
set(LLVM_LINK_COMPONENTS support)
-set(LLVM_USED_LIBS clangFormat clangTooling clangBasic clangAST)
add_clang_executable(clang-format
ClangFormat.cpp
)
target_link_libraries(clang-format
+ clangBasic
clangFormat
+ clangLex
+ clangRewrite
clangTooling
- clangBasic
- clangRewriteFrontend
)
install(TARGETS clang-format RUNTIME DESTINATION bin)
diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp
index 768165b..cebb275 100644
--- a/tools/clang-format/ClangFormat.cpp
+++ b/tools/clang-format/ClangFormat.cpp
@@ -17,13 +17,14 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Version.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"
-#include "llvm/ADT/StringMap.h"
using namespace llvm;
@@ -31,7 +32,7 @@ static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
// Mark all our options with this category, everything else (except for -version
// and -help) will be hidden.
-cl::OptionCategory ClangFormatCategory("Clang-format options");
+static cl::OptionCategory ClangFormatCategory("Clang-format options");
static cl::list<unsigned>
Offsets("offset",
@@ -62,6 +63,14 @@ static cl::opt<std::string>
Style("style",
cl::desc(clang::format::StyleOptionHelpDescription),
cl::init("file"), cl::cat(ClangFormatCategory));
+static cl::opt<std::string>
+FallbackStyle("fallback-style",
+ cl::desc("The name of the predefined style used as a\n"
+ "fallback in case clang-format is invoked with\n"
+ "-style=file, but can not find the .clang-format\n"
+ "file to use.\n"
+ "Use -fallback-style=none to skip formatting."),
+ cl::init("LLVM"), cl::cat(ClangFormatCategory));
static cl::opt<std::string>
AssumeFilename("assume-filename",
@@ -94,7 +103,7 @@ static cl::list<std::string> FileNames(cl::Positional, cl::desc("[<file> ...]"),
namespace clang {
namespace format {
-static FileID createInMemoryFile(StringRef FileName, const MemoryBuffer *Source,
+static FileID createInMemoryFile(StringRef FileName, MemoryBuffer *Source,
SourceManager &Sources, FileManager &Files) {
const FileEntry *Entry = Files.getVirtualFile(FileName == "-" ? "<stdin>" :
FileName,
@@ -173,6 +182,26 @@ static bool fillRanges(SourceManager &Sources, FileID ID,
return false;
}
+static void outputReplacementXML(StringRef Text) {
+ size_t From = 0;
+ size_t Index;
+ while ((Index = Text.find_first_of("\n\r", From)) != StringRef::npos) {
+ llvm::outs() << Text.substr(From, Index - From);
+ switch (Text[Index]) {
+ case '\n':
+ llvm::outs() << "&#10;";
+ break;
+ case '\r':
+ llvm::outs() << "&#13;";
+ break;
+ default:
+ llvm_unreachable("Unexpected character encountered!");
+ }
+ From = Index + 1;
+ }
+ llvm::outs() << Text.substr(From);
+}
+
// Returns true on error.
static bool format(StringRef FileName) {
FileManager Files((FileSystemOptions()));
@@ -180,11 +209,13 @@ static bool format(StringRef FileName) {
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
new DiagnosticOptions);
SourceManager Sources(Diagnostics, Files);
- OwningPtr<MemoryBuffer> Code;
- if (error_code ec = MemoryBuffer::getFileOrSTDIN(FileName, Code)) {
- llvm::errs() << ec.message() << "\n";
+ ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
+ MemoryBuffer::getFileOrSTDIN(FileName);
+ if (std::error_code EC = CodeOrErr.getError()) {
+ llvm::errs() << EC.message() << "\n";
return true;
}
+ std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get());
if (Code->getBufferSize() == 0)
return false; // Empty files are formatted correctly.
FileID ID = createInMemoryFile(FileName, Code.get(), Sources, Files);
@@ -192,8 +223,8 @@ static bool format(StringRef FileName) {
if (fillRanges(Sources, ID, Code.get(), Ranges))
return true;
- FormatStyle FormatStyle =
- getStyle(Style, (FileName == "-") ? AssumeFilename : FileName);
+ FormatStyle FormatStyle = getStyle(
+ Style, (FileName == "-") ? AssumeFilename : FileName, FallbackStyle);
Lexer Lex(ID, Sources.getBuffer(ID), Sources,
getFormattingLangOpts(FormatStyle.Standard));
tooling::Replacements Replaces = reformat(FormatStyle, Lex, Sources, Ranges);
@@ -205,8 +236,9 @@ static bool format(StringRef FileName) {
I != E; ++I) {
llvm::outs() << "<replacement "
<< "offset='" << I->getOffset() << "' "
- << "length='" << I->getLength() << "'>"
- << I->getReplacementText() << "</replacement>\n";
+ << "length='" << I->getLength() << "'>";
+ outputReplacementXML(I->getReplacementText());
+ llvm::outs() << "</replacement>\n";
}
llvm::outs() << "</replacements>\n";
} else {
@@ -217,8 +249,8 @@ static bool format(StringRef FileName) {
return true;
} else {
if (Cursor.getNumOccurrences() != 0)
- outs() << "{ \"Cursor\": " << tooling::shiftedCodePosition(
- Replaces, Cursor) << " }\n";
+ outs() << "{ \"Cursor\": "
+ << tooling::shiftedCodePosition(Replaces, Cursor) << " }\n";
Rewrite.getEditBuffer(ID).write(outs());
}
}
@@ -228,6 +260,11 @@ static bool format(StringRef FileName) {
} // namespace format
} // namespace clang
+static void PrintVersion() {
+ raw_ostream &OS = outs();
+ OS << clang::getClangToolFullVersion("clang-format") << '\n';
+}
+
int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal();
@@ -241,6 +278,7 @@ int main(int argc, const char **argv) {
I->second->setHiddenFlag(cl::ReallyHidden);
}
+ cl::SetVersionPrinter(PrintVersion);
cl::ParseCommandLineOptions(
argc, argv,
"A tool to format C/C++/Obj-C code.\n\n"
@@ -256,7 +294,8 @@ int main(int argc, const char **argv) {
if (DumpConfig) {
std::string Config =
clang::format::configurationAsText(clang::format::getStyle(
- Style, FileNames.empty() ? AssumeFilename : FileNames[0]));
+ Style, FileNames.empty() ? AssumeFilename : FileNames[0],
+ FallbackStyle));
llvm::outs() << Config << "\n";
return 0;
}
diff --git a/tools/clang-format/Makefile b/tools/clang-format/Makefile
index 4902244..a26ef59 100644
--- a/tools/clang-format/Makefile
+++ b/tools/clang-format/Makefile
@@ -18,7 +18,7 @@ include $(CLANG_LEVEL)/../../Makefile.config
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
USEDLIBS = clangFormat.a clangTooling.a clangFrontend.a clangSerialization.a \
clangDriver.a clangParse.a clangSema.a clangAnalysis.a \
- clangRewriteFrontend.a clangRewriteCore.a clangEdit.a clangAST.a \
+ clangRewriteFrontend.a clangRewrite.a clangEdit.a clangAST.a \
clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
diff --git a/tools/clang-format/clang-format-diff.py b/tools/clang-format/clang-format-diff.py
index 60b8fb7..d6d0d44 100755
--- a/tools/clang-format/clang-format-diff.py
+++ b/tools/clang-format/clang-format-diff.py
@@ -15,9 +15,10 @@ ClangFormat Diff Reformatter
This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
-Example usage for git users:
+Example usage for git/svn users:
git diff -U0 HEAD^ | clang-format-diff.py -p1 -i
+ svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
"""
@@ -37,12 +38,20 @@ binary = 'clang-format'
def main():
parser = argparse.ArgumentParser(description=
'Reformat changed lines in diff. Without -i '
- 'option just output the diff that would be'
+ 'option just output the diff that would be '
'introduced.')
parser.add_argument('-i', action='store_true', default=False,
help='apply edits to files instead of displaying a diff')
- parser.add_argument('-p', default=0,
+ parser.add_argument('-p', metavar='NUM', default=0,
help='strip the smallest prefix containing P slashes')
+ parser.add_argument('-regex', metavar='PATTERN', default=None,
+ help='custom pattern selecting file paths to reformat '
+ '(case sensitive, overrides -iregex)')
+ parser.add_argument('-iregex', metavar='PATTERN', default=
+ r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc|js|proto'
+ r'|protodevel)',
+ help='custom pattern selecting file paths to reformat '
+ '(case insensitive, overridden by -regex)')
parser.add_argument(
'-style',
help=
@@ -59,10 +68,12 @@ def main():
if filename == None:
continue
- # FIXME: Add other types containing C++/ObjC code.
- if not (filename.endswith(".cpp") or filename.endswith(".cc") or
- filename.endswith(".h")):
- continue
+ if args.regex is not None:
+ if not re.match('^%s$' % args.regex, filename):
+ continue
+ else:
+ if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
+ continue
match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
if match:
@@ -85,11 +96,8 @@ def main():
if args.style:
command.extend(['-style', args.style])
p = subprocess.Popen(command, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- stdin=subprocess.PIPE)
+ stderr=None, stdin=subprocess.PIPE)
stdout, stderr = p.communicate()
- if stderr:
- print stderr
if p.returncode != 0:
sys.exit(p.returncode);
@@ -102,7 +110,7 @@ def main():
'(before formatting)', '(after formatting)')
diff_string = string.join(diff, '')
if len(diff_string) > 0:
- print diff_string
+ sys.stdout.write(diff_string)
if __name__ == '__main__':
main()
diff --git a/tools/clang-format/clang-format.py b/tools/clang-format/clang-format.py
index f5a5756..16a1879 100644
--- a/tools/clang-format/clang-format.py
+++ b/tools/clang-format/clang-format.py
@@ -32,48 +32,51 @@ binary = 'clang-format'
# used.
style = 'file'
-# Get the current text.
-buf = vim.current.buffer
-text = '\n'.join(buf)
+def main():
+ # Get the current text.
+ buf = vim.current.buffer
+ text = '\n'.join(buf)
-# Determine range to format.
-cursor = int(vim.eval('line2byte(line("."))+col(".")')) - 2
-lines = '%s:%s' % (vim.current.range.start + 1, vim.current.range.end + 1)
+ # Determine range to format.
+ lines = '%s:%s' % (vim.current.range.start + 1, vim.current.range.end + 1)
-# Avoid flashing an ugly, ugly cmd prompt on Windows when invoking clang-format.
-startupinfo = None
-if sys.platform.startswith('win32'):
- startupinfo = subprocess.STARTUPINFO()
- startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
- startupinfo.wShowWindow = subprocess.SW_HIDE
+ # Determine the cursor position.
+ cursor = int(vim.eval('line2byte(line("."))+col(".")')) - 2
+ if cursor < 0:
+ print 'Couldn\'t determine cursor position. Is your file empty?'
+ return
-# Call formatter.
-command = [binary, '-lines', lines, '-style', style, '-cursor', str(cursor)]
-if vim.current.buffer.name:
- command.extend(['-assume-filename', vim.current.buffer.name])
-p = subprocess.Popen(command,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- stdin=subprocess.PIPE, startupinfo=startupinfo)
-stdout, stderr = p.communicate(input=text)
+ # Avoid flashing an ugly, ugly cmd prompt on Windows when invoking clang-format.
+ startupinfo = None
+ if sys.platform.startswith('win32'):
+ startupinfo = subprocess.STARTUPINFO()
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ startupinfo.wShowWindow = subprocess.SW_HIDE
-# If successful, replace buffer contents.
-if stderr:
- message = stderr.splitlines()[0]
- parts = message.split(' ', 2)
- if len(parts) > 2:
- message = parts[2]
- print 'Formatting failed: %s (total %d warnings, %d errors)' % (
- message, stderr.count('warning:'), stderr.count('error:'))
+ # Call formatter.
+ command = [binary, '-lines', lines, '-style', style, '-cursor', str(cursor)]
+ if vim.current.buffer.name:
+ command.extend(['-assume-filename', vim.current.buffer.name])
+ p = subprocess.Popen(command,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ stdin=subprocess.PIPE, startupinfo=startupinfo)
+ stdout, stderr = p.communicate(input=text)
-if not stdout:
- print ('No output from clang-format (crashed?).\n' +
- 'Please report to bugs.llvm.org.')
-else:
- lines = stdout.split('\n')
- output = json.loads(lines[0])
- lines = lines[1:]
- sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
- for op in reversed(sequence.get_opcodes()):
- if op[0] is not 'equal':
- vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
- vim.command('goto %d' % (output['Cursor'] + 1))
+ # If successful, replace buffer contents.
+ if stderr:
+ print stderr
+
+ if not stdout:
+ print ('No output from clang-format (crashed?).\n' +
+ 'Please report to bugs.llvm.org.')
+ else:
+ lines = stdout.split('\n')
+ output = json.loads(lines[0])
+ lines = lines[1:]
+ sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
+ for op in reversed(sequence.get_opcodes()):
+ if op[0] is not 'equal':
+ vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
+ vim.command('goto %d' % (output['Cursor'] + 1))
+
+main()
diff --git a/tools/clang-format/git-clang-format b/tools/clang-format/git-clang-format
index b0737ed..c40b74d 100755
--- a/tools/clang-format/git-clang-format
+++ b/tools/clang-format/git-clang-format
@@ -75,6 +75,9 @@ def main():
'm', # ObjC
'mm', # ObjC++
'cc', 'cp', 'cpp', 'c++', 'cxx', 'hpp', # C++
+ # Other languages that clang-format supports
+ 'proto', 'protodevel', # Protocol Buffers
+ 'js', # JavaScript
])
p = argparse.ArgumentParser(
OpenPOWER on IntegriCloud