// Returns true on error. static bool format(StringRef FileName) { ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr = MemoryBuffer::getFileOrSTDIN(FileName); if (std::error_code EC = CodeOrErr.getError()) { 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. std::vector<tooling::Range> Ranges; if (fillRanges(Code.get(), Ranges)) return true; StringRef AssumedFileName = (FileName == "-") ? AssumeFileName : FileName; FormatStyle FormatStyle = getStyle(Style, AssumedFileName, FallbackStyle); if (SortIncludes.getNumOccurrences() != 0) FormatStyle.SortIncludes = SortIncludes; unsigned CursorPosition = Cursor; Replacements Replaces = sortIncludes(FormatStyle, Code->getBuffer(), Ranges, AssumedFileName, &CursorPosition); auto ChangedCode = tooling::applyAllReplacements(Code->getBuffer(), Replaces); if (!ChangedCode) { llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n"; return true; } for (const auto &R : Replaces) Ranges.push_back({R.getOffset(), R.getLength()}); bool IncompleteFormat = false; Replacements FormatChanges = reformat(FormatStyle, *ChangedCode, Ranges, AssumedFileName, &IncompleteFormat); Replaces = tooling::mergeReplacements(Replaces, FormatChanges); if (OutputXML) { outs() << "<?xml version='1.0'?>\n<replacements " "xml:space='preserve' incomplete_format='" << (IncompleteFormat ? "true" : "false") << "'>\n"; if (Cursor.getNumOccurrences() != 0) outs() << "<cursor>" << tooling::shiftedCodePosition(FormatChanges, CursorPosition) << "</cursor>\n"; outputReplacementsXML(Replaces); outs() << "</replacements>\n"; } else { IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem( new vfs::InMemoryFileSystem); FileManager Files(FileSystemOptions(), InMemoryFileSystem); DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), new DiagnosticOptions); SourceManager Sources(Diagnostics, Files); FileID ID = createInMemoryFile(AssumedFileName, Code.get(), Sources, Files, InMemoryFileSystem.get()); Rewriter Rewrite(Sources, LangOptions()); tooling::applyAllReplacements(Replaces, Rewrite); if (Inplace) { if (FileName == "-") errs() << "error: cannot use -i when reading from stdin.\n"; else if (Rewrite.overwriteChangedFiles()) return true; } else { if (Cursor.getNumOccurrences() != 0) outs() << "{ \"Cursor\": " << tooling::shiftedCodePosition(FormatChanges, CursorPosition) << ", \"IncompleteFormat\": " << (IncompleteFormat ? "true" : "false") << " }\n"; Rewrite.getEditBuffer(ID).write(outs()); } } return false; }
// Returns true on error. static bool format(StringRef FileName) { if (!OutputXML && Inplace && FileName == "-") { errs() << "error: cannot use -i when reading from stdin.\n"; return false; } // On Windows, overwriting a file with an open file mapping doesn't work, // so read the whole file into memory when formatting in-place. ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr = !OutputXML && Inplace ? MemoryBuffer::getFileAsStream(FileName) : MemoryBuffer::getFileOrSTDIN(FileName); if (std::error_code EC = CodeOrErr.getError()) { 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. std::vector<tooling::Range> Ranges; if (fillRanges(Code.get(), Ranges)) return true; StringRef AssumedFileName = (FileName == "-") ? AssumeFileName : FileName; llvm::Expected<FormatStyle> FormatStyle = getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer()); if (!FormatStyle) { llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n"; return true; } if (SortIncludes.getNumOccurrences() != 0) FormatStyle->SortIncludes = SortIncludes; unsigned CursorPosition = Cursor; Replacements Replaces = sortIncludes(*FormatStyle, Code->getBuffer(), Ranges, AssumedFileName, &CursorPosition); auto ChangedCode = tooling::applyAllReplacements(Code->getBuffer(), Replaces); if (!ChangedCode) { llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n"; return true; } // Get new affected ranges after sorting `#includes`. Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); FormattingAttemptStatus Status; Replacements FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status); Replaces = Replaces.merge(FormatChanges); if (OutputXML) { outs() << "<?xml version='1.0'?>\n<replacements " "xml:space='preserve' incomplete_format='" << (Status.FormatComplete ? "false" : "true") << "'"; if (!Status.FormatComplete) outs() << " line='" << Status.Line << "'"; outs() << ">\n"; if (Cursor.getNumOccurrences() != 0) outs() << "<cursor>" << FormatChanges.getShiftedCodePosition(CursorPosition) << "</cursor>\n"; outputReplacementsXML(Replaces); outs() << "</replacements>\n"; } else { IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem( new vfs::InMemoryFileSystem); FileManager Files(FileSystemOptions(), InMemoryFileSystem); DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), new DiagnosticOptions); SourceManager Sources(Diagnostics, Files); FileID ID = createInMemoryFile(AssumedFileName, Code.get(), Sources, Files, InMemoryFileSystem.get()); Rewriter Rewrite(Sources, LangOptions()); tooling::applyAllReplacements(Replaces, Rewrite); if (Inplace) { if (Rewrite.overwriteChangedFiles()) return true; } else { if (Cursor.getNumOccurrences() != 0) { outs() << "{ \"Cursor\": " << FormatChanges.getShiftedCodePosition(CursorPosition) << ", \"IncompleteFormat\": " << (Status.FormatComplete ? "false" : "true"); if (!Status.FormatComplete) outs() << ", \"Line\": " << Status.Line; outs() << " }\n"; } Rewrite.getEditBuffer(ID).write(outs()); } } return false; }