2018-03-09 22:00:34 +08:00
|
|
|
//===--- AST.h - Utility AST functions -------------------------*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2018-03-09 22:00:34 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Various code that examines C++ source code using AST.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
|
|
|
|
|
2019-02-28 21:49:25 +08:00
|
|
|
#include "index/SymbolID.h"
|
2018-06-22 18:46:59 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
2019-10-30 16:04:10 +08:00
|
|
|
#include "clang/AST/NestedNameSpecifier.h"
|
2018-03-09 22:00:34 +08:00
|
|
|
#include "clang/Basic/SourceLocation.h"
|
2019-02-28 21:49:25 +08:00
|
|
|
#include "clang/Lex/MacroInfo.h"
|
2019-10-30 16:04:10 +08:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2019-11-11 19:38:17 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2019-10-30 16:04:10 +08:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2018-03-09 22:00:34 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
class SourceManager;
|
|
|
|
class Decl;
|
|
|
|
|
|
|
|
namespace clangd {
|
|
|
|
|
2018-10-18 20:23:05 +08:00
|
|
|
/// Returns true if the declaration is considered implementation detail based on
|
|
|
|
/// heuristics. For example, a declaration whose name is not explicitly spelled
|
|
|
|
/// in code is considered implementation detail.
|
|
|
|
bool isImplementationDetail(const Decl *D);
|
|
|
|
|
2019-12-10 17:08:39 +08:00
|
|
|
/// Find the source location of the identifier for \p D.
|
|
|
|
/// Transforms macro locations to locations spelled inside files. All code
|
|
|
|
/// that needs locations of declaration names (e.g. the index) should go through
|
|
|
|
/// this function.
|
|
|
|
SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM);
|
2018-03-09 22:00:34 +08:00
|
|
|
|
2018-06-22 18:46:59 +08:00
|
|
|
/// Returns the qualified name of ND. The scope doesn't contain unwritten scopes
|
|
|
|
/// like inline namespaces.
|
|
|
|
std::string printQualifiedName(const NamedDecl &ND);
|
|
|
|
|
2018-10-17 19:19:02 +08:00
|
|
|
/// Returns the first enclosing namespace scope starting from \p DC.
|
|
|
|
std::string printNamespaceScope(const DeclContext &DC);
|
|
|
|
|
2019-10-16 17:53:59 +08:00
|
|
|
/// Returns the name of the namespace inside the 'using namespace' directive, as
|
|
|
|
/// written in the code. E.g., passing 'using namespace ::std' will result in
|
|
|
|
/// '::std'.
|
|
|
|
std::string printUsingNamespaceName(const ASTContext &Ctx,
|
|
|
|
const UsingDirectiveDecl &D);
|
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
/// Prints unqualified name of the decl for the purpose of displaying it to the
|
|
|
|
/// user. Anonymous decls return names of the form "(anonymous {kind})", e.g.
|
|
|
|
/// "(anonymous struct)" or "(anonymous namespace)".
|
|
|
|
std::string printName(const ASTContext &Ctx, const NamedDecl &ND);
|
|
|
|
|
2019-04-12 18:09:14 +08:00
|
|
|
/// Prints template arguments of a decl as written in the source code, including
|
|
|
|
/// enclosing '<' and '>', e.g for a partial specialization like: template
|
|
|
|
/// <typename U> struct Foo<int, U> will return '<int, U>'. Returns an empty
|
|
|
|
/// string if decl is not a template specialization.
|
|
|
|
std::string printTemplateSpecializationArgs(const NamedDecl &ND);
|
|
|
|
|
2018-08-07 16:57:52 +08:00
|
|
|
/// Gets the symbol ID for a declaration, if possible.
|
|
|
|
llvm::Optional<SymbolID> getSymbolID(const Decl *D);
|
|
|
|
|
2018-09-06 17:59:37 +08:00
|
|
|
/// Gets the symbol ID for a macro, if possible.
|
|
|
|
/// Currently, this is an encoded USR of the macro, which incorporates macro
|
|
|
|
/// locations (e.g. file name, offset in file).
|
|
|
|
/// FIXME: the USR semantics might not be stable enough as the ID for index
|
|
|
|
/// macro (e.g. a change in definition offset can result in a different USR). We
|
|
|
|
/// could change these semantics in the future by reimplementing this funcure
|
|
|
|
/// (e.g. avoid USR for macros).
|
2019-11-11 19:38:17 +08:00
|
|
|
llvm::Optional<SymbolID> getSymbolID(const llvm::StringRef MacroName,
|
2018-09-06 17:59:37 +08:00
|
|
|
const MacroInfo *MI,
|
|
|
|
const SourceManager &SM);
|
|
|
|
|
2019-07-18 23:13:45 +08:00
|
|
|
/// Returns a QualType as string. The result doesn't contain unwritten scopes
|
2020-01-04 23:28:41 +08:00
|
|
|
/// like anonymous/inline namespace.
|
2019-12-18 18:23:47 +08:00
|
|
|
std::string printType(const QualType QT, const DeclContext &CurContext);
|
2019-08-08 15:21:06 +08:00
|
|
|
|
|
|
|
/// Indicates if \p D is a template instantiation implicitly generated by the
|
|
|
|
/// compiler, e.g.
|
|
|
|
/// template <class T> struct vector {};
|
|
|
|
/// vector<int> v; // 'vector<int>' is an implicit instantiation
|
|
|
|
bool isImplicitTemplateInstantiation(const NamedDecl *D);
|
|
|
|
/// Indicates if \p D is an explicit template specialization, e.g.
|
|
|
|
/// template <class T> struct vector {};
|
|
|
|
/// template <> struct vector<bool> {}; // <-- explicit specialization
|
|
|
|
///
|
|
|
|
/// Note that explicit instantiations are NOT explicit specializations, albeit
|
|
|
|
/// they look similar.
|
|
|
|
/// template struct vector<bool>; // <-- explicit instantiation, NOT an
|
|
|
|
/// explicit specialization.
|
|
|
|
bool isExplicitTemplateSpecialization(const NamedDecl *D);
|
2019-07-12 00:04:18 +08:00
|
|
|
|
2019-10-18 20:07:19 +08:00
|
|
|
/// Returns a nested name specifier loc of \p ND if it was present in the
|
|
|
|
/// source, e.g.
|
|
|
|
/// void ns::something::foo() -> returns 'ns::something'
|
|
|
|
/// void foo() -> returns null
|
|
|
|
NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND);
|
|
|
|
|
2019-11-19 04:29:17 +08:00
|
|
|
// Returns a type corresponding to a declaration of that type.
|
|
|
|
// Unlike the method on ASTContext, attempts to preserve the type as-written
|
|
|
|
// (i.e. vector<T*> rather than vector<type-parameter-0-0 *>.
|
|
|
|
QualType declaredType(const TypeDecl *D);
|
|
|
|
|
[clangd] Untangle Hover from XRefs, move into own file.
Summary:
This is mostly mechanical, with a few exceptions:
- getDeducedType moved into AST.h where it belongs. It now takes
ASTContext instead of ParsedAST, and avoids using the preprocessor.
- hover now uses SelectionTree directly rather than via
getDeclAtPosition helper
- hover on 'auto' used to find the decl that contained the 'auto' and
use that to set Kind and documentation for the hover result.
Now we use targetDecl() to find the decl matching the deduced type instead.
This changes tests, e.g. 'variable' -> class for auto on lambdas.
I think this is better, but the motivation was to avoid depending on
the internals of DeducedTypeVisitor. This functionality is removed
from the visitor.
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70357
2019-11-17 00:00:19 +08:00
|
|
|
/// Retrieves the deduced type at a given location (auto, decltype).
|
|
|
|
/// It will return the underlying type.
|
|
|
|
llvm::Optional<QualType> getDeducedType(ASTContext &, SourceLocation Loc);
|
|
|
|
|
2019-10-30 16:04:10 +08:00
|
|
|
/// Gets the nested name specifier necessary for spelling \p ND in \p
|
|
|
|
/// DestContext, at \p InsertionPoint. It selects the shortest suffix of \p ND
|
|
|
|
/// such that it is visible in \p DestContext.
|
|
|
|
/// Returns an empty string if no qualification is necessary. For example, if
|
|
|
|
/// you want to qualify clang::clangd::bar::foo in clang::clangd::x, this
|
|
|
|
/// function will return bar. Note that the result might be sub-optimal for
|
|
|
|
/// classes, e.g. when the \p ND is a member of the base class.
|
|
|
|
///
|
|
|
|
/// This version considers all the using namespace directives before \p
|
|
|
|
/// InsertionPoint. i.e, if you have `using namespace
|
|
|
|
/// clang::clangd::bar`, this function will return an empty string for the
|
|
|
|
/// example above since no qualification is necessary in that case.
|
2019-10-01 16:58:35 +08:00
|
|
|
/// FIXME: Also take using directives and namespace aliases inside function body
|
|
|
|
/// into account.
|
2019-10-30 16:04:10 +08:00
|
|
|
std::string getQualification(ASTContext &Context,
|
|
|
|
const DeclContext *DestContext,
|
|
|
|
SourceLocation InsertionPoint,
|
|
|
|
const NamedDecl *ND);
|
|
|
|
|
|
|
|
/// This function uses the \p VisibleNamespaces to figure out if a shorter
|
|
|
|
/// qualification is sufficient for \p ND, and ignores any using namespace
|
|
|
|
/// directives. It can be useful if there's no AST for the DestContext, but some
|
|
|
|
/// pseudo-parsing is done. i.e. if \p ND is ns1::ns2::X and \p DestContext is
|
|
|
|
/// ns1::, users can provide `ns2::` as visible to change the result to be
|
|
|
|
/// empty.
|
|
|
|
/// Elements in VisibleNamespaces should be in the form: `ns::`, with trailing
|
|
|
|
/// "::".
|
|
|
|
/// Note that this is just textual and might be incorrect. e.g. when there are
|
|
|
|
/// two namespaces ns1::a and ns2::a, the function will early exit if "a::" is
|
|
|
|
/// present in \p VisibleNamespaces, no matter whether it is from ns1:: or ns2::
|
|
|
|
std::string getQualification(ASTContext &Context,
|
|
|
|
const DeclContext *DestContext,
|
2019-12-18 18:23:47 +08:00
|
|
|
const NamedDecl *ND,
|
2019-10-30 16:04:10 +08:00
|
|
|
llvm::ArrayRef<std::string> VisibleNamespaces);
|
|
|
|
|
2020-02-04 21:42:06 +08:00
|
|
|
/// Whether we must avoid computing linkage for D during code completion.
|
|
|
|
/// Clang aggressively caches linkage computation, which is stable after the AST
|
|
|
|
/// is built. Unfortunately the AST is incomplete during code completion, so
|
|
|
|
/// linkage may still change.
|
|
|
|
///
|
|
|
|
/// Example: `auto x = []{^}` at file scope.
|
|
|
|
/// During code completion, the initializer for x hasn't been parsed yet.
|
|
|
|
/// x has type `undeduced auto`, and external linkage.
|
|
|
|
/// If we compute linkage at this point, the external linkage will be cached.
|
|
|
|
///
|
|
|
|
/// After code completion the initializer is attached, and x has a lambda type.
|
|
|
|
/// This means x has "unique external" linkage. If we computed linkage above,
|
|
|
|
/// the cached value is incorrect. (clang catches this with an assertion).
|
|
|
|
bool hasUnstableLinkage(const Decl *D);
|
|
|
|
|
2018-03-09 22:00:34 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|
|
|
|
|
|
|
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
|