43
43
#include " swift/IDE/IDERequests.h"
44
44
#include " swift/IDE/ModuleInterfacePrinting.h"
45
45
#include " swift/IDE/REPLCodeCompletion.h"
46
+ #include " swift/IDE/SignatureHelp.h"
47
+ #include " swift/IDE/SignatureHelpFormatter.h"
46
48
#include " swift/IDE/SourceEntityWalker.h"
47
49
#include " swift/IDE/SyntaxModel.h"
48
50
#include " swift/IDE/TypeContextInfo.h"
@@ -117,6 +119,7 @@ enum class ActionType {
117
119
Range,
118
120
TypeContextInfo,
119
121
ConformingMethodList,
122
+ SignatureHelp,
120
123
};
121
124
122
125
class NullDebuggerClient : public DebuggerClient {
@@ -251,7 +254,9 @@ Action(llvm::cl::desc("Mode:"), llvm::cl::init(ActionType::None),
251
254
" Print types for all expressions in the file" ),
252
255
clEnumValN(ActionType::ConformingMethodList,
253
256
" 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" )));
255
260
256
261
static llvm::cl::opt<std::string>
257
262
SourceFilename (" source-filename" , llvm::cl::desc(" Name of the source file" ),
@@ -1446,6 +1451,101 @@ printCodeCompletionLookedupTypeNames(ArrayRef<NullTerminatedStringRef> names,
1446
1451
OS << " ]\n " ;
1447
1452
}
1448
1453
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
+
1449
1549
static int printCodeCompletionResults (
1450
1550
CancellableResult<CodeCompleteResult> CancellableResult,
1451
1551
bool IncludeKeywords, bool IncludeComments, bool IncludeSourceText,
@@ -1463,6 +1563,27 @@ static int printCodeCompletionResults(
1463
1563
});
1464
1564
}
1465
1565
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
+
1466
1587
static int
1467
1588
doCodeCompletion (const CompilerInvocation &InitInvok, StringRef SourceFilename,
1468
1589
StringRef SecondSourceFileName, StringRef CodeCompletionToken,
@@ -3470,19 +3591,6 @@ class ASTCommentPrinter : public ASTWalker {
3470
3591
ASTCommentPrinter (SourceManager &SM, XMLValidator &TheXMLValidator)
3471
3592
: OS(llvm::outs()), SM(SM), TheXMLValidator(TheXMLValidator) {}
3472
3593
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
-
3486
3594
void printDeclName (const ValueDecl *VD) {
3487
3595
if (auto *NTD = dyn_cast<NominalTypeDecl>(VD->getDeclContext ())) {
3488
3596
Identifier Id = NTD->getName ();
@@ -3555,7 +3663,7 @@ class ASTCommentPrinter : public ASTWalker {
3555
3663
}
3556
3664
OS << " [" ;
3557
3665
for (auto &SRC : RC.Comments )
3558
- printWithEscaping (SRC.RawText );
3666
+ printWithEscaping (SRC.RawText , OS );
3559
3667
OS << " ]" ;
3560
3668
}
3561
3669
@@ -3566,7 +3674,7 @@ class ASTCommentPrinter : public ASTWalker {
3566
3674
return ;
3567
3675
}
3568
3676
OS << " [" ;
3569
- printWithEscaping (Brief);
3677
+ printWithEscaping (Brief, OS );
3570
3678
OS << " ]" ;
3571
3679
}
3572
3680
@@ -3582,7 +3690,7 @@ class ASTCommentPrinter : public ASTWalker {
3582
3690
return ;
3583
3691
}
3584
3692
OS << " [" ;
3585
- printWithEscaping (XML);
3693
+ printWithEscaping (XML, OS );
3586
3694
OS << " ]" ;
3587
3695
3588
3696
auto Status = TheXMLValidator.validate (XML);
@@ -4849,6 +4957,16 @@ int main(int argc, char *argv[]) {
4849
4957
options::ConformingMethodListExpectedTypes);
4850
4958
break ;
4851
4959
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
+
4852
4970
case ActionType::SyntaxColoring:
4853
4971
ExitCode = doSyntaxColoring (InitInvok,
4854
4972
options::SourceFilename,
0 commit comments