2011-02-04 22:28:15 +00:00
|
|
|
//===--- iwyu_include_picker.h - map to canonical #includes for iwyu ------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-02-19 02:32:52 +00:00
|
|
|
// The include-picker provides a list of candidate #include-lines
|
|
|
|
// that iwyu can suggest in order to include a particular symbol
|
|
|
|
// or file.
|
2011-02-04 22:28:15 +00:00
|
|
|
//
|
2011-02-19 02:32:52 +00:00
|
|
|
// It seems like the 'file' case would be easy ("to include
|
|
|
|
// /usr/include/math.h, say '#include <math.h>"), but it's
|
|
|
|
// not because many header files are private, and should not
|
|
|
|
// be included by users directly. A private header will have
|
|
|
|
// one or (occassionally) more public headers that it maps to.
|
|
|
|
// The include-picker keeps track of these mappings.
|
2011-02-04 22:28:15 +00:00
|
|
|
//
|
2011-02-19 02:32:52 +00:00
|
|
|
// It's also possible for a public file to have an include-picker
|
|
|
|
// mapping. This means: "it's ok to #include this file directly, but
|
|
|
|
// you can also get the contents of this file by #including this other
|
|
|
|
// file as well." One example is that <ostream> maps to both
|
|
|
|
// <ostream> and <iostream>. Other parts of iwyu can decide which
|
|
|
|
// #include to suggest based on its own heuristics (whether the file
|
|
|
|
// already needs to #include <iostream> for some other reason, for
|
|
|
|
// instance).
|
|
|
|
//
|
|
|
|
// Some of these mappings are hard-coded, based on my own examination
|
|
|
|
// of gcc headers on ubuntu. Some mappings are determined at runtime,
|
|
|
|
// based on #pragmas or other writeup in the source files themselves.
|
|
|
|
//
|
|
|
|
// Mapping a symbol to a file has the same issues. In most cases, a
|
|
|
|
// symbol maps to the file that defines it, and iwyu_include_picker
|
|
|
|
// has nothing useful to say. But some symbols -- which we hard-code
|
|
|
|
// -- can be provided by several files. NULL is a canonical example
|
|
|
|
// of this.
|
|
|
|
//
|
|
|
|
// The include-picker also provides some helper functions for
|
|
|
|
// converting from file-paths to #include paths, including, routines to
|
|
|
|
// normalize a file-path to get rid of /usr/include/ prefixes.
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
#ifndef DEVTOOLS_MAINTENANCE_INCLUDE_WHAT_YOU_USE_IWYU_INCLUDE_PICKER_H_
|
|
|
|
#define DEVTOOLS_MAINTENANCE_INCLUDE_WHAT_YOU_USE_IWYU_INCLUDE_PICKER_H_
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <set>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2011-02-08 06:12:32 +00:00
|
|
|
#include "port.h"
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
namespace include_what_you_use {
|
|
|
|
|
|
|
|
using std::map;
|
|
|
|
using std::set;
|
|
|
|
using std::string;
|
|
|
|
using std::vector;
|
|
|
|
|
|
|
|
|
2011-02-19 02:32:52 +00:00
|
|
|
// Below, we talk 'quoted' includes. A quoted include is something
|
|
|
|
// that would be written on an #include line, complete with the <> or
|
|
|
|
// "". In the line '#include <time.h>', "<time.h>" is the quoted
|
|
|
|
// include.
|
|
|
|
|
|
|
|
// Converts a file-path, such as /usr/include/stdio.h, to a
|
|
|
|
// quoted include, such as <stdio.h>.
|
|
|
|
string ConvertToQuotedInclude(const string& filepath);
|
|
|
|
|
|
|
|
// Returns whether this is a system (as opposed to user) include
|
|
|
|
// file, based on where it lives.
|
|
|
|
bool IsSystemIncludeFile(const string& filepath);
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
class IncludePicker {
|
|
|
|
public:
|
2011-02-19 02:32:52 +00:00
|
|
|
enum Visibility { kUnusedVisibility, kPublic, kPrivate };
|
|
|
|
|
|
|
|
// If we map from A to B, it means that every time we need a
|
|
|
|
// symbol from A, we can also get it from B. Another way
|
|
|
|
// to think about it is that map_to "re-exports" all the
|
|
|
|
// symbols from map_from.
|
|
|
|
struct IncludeMapEntry { // A POD so we can make the input static
|
2011-03-04 00:00:14 +00:00
|
|
|
const char* map_from; // A quoted-include, or a symbol name
|
2011-02-19 02:32:52 +00:00
|
|
|
Visibility from_visibility;
|
|
|
|
const char* map_to; // A quoted-include
|
|
|
|
Visibility to_visibility;
|
|
|
|
};
|
|
|
|
|
2011-03-04 00:00:14 +00:00
|
|
|
typedef map<string, vector<string> > IncludeMap; // map_from to <map_to,...>
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
IncludePicker();
|
|
|
|
|
2011-02-19 02:32:52 +00:00
|
|
|
// ----- Routines to dynamically modify the include-picker
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
// Call this for every #include seen during iwyu analysis. The
|
|
|
|
// include-picker can use this data to better suggest #includes,
|
For some reason I was telling the include-picker about
includes-as-written rather than the actual file-path of the
included file. Since the include-picker deals with actual
file-paths (of the decls), this made no sense, and indeed we
were seeing when code depended on a search path, we weren't
finding the proper include-mapping for it.
For instance, python .h files has
#include "dictobject.h"
rather than
#include "third_party/python2_4_3/gcc-3.4-glibc-2.11.1-grte-k8-linux-python2.6-opt/include/python2.6/dictobject.h
Thus, while we had code that correctly mapped
third_party/python2_4_3 to <Python.h>, it wasn't firing on the
above code because the include-picker saw it as just
"dictobject.h". This is now fixed by using the actual
file-path.
While testing, I discovered the test-file was often calling
AddDirectInclude() improperly (with extra "'s). It didn't
happen to matter, but I cleaned it up.
R=wan,dsturtevant
DELTA=43 (5 added, 2 deleted, 36 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1574
2011-04-27 00:04:37 +01:00
|
|
|
// perhaps.
|
2011-02-19 02:32:52 +00:00
|
|
|
void AddDirectInclude(const string& includer_filepath,
|
For some reason I was telling the include-picker about
includes-as-written rather than the actual file-path of the
included file. Since the include-picker deals with actual
file-paths (of the decls), this made no sense, and indeed we
were seeing when code depended on a search path, we weren't
finding the proper include-mapping for it.
For instance, python .h files has
#include "dictobject.h"
rather than
#include "third_party/python2_4_3/gcc-3.4-glibc-2.11.1-grte-k8-linux-python2.6-opt/include/python2.6/dictobject.h
Thus, while we had code that correctly mapped
third_party/python2_4_3 to <Python.h>, it wasn't firing on the
above code because the include-picker saw it as just
"dictobject.h". This is now fixed by using the actual
file-path.
While testing, I discovered the test-file was often calling
AddDirectInclude() improperly (with extra "'s). It didn't
happen to matter, but I cleaned it up.
R=wan,dsturtevant
DELTA=43 (5 added, 2 deleted, 36 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1574
2011-04-27 00:04:37 +01:00
|
|
|
const string& includee_filepath);
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2011-02-19 02:32:52 +00:00
|
|
|
// Add this to say "map_to re-exports everything in file map_from".
|
|
|
|
// Both map_to and map_from should be quoted includes.
|
2011-03-04 00:00:14 +00:00
|
|
|
void AddMapping(const string& map_from, const string& map_to);
|
|
|
|
|
|
|
|
// Indicate that the given quoted include should be considered
|
|
|
|
// a "private" include. If possible, we use the include-picker
|
|
|
|
// mappings to map such includes to public (not-private) includs.
|
|
|
|
void MarkIncludeAsPrivate(const string& quoted_include);
|
2011-02-11 23:08:41 +00:00
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
// Call this after iwyu preprocessing is done. No more calls to
|
2011-02-19 02:32:52 +00:00
|
|
|
// AddDirectInclude() or AddMapping() are allowed after this.
|
2011-02-04 22:28:15 +00:00
|
|
|
void FinalizeAddedIncludes();
|
|
|
|
|
2011-02-19 02:32:52 +00:00
|
|
|
// ----- Include-picking API
|
|
|
|
|
|
|
|
// Returns the set of all public header files that 'provide' the
|
|
|
|
// given symbol. For instance, NULL can map to stddef.h, stdlib.h,
|
2011-02-04 22:28:15 +00:00
|
|
|
// etc. Most symbols don't have pre-defined headers they map to,
|
|
|
|
// and we return the empty vector in that case. Ordering is
|
|
|
|
// important (which is why we return a vector, not a set): all else
|
|
|
|
// being equal, the first element of the vector is the "best" (or
|
|
|
|
// most standard) header for the symbol.
|
|
|
|
vector<string> GetPublicHeadersForSymbol(const string& symbol) const;
|
|
|
|
|
|
|
|
// Returns the set of all public header files that a given header
|
2011-02-19 02:32:52 +00:00
|
|
|
// file -- specified as a full path -- would map to, as a set of
|
|
|
|
// quoted includes such as '<stdio.h>'. If the include-picker has
|
|
|
|
// no mapping information for this file, the return vector has just
|
|
|
|
// the input file (now include-quoted). Ordering is important
|
2011-02-04 22:28:15 +00:00
|
|
|
// (which is why we return a vector, not a set): all else being
|
|
|
|
// equal, the first element of the vector is the "best" (or most
|
2011-02-19 02:32:52 +00:00
|
|
|
// standard) header for the input header.
|
|
|
|
vector<string> GetPublicHeadersForFilepath(const string& filepath) const;
|
|
|
|
|
|
|
|
// Returns true if there is a mapping (possibly indirect) from
|
|
|
|
// map_from to map_to. This means that to_file 're-exports' all the
|
|
|
|
// symbols from from_file. Both map_from_filepath and
|
|
|
|
// map_to_filepath should be full file-paths.
|
|
|
|
bool HasMapping(const string& map_from_filepath,
|
|
|
|
const string& map_to_filepath) const;
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
private:
|
2011-02-19 02:32:52 +00:00
|
|
|
// Given a map whose keys may have globs (* or [] or ?), expand the
|
|
|
|
// globs by matching them against all #includes seen by iwyu.
|
|
|
|
void ExpandGlobs();
|
|
|
|
|
2011-03-04 00:00:14 +00:00
|
|
|
// Helper routine to parse the internal, hard-coded mappings.
|
|
|
|
void InsertInto(const IncludePicker::IncludeMapEntry& e,
|
|
|
|
IncludePicker::IncludeMap* include_map);
|
|
|
|
|
|
|
|
// Adds an entry to filepath_visibility_map_, with error checking.
|
|
|
|
void MarkVisibility(const string& quoted_include,
|
|
|
|
IncludePicker::Visibility vis);
|
|
|
|
|
|
|
|
// For the given key, return the vector of values associated with
|
|
|
|
// that key, or an empty vector if the key does not exist in the
|
|
|
|
// map, filtering out private files.
|
|
|
|
vector<string> GetPublicValues(const IncludeMap& m, const string& key) const;
|
|
|
|
|
2011-02-19 02:32:52 +00:00
|
|
|
// One map from symbols to includes, one from filepaths to includes.
|
|
|
|
IncludeMap symbol_include_map_;
|
|
|
|
IncludeMap filepath_include_map_;
|
|
|
|
|
2011-03-04 00:00:14 +00:00
|
|
|
// A map of all quoted-includes to whether they're public or private.
|
|
|
|
// Quoted-includes that are not present in this map are assumed public.
|
|
|
|
map<string, Visibility> filepath_visibility_map_;
|
|
|
|
|
2011-02-19 02:32:52 +00:00
|
|
|
// All the includes we've seen so far, to help with globbing.
|
|
|
|
set<string> all_quoted_includes_;
|
2011-02-11 23:08:41 +00:00
|
|
|
|
|
|
|
// Make sure we don't do any non-const operations after finalizing.
|
|
|
|
bool has_called_finalize_added_include_lines_;
|
2011-02-04 22:28:15 +00:00
|
|
|
}; // class IncludePicker
|
|
|
|
|
|
|
|
} // namespace include_what_you_use
|
|
|
|
|
|
|
|
#endif // DEVTOOLS_MAINTENANCE_INCLUDE_WHAT_YOU_USE_IWYU_INCLUDE_PICKER_H_
|