13
13
#include " FindTarget.h"
14
14
#include " FormattedString.h"
15
15
#include " Logger.h"
16
+ #include " ParsedAST.h"
16
17
#include " Selection.h"
17
18
#include " SourceCode.h"
18
19
#include " index/SymbolCollector.h"
21
22
#include " clang/AST/Decl.h"
22
23
#include " clang/AST/DeclBase.h"
23
24
#include " clang/AST/DeclTemplate.h"
25
+ #include " clang/AST/Expr.h"
26
+ #include " clang/AST/ExprCXX.h"
24
27
#include " clang/AST/PrettyPrinter.h"
25
28
#include " clang/AST/Type.h"
26
29
#include " clang/Index/IndexSymbol.h"
30
+ #include " llvm/ADT/None.h"
31
+ #include " llvm/ADT/Optional.h"
27
32
#include " llvm/ADT/STLExtras.h"
28
33
#include " llvm/ADT/SmallVector.h"
29
34
#include " llvm/ADT/StringExtras.h"
30
35
#include " llvm/ADT/StringRef.h"
36
+ #include " llvm/Support/Casting.h"
37
+ #include " llvm/Support/ErrorHandling.h"
31
38
#include " llvm/Support/raw_ostream.h"
32
39
#include < string>
33
40
@@ -410,6 +417,45 @@ HoverInfo getHoverContents(const DefinedMacro &Macro, ParsedAST &AST) {
410
417
}
411
418
return HI;
412
419
}
420
+
421
+ bool isLiteral (const Expr *E) {
422
+ // Unfortunately there's no common base Literal classes inherits from
423
+ // (apart from Expr), therefore this is a nasty blacklist.
424
+ return llvm::isa<CharacterLiteral>(E) || llvm::isa<CompoundLiteralExpr>(E) ||
425
+ llvm::isa<CXXBoolLiteralExpr>(E) ||
426
+ llvm::isa<CXXNullPtrLiteralExpr>(E) ||
427
+ llvm::isa<FixedPointLiteral>(E) || llvm::isa<FloatingLiteral>(E) ||
428
+ llvm::isa<ImaginaryLiteral>(E) || llvm::isa<IntegerLiteral>(E) ||
429
+ llvm::isa<StringLiteral>(E) || llvm::isa<UserDefinedLiteral>(E);
430
+ }
431
+
432
+ llvm::StringLiteral getNameForExpr (const Expr *E) {
433
+ // FIXME: Come up with names for `special` expressions.
434
+ return " expression" ;
435
+ }
436
+
437
+ // Generates hover info for evaluatable expressions.
438
+ // FIXME: Support hover for literals (esp user-defined)
439
+ llvm::Optional<HoverInfo> getHoverContents (const Expr *E, ParsedAST &AST) {
440
+ // There's not much value in hovering over "42" and getting a hover card
441
+ // saying "42 is an int", similar for other literals.
442
+ if (isLiteral (E))
443
+ return llvm::None;
444
+
445
+ HoverInfo HI;
446
+ // For expressions we currently print the type and the value, iff it is
447
+ // evaluatable.
448
+ if (auto Val = printExprValue (E, AST.getASTContext ())) {
449
+ auto Policy =
450
+ printingPolicyForDecls (AST.getASTContext ().getPrintingPolicy ());
451
+ Policy.SuppressTagKeyword = true ;
452
+ HI.Type = E->getType ().getAsString (Policy);
453
+ HI.Value = *Val;
454
+ HI.Name = getNameForExpr (E);
455
+ return HI;
456
+ }
457
+ return llvm::None;
458
+ }
413
459
} // namespace
414
460
415
461
llvm::Optional<HoverInfo> getHover (ParsedAST &AST, Position Pos,
@@ -439,11 +485,11 @@ llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
439
485
// Look for a close enclosing expression to show the value of.
440
486
if (!HI->Value )
441
487
HI->Value = printExprValue (N, AST.getASTContext ());
488
+ } else if (const Expr *E = N->ASTNode .get <Expr>()) {
489
+ HI = getHoverContents (E, AST);
442
490
}
443
491
// FIXME: support hovers for other nodes?
444
- // - certain expressions (sizeof etc)
445
492
// - built-in types
446
- // - literals (esp user-defined)
447
493
}
448
494
}
449
495
@@ -469,6 +515,8 @@ markup::Document HoverInfo::present() const {
469
515
// class `X`
470
516
//
471
517
// function `foo` → `int`
518
+ //
519
+ // expression : `int`
472
520
// Note that we are making use of a level-3 heading because VSCode renders
473
521
// level 1 and 2 headers in a huge font, see
474
522
// https://github.com/microsoft/vscode/issues/88417 for details.
0 commit comments