Skip to content

Commit

Permalink
[IDE] Add an entry point to get decls out of 'ReconstructType'
Browse files Browse the repository at this point in the history
For now, just tack the testing onto the existing walker that checks the
types.  It doesn't seem to work at all for local declarations yet, but
at least we get some top-level stuff.
  • Loading branch information
benlangmuir committed Mar 10, 2016
1 parent ab44684 commit 5725d22
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 0 deletions.
3 changes: 3 additions & 0 deletions include/swift/IDE/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ void getLocationInfoForClangNode(ClangNode ClangNode,

Optional<std::pair<unsigned, unsigned>> parseLineCol(StringRef LineCol);

Decl *getDeclFromMangledSymbolName(ASTContext &context, StringRef mangledName,
std::string &error);

Type getTypeFromMangledTypename(ASTContext &Ctx,
const char *mangled_typename,
std::string &error);
Expand Down
20 changes: 20 additions & 0 deletions lib/IDE/ReconstructType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2356,6 +2356,26 @@ VisitNode(ASTContext *ast, std::vector<Demangle::NodePointer> &nodes,
nodes.pop_back();
}

Decl *ide::getDeclFromMangledSymbolName(ASTContext &context,
StringRef mangledName,
std::string &error) {
std::vector<Demangle::NodePointer> nodes;
nodes.push_back(
Demangle::demangleSymbolAsNode(mangledName.data(), mangledName.size()));
VisitNodeResult emptyGenericContext;
VisitNodeResult result;
VisitNode(&context, nodes, result, emptyGenericContext, nullptr);
error = result._error;
if (error.empty() && result._decls.size() == 1) {
return result._decls.front();
} else {
llvm::raw_string_ostream OS(error);
OS << "decl for symbol name '" << mangledName << "' was not found";
return nullptr;
}
return nullptr;
}

Type ide::getTypeFromMangledTypename(ASTContext &Ctx,
const char *mangled_typename,
std::string &error) {
Expand Down
17 changes: 17 additions & 0 deletions test/IDE/reconstruct_type_from_mangled_name.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
// RUN: %target-swift-ide-test -reconstruct-type -source-filename %s | FileCheck %s -implicit-check-not="cannot reconstruct"


class Mystruct1 {
// CHECK: reconstructed decl from usr for 'Mystruct1' is 'class Mystruct1'
func s1f1() -> Int { return 0 }
// CHECK: reconstructed decl from usr for 's1f1' is 'func s1f1() -> Int'
var intField = 3
// CHECK: reconstructed decl from usr for 'intField' is 'var intField: Int'
}

class Myclass1 {
// CHECK: reconstructed decl from usr for 'Myclass1' is 'class Myclass1'
var intField = 4
// CHECK: reconstructed decl from usr for 'intField' is 'var intField: Int'
}

func f1() {
// CHECK: reconstructed decl from usr for 'f1' is 'func f1()'
var s1ins = Mystruct1()
// FIXME: we want to check the local decl, not its type...
// CHECK: reconstructed decl from usr for 's1ins' is 'class Mystruct1'
s1ins.intField = 34

// CHECK: reconstructed type from usr for 's1ins' is 'Mystruct1'
Expand All @@ -27,19 +36,27 @@ func f1() {
}

class Myclass2 {
// CHECK: reconstructed decl from usr for 'Myclass2' is 'class Myclass2'
func f1() {
// CHECK: reconstructed decl from usr for 'f1' is 'func f1()'
var arr1 = [1, 2]
// FIXME: cannot reconstruct
// CHECK: cannot reconstruct decl from usr for 'arr1'
arr1.append(1)

// CHECK: reconstructed type from usr for 'arr1' is 'Array<Int>'
// CHECK: reconstructed type from usr for 'append' is '@lvalue Array<Int> -> Int -> ()'

var arr2 : [Mystruct1]
// FIXME: cannot reconstruct
// CHECK: cannot reconstruct decl from usr for 'arr2'
arr2.append(Mystruct1())
// CHECK: reconstructed type from usr for 'arr2' is 'Array<Mystruct1>'
// CHECK: reconstructed type from usr for 'append' is '@lvalue Array<Mystruct1> -> Mystruct1 -> ()'

var arr3 : [Myclass1]
// FIXME: cannot reconstruct
// CHECK: cannot reconstruct decl from usr for 'arr3'
arr3.append(Myclass1())
// CHECK: reconstructed type from usr for 'arr3' is 'Array<Myclass1>'
// CHECK: reconstructed type from usr for 'append' is '@lvalue Array<Myclass1> -> Myclass1 -> ()'
Expand Down
33 changes: 33 additions & 0 deletions tools/swift-ide-test/swift-ide-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2373,6 +2373,12 @@ class TypeReconstructWalker : public SourceEntityWalker {
TypeReconstructWalker(ASTContext &Ctx, llvm::raw_ostream &Stream)
: Ctx(Ctx), Stream(Stream) {}

bool walkToDeclPre(Decl *D, CharSourceRange range) override {
if (auto *VD = dyn_cast<ValueDecl>(D))
tryDemangleDecl(VD, range);
return true;
}

bool visitDeclReference(ValueDecl *D, CharSourceRange Range,
TypeDecl *CtorTyRef, Type T) override {
if (T.isNull())
Expand All @@ -2397,6 +2403,33 @@ class TypeReconstructWalker : public SourceEntityWalker {
}
return true;
}

private:
void tryDemangleDecl(ValueDecl *VD, CharSourceRange range) {
Mangle::Mangler mangler(/*DWARFMangling=*/true);
mangler.mangleDeclName(VD);

std::string mangledName;
{
llvm::raw_string_ostream OS(mangledName);
printDeclUSR(VD, OS);
}

// Put the expected symbol _T prefix on the name by replacing the s:.
assert(StringRef(mangledName).startswith("s:"));
mangledName[0] = '_';
mangledName[1] = 'T';

std::string error;
if (Decl *reDecl = getDeclFromMangledSymbolName(Ctx, mangledName, error)) {
Stream << "reconstructed decl from usr for '" << range.str() << "' is '";
reDecl->print(Stream, PrintOptions());
Stream << "'\n";
} else {
Stream << "cannot reconstruct decl from usr for '" << range.str()
<< "'\n";
}
}
};

static int doReconstructType(const CompilerInvocation &InitInvok,
Expand Down

0 comments on commit 5725d22

Please sign in to comment.