@@ -731,6 +731,117 @@ swift::collectExpressionType(SourceFile &SF,
731731 return Scratch;
732732}
733733
734+ // / This walker will traverse the AST and report types for every variable
735+ // / declaration.
736+ class VariableTypeCollector : public SourceEntityWalker {
737+ private:
738+ const SourceManager &SM;
739+ unsigned int BufferId;
740+
741+ // / The range in which variable types are to be collected.
742+ SourceRange TotalRange;
743+
744+ // / The output vector for VariableTypeInfos emitted during traversal.
745+ std::vector<VariableTypeInfo> &Results;
746+
747+ // / We print all types into a single output stream (e.g. into a string buffer)
748+ // / and provide offsets into this string buffer to describe individual types,
749+ // / i.e. \c OS builds a string that contains all null-terminated printed type
750+ // / strings. When referring to one of these types, we can use the offsets at
751+ // / which it starts in the \c OS.
752+ llvm::raw_ostream &OS;
753+
754+ // / Map from a printed type to the offset in \c OS where the type starts.
755+ llvm::StringMap<uint32_t > TypeOffsets;
756+
757+ // / Returns the start offset of this string in \c OS. If \c PrintedType
758+ // / hasn't been printed to \c OS yet, this function will do so.
759+ uint32_t getTypeOffset (StringRef PrintedType) {
760+ auto It = TypeOffsets.find (PrintedType);
761+ if (It == TypeOffsets.end ()) {
762+ TypeOffsets[PrintedType] = OS.tell ();
763+ OS << PrintedType << ' \0 ' ;
764+ }
765+ return TypeOffsets[PrintedType];
766+ }
767+
768+ // / Checks whether the given range overlaps the total range in which we
769+ // / collect variable types.
770+ bool overlapsTotalRange (SourceRange Range) {
771+ return TotalRange.isInvalid () || Range.overlaps (TotalRange);
772+ }
773+
774+ public:
775+ VariableTypeCollector (const SourceFile &SF, SourceRange Range,
776+ std::vector<VariableTypeInfo> &Results,
777+ llvm::raw_ostream &OS)
778+ : SM(SF.getASTContext().SourceMgr), BufferId(*SF.getBufferID()),
779+ TotalRange (Range), Results(Results), OS(OS) {}
780+
781+ bool walkToDeclPre (Decl *D, CharSourceRange DeclNameRange) override {
782+ if (DeclNameRange.isInvalid ()) {
783+ return true ;
784+ }
785+ // Skip this declaration and its subtree if outside the range
786+ if (!overlapsTotalRange (D->getSourceRange ())) {
787+ return false ;
788+ }
789+ if (auto VD = dyn_cast<VarDecl>(D)) {
790+ unsigned VarOffset =
791+ SM.getLocOffsetInBuffer (DeclNameRange.getStart (), BufferId);
792+ unsigned VarLength = DeclNameRange.getByteLength ();
793+ // Print the type to a temporary buffer
794+ SmallString<64 > Buffer;
795+ {
796+ llvm::raw_svector_ostream OS (Buffer);
797+ PrintOptions Options;
798+ Options.SynthesizeSugarOnTypes = true ;
799+ auto Ty = VD->getType ();
800+ // Skip this declaration and its children if the type is an error type.
801+ if (Ty->is <ErrorType>()) {
802+ return false ;
803+ }
804+ Ty->print (OS, Options);
805+ }
806+ // Transfer the type to `OS` if needed and get the offset of this string
807+ // in `OS`.
808+ auto TyOffset = getTypeOffset (Buffer.str ());
809+ bool HasExplicitType =
810+ VD->getTypeReprOrParentPatternTypeRepr () != nullptr ;
811+ // Add the type information to the result list.
812+ Results.emplace_back (VarOffset, VarLength, HasExplicitType, TyOffset);
813+ }
814+ return true ;
815+ }
816+
817+ bool walkToStmtPre (Stmt *S) override {
818+ // Skip this statement and its subtree if outside the range
819+ return overlapsTotalRange (S->getSourceRange ());
820+ }
821+
822+ bool walkToExprPre (Expr *E) override {
823+ // Skip this expression and its subtree if outside the range
824+ return overlapsTotalRange (E->getSourceRange ());
825+ }
826+
827+ bool walkToPatternPre (Pattern *P) override {
828+ // Skip this pattern and its subtree if outside the range
829+ return overlapsTotalRange (P->getSourceRange ());
830+ }
831+ };
832+
833+ VariableTypeInfo::VariableTypeInfo (uint32_t Offset, uint32_t Length,
834+ bool HasExplicitType, uint32_t TypeOffset)
835+ : Offset(Offset), Length(Length), HasExplicitType(HasExplicitType),
836+ TypeOffset(TypeOffset) {}
837+
838+ void swift::collectVariableType (
839+ SourceFile &SF, SourceRange Range,
840+ std::vector<VariableTypeInfo> &VariableTypeInfos, llvm::raw_ostream &OS) {
841+ VariableTypeCollector Walker (SF, Range, VariableTypeInfos, OS);
842+ Walker.walk (SF);
843+ }
844+
734845ArrayRef<ValueDecl*> swift::
735846canDeclProvideDefaultImplementationFor (ValueDecl* VD) {
736847 return evaluateOrDefault (VD->getASTContext ().evaluator ,
0 commit comments