1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/.
12 #include "config_clang.h"
19 class IncludeForm final
: public PPCallbacks
, public loplugin::RewritePlugin
{
21 explicit IncludeForm(loplugin::InstantiationData
const & data
):
23 { compiler
.getPreprocessor().addPPCallbacks(std::unique_ptr
<PPCallbacks
>(this)); }
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
37 if (ignoreLocation(HashLoc
)) {
40 if (File
== nullptr) { // in case of "fatal error: '...' file not found"
43 if (IncludeTok
.getIdentifierInfo()->getPPKeywordID() != tok::pp_include
)
47 auto const uno
= isInUnoIncludeFile(HashLoc
)
48 && !compiler
.getSourceManager().isInMainFile(HashLoc
);
49 // exclude the various compat.cxx that are included in
51 //TODO: 'uno' should be false if HashLoc is inside an
52 // '#ifdef LIBO_INTERNAL_ONLY' block
56 = (!(loplugin::hasPathnamePrefix(SearchPath
, SRCDIR
"/")
57 || loplugin::hasPathnamePrefix(SearchPath
, BUILDDIR
"/"))
58 || loplugin::hasPathnamePrefix(
59 SearchPath
, WORKDIR
"/UnpackedTarball/"));
61 auto dir1
= std::string(SearchPath
);
62 loplugin::normalizeDotDotInFilePath(dir1
);
63 auto const file
= StringRef(
64 compiler
.getSourceManager().getPresumedLoc(HashLoc
)
66 auto pos
= file
.rfind('/');
68 auto const pos2
= file
.rfind('\\');
69 if (pos2
!= StringRef::npos
70 && (pos
== StringRef::npos
|| pos2
> pos
))
75 auto dir2
= std::string(compat::take_front(file
, pos
));
76 loplugin::normalizeDotDotInFilePath(dir2
);
77 shouldUseAngles
= !loplugin::isSamePathname(dir1
, dir2
);
79 if (shouldUseAngles
== IsAngled
) {
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
? '>' : '"'))
90 FilenameRange
.getBegin(), 1, shouldUseAngles
? "<" : "\"")
91 && replaceText(last
, 1, shouldUseAngles
? ">" : "\""))
93 //TODO: atomically only replace both or neither
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()
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: */