return SymbolID(USR);
}
-// FIXME: This should be handled while printing underlying decls instead.
std::string printType(const QualType QT, const DeclContext &CurContext) {
std::string Result;
llvm::raw_string_ostream OS(Result);
- auto Decls =
- explicitReferenceTargets(DynTypedNode::create(QT), DeclRelation::Alias);
- if (!Decls.empty())
- OS << getQualification(CurContext.getParentASTContext(), &CurContext,
- Decls.front(),
- /*VisibleNamespaces=*/llvm::ArrayRef<std::string>{});
PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
- PP.SuppressScope = true;
PP.SuppressTagKeyword = true;
+ PP.SuppressUnwrittenScope = true;
+
+ class PrintCB : public PrintingCallbacks {
+ public:
+ PrintCB(const DeclContext *CurContext) : CurContext(CurContext) {}
+ virtual ~PrintCB() {}
+ virtual bool isScopeVisible(const DeclContext *DC) const {
+ return DC->Encloses(CurContext);
+ }
+
+ private:
+ const DeclContext *CurContext;
+ };
+ PrintCB PCB(&CurContext);
+ PP.Callbacks = &PCB;
+
QT.print(OS, PP);
return OS.str();
}
EXPECT_EQ(apply(R"cpp(au^to x = "test";)cpp"),
R"cpp(const char * x = "test";)cpp");
+ EXPECT_EQ(apply("ns::Class * foo() { au^to c = foo(); }"),
+ "ns::Class * foo() { ns::Class * c = foo(); }");
+ EXPECT_EQ(apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
+ "void ns::Func() { Class::Nested * x = new ns::Class::Nested{}; }");
+
EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;");
// expanding types in structured bindings is syntactically invalid.
EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};");
})cpp";
EXPECT_EQ(apply(ConstCheckInput), ConstCheckOutput);
+ // Check const qualifier with namespace
+ std::string ConstNamespaceCheckInput = R"cpp(
+namespace X { struct Y { int z; }; }
+int f(const X::Y &y) {
+ [[return y.z + y.z;]]
+})cpp";
+ std::string ConstNamespaceCheckOutput = R"cpp(
+namespace X { struct Y { int z; }; }
+int extracted(const X::Y &y) {
+return y.z + y.z;
+}
+int f(const X::Y &y) {
+ return extracted(y);
+})cpp";
+ EXPECT_EQ(apply(ConstNamespaceCheckInput), ConstNamespaceCheckOutput);
+
// Don't extract when we need to make a function as a parameter.
EXPECT_THAT(apply("void f() { [[int a; f();]] }"), StartsWith("fail"));
namespace clang {
+class DeclContext;
class LangOptions;
class SourceManager;
class Stmt;
virtual std::string remapPath(StringRef Path) const {
return std::string(Path);
}
+
+ /// When printing type to be inserted into code in specific context, this
+ /// callback can be used to avoid printing the redundant part of the
+ /// qualifier. For example, when inserting code inside namespace foo, we
+ /// should print bar::SomeType instead of foo::bar::SomeType.
+ /// To do this, shouldPrintScope should return true on "foo" NamespaceDecl.
+ /// The printing stops at the first isScopeVisible() == true, so there will
+ /// be no calls with outer scopes.
+ virtual bool isScopeVisible(const DeclContext *DC) const { return false; }
};
/// Describes how types, statements, expressions, and declarations should be
if (DC->isFunctionOrMethod())
return;
+ if (Policy.Callbacks && Policy.Callbacks->isScopeVisible(DC))
+ return;
+
if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
if (Policy.SuppressUnwrittenScope && NS->isAnonymousNamespace())
return AppendScope(DC->getParent(), OS, NameInScope);