Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / includeform.cxx
blobfe7bad18918f2aeed8a5b1b7491c4d27a0aaa426
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 "compat.hxx"
15 #include "plugin.hxx"
17 namespace {
19 class IncludeForm final: public PPCallbacks, public loplugin::RewritePlugin {
20 public:
21 explicit IncludeForm(loplugin::InstantiationData const & data):
22 RewritePlugin(data)
23 { compiler.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(this)); }
25 private:
26 void run() override {}
28 void InclusionDirective(
29 SourceLocation HashLoc, Token const & IncludeTok, StringRef,
30 bool IsAngled, CharSourceRange FilenameRange, FileEntry const * File,
31 StringRef SearchPath, StringRef, clang::Module const *
32 #if CLANG_VERSION >= 70000
33 , SrcMgr::CharacteristicKind
34 #endif
35 ) override
37 if (ignoreLocation(HashLoc)) {
38 return;
40 if (File == nullptr) { // in case of "fatal error: '...' file not found"
41 return;
43 if (IncludeTok.getIdentifierInfo()->getPPKeywordID() != tok::pp_include)
45 return;
47 auto const uno = isInUnoIncludeFile(HashLoc)
48 && !compiler.getSourceManager().isInMainFile(HashLoc);
49 // exclude the various compat.cxx that are included in
50 // isInUnoIncludeFile
51 //TODO: 'uno' should be false if HashLoc is inside an
52 // '#ifdef LIBO_INTERNAL_ONLY' block
53 bool shouldUseAngles;
54 if (uno) {
55 shouldUseAngles
56 = (!(loplugin::hasPathnamePrefix(SearchPath, SRCDIR "/")
57 || loplugin::hasPathnamePrefix(SearchPath, BUILDDIR "/"))
58 || loplugin::hasPathnamePrefix(
59 SearchPath, WORKDIR "/UnpackedTarball/"));
60 } else {
61 auto dir1 = std::string(SearchPath);
62 loplugin::normalizeDotDotInFilePath(dir1);
63 auto const file = StringRef(
64 compiler.getSourceManager().getPresumedLoc(HashLoc)
65 .getFilename());
66 auto pos = file.rfind('/');
67 #if defined _WIN32
68 auto const pos2 = file.rfind('\\');
69 if (pos2 != StringRef::npos
70 && (pos == StringRef::npos || pos2 > pos))
72 pos = pos2;
74 #endif
75 auto dir2 = std::string(compat::take_front(file, pos));
76 loplugin::normalizeDotDotInFilePath(dir2);
77 shouldUseAngles = !loplugin::isSamePathname(dir1, dir2);
79 if (shouldUseAngles == IsAngled) {
80 return;
82 if (rewriter != nullptr) {
83 auto last = FilenameRange.getEnd().getLocWithOffset(-1);
84 if ((compiler.getSourceManager().getCharacterData(
85 FilenameRange.getBegin())[0]
86 == (IsAngled ? '<' : '"'))
87 && (compiler.getSourceManager().getCharacterData(last)[0]
88 == (IsAngled ? '>' : '"'))
89 && replaceText(
90 FilenameRange.getBegin(), 1, shouldUseAngles ? "<" : "\"")
91 && replaceText(last, 1, shouldUseAngles ? ">" : "\""))
93 //TODO: atomically only replace both or neither
94 return;
97 report(
98 DiagnosticsEngine::Warning,
99 ("%select{|in UNO API include file, }0replace"
100 " %select{\"...\"|<...>}1 include form with"
101 " %select{\"...\"|<...>}2 for inclusion of %select{%select{a"
102 " source file next to the current source file|a source file not"
103 " next to the current source file, or a header}2|%select{a source"
104 " file|a header}2}0, %3"),
105 FilenameRange.getBegin())
106 << uno << IsAngled << shouldUseAngles << File->getName()
107 << FilenameRange;
111 static loplugin::Plugin::Registration<IncludeForm> reg("includeform", true);
115 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */