Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / compilerplugins / clang / includeform.cxx
blobda955c20d3bb0375b57f9cdf564ff637b55d25c7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <memory>
12 #include "config_clang.h"
14 #include "plugin.hxx"
16 // Enforces the "Rules for #include directives (C/C++)" described in README.md.
18 namespace {
20 class IncludeForm final: public PPCallbacks, public loplugin::RewritePlugin {
21 public:
22 explicit IncludeForm(loplugin::InstantiationData const & data):
23 RewritePlugin(data)
24 { compiler.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(this)); }
26 private:
27 void run() override {}
29 void InclusionDirective(
30 SourceLocation HashLoc, Token const & IncludeTok, StringRef,
31 bool IsAngled, CharSourceRange FilenameRange,
32 #if CLANG_VERSION >= 160000
33 OptionalFileEntryRef File,
34 #elif CLANG_VERSION >= 150000
35 Optional<FileEntryRef> File,
36 #else
37 FileEntry const * File,
38 #endif
39 StringRef SearchPath, StringRef, clang::Module const *, SrcMgr::CharacteristicKind) override
41 if (ignoreLocation(HashLoc)) {
42 return;
44 if (!File) { // in case of "fatal error: '...' file not found"
45 return;
47 if (IncludeTok.getIdentifierInfo()->getPPKeywordID() != tok::pp_include)
49 return;
51 auto const uno = isInUnoIncludeFile(HashLoc)
52 && !compiler.getSourceManager().isInMainFile(HashLoc);
53 // exclude the various compat.cxx that are included in
54 // isInUnoIncludeFile
55 //TODO: 'uno' should be false if HashLoc is inside an
56 // '#ifdef LIBO_INTERNAL_ONLY' block
57 bool shouldUseAngles;
58 if (uno) {
59 shouldUseAngles
60 = (!(loplugin::hasPathnamePrefix(SearchPath, SRCDIR "/")
61 || loplugin::hasPathnamePrefix(SearchPath, BUILDDIR "/"))
62 || loplugin::hasPathnamePrefix(
63 SearchPath, WORKDIR "/UnpackedTarball/"));
64 } else {
65 auto dir1 = std::string(SearchPath);
66 loplugin::normalizeDotDotInFilePath(dir1);
67 auto const file = StringRef(
68 compiler.getSourceManager().getPresumedLoc(HashLoc)
69 .getFilename());
70 auto pos = file.rfind('/');
71 #if defined _WIN32
72 auto const pos2 = file.rfind('\\');
73 if (pos2 != StringRef::npos
74 && (pos == StringRef::npos || pos2 > pos))
76 pos = pos2;
78 #endif
79 auto dir2 = std::string(file.take_front(pos));
80 loplugin::normalizeDotDotInFilePath(dir2);
81 shouldUseAngles = !loplugin::isSamePathname(dir1, dir2);
83 if (shouldUseAngles == IsAngled) {
84 return;
86 if (rewriter != nullptr) {
87 auto last = FilenameRange.getEnd().getLocWithOffset(-1);
88 if ((compiler.getSourceManager().getCharacterData(
89 FilenameRange.getBegin())[0]
90 == (IsAngled ? '<' : '"'))
91 && (compiler.getSourceManager().getCharacterData(last)[0]
92 == (IsAngled ? '>' : '"'))
93 && replaceText(
94 FilenameRange.getBegin(), 1, shouldUseAngles ? "<" : "\"")
95 && replaceText(last, 1, shouldUseAngles ? ">" : "\""))
97 //TODO: atomically only replace both or neither
98 return;
101 report(
102 DiagnosticsEngine::Warning,
103 ("%select{|in UNO API include file, }0replace"
104 " %select{\"...\"|<...>}1 include form with"
105 " %select{\"...\"|<...>}2 for inclusion of %select{%select{a"
106 " source file next to the current source file|a source file not"
107 " next to the current source file, or a header}2|%select{a source"
108 " file|a header}2}0, %3"),
109 FilenameRange.getBegin())
110 << uno << IsAngled << shouldUseAngles << File->getName()
111 << FilenameRange;
115 static loplugin::Plugin::Registration<IncludeForm> reg("includeform", true);
119 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */