aboutsummaryrefslogtreecommitdiff
path: root/include-fixer/find-all-symbols/SymbolInfo.h
blob: 92d360d3646efcf06b2bf1ee9d4bad90727728c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//===-- SymbolInfo.h - Symbol Info ------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H
#define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H

#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <set>
#include <string>
#include <vector>

namespace clang {
namespace find_all_symbols {
/// \brief Describes a named symbol from a header.
/// Symbols with the same qualified name and type (e.g. function overloads)
/// that appear in the same header are represented by a single SymbolInfo.
///
/// TODO: keep track of instances, e.g. overload locations and signatures.
class SymbolInfo {
public:
  /// \brief The SymbolInfo Type.
  enum class SymbolKind {
    Function,
    Class,
    Variable,
    TypedefName,
    EnumDecl,
    EnumConstantDecl,
    Macro,
    Unknown,
  };

  /// \brief The Context Type.
  enum class ContextType {
    Namespace, // Symbols declared in a namespace.
    Record,    // Symbols declared in a class.
    EnumDecl,  // Enum constants declared in a enum declaration.
  };

  /// \brief A pair of <ContextType, ContextName>.
  typedef std::pair<ContextType, std::string> Context;

  // \brief Signals are signals gathered by observing how a symbol is used.
  // These are used to rank results.
  struct Signals {
    Signals() {}
    Signals(unsigned Seen, unsigned Used) : Seen(Seen), Used(Used) {}

    // Number of times this symbol was visible to a TU.
    unsigned Seen = 0;

    // Number of times this symbol was referenced a TU's main file.
    unsigned Used = 0;

    Signals &operator+=(const Signals &RHS);
    Signals operator+(const Signals &RHS) const;
    bool operator==(const Signals &RHS) const;
  };

  using SignalMap = std::map<SymbolInfo, Signals>;

  // The default constructor is required by YAML traits in
  // LLVM_YAML_IS_DOCUMENT_LIST_VECTOR.
  SymbolInfo() : Type(SymbolKind::Unknown) {}

  SymbolInfo(llvm::StringRef Name, SymbolKind Type, llvm::StringRef FilePath,
             const std::vector<Context> &Contexts);

  void SetFilePath(llvm::StringRef Path) { FilePath = Path; }

  /// \brief Get symbol name.
  llvm::StringRef getName() const { return Name; }

  /// \brief Get the fully-qualified symbol name.
  std::string getQualifiedName() const;

  /// \brief Get symbol type.
  SymbolKind getSymbolKind() const { return Type; }

  /// \brief Get a relative file path where symbol comes from.
  llvm::StringRef getFilePath() const { return FilePath; }

  /// \brief Get symbol contexts.
  const std::vector<SymbolInfo::Context> &getContexts() const {
    return Contexts;
  }

  bool operator<(const SymbolInfo &Symbol) const;

  bool operator==(const SymbolInfo &Symbol) const;

private:
  friend struct llvm::yaml::MappingTraits<struct SymbolAndSignals>;

  /// \brief Identifier name.
  std::string Name;

  /// \brief Symbol type.
  SymbolKind Type;

  /// \brief The file path where the symbol comes from. It's a relative file
  /// path based on the build directory.
  std::string FilePath;

  /// \brief Contains information about symbol contexts. Context information is
  /// stored from the inner-most level to outer-most level.
  ///
  /// For example, if a symbol 'x' is declared as:
  ///     namespace na { namespace nb { class A { int x; } } }
  /// The contexts would be { {RECORD, "A"}, {NAMESPACE, "nb"}, {NAMESPACE,
  /// "na"} }.
  /// The name of an anonymous namespace is "".
  ///
  /// If the symbol is declared in `TranslationUnitDecl`, it has no context.
  std::vector<Context> Contexts;
};

struct SymbolAndSignals {
  SymbolInfo Symbol;
  SymbolInfo::Signals Signals;
  bool operator==(const SymbolAndSignals& RHS) const;
};

/// \brief Write SymbolInfos to a stream (YAML format).
bool WriteSymbolInfosToStream(llvm::raw_ostream &OS,
                              const SymbolInfo::SignalMap &Symbols);

/// \brief Read SymbolInfos from a YAML document.
std::vector<SymbolAndSignals> ReadSymbolInfosFromYAML(llvm::StringRef Yaml);

} // namespace find_all_symbols
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_FIND_ALL_SYMBOLS_SYMBOLINFO_H