@@ -831,13 +831,27 @@ static bool setBufferForFile(StringRef SourceFilename,
831
831
return false ;
832
832
}
833
833
834
- static bool doCodeCompletionImpl (
835
- CodeCompletionCallbacksFactory *callbacksFactory,
836
- const CompilerInvocation &InitInvok,
837
- StringRef SourceFilename,
838
- StringRef SecondSourceFileName,
839
- StringRef CodeCompletionToken,
840
- bool CodeCompletionDiagnostics) {
834
+ // / Result returned from \c performWithCompletionLikeOperationParams.
835
+ struct CompletionLikeOperationParams {
836
+ swift::CompilerInvocation &Invocation;
837
+ llvm::ArrayRef<const char *> Args;
838
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem;
839
+ llvm::MemoryBuffer *CompletionBuffer;
840
+ unsigned int Offset;
841
+ swift::DiagnosticConsumer *DiagC;
842
+ };
843
+
844
+ // / Run \p PerformOperation with the parameters that are needed to perform a
845
+ // / completion like operation on a \c CompletionInstance. This function will
846
+ // / return the same value as \p PerformOperation.
847
+ // / In case there was an error setting up the parameters for the operation,
848
+ // / this method returns \c true and does not call \p PerformOperation.
849
+ static bool performWithCompletionLikeOperationParams (
850
+ const CompilerInvocation &InitInvok, StringRef SourceFilename,
851
+ StringRef SecondSourceFileName, StringRef CodeCompletionToken,
852
+ bool CodeCompletionDiagnostics,
853
+ llvm::function_ref<bool (CompletionLikeOperationParams Params)>
854
+ PerformOperation) {
841
855
std::unique_ptr<llvm::MemoryBuffer> FileBuf;
842
856
if (setBufferForFile (SourceFilename, FileBuf))
843
857
return true ;
@@ -865,68 +879,149 @@ static bool doCodeCompletionImpl(
865
879
}
866
880
867
881
PrintingDiagnosticConsumer PrintDiags;
868
- CompletionInstance CompletionInst;
869
- std::string CompletionError;
870
- bool CallbackCalled = false ;
871
- CompletionInst.performOperation (
872
- Invocation, /* Args=*/ {}, llvm::vfs::getRealFileSystem (), CleanFile.get (),
873
- Offset, CodeCompletionDiagnostics ? &PrintDiags : nullptr ,
874
- [&](CancellableResult<CompletionInstanceResult> Result) {
875
- CallbackCalled = true ;
876
- switch (Result.getKind ()) {
877
- case CancellableResultKind::Success: {
878
- assert (!Result->DidReuseAST &&
879
- " reusing AST context without enabling it" );
880
-
881
- if (!Result->DidFindCodeCompletionToken ) {
882
- // Return empty results by not performing the second pass and never
883
- // calling the consumer of the callback factory.
884
- return ;
885
- }
886
882
887
- performCodeCompletionSecondPass (*Result->CI .getCodeCompletionFile (),
888
- *callbacksFactory);
889
- break ;
890
- }
891
- case CancellableResultKind::Failure:
892
- CompletionError = " error: " + Result.getError ();
893
- break ;
894
- case CancellableResultKind::Cancelled:
895
- CompletionError = " request cancelled" ;
896
- break ;
883
+ CompletionLikeOperationParams Params{Invocation,
884
+ /* Args=*/ {},
885
+ llvm::vfs::getRealFileSystem (),
886
+ CleanFile.get (),
887
+ Offset,
888
+ CodeCompletionDiagnostics ? &PrintDiags
889
+ : nullptr };
890
+
891
+ return PerformOperation (Params);
892
+ }
893
+
894
+ static bool
895
+ doCodeCompletionImpl (CodeCompletionCallbacksFactory *callbacksFactory,
896
+ const CompilerInvocation &InitInvok,
897
+ StringRef SourceFilename, StringRef SecondSourceFileName,
898
+ StringRef CodeCompletionToken,
899
+ bool CodeCompletionDiagnostics) {
900
+ return performWithCompletionLikeOperationParams (
901
+ InitInvok, SourceFilename, SecondSourceFileName, CodeCompletionToken,
902
+ CodeCompletionDiagnostics,
903
+ [&](CompletionLikeOperationParams Params) -> bool {
904
+ PrintingDiagnosticConsumer PrintDiags;
905
+ CompletionInstance CompletionInst;
906
+ std::string CompletionError;
907
+ bool CallbackCalled = false ;
908
+ CompletionInst.performOperation (
909
+ Params.Invocation , Params.Args , Params.FileSystem ,
910
+ Params.CompletionBuffer , Params.Offset , Params.DiagC ,
911
+ [&](CancellableResult<CompletionInstanceResult> Result) {
912
+ CallbackCalled = true ;
913
+ switch (Result.getKind ()) {
914
+ case CancellableResultKind::Success: {
915
+ assert (!Result->DidReuseAST &&
916
+ " reusing AST context without enabling it" );
917
+
918
+ if (!Result->DidFindCodeCompletionToken ) {
919
+ // Return empty results by not performing the second pass and
920
+ // never calling the consumer of the callback factory.
921
+ return ;
922
+ }
923
+
924
+ performCodeCompletionSecondPass (
925
+ *Result->CI .getCodeCompletionFile (), *callbacksFactory);
926
+ break ;
927
+ }
928
+ case CancellableResultKind::Failure:
929
+ CompletionError = " error: " + Result.getError ();
930
+ break ;
931
+ case CancellableResultKind::Cancelled:
932
+ CompletionError = " request cancelled" ;
933
+ break ;
934
+ }
935
+ });
936
+ assert (CallbackCalled &&
937
+ " Expected callback to be called synchronously" );
938
+ if (CompletionError == " error: did not find code completion token" ) {
939
+ // Do not consider failure to find the code completion token as a
940
+ // critical failure that returns a non-zero exit code. Instead, allow
941
+ // the caller to match the error message.
942
+ llvm::outs () << CompletionError << ' \n ' ;
943
+ } else if (!CompletionError.empty ()) {
944
+ llvm::errs () << CompletionError << ' \n ' ;
945
+ return true ;
897
946
}
947
+ return false ;
898
948
});
899
- assert (CallbackCalled &&
900
- " We should always receive a callback call for code completion" );
901
- if (CompletionError == " error: did not find code completion token" ) {
902
- // Do not consider failure to find the code completion token as a critical
903
- // failure that returns a non-zero exit code. Instead, allow the caller to
904
- // match the error message.
905
- llvm::outs () << CompletionError << ' \n ' ;
906
- } else if (!CompletionError.empty ()) {
907
- llvm::errs () << CompletionError << ' \n ' ;
908
- return true ;
949
+ }
950
+
951
+ template <typename ResultType>
952
+ static int printResult (CancellableResult<ResultType> Result,
953
+ llvm::function_ref<int (ResultType &)> PrintSuccess) {
954
+ switch (Result.getKind ()) {
955
+ case CancellableResultKind::Success: {
956
+ return PrintSuccess (Result.getResult ());
957
+ }
958
+ case CancellableResultKind::Failure:
959
+ llvm::errs () << " error: " << Result.getError () << ' \n ' ;
960
+ return 1 ;
961
+ case CancellableResultKind::Cancelled:
962
+ llvm::errs () << " request cancelled\n " ;
963
+ return 1 ;
964
+ break ;
909
965
}
910
- return false ;
966
+ }
967
+
968
+ static int printTypeContextInfo (
969
+ CancellableResult<TypeContextInfoResult> CancellableResult) {
970
+ return printResult<TypeContextInfoResult>(
971
+ CancellableResult, [](TypeContextInfoResult &Result) {
972
+ llvm::outs () << " -----BEGIN TYPE CONTEXT INFO-----\n " ;
973
+ for (auto resultItem : Result.Results ) {
974
+ llvm::outs () << " - TypeName: " ;
975
+ resultItem.ExpectedTy .print (llvm::outs ());
976
+ llvm::outs () << " \n " ;
977
+
978
+ llvm::outs () << " TypeUSR: " ;
979
+ printTypeUSR (resultItem.ExpectedTy , llvm::outs ());
980
+ llvm::outs () << " \n " ;
981
+
982
+ llvm::outs () << " ImplicitMembers:" ;
983
+ if (resultItem.ImplicitMembers .empty ())
984
+ llvm::outs () << " []" ;
985
+ llvm::outs () << " \n " ;
986
+ for (auto VD : resultItem.ImplicitMembers ) {
987
+ llvm::outs () << " - " ;
988
+
989
+ llvm::outs () << " Name: " ;
990
+ VD->getName ().print (llvm::outs ());
991
+ llvm::outs () << " \n " ;
992
+
993
+ StringRef BriefDoc = VD->getBriefComment ();
994
+ if (!BriefDoc.empty ()) {
995
+ llvm::outs () << " DocBrief: \" " ;
996
+ llvm::outs () << VD->getBriefComment ();
997
+ llvm::outs () << " \"\n " ;
998
+ }
999
+ }
1000
+ }
1001
+ llvm::outs () << " -----END TYPE CONTEXT INFO-----\n " ;
1002
+ return 0 ;
1003
+ });
911
1004
}
912
1005
913
1006
static int doTypeContextInfo (const CompilerInvocation &InitInvok,
914
1007
StringRef SourceFilename,
915
1008
StringRef SecondSourceFileName,
916
1009
StringRef CodeCompletionToken,
917
1010
bool CodeCompletionDiagnostics) {
918
- // Create a CodeCompletionConsumer.
919
- std::unique_ptr<ide::TypeContextInfoConsumer> Consumer (
920
- new ide::PrintingTypeContextInfoConsumer (llvm::outs ()));
921
-
922
- // Create a factory for code completion callbacks that will feed the
923
- // Consumer.
924
- std::unique_ptr<CodeCompletionCallbacksFactory> callbacksFactory (
925
- ide::makeTypeContextInfoCallbacksFactory (*Consumer));
926
-
927
- return doCodeCompletionImpl (callbacksFactory.get (), InitInvok, SourceFilename,
928
- SecondSourceFileName, CodeCompletionToken,
929
- CodeCompletionDiagnostics);
1011
+ return performWithCompletionLikeOperationParams (
1012
+ InitInvok, SourceFilename, SecondSourceFileName, CodeCompletionToken,
1013
+ CodeCompletionDiagnostics,
1014
+ [&](CompletionLikeOperationParams Params) -> bool {
1015
+ CompletionInstance CompletionInst;
1016
+ int ExitCode = 2 ;
1017
+ CompletionInst.typeContextInfo (
1018
+ Params.Invocation , Params.Args , Params.FileSystem ,
1019
+ Params.CompletionBuffer , Params.Offset , Params.DiagC ,
1020
+ [&](CancellableResult<TypeContextInfoResult> Result) {
1021
+ ExitCode = printTypeContextInfo (Result);
1022
+ });
1023
+ return ExitCode;
1024
+ });
930
1025
}
931
1026
932
1027
static int
0 commit comments