4343#include " swift/IDE/IDERequests.h"
4444#include " swift/IDE/ModuleInterfacePrinting.h"
4545#include " swift/IDE/REPLCodeCompletion.h"
46+ #include " swift/IDE/SignatureHelp.h"
47+ #include " swift/IDE/SignatureHelpFormatter.h"
4648#include " swift/IDE/SourceEntityWalker.h"
4749#include " swift/IDE/SyntaxModel.h"
4850#include " swift/IDE/TypeContextInfo.h"
@@ -117,6 +119,7 @@ enum class ActionType {
117119 Range,
118120 TypeContextInfo,
119121 ConformingMethodList,
122+ SignatureHelp,
120123};
121124
122125class NullDebuggerClient : public DebuggerClient {
@@ -251,7 +254,9 @@ Action(llvm::cl::desc("Mode:"), llvm::cl::init(ActionType::None),
251254 " Print types for all expressions in the file" ),
252255 clEnumValN(ActionType::ConformingMethodList,
253256 " conforming-methods" ,
254- " Perform conforming method analysis for expression" )));
257+ " Perform conforming method analysis for expression" ),
258+ clEnumValN(ActionType::SignatureHelp, " signature-help" ,
259+ " Perform signature help" )));
255260
256261static llvm::cl::opt<std::string>
257262SourceFilename (" source-filename" , llvm::cl::desc(" Name of the source file" ),
@@ -1446,6 +1451,101 @@ printCodeCompletionLookedupTypeNames(ArrayRef<NullTerminatedStringRef> names,
14461451 OS << " ]\n " ;
14471452}
14481453
1454+ static void printWithEscaping (StringRef Str, llvm::raw_ostream &OS) {
1455+ for (char C : Str) {
1456+ switch (C) {
1457+ case ' \n ' :
1458+ OS << " \\ n" ;
1459+ break ;
1460+ case ' \r ' :
1461+ OS << " \\ r" ;
1462+ break ;
1463+ case ' \t ' :
1464+ OS << " \\ t" ;
1465+ break ;
1466+ case ' \v ' :
1467+ OS << " \\ v" ;
1468+ break ;
1469+ case ' \f ' :
1470+ OS << " \\ f" ;
1471+ break ;
1472+ default :
1473+ OS << C;
1474+ break ;
1475+ }
1476+ }
1477+ }
1478+
1479+ static void printSignatureHelpResultsImpl (const FormattedSignatureHelp &Result,
1480+ llvm::raw_ostream &OS) {
1481+ OS << " Begin signatures, " << Result.Signatures .size () << " items\n " ;
1482+
1483+ for (unsigned i = 0 ; i < Result.Signatures .size (); ++i) {
1484+ const auto &Signature = Result.Signatures [i];
1485+ if (i == Result.ActiveSignature ) {
1486+ OS << " Signature[Active]: " ;
1487+ } else {
1488+ OS << " Signature: " ;
1489+ }
1490+
1491+ StringRef signatureText = Signature.Text ;
1492+ std::string formattedSignature;
1493+ llvm::raw_string_ostream signatureOS (formattedSignature);
1494+
1495+ unsigned currentPos = 0 ;
1496+ for (unsigned j = 0 ; j < Signature.Params .size (); ++j) {
1497+ const auto &Param = Signature.Params [j];
1498+
1499+ if (Param.Offset > currentPos) {
1500+ signatureOS << signatureText.substr (currentPos,
1501+ Param.Offset - currentPos);
1502+ }
1503+
1504+ signatureOS << " <param name=\" " << Param.Name << " \" " ;
1505+ if (Signature.ActiveParam && *Signature.ActiveParam == j) {
1506+ signatureOS << " active" ;
1507+ }
1508+ signatureOS << " >" ;
1509+ signatureOS << signatureText.substr (Param.Offset , Param.Length );
1510+ signatureOS << " </param>" ;
1511+
1512+ currentPos = Param.Offset + Param.Length ;
1513+ }
1514+
1515+ if (currentPos < signatureText.size ()) {
1516+ signatureOS << signatureText.substr (currentPos);
1517+ }
1518+
1519+ OS << formattedSignature;
1520+
1521+ if (!Signature.DocComment .empty ()) {
1522+ OS << " ; Documentation=" ;
1523+ printWithEscaping (Signature.DocComment , OS);
1524+ }
1525+
1526+ OS << " \n " ;
1527+ }
1528+
1529+ OS << " End signatures\n " ;
1530+ }
1531+
1532+ static int printSignatureHelpResults (
1533+ CancellableResult<SignatureHelpResults> CancellableResult) {
1534+ llvm::raw_fd_ostream &OS = llvm::outs ();
1535+ return printResult<SignatureHelpResults>(
1536+ CancellableResult, [&](const SignatureHelpResults &Results) {
1537+ if (Results.Result ) {
1538+ llvm::BumpPtrAllocator Allocator;
1539+ SignatureHelpFormatter Formatter (Allocator);
1540+ auto FormattedResult = Formatter.format (*Results.Result );
1541+ printSignatureHelpResultsImpl (FormattedResult, OS);
1542+ } else {
1543+ OS << " No signature help results\n " ;
1544+ }
1545+ return 0 ;
1546+ });
1547+ }
1548+
14491549static int printCodeCompletionResults (
14501550 CancellableResult<CodeCompleteResult> CancellableResult,
14511551 bool IncludeKeywords, bool IncludeComments, bool IncludeSourceText,
@@ -1463,6 +1563,27 @@ static int printCodeCompletionResults(
14631563 });
14641564}
14651565
1566+ static int doSignatureHelp (const CompilerInvocation &InitInvok,
1567+ StringRef SourceFilename,
1568+ StringRef SecondSourceFileName,
1569+ StringRef SignatureHelpToken,
1570+ bool SignatureHelpDiagnostics) {
1571+ return performWithCompletionLikeOperationParams (
1572+ InitInvok, SourceFilename, SecondSourceFileName, SignatureHelpToken,
1573+ SignatureHelpDiagnostics,
1574+ [&](CompletionLikeOperationParams Params) -> bool {
1575+ IDEInspectionInstance Inst (std::make_shared<PluginRegistry>());
1576+ int ExitCode = 2 ;
1577+ Inst.signatureHelp (Params.Invocation , Params.Args , Params.FileSystem ,
1578+ Params.CompletionBuffer , Params.Offset , Params.DiagC ,
1579+ /* CancellationFlag=*/ nullptr ,
1580+ [&](CancellableResult<SignatureHelpResults> Result) {
1581+ ExitCode = printSignatureHelpResults (Result);
1582+ });
1583+ return ExitCode;
1584+ });
1585+ }
1586+
14661587static int
14671588doCodeCompletion (const CompilerInvocation &InitInvok, StringRef SourceFilename,
14681589 StringRef SecondSourceFileName, StringRef CodeCompletionToken,
@@ -3470,19 +3591,6 @@ class ASTCommentPrinter : public ASTWalker {
34703591 ASTCommentPrinter (SourceManager &SM, XMLValidator &TheXMLValidator)
34713592 : OS(llvm::outs()), SM(SM), TheXMLValidator(TheXMLValidator) {}
34723593
3473- void printWithEscaping (StringRef Str) {
3474- for (char C : Str) {
3475- switch (C) {
3476- case ' \n ' : OS << " \\ n" ; break ;
3477- case ' \r ' : OS << " \\ r" ; break ;
3478- case ' \t ' : OS << " \\ t" ; break ;
3479- case ' \v ' : OS << " \\ v" ; break ;
3480- case ' \f ' : OS << " \\ f" ; break ;
3481- default : OS << C; break ;
3482- }
3483- }
3484- }
3485-
34863594 void printDeclName (const ValueDecl *VD) {
34873595 if (auto *NTD = dyn_cast<NominalTypeDecl>(VD->getDeclContext ())) {
34883596 Identifier Id = NTD->getName ();
@@ -3555,7 +3663,7 @@ class ASTCommentPrinter : public ASTWalker {
35553663 }
35563664 OS << " [" ;
35573665 for (auto &SRC : RC.Comments )
3558- printWithEscaping (SRC.RawText );
3666+ printWithEscaping (SRC.RawText , OS );
35593667 OS << " ]" ;
35603668 }
35613669
@@ -3566,7 +3674,7 @@ class ASTCommentPrinter : public ASTWalker {
35663674 return ;
35673675 }
35683676 OS << " [" ;
3569- printWithEscaping (Brief);
3677+ printWithEscaping (Brief, OS );
35703678 OS << " ]" ;
35713679 }
35723680
@@ -3582,7 +3690,7 @@ class ASTCommentPrinter : public ASTWalker {
35823690 return ;
35833691 }
35843692 OS << " [" ;
3585- printWithEscaping (XML);
3693+ printWithEscaping (XML, OS );
35863694 OS << " ]" ;
35873695
35883696 auto Status = TheXMLValidator.validate (XML);
@@ -4849,6 +4957,16 @@ int main(int argc, char *argv[]) {
48494957 options::ConformingMethodListExpectedTypes);
48504958 break ;
48514959
4960+ case ActionType::SignatureHelp:
4961+ if (options::CodeCompletionToken.empty ()) {
4962+ llvm::errs () << " signature help token name required\n " ;
4963+ return 1 ;
4964+ }
4965+ ExitCode = doSignatureHelp (
4966+ InitInvok, options::SourceFilename, options::SecondSourceFilename,
4967+ options::CodeCompletionToken, options::CodeCompletionDiagnostics);
4968+ break ;
4969+
48524970 case ActionType::SyntaxColoring:
48534971 ExitCode = doSyntaxColoring (InitInvok,
48544972 options::SourceFilename,
0 commit comments