@@ -53,6 +53,14 @@ static cl::list<unsigned>
53
53
" of the file.\n "
54
54
" Can only be used with one input file." ),
55
55
cl::cat(ClangFormatCategory));
56
+ static cl::list<std::string>
57
+ LineRanges (" lines" , cl::desc(" <start line>:<end line> - format a range of\n "
58
+ " lines (both 1-based).\n "
59
+ " Multiple ranges can be formatted by specifying\n "
60
+ " several -lines arguments.\n "
61
+ " Can't be used with -offset and -length.\n "
62
+ " Can only be used with one input file." ),
63
+ cl::cat(ClangFormatCategory));
56
64
static cl::opt<std::string>
57
65
Style (" style" ,
58
66
cl::desc (" Coding style, currently supports:\n "
@@ -150,21 +158,43 @@ FormatStyle getStyle(StringRef StyleName, StringRef FileName) {
150
158
return Style ;
151
159
}
152
160
161
+ // Parses <start line>:<end line> input to a pair of line numbers.
153
162
// Returns true on error.
154
- static bool format (std::string FileName) {
155
- FileManager Files ((FileSystemOptions ()));
156
- DiagnosticsEngine Diagnostics (
157
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
158
- new DiagnosticOptions);
159
- SourceManager Sources (Diagnostics, Files);
160
- OwningPtr<MemoryBuffer> Code;
161
- if (error_code ec = MemoryBuffer::getFileOrSTDIN (FileName, Code)) {
162
- llvm::errs () << ec.message () << " \n " ;
163
- return true ;
163
+ static bool parseLineRange (StringRef Input, unsigned &FromLine,
164
+ unsigned &ToLine) {
165
+ std::pair<StringRef, StringRef> LineRange = Input.split (' :' );
166
+ return LineRange.first .getAsInteger (0 , FromLine) ||
167
+ LineRange.second .getAsInteger (0 , ToLine);
168
+ }
169
+
170
+ static bool fillRanges (SourceManager &Sources, FileID ID,
171
+ const MemoryBuffer *Code,
172
+ std::vector<CharSourceRange> &Ranges) {
173
+ if (!LineRanges.empty ()) {
174
+ if (!Offsets.empty () || !Lengths.empty ()) {
175
+ llvm::errs () << " error: cannot use -lines with -offset/-length\n " ;
176
+ return true ;
177
+ }
178
+
179
+ for (unsigned i = 0 , e = LineRanges.size (); i < e; ++i) {
180
+ unsigned FromLine, ToLine;
181
+ if (parseLineRange (LineRanges[i], FromLine, ToLine)) {
182
+ llvm::errs () << " error: invalid <start line>:<end line> pair\n " ;
183
+ return true ;
184
+ }
185
+ if (FromLine > ToLine) {
186
+ llvm::errs () << " error: start line should be less than end line\n " ;
187
+ return true ;
188
+ }
189
+ SourceLocation Start = Sources.translateLineCol (ID, FromLine, 1 );
190
+ SourceLocation End = Sources.translateLineCol (ID, ToLine, UINT_MAX);
191
+ if (Start.isInvalid () || End.isInvalid ())
192
+ return true ;
193
+ Ranges.push_back (CharSourceRange::getCharRange (Start, End));
194
+ }
195
+ return false ;
164
196
}
165
- if (Code->getBufferSize () == 0 )
166
- return true ; // Empty files are formatted correctly.
167
- FileID ID = createInMemoryFile (FileName, Code.get (), Sources, Files);
197
+
168
198
if (Offsets.empty ())
169
199
Offsets.push_back (0 );
170
200
if (Offsets.size () != Lengths.size () &&
@@ -173,7 +203,6 @@ static bool format(std::string FileName) {
173
203
<< " error: number of -offset and -length arguments must match.\n " ;
174
204
return true ;
175
205
}
176
- std::vector<CharSourceRange> Ranges;
177
206
for (unsigned i = 0 , e = Offsets.size (); i != e; ++i) {
178
207
if (Offsets[i] >= Code->getBufferSize ()) {
179
208
llvm::errs () << " error: offset " << Offsets[i]
@@ -196,6 +225,28 @@ static bool format(std::string FileName) {
196
225
}
197
226
Ranges.push_back (CharSourceRange::getCharRange (Start, End));
198
227
}
228
+ return false ;
229
+ }
230
+
231
+ // Returns true on error.
232
+ static bool format (std::string FileName) {
233
+ FileManager Files ((FileSystemOptions ()));
234
+ DiagnosticsEngine Diagnostics (
235
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
236
+ new DiagnosticOptions);
237
+ SourceManager Sources (Diagnostics, Files);
238
+ OwningPtr<MemoryBuffer> Code;
239
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN (FileName, Code)) {
240
+ llvm::errs () << ec.message () << " \n " ;
241
+ return true ;
242
+ }
243
+ if (Code->getBufferSize () == 0 )
244
+ return true ; // Empty files are formatted correctly.
245
+ FileID ID = createInMemoryFile (FileName, Code.get (), Sources, Files);
246
+ std::vector<CharSourceRange> Ranges;
247
+ if (fillRanges (Sources, ID, Code.get (), Ranges))
248
+ return true ;
249
+
199
250
FormatStyle FormatStyle = getStyle (Style , FileName);
200
251
Lexer Lex (ID, Sources.getBuffer (ID), Sources,
201
252
getFormattingLangOpts (FormatStyle.Standard ));
@@ -282,8 +333,8 @@ int main(int argc, const char **argv) {
282
333
Error = clang::format::format (FileNames[0 ]);
283
334
break ;
284
335
default :
285
- if (!Offsets.empty () || !Lengths.empty ()) {
286
- llvm::errs () << " error: \" -offset\" and \" -length \" can only be used for "
336
+ if (!Offsets.empty () || !Lengths.empty () || !LineRanges. empty () ) {
337
+ llvm::errs () << " error: -offset, -length and -lines can only be used for "
287
338
" single file.\n " ;
288
339
return 1 ;
289
340
}
0 commit comments