bump product version to 6.3.0.0.beta1
[LibreOffice.git] / compilerplugins / clang / plugin.hxx
blob984bd11cd31516f59266ba97459f811c072b8e79
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * Based on LLVM/Clang.
7 * This file is distributed under the University of Illinois Open Source
8 * License. See LICENSE.TXT for details.
12 #ifndef PLUGIN_H
13 #define PLUGIN_H
15 #include <clang/AST/ASTContext.h>
16 #include <clang/AST/RecursiveASTVisitor.h>
17 #include <clang/Basic/FileManager.h>
18 #include <clang/Basic/SourceManager.h>
19 #include <clang/Frontend/CompilerInstance.h>
20 #include <clang/Lex/Preprocessor.h>
21 #include <unordered_map>
22 #include <vector>
24 #include <clang/Rewrite/Core/Rewriter.h>
26 #include "compat.hxx"
27 #include "pluginhandler.hxx"
29 using namespace clang;
30 using namespace llvm;
32 namespace loplugin
35 struct InstantiationData
37 const char* name;
38 PluginHandler& handler;
39 CompilerInstance& compiler;
40 Rewriter* rewriter;
43 /**
44 Base class for plugins.
46 If you want to create a non-rewriter action, inherit from this class. Remember to also
47 use Plugin::Registration.
49 class Plugin
51 public:
52 explicit Plugin( const InstantiationData& data );
53 virtual ~Plugin() {}
54 // The main function of the plugin.
55 // Note that for shared plugins, its functionality must be split into preRun() and postRun(),
56 // see sharedvisitor/generator.cxx .
57 virtual void run() = 0;
58 // Should be called from run() before TraverseDecl().
59 // If returns false, run() should not do anything.
60 virtual bool preRun() { return true; }
61 virtual void postRun() {}
62 template< typename T > class Registration;
63 // Returns location right after the end of the token that starts at the given location.
64 SourceLocation locationAfterToken( SourceLocation location );
65 virtual bool setSharedPlugin( Plugin* /*plugin*/, const char* /*name*/ ) { return false; }
66 enum { isPPCallback = false };
67 enum { isSharedPlugin = false };
68 protected:
69 DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()) const;
70 bool ignoreLocation( SourceLocation loc ) const
71 { return handler.ignoreLocation(loc); }
72 bool ignoreLocation( const Decl* decl ) const;
73 bool ignoreLocation( const Stmt* stmt ) const;
74 CompilerInstance& compiler;
75 PluginHandler& handler;
76 /**
77 Returns the parent of the given AST node. Clang's internal AST representation doesn't provide this information,
78 it can only provide children, but getting the parent is often useful for inspecting a part of the AST.
80 const Stmt* getParentStmt( const Stmt* stmt );
81 Stmt* getParentStmt( Stmt* stmt );
82 const FunctionDecl* getParentFunctionDecl( const Stmt* stmt );
84 /// to check file names against whitelists, so that it works with preprocessed input too
85 StringRef getFileNameOfSpellingLoc(SourceLocation spellingLocation) const;
86 /**
87 Checks if the location is inside a UNO file, more specifically, if it forms part of the URE stable interface,
88 which is not allowed to be changed.
90 bool isInUnoIncludeFile(SourceLocation spellingLocation) const;
91 bool isInUnoIncludeFile(const FunctionDecl*) const;
93 bool isDebugMode() const { return handler.isDebugMode(); }
95 static bool isUnitTestMode();
97 bool containsPreprocessingConditionalInclusion(SourceRange range);
99 enum class IdenticalDefaultArgumentsResult { No, Yes, Maybe };
100 IdenticalDefaultArgumentsResult checkIdenticalDefaultArguments(
101 Expr const * argument1, Expr const * argument2);
103 private:
104 static void registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName,
105 bool isPPCallback, bool isSharedPlugin, bool byDefault );
106 template< typename T > static Plugin* createHelper( const InstantiationData& data );
107 bool evaluate(const Expr* expr, APSInt& x);
109 enum { isRewriter = false };
110 const char* name;
113 template<typename Derived>
114 class FilteringPlugin : public RecursiveASTVisitor<Derived>, public Plugin
116 public:
117 explicit FilteringPlugin( const InstantiationData& data ) : Plugin(data) {}
119 bool TraverseNamespaceDecl(NamespaceDecl * decl) {
120 if (ignoreLocation(compat::getBeginLoc(decl)))
121 return true;
122 return RecursiveASTVisitor<Derived>::TraverseNamespaceDecl(decl);
127 Base class for rewriter plugins.
129 Remember to also use Plugin::Registration.
131 class RewritePlugin
132 : public Plugin
134 public:
135 explicit RewritePlugin( const InstantiationData& data );
136 protected:
137 enum RewriteOption
139 // This enum allows passing just 'RemoveLineIfEmpty' to functions below.
140 // If the resulting line would be completely empty, it'll be removed.
141 RemoveLineIfEmpty = 1 << 0,
142 // Use this to remove the declaration/statement as a whole, i.e. all whitespace before the statement
143 // and the trailing semicolon (is not part of the AST element range itself).
144 // The trailing semicolon must be present.
145 RemoveWholeStatement = 1 << 1,
146 // Removes also all whitespace preceding and following the expression (completely, so that
147 // the preceding and following tokens would be right next to each other, follow with insertText( " " )
148 // if this is not wanted). Despite the name, indentation whitespace is not removed.
149 RemoveAllWhitespace = 1 << 2
151 struct RewriteOptions
152 : public Rewriter::RewriteOptions
154 RewriteOptions() : flags( 0 ) {}
155 explicit RewriteOptions( RewriteOption option );
156 const int flags;
158 // syntactic sugar to be able to write 'RemoveLineIfEmpty | RemoveWholeStatement'
159 friend RewriteOption operator|( RewriteOption option1, RewriteOption option2 );
160 // These following insert/remove/replaceText functions map to functions
161 // in clang::Rewriter, with these differences:
162 // - they (more intuitively) return false on failure rather than true
163 // - they report a warning when the change cannot be done
164 // - There are more options for easier removal of surroundings of a statement/expression.
165 bool insertText( SourceLocation Loc, StringRef Str,
166 bool InsertAfter = true, bool indentNewLines = false );
167 bool insertTextAfter( SourceLocation Loc, StringRef Str );
168 bool insertTextAfterToken( SourceLocation Loc, StringRef Str );
169 bool insertTextBefore( SourceLocation Loc, StringRef Str );
170 bool removeText( SourceLocation Start, unsigned Length, RewriteOptions opts = RewriteOptions());
171 bool removeText( CharSourceRange range, RewriteOptions opts = RewriteOptions());
172 bool removeText( SourceRange range, RewriteOptions opts = RewriteOptions());
173 bool replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr );
174 bool replaceText( SourceRange range, StringRef NewStr );
175 bool replaceText( SourceRange range, SourceRange replacementRange );
176 Rewriter* rewriter;
177 private:
178 template< typename T > friend class Plugin::Registration;
179 enum { isRewriter = true };
180 bool wouldRewriteWorkdir(SourceLocation loc);
181 bool reportEditFailure( SourceLocation loc );
182 bool adjustRangeForOptions( CharSourceRange* range, RewriteOptions options );
186 Plugin registration helper.
188 If you create a new helper class, create also an instance of this class to automatically register it.
189 The passed argument is name of the plugin, used for explicitly invoking rewriter plugins
190 (it is ignored for non-rewriter plugins).
192 @code
193 static Plugin::Registration< NameOfClass > X( "nameofclass" );
194 @endcode
196 template< typename T >
197 class Plugin::Registration
199 public:
200 Registration( const char* optionName, bool byDefault = !T::isRewriter );
203 class RegistrationCreate
205 public:
206 template< typename T, bool > static T* create( const InstantiationData& data );
209 inline
210 bool Plugin::ignoreLocation( const Decl* decl ) const
212 return ignoreLocation( decl->getLocation());
215 inline
216 bool Plugin::ignoreLocation( const Stmt* stmt ) const
218 // Invalid location can happen at least for ImplicitCastExpr of
219 // ImplicitParam 'self' in Objective C method declarations:
220 return compat::getBeginLoc(stmt).isValid() && ignoreLocation( compat::getBeginLoc(stmt));
223 template< typename T >
224 Plugin* Plugin::createHelper( const InstantiationData& data )
226 return new T( data );
229 template< typename T >
230 inline
231 Plugin::Registration< T >::Registration( const char* optionName, bool byDefault )
233 registerPlugin( &T::template createHelper< T >, optionName, T::isPPCallback, T::isSharedPlugin, byDefault );
236 inline
237 RewritePlugin::RewriteOptions::RewriteOptions( RewriteOption option )
238 : flags( option )
240 // Note that 'flags' stores also RemoveLineIfEmpty, it must be kept in sync with the base class.
241 if( flags & RewritePlugin::RemoveLineIfEmpty )
242 RemoveLineIfEmpty = true;
245 inline
246 RewritePlugin::RewriteOption operator|( RewritePlugin::RewriteOption option1, RewritePlugin::RewriteOption option2 )
248 return static_cast< RewritePlugin::RewriteOption >( int( option1 ) | int( option2 ));
251 template<typename Derived>
252 class FilteringRewritePlugin : public RecursiveASTVisitor<Derived>, public RewritePlugin
254 public:
255 explicit FilteringRewritePlugin( const InstantiationData& data ) : RewritePlugin(data) {}
257 bool TraverseNamespaceDecl(NamespaceDecl * decl) {
258 if (ignoreLocation(compat::getBeginLoc(decl)))
259 return true;
260 return RecursiveASTVisitor<Derived>::TraverseNamespaceDecl(decl);
264 void normalizeDotDotInFilePath(std::string&);
266 // Same as pathname.startswith(prefix), except on Windows, where pathname and
267 // prefix may also contain backslashes:
268 bool hasPathnamePrefix(StringRef pathname, StringRef prefix);
270 // Same as pathname == other, except on Windows, where pathname and other may
271 // also contain backslashes:
272 bool isSamePathname(StringRef pathname, StringRef other);
274 } // namespace
276 #endif // COMPILEPLUGIN_H
278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */