mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge remote-tracking branch 'origin/main' into rebranch
This commit is contained in:
85
include/swift/IDE/SignatureHelpFormatter.h
Normal file
85
include/swift/IDE/SignatureHelpFormatter.h
Normal file
@@ -0,0 +1,85 @@
|
||||
//===--- SignatureHelpFormatter.h --- ---------------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2025 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_IDE_SIGNATURE_HELP_FORMATTER_H
|
||||
#define SWIFT_IDE_SIGNATURE_HELP_FORMATTER_H
|
||||
|
||||
#include "swift/IDE/SignatureHelp.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
class DeclContext;
|
||||
|
||||
namespace ide {
|
||||
|
||||
class CodeCompletionString;
|
||||
|
||||
struct FormattedSignatureHelp {
|
||||
struct Parameter {
|
||||
/// The offset of the parameter text in the signature text.
|
||||
unsigned Offset;
|
||||
|
||||
/// The length of the parameter text in the signature text.
|
||||
unsigned Length;
|
||||
|
||||
/// The internal parameter name.
|
||||
llvm::StringRef Name;
|
||||
|
||||
Parameter() {}
|
||||
};
|
||||
|
||||
struct Signature {
|
||||
llvm::StringRef Text;
|
||||
llvm::StringRef DocComment;
|
||||
std::optional<unsigned> ActiveParam;
|
||||
llvm::ArrayRef<Parameter> Params;
|
||||
|
||||
Signature(llvm::StringRef Text, llvm::StringRef DocComment,
|
||||
std::optional<unsigned> ActiveParam,
|
||||
llvm::ArrayRef<Parameter> Params)
|
||||
: Text(Text), DocComment(DocComment), ActiveParam(ActiveParam),
|
||||
Params(Params) {}
|
||||
};
|
||||
|
||||
llvm::ArrayRef<Signature> Signatures;
|
||||
unsigned ActiveSignature;
|
||||
|
||||
FormattedSignatureHelp(llvm::ArrayRef<Signature> Signatures,
|
||||
unsigned ActiveSignature)
|
||||
: Signatures(Signatures), ActiveSignature(ActiveSignature) {}
|
||||
};
|
||||
|
||||
class SignatureHelpFormatter {
|
||||
private:
|
||||
llvm::BumpPtrAllocator &Allocator;
|
||||
|
||||
public:
|
||||
SignatureHelpFormatter(llvm::BumpPtrAllocator &Allocator)
|
||||
: Allocator(Allocator) {}
|
||||
|
||||
FormattedSignatureHelp format(ide::SignatureHelpResult Result);
|
||||
|
||||
private:
|
||||
FormattedSignatureHelp::Signature
|
||||
formatSignature(const DeclContext *DC, const ide::Signature &Signature);
|
||||
|
||||
CodeCompletionString *createSignatureString(const ide::Signature &Signature,
|
||||
const DeclContext *DC);
|
||||
};
|
||||
|
||||
} // namespace ide
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_IDE_SIGNATURE_HELP_FORMATTER_H
|
||||
@@ -19,6 +19,7 @@ add_swift_host_library(swiftIDE STATIC
|
||||
CompletionOverrideLookup.cpp
|
||||
ConformingMethodList.cpp
|
||||
SignatureHelp.cpp
|
||||
SignatureHelpFormatter.cpp
|
||||
CursorInfo.cpp
|
||||
ExprCompletion.cpp
|
||||
ExprContextAnalysis.cpp
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
#ifndef SWIFT_LIB_IDE_CODE_COMPLETION_RESULT_BUILDER_H
|
||||
#define SWIFT_LIB_IDE_CODE_COMPLETION_RESULT_BUILDER_H
|
||||
|
||||
#include "CodeCompletionStringBuilder.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/IDE/CodeCompletionResult.h"
|
||||
#include "swift/IDE/CodeCompletionResultSink.h"
|
||||
#include "swift/IDE/CodeCompletionStringBuilder.h"
|
||||
|
||||
namespace clang {
|
||||
class Module;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/IDE/CodeCompletionStringBuilder.h"
|
||||
#include "CodeCompletionStringBuilder.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/GenericEnvironment.h"
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/IDE/CodeCompletionStringPrinter.h"
|
||||
#include "CodeCompletionStringBuilder.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
#include "swift/IDE/CodeCompletionStringBuilder.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::ide;
|
||||
|
||||
204
lib/IDE/SignatureHelpFormatter.cpp
Normal file
204
lib/IDE/SignatureHelpFormatter.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
//===--- SignatureHelpFormatter.cpp --- -------------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2025 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/IDE/SignatureHelpFormatter.h"
|
||||
#include "CodeCompletionStringBuilder.h"
|
||||
#include "swift/AST/ParameterList.h"
|
||||
#include "swift/IDE/CommentConversion.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::ide;
|
||||
|
||||
using ChunkKind = CodeCompletionString::Chunk::ChunkKind;
|
||||
|
||||
/// \returns Array of parameters of \p VD accounting for implicitly curried
|
||||
/// instance methods.
|
||||
static ArrayRef<const ParamDecl *>
|
||||
getParameterArray(const ValueDecl *VD, bool IsImplicitlyCurried,
|
||||
const ParamDecl *&Scratch) {
|
||||
if (!VD)
|
||||
return {};
|
||||
|
||||
if (IsImplicitlyCurried) {
|
||||
auto *FD = dyn_cast<AbstractFunctionDecl>(VD);
|
||||
assert(FD && FD->hasImplicitSelfDecl());
|
||||
|
||||
Scratch = FD->getImplicitSelfDecl();
|
||||
return ArrayRef(&Scratch, 1);
|
||||
}
|
||||
|
||||
if (auto *ParamList = VD->getParameterList())
|
||||
return ParamList->getArray();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static StringRef copyAndClearString(llvm::BumpPtrAllocator &Allocator,
|
||||
SmallVectorImpl<char> &Str) {
|
||||
auto Ref = StringRef(Str.data(), Str.size()).copy(Allocator);
|
||||
Str.clear();
|
||||
return Ref;
|
||||
}
|
||||
|
||||
CodeCompletionString *
|
||||
SignatureHelpFormatter::createSignatureString(const ide::Signature &Signature,
|
||||
const DeclContext *DC) {
|
||||
ValueDecl *FD = Signature.FuncD;
|
||||
AnyFunctionType *AFT = Signature.FuncTy;
|
||||
|
||||
GenericSignature GenericSig;
|
||||
if (FD) {
|
||||
if (auto *GC = FD->getAsGenericContext())
|
||||
GenericSig = GC->getGenericSignature();
|
||||
}
|
||||
|
||||
CodeCompletionStringBuilder StringBuilder(
|
||||
Allocator, /*AnnotateResults=*/false,
|
||||
/*UnderscoreEmptyArgumentLabel=*/!Signature.IsSubscript,
|
||||
/*FullParameterFlags=*/true);
|
||||
|
||||
DeclBaseName BaseName;
|
||||
|
||||
if (!Signature.IsSecondApply && FD) {
|
||||
BaseName = FD->getBaseName();
|
||||
} else if (Signature.IsSubscript) {
|
||||
BaseName = DeclBaseName::createSubscript();
|
||||
}
|
||||
|
||||
if (!BaseName.empty())
|
||||
StringBuilder.addValueBaseName(BaseName,
|
||||
/*IsMember=*/bool(Signature.BaseType));
|
||||
|
||||
StringBuilder.addLeftParen();
|
||||
|
||||
const ParamDecl *ParamScratch;
|
||||
StringBuilder.addCallArgumentPatterns(
|
||||
AFT->getParams(),
|
||||
getParameterArray(FD, Signature.IsImplicitlyCurried, ParamScratch), DC,
|
||||
GenericSig, DefaultArgumentOutputMode::All,
|
||||
/*includeDefaultValues=*/true);
|
||||
|
||||
StringBuilder.addRightParen();
|
||||
|
||||
if (!Signature.IsImplicitlyCurried) {
|
||||
if (Signature.IsSecondApply) {
|
||||
// For a second apply, we don't pass the declaration to avoid adding
|
||||
// incorrect rethrows and reasync which are only usable in a single apply.
|
||||
StringBuilder.addEffectsSpecifiers(AFT, /*AFD=*/nullptr);
|
||||
} else {
|
||||
StringBuilder.addEffectsSpecifiers(
|
||||
AFT, dyn_cast_or_null<AbstractFunctionDecl>(FD));
|
||||
}
|
||||
}
|
||||
|
||||
if (FD && FD->isImplicitlyUnwrappedOptional()) {
|
||||
StringBuilder.addTypeAnnotationForImplicitlyUnwrappedOptional(
|
||||
AFT->getResult(), DC, GenericSig);
|
||||
} else {
|
||||
StringBuilder.addTypeAnnotation(AFT->getResult(), DC, GenericSig);
|
||||
}
|
||||
|
||||
return StringBuilder.createCompletionString();
|
||||
}
|
||||
|
||||
FormattedSignatureHelp::Signature
|
||||
SignatureHelpFormatter::formatSignature(const DeclContext *DC,
|
||||
const ide::Signature &Signature) {
|
||||
auto *FD = Signature.FuncD;
|
||||
auto *AFT = Signature.FuncTy;
|
||||
|
||||
bool IsConstructor = isa_and_nonnull<ConstructorDecl>(FD);
|
||||
|
||||
auto *SignatureString = createSignatureString(Signature, DC);
|
||||
|
||||
llvm::SmallString<512> SS;
|
||||
llvm::raw_svector_ostream OS(SS);
|
||||
|
||||
bool SkipResult = AFT->getResult()->isVoid() || IsConstructor;
|
||||
|
||||
SmallVector<FormattedSignatureHelp::Parameter, 8> FormattedParams;
|
||||
|
||||
auto Chunks = SignatureString->getChunks();
|
||||
auto C = Chunks.begin();
|
||||
while (C != Chunks.end()) {
|
||||
if (C->is(ChunkKind::TypeAnnotation) && SkipResult) {
|
||||
++C;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (C->is(ChunkKind::TypeAnnotation))
|
||||
OS << " -> ";
|
||||
|
||||
if (C->is(ChunkKind::CallArgumentBegin)) {
|
||||
unsigned NestingLevel = C->getNestingLevel();
|
||||
++C;
|
||||
|
||||
auto &P = FormattedParams.emplace_back();
|
||||
P.Offset = SS.size();
|
||||
|
||||
do {
|
||||
if (!C->is(ChunkKind::CallArgumentClosureType) && C->hasText())
|
||||
OS << C->getText();
|
||||
|
||||
++C;
|
||||
} while (C != Chunks.end() && !C->endsPreviousNestedGroup(NestingLevel));
|
||||
|
||||
P.Length = SS.size() - P.Offset;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (C->hasText())
|
||||
OS << C->getText();
|
||||
|
||||
++C;
|
||||
}
|
||||
|
||||
StringRef SignatureText = copyAndClearString(Allocator, SS);
|
||||
|
||||
// Parameter names.
|
||||
const ParamDecl *ParamScratch;
|
||||
auto ParamDecls =
|
||||
getParameterArray(FD, Signature.IsImplicitlyCurried, ParamScratch);
|
||||
|
||||
if (!ParamDecls.empty()) {
|
||||
for (unsigned i = 0; i < FormattedParams.size(); ++i) {
|
||||
FormattedParams[i].Name = ParamDecls[i]->getParameterName().str();
|
||||
}
|
||||
}
|
||||
|
||||
// Documentation.
|
||||
StringRef DocComment;
|
||||
if (FD) {
|
||||
ide::getRawDocumentationComment(FD, OS);
|
||||
DocComment = copyAndClearString(Allocator, SS);
|
||||
}
|
||||
|
||||
return FormattedSignatureHelp::Signature(
|
||||
SignatureText, DocComment, Signature.ParamIdx,
|
||||
ArrayRef(FormattedParams).copy(Allocator));
|
||||
}
|
||||
|
||||
FormattedSignatureHelp
|
||||
SignatureHelpFormatter::format(SignatureHelpResult Result) {
|
||||
SmallVector<FormattedSignatureHelp::Signature, 8> FormattedSignatures;
|
||||
FormattedSignatures.reserve(Result.Signatures.size());
|
||||
|
||||
for (auto &Signature : Result.Signatures) {
|
||||
FormattedSignatures.push_back(formatSignature(Result.DC, Signature));
|
||||
}
|
||||
|
||||
// FIXME: Ideally we should select an active signature based on the context.
|
||||
unsigned ActiveSignature = 0;
|
||||
|
||||
return FormattedSignatureHelp(ArrayRef(FormattedSignatures).copy(Allocator),
|
||||
ActiveSignature);
|
||||
}
|
||||
@@ -137,7 +137,7 @@ extension Unicode {
|
||||
/// consuming elements from the given source as necessary.
|
||||
///
|
||||
/// If the normalizer returns `nil`, the source was exhausted.
|
||||
/// One a source is exhausted, you may:
|
||||
/// Once a source is exhausted, you may:
|
||||
///
|
||||
/// - Call `resume` again some time later with a different source
|
||||
/// to continue processing the same logical text stream, or
|
||||
|
||||
7
test/IDE/signature_help_closure_param.swift
Normal file
7
test/IDE/signature_help_closure_param.swift
Normal file
@@ -0,0 +1,7 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=CLOSURE_PARAM -source-filename=%s | %FileCheck %s --check-prefix=CLOSURE_PARAM
|
||||
|
||||
func apply<Value, Result>(value: Value, body: (Value) -> Result) -> Result {
|
||||
return body(#^CLOSURE_PARAM^#)
|
||||
// CLOSURE_PARAM: Begin signatures, 1 items
|
||||
// CLOSURE_PARAM-DAG: Signature[Active]: body(<param active>Value</param>) -> Result
|
||||
}
|
||||
74
test/IDE/signature_help_currying.swift
Normal file
74
test/IDE/signature_help_currying.swift
Normal file
@@ -0,0 +1,74 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=CURRY_TOPLEVEL -source-filename=%s | %FileCheck %s --check-prefix=CURRY_TOPLEVEL
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=CURRY_MEMBER_PARTIAL -source-filename=%s | %FileCheck %s --check-prefix=CURRY_MEMBER_PARTIAL
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=CURRY_MEMBER_FULL -source-filename=%s | %FileCheck %s --check-prefix=CURRY_MEMBER_FULL
|
||||
|
||||
struct Adder {
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(oneTo x: inout Int) {
|
||||
x += 1
|
||||
}
|
||||
|
||||
func add<T: AdditiveArithmetic>(_ x: T, to y: T) -> T {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(first: Double!, second: Float, third: Int) -> Double {
|
||||
return first + Double(second) + Double(third)
|
||||
}
|
||||
|
||||
func add(arg1 param1: Double, arg2: Float, arg3 param3: Int) -> Double {
|
||||
return param1 + Double(arg2) + Double(param3)
|
||||
}
|
||||
|
||||
func add(numbers: Double...) -> Double {
|
||||
return numbers.reduce(into: 0) { $0 += $1 }
|
||||
}
|
||||
|
||||
func add(x: Int, y: Int, with adder: (Int, Int) throws -> Int) rethrows -> Int! {
|
||||
return try adder(x, y)
|
||||
}
|
||||
|
||||
func add(x: Int) -> (Int) -> Int {
|
||||
return { (y: Int) in x + y }
|
||||
}
|
||||
}
|
||||
|
||||
func topLevelCurried(x: Int) -> (Double) -> (String) -> Void {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
func testCurryTopLevel() {
|
||||
topLevelCurried(x: 1)(#^CURRY_TOPLEVEL^#)
|
||||
// CURRY_TOPLEVEL: Begin signatures, 1 items
|
||||
// CURRY_TOPLEVEL-DAG: Signature[Active]: (<param active>Double</param>) -> (String) -> Void
|
||||
}
|
||||
|
||||
func testCurryMemberPartial() {
|
||||
Adder.add(#^CURRY_MEMBER_PARTIAL^#)
|
||||
// CURRY_MEMBER_PARTIAL: Begin signatures, 8 items
|
||||
// CURRY_MEMBER_PARTIAL-DAG: Signature[Active]: add(<param name="self" active>_ self: Adder</param>) -> (Int, Int) -> Int
|
||||
// CURRY_MEMBER_PARTIAL-DAG: Signature: add(<param name="self" active>_ self: Adder</param>) -> (inout Int) -> ()
|
||||
// CURRY_MEMBER_PARTIAL-DAG: Signature: add(<param name="self" active>_ self: Adder</param>) -> (AdditiveArithmetic, AdditiveArithmetic) -> AdditiveArithmetic
|
||||
// CURRY_MEMBER_PARTIAL-DAG: Signature: add(<param name="self" active>_ self: Adder</param>) -> (Double?, Float, Int) -> Double
|
||||
// CURRY_MEMBER_PARTIAL-DAG: Signature: add(<param name="self" active>_ self: Adder</param>) -> (Double, Float, Int) -> Double
|
||||
// CURRY_MEMBER_PARTIAL-DAG: Signature: add(<param name="self" active>_ self: Adder</param>) -> (Double...) -> Double
|
||||
// CURRY_MEMBER_PARTIAL-DAG: Signature: add(<param name="self" active>_ self: Adder</param>) -> (Int, Int, (Int, Int) throws -> Int) throws -> Int?
|
||||
// CURRY_MEMBER_PARTIAL-DAG: Signature: add(<param name="self" active>_ self: Adder</param>) -> (Int) -> (Int) -> Int
|
||||
}
|
||||
|
||||
func testCurryMemberFull() {
|
||||
let adder = Adder()
|
||||
Adder.add(adder)(#^CURRY_MEMBER_FULL^#)
|
||||
// CURRY_MEMBER_FULL: Begin signatures, 8 items
|
||||
// CURRY_MEMBER_FULL-DAG: Signature[Active]: (<param name="x" active>_ x: Int</param>, <param name="y">to: Int</param>) -> Int
|
||||
// CURRY_MEMBER_FULL-DAG: Signature: (<param name="x" active>oneTo: inout Int</param>)
|
||||
// CURRY_MEMBER_FULL-DAG: Signature: (<param name="x" active>_ x: AdditiveArithmetic</param>, <param name="y">to: AdditiveArithmetic</param>) -> AdditiveArithmetic
|
||||
// CURRY_MEMBER_FULL-DAG: Signature: (<param name="first" active>first: Double!</param>, <param name="second">second: Float</param>, <param name="third">third: Int</param>) -> Double
|
||||
// CURRY_MEMBER_FULL-DAG: Signature: (<param name="param1" active>arg1: Double</param>, <param name="arg2">arg2: Float</param>, <param name="param3">arg3: Int</param>) -> Double
|
||||
// CURRY_MEMBER_FULL-DAG: Signature: (<param name="numbers" active>numbers: Double...</param>) -> Double
|
||||
// CURRY_MEMBER_FULL-DAG: Signature: (<param name="x" active>x: Int</param>, <param name="y">y: Int</param>, <param name="adder">with: (Int, Int) throws -> Int</param>) throws -> Int!
|
||||
// CURRY_MEMBER_FULL-DAG: Signature: (<param name="x" active>x: Int</param>) -> (Int) -> Int
|
||||
}
|
||||
34
test/IDE/signature_help_default_args.swift
Normal file
34
test/IDE/signature_help_default_args.swift
Normal file
@@ -0,0 +1,34 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=DEFAULT_ARGS -source-filename=%s | %FileCheck %s --check-prefix=DEFAULT_ARGS
|
||||
|
||||
func add(_ x: Int = 10, to y: Int) -> Int {}
|
||||
|
||||
func add(oneTo x: inout Int) {}
|
||||
|
||||
func add(_ x: Int, to y: Int? = nil) -> String {}
|
||||
|
||||
func add(first: Double!, second: Float = .pi, third: Int) -> Double {}
|
||||
|
||||
struct S {
|
||||
let a: Bool
|
||||
}
|
||||
|
||||
func add(s: S = S(a: false)) -> Double {}
|
||||
|
||||
func add(x: Int, y: Int, with adder: (Int, Int) -> Int = { $0 + $1 }) -> Int {}
|
||||
|
||||
let importantValue = 42
|
||||
|
||||
func add(x: Int = importantValue) {}
|
||||
|
||||
func add(x: Int, line: UInt = #line, file: StaticString = #file) {}
|
||||
|
||||
add(#^DEFAULT_ARGS^#)
|
||||
// DEFAULT_ARGS: Begin signatures, 8 items
|
||||
// DEFAULT_ARGS-DAG: Signature[Active]: add(<param name="x" active>_ x: Int = 10</param>, <param name="y">to: Int</param>) -> Int
|
||||
// DEFAULT_ARGS-DAG: Signature: add(<param name="x" active>oneTo: inout Int</param>)
|
||||
// DEFAULT_ARGS-DAG: Signature: add(<param name="x" active>_ x: Int</param>, <param name="y">to: Int? = nil</param>) -> String
|
||||
// DEFAULT_ARGS-DAG: Signature: add(<param name="first" active>first: Double!</param>, <param name="second">second: Float = .pi</param>, <param name="third">third: Int</param>) -> Double
|
||||
// DEFAULT_ARGS-DAG: Signature: add(<param name="s" active>s: S = S(a: false)</param>) -> Double
|
||||
// DEFAULT_ARGS-DAG: Signature: add(<param name="x" active>x: Int</param>, <param name="y">y: Int</param>, <param name="adder">with: (Int, Int) -> Int = { $0 + $1 }</param>) -> Int
|
||||
// DEFAULT_ARGS-DAG: Signature: add(<param name="x" active>x: Int = importantValue</param>)
|
||||
// DEFAULT_ARGS-DAG: Signature: add(<param name="x" active>x: Int</param>, <param name="line">line: UInt = #line</param>, <param name="file">file: StaticString = #file</param>)
|
||||
21
test/IDE/signature_help_doc.swift
Normal file
21
test/IDE/signature_help_doc.swift
Normal file
@@ -0,0 +1,21 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=DOC -source-filename=%s | %FileCheck %s --check-prefix=DOC
|
||||
|
||||
/// Adds two integers.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - x: The first integer to add.
|
||||
/// - y: The second integer to add.
|
||||
///
|
||||
/// Usage:
|
||||
/// ```swift
|
||||
/// add(1, to: 2) // 3
|
||||
/// ```
|
||||
///
|
||||
/// - Returns: The sum of the two integers.
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
add(#^DOC^#)
|
||||
// DOC: Begin signatures, 1 items
|
||||
// DOC-DAG: Signature[Active]: add(<param name="x" active>_ x: Int</param>, <param name="y">to: Int</param>) -> Int; Documentation=Adds two integers.\n\n- Parameters:\n - x: The first integer to add.\n - y: The second integer to add.\n\nUsage:\n```swift\nadd(1, to: 2) // 3\n```\n\n- Returns: The sum of the two integers.
|
||||
19
test/IDE/signature_help_enum_case.swift
Normal file
19
test/IDE/signature_help_enum_case.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=LABELLED -source-filename=%s | %FileCheck %s --check-prefix=LABELLED
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=UNLABELLED -source-filename=%s | %FileCheck %s --check-prefix=UNLABELLED
|
||||
|
||||
enum Barcode {
|
||||
case upc(numberSystem: Int, manufacturer: Int, product: Int, check: Int)
|
||||
case qrCode(String)
|
||||
}
|
||||
|
||||
func testLabeled() {
|
||||
Barcode.upc(#^LABELLED^#, manufacturer: 85909, product: 51226, check: 3)
|
||||
// LABELLED: Begin signatures, 1 items
|
||||
// LABELLED-DAG: Signature[Active]: upc(<param name="numberSystem" active>numberSystem: Int</param>, <param name="manufacturer">manufacturer: Int</param>, <param name="product">product: Int</param>, <param name="check">check: Int</param>) -> Barcode
|
||||
}
|
||||
|
||||
func testUnlabled() {
|
||||
Barcode.qrCode(#^UNLABELLED^#)
|
||||
// UNLABELLED: Begin signatures, 1 items
|
||||
// UNLABELLED-DAG: Signature[Active]: qrCode(<param active>String</param>) -> Barcode
|
||||
}
|
||||
9
test/IDE/signature_help_init.swift
Normal file
9
test/IDE/signature_help_init.swift
Normal file
@@ -0,0 +1,9 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=INIT -source-filename=%s | %FileCheck %s --check-prefix=INIT
|
||||
|
||||
struct Person {
|
||||
init(name: String, age: Int, profession job: String) { }
|
||||
}
|
||||
|
||||
Person(name: "John", age: #^INIT^#)
|
||||
// INIT: Begin signatures, 1 items
|
||||
// INIT-DAG: Signature[Active]: init(<param name="name">name: String</param>, <param name="age" active>age: Int</param>, <param name="job">profession: String</param>)
|
||||
11
test/IDE/signature_help_member_closure.swift
Normal file
11
test/IDE/signature_help_member_closure.swift
Normal file
@@ -0,0 +1,11 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=MEMBER_CLOSURE -source-filename=%s | %FileCheck %s --check-prefix=MEMBER_CLOSURE
|
||||
|
||||
struct Observable {
|
||||
var observer: (String, Int?, [AnyHashable: [Double?]]) async throws -> [Observable?]
|
||||
|
||||
func notify() async throws {
|
||||
_ = try await observer("EVENT", #^MEMBER_CLOSURE^#, [:])
|
||||
// MEMBER_CLOSURE: Begin signatures, 1 items
|
||||
// MEMBER_CLOSURE-DAG: Signature[Active]: observer(<param>String</param>, <param active>Int?</param>, <param>[AnyHashable : [Double?]]</param>) async throws -> [Observable?]
|
||||
}
|
||||
}
|
||||
47
test/IDE/signature_help_member_func.swift
Normal file
47
test/IDE/signature_help_member_func.swift
Normal file
@@ -0,0 +1,47 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=MEMBER_FUNC -source-filename=%s | %FileCheck %s --check-prefix=MEMBER_FUNC
|
||||
|
||||
struct Adder {
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(oneTo x: inout Int) {
|
||||
x += 1
|
||||
}
|
||||
|
||||
func add<T: AdditiveArithmetic>(_ x: T, to y: T) -> T {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(first: Double!, second: Float, third: Int) -> Double {
|
||||
return first + Double(second) + Double(third)
|
||||
}
|
||||
|
||||
func add(arg1 param1: Double, arg2: Float, arg3 param3: Int) -> Double {
|
||||
return param1 + Double(arg2) + Double(param3)
|
||||
}
|
||||
|
||||
func add(numbers: Double...) -> Double {
|
||||
return numbers.reduce(into: 0) { $0 += $1 }
|
||||
}
|
||||
|
||||
func add(x: Int, y: Int, with adder: (Int, Int) -> Int) -> Int {
|
||||
return adder(x, y)
|
||||
}
|
||||
|
||||
func add(x: Int) -> (Int) -> Int {
|
||||
return { (y: Int) in x + y }
|
||||
}
|
||||
}
|
||||
|
||||
let adder = Adder()
|
||||
adder.add(#^MEMBER_FUNC^#)
|
||||
// MEMBER_FUNC: Begin signatures, 8 items
|
||||
// MEMBER_FUNC-DAG: Signature[Active]: add(<param name="x" active>_ x: Int</param>, <param name="y">to: Int</param>) -> Int
|
||||
// MEMBER_FUNC-DAG: Signature: add(<param name="x" active>oneTo: inout Int</param>)
|
||||
// MEMBER_FUNC-DAG: Signature: add(<param name="x" active>_ x: AdditiveArithmetic</param>, <param name="y">to: AdditiveArithmetic</param>) -> AdditiveArithmetic
|
||||
// MEMBER_FUNC-DAG: Signature: add(<param name="first" active>first: Double!</param>, <param name="second">second: Float</param>, <param name="third">third: Int</param>) -> Double
|
||||
// MEMBER_FUNC-DAG: Signature: add(<param name="param1" active>arg1: Double</param>, <param name="arg2">arg2: Float</param>, <param name="param3">arg3: Int</param>) -> Double
|
||||
// MEMBER_FUNC-DAG: Signature: add(<param name="numbers" active>numbers: Double...</param>) -> Double
|
||||
// MEMBER_FUNC-DAG: Signature: add(<param name="x" active>x: Int</param>, <param name="y">y: Int</param>, <param name="adder">with: (Int, Int) -> Int</param>) -> Int
|
||||
// MEMBER_FUNC-DAG: Signature: add(<param name="x" active>x: Int</param>) -> (Int) -> Int
|
||||
12
test/IDE/signature_help_member_generic.swift
Normal file
12
test/IDE/signature_help_member_generic.swift
Normal file
@@ -0,0 +1,12 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=MEMBER_GENERIC -source-filename=%s | %FileCheck %s --check-prefix=MEMBER_GENERIC
|
||||
|
||||
struct Vector<Value> {
|
||||
init(elements: [Value]) { }
|
||||
|
||||
func dot(with other: Vector<Value>) -> Value { fatalError() }
|
||||
}
|
||||
|
||||
let vec = Vector(elements: [1.0, 2.1, 3.4])
|
||||
vec.dot(with: #^MEMBER_GENERIC^#)
|
||||
// MEMBER_GENERIC: Begin signatures, 1 items
|
||||
// MEMBER_GENERIC-DAG: Signature[Active]: dot(<param name="other" active>with: Vector<Double></param>) -> Double
|
||||
23
test/IDE/signature_help_member_subscript.swift
Normal file
23
test/IDE/signature_help_member_subscript.swift
Normal file
@@ -0,0 +1,23 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=MEMBER_SUBSCRIPT -source-filename=%s | %FileCheck %s --check-prefix=MEMBER_SUBSCRIPT
|
||||
|
||||
struct Matrix {
|
||||
subscript(row: Int, column: Int) -> Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
subscript(row r: Int) -> [Int] {
|
||||
return []
|
||||
}
|
||||
|
||||
subscript(column c: Int) -> [Int] {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
let matrix = Matrix()
|
||||
matrix[#^MEMBER_SUBSCRIPT^#]
|
||||
// MEMBER_SUBSCRIPT: Begin signatures, 4 items
|
||||
// MEMBER_SUBSCRIPT-DAG: Signature[Active]: subscript(<param active>keyPath: KeyPath<Matrix, Value></param>) -> Value
|
||||
// MEMBER_SUBSCRIPT-DAG: Signature: subscript(<param name="row" active>row: Int</param>, <param name="column">column: Int</param>) -> Int
|
||||
// MEMBER_SUBSCRIPT-DAG: Signature: subscript(<param name="r" active>row: Int</param>) -> [Int]
|
||||
// MEMBER_SUBSCRIPT-DAG: Signature: subscript(<param name="c" active>column: Int</param>) -> [Int]
|
||||
9
test/IDE/signature_help_raw_identifier.swift
Normal file
9
test/IDE/signature_help_raw_identifier.swift
Normal file
@@ -0,0 +1,9 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=RAW_ID -source-filename=%s | %FileCheck %s --check-prefix=RAW_ID
|
||||
|
||||
struct `Raw Identifier` {
|
||||
func `some method :)`(`argument label!` `param label?`: Int) {}
|
||||
}
|
||||
|
||||
`Raw Identifier`().`some method :)`(#^RAW_ID^#)
|
||||
// RAW_ID: Begin signatures, 1 items
|
||||
// RAW_ID-DAG: Signature[Active]: `some method :)`(<param name="param label?" active>`argument label!`: Int</param>)
|
||||
44
test/IDE/signature_help_top_level.swift
Normal file
44
test/IDE/signature_help_top_level.swift
Normal file
@@ -0,0 +1,44 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=TOP_LEVEL -source-filename=%s | %FileCheck %s --check-prefix=TOP_LEVEL
|
||||
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(oneTo x: inout Int) {
|
||||
x += 1
|
||||
}
|
||||
|
||||
func add<T: AdditiveArithmetic>(_ x: T, to y: T) -> T {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(first: Double!, second: Float, third: Int) -> Double {
|
||||
return first + Double(second) + Double(third)
|
||||
}
|
||||
|
||||
func add(arg1 param1: Double, arg2: Float, arg3 param3: Int) -> Double {
|
||||
return param1 + Double(arg2) + Double(param3)
|
||||
}
|
||||
|
||||
func add(numbers: Double...) -> Double {
|
||||
return numbers.reduce(into: 0) { $0 += $1 }
|
||||
}
|
||||
|
||||
func add(x: Int, y: Int, with adder: (Int, Int) -> Int) -> Int {
|
||||
return adder(x, y)
|
||||
}
|
||||
|
||||
func add(x: Int) -> (Int) -> Int {
|
||||
return { (y: Int) in x + y }
|
||||
}
|
||||
|
||||
add(#^TOP_LEVEL^#)
|
||||
// TOP_LEVEL: Begin signatures, 8 items
|
||||
// TOP_LEVEL-DAG: Signature[Active]: add(<param name="x" active>_ x: Int</param>, <param name="y">to: Int</param>) -> Int
|
||||
// TOP_LEVEL-DAG: Signature: add(<param name="x" active>oneTo: inout Int</param>)
|
||||
// TOP_LEVEL-DAG: Signature: add(<param name="x" active>_ x: AdditiveArithmetic</param>, <param name="y">to: AdditiveArithmetic</param>) -> AdditiveArithmetic
|
||||
// TOP_LEVEL-DAG: Signature: add(<param name="first" active>first: Double!</param>, <param name="second">second: Float</param>, <param name="third">third: Int</param>) -> Double
|
||||
// TOP_LEVEL-DAG: Signature: add(<param name="param1" active>arg1: Double</param>, <param name="arg2">arg2: Float</param>, <param name="param3">arg3: Int</param>) -> Double
|
||||
// TOP_LEVEL-DAG: Signature: add(<param name="numbers" active>numbers: Double...</param>) -> Double
|
||||
// TOP_LEVEL-DAG: Signature: add(<param name="x" active>x: Int</param>, <param name="y">y: Int</param>, <param name="adder">with: (Int, Int) -> Int</param>) -> Int
|
||||
// TOP_LEVEL-DAG: Signature: add(<param name="x" active>x: Int</param>) -> (Int) -> Int
|
||||
9
test/IDE/signature_help_top_level_generic.swift
Normal file
9
test/IDE/signature_help_top_level_generic.swift
Normal file
@@ -0,0 +1,9 @@
|
||||
// RUN: %target-swift-ide-test -signature-help -code-completion-token=TOP_LEVEL_GENERIC -source-filename=%s | %FileCheck %s --check-prefix=TOP_LEVEL_GENERIC
|
||||
|
||||
func add<T>(x: T, y: T, with adder: (T, T) -> T) -> T where T: AdditiveArithmetic {
|
||||
return adder(x, y)
|
||||
}
|
||||
|
||||
add(x: "A", y: "B", with: #^TOP_LEVEL_GENERIC^#)
|
||||
// TOP_LEVEL_GENERIC: Begin signatures, 1 items
|
||||
// TOP_LEVEL_GENERIC-DAG: Signature[Active]: add(<param name="x">x: String</param>, <param name="y">y: String</param>, <param name="adder" active>with: (String, String) -> String</param>) -> String
|
||||
64
test/SourceKit/SignatureHelp/signature_help.swift
Normal file
64
test/SourceKit/SignatureHelp/signature_help.swift
Normal file
@@ -0,0 +1,64 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=18:10 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
struct Calculator {
|
||||
/// Adds two numbers together.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - x: The first number to add.
|
||||
/// - y: The second number to add.
|
||||
/// - Returns: The sum of x and y.
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(first: Double, second: Float) -> Double {
|
||||
return first + Double(second)
|
||||
}
|
||||
}
|
||||
|
||||
let calc = Calculator()
|
||||
calc.add()
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "add(_ x: Int, to: Int) -> Int",
|
||||
key.doc_comment: "Adds two numbers together.\n\n- Parameters:\n - x: The first number to add.\n - y: The second number to add.\n- Returns: The sum of x and y.",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 8
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 14,
|
||||
key.namelength: 7
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(first: Double, second: Float) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "first",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
},
|
||||
{
|
||||
key.name: "second",
|
||||
key.nameoffset: 19,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=2:15 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
func apply<Value, Result>(value: Value, body: (Value) -> Result) -> Result {
|
||||
return body()
|
||||
}
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "body(Value) -> Result",
|
||||
key.parameters: [
|
||||
{
|
||||
key.nameoffset: 5,
|
||||
key.namelength: 5
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,305 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=40:25 %t/input.swift -- %t/input.swift > %t/actual_curry_toplevel.result
|
||||
// RUN: diff -u %t/expected_curry_toplevel.result %t/actual_curry_toplevel.result
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=44:13 %t/input.swift -- %t/input.swift > %t/actual_curry_member_partial.result
|
||||
// RUN: diff -u %t/expected_curry_member_partial.result %t/actual_curry_member_partial.result
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=49:20 %t/input.swift -- %t/input.swift > %t/actual_curry_member_full.result
|
||||
// RUN: diff -u %t/expected_curry_member_full.result %t/actual_curry_member_full.result
|
||||
|
||||
//--- input.swift
|
||||
struct Adder {
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(oneTo x: inout Int) {
|
||||
x += 1
|
||||
}
|
||||
|
||||
func add<T: AdditiveArithmetic>(_ x: T, to y: T) -> T {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(first: Double!, second: Float, third: Int) -> Double {
|
||||
return first + Double(second) + Double(third)
|
||||
}
|
||||
|
||||
func add(arg1 param1: Double, arg2: Float, arg3 param3: Int) -> Double {
|
||||
return param1 + Double(arg2) + Double(param3)
|
||||
}
|
||||
|
||||
func add(numbers: Double...) -> Double {
|
||||
return numbers.reduce(into: 0) { $0 += $1 }
|
||||
}
|
||||
|
||||
func add(x: Int, y: Int, with adder: (Int, Int) throws -> Int) rethrows -> Int! {
|
||||
return adder(x, y)
|
||||
}
|
||||
|
||||
func add(x: Int) -> (Int) -> Int {
|
||||
return { (y: Int) in x + y }
|
||||
}
|
||||
}
|
||||
|
||||
func topLevelCurried(x: Int) -> (Double) -> (String) -> Void {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
func testCurryTopLevel() {
|
||||
topLevelCurried(x: 1)()
|
||||
}
|
||||
|
||||
func testCurryMemberPartial() {
|
||||
Adder.add()
|
||||
}
|
||||
|
||||
func testCurryMemberFull() {
|
||||
let adder = Adder()
|
||||
Adder.add(adder)()
|
||||
}
|
||||
|
||||
//--- expected_curry_toplevel.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "(Double) -> (String) -> Void",
|
||||
key.parameters: [
|
||||
{
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 6
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
//--- expected_curry_member_partial.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "add(_ self: Adder) -> (Int, Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "self",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ self: Adder) -> (inout Int) -> ()",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "self",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ self: Adder) -> (AdditiveArithmetic, AdditiveArithmetic) -> AdditiveArithmetic",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "self",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ self: Adder) -> (Double?, Float, Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "self",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ self: Adder) -> (Double, Float, Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "self",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ self: Adder) -> (Double...) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "self",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ self: Adder) -> (Int, Int, (Int, Int) throws -> Int) throws -> Int?",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "self",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ self: Adder) -> (Int) -> (Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "self",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
//--- expected_curry_member_full.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "(_ x: Int, to: Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 8
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 11,
|
||||
key.namelength: 7
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "(oneTo: inout Int)",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 16
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "(_ x: AdditiveArithmetic, to: AdditiveArithmetic) -> AdditiveArithmetic",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 23
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 26,
|
||||
key.namelength: 22
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "(first: Double!, second: Float, third: Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "first",
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 14
|
||||
},
|
||||
{
|
||||
key.name: "second",
|
||||
key.nameoffset: 17,
|
||||
key.namelength: 13
|
||||
},
|
||||
{
|
||||
key.name: "third",
|
||||
key.nameoffset: 32,
|
||||
key.namelength: 10
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "(arg1: Double, arg2: Float, arg3: Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "param1",
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 12
|
||||
},
|
||||
{
|
||||
key.name: "arg2",
|
||||
key.nameoffset: 15,
|
||||
key.namelength: 11
|
||||
},
|
||||
{
|
||||
key.name: "param3",
|
||||
key.nameoffset: 28,
|
||||
key.namelength: 9
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "(numbers: Double...) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "numbers",
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 18
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "(x: Int, y: Int, with: (Int, Int) throws -> Int) throws -> Int!",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 9,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "adder",
|
||||
key.nameoffset: 17,
|
||||
key.namelength: 30
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "(x: Int) -> (Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 1,
|
||||
key.namelength: 6
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=23:5 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
func add(_ x: Int = 10, to y: Int) -> Int {}
|
||||
|
||||
func add(oneTo x: inout Int) {}
|
||||
|
||||
func add(_ x: Int, to y: Int? = nil) -> String {}
|
||||
|
||||
func add(first: Double!, second: Float = .pi, third: Int) -> Double {}
|
||||
|
||||
struct S {
|
||||
let a: Bool
|
||||
}
|
||||
|
||||
func add(s: S = S(a: false)) -> Double {}
|
||||
|
||||
func add(x: Int, y: Int, with adder: (Int, Int) -> Int = { $0 + $1 }) -> Int {}
|
||||
|
||||
let importantValue = 42
|
||||
|
||||
func add(x: Int = importantValue) {}
|
||||
|
||||
func add(x: Int, line: UInt = #line, file: StaticString = #file) {}
|
||||
|
||||
add()
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "add(_ x: Int = 10, to: Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 13
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 19,
|
||||
key.namelength: 7
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(oneTo: inout Int)",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 16
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ x: Int, to: Int? = nil) -> String",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 8
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 14,
|
||||
key.namelength: 14
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(first: Double!, second: Float = .pi, third: Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "first",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 14
|
||||
},
|
||||
{
|
||||
key.name: "second",
|
||||
key.nameoffset: 20,
|
||||
key.namelength: 19
|
||||
},
|
||||
{
|
||||
key.name: "third",
|
||||
key.nameoffset: 41,
|
||||
key.namelength: 10
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(s: S = S(a: false)) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "s",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 18
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(x: Int, y: Int, with: (Int, Int) -> Int = { $0 + $1 }) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 12,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "adder",
|
||||
key.nameoffset: 20,
|
||||
key.namelength: 37
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(x: Int = importantValue)",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 23
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(x: Int, line: UInt = #line, file: StaticString = #file)",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "line",
|
||||
key.nameoffset: 12,
|
||||
key.namelength: 18
|
||||
},
|
||||
{
|
||||
key.name: "file",
|
||||
key.nameoffset: 32,
|
||||
key.namelength: 26
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=17:8 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
/// Adds two integers.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - x: The first integer to add.
|
||||
/// - y: The second integer to add.
|
||||
///
|
||||
/// Usage:
|
||||
/// ```swift
|
||||
/// add(1, to: 2) // 3
|
||||
/// ```
|
||||
///
|
||||
/// - Returns: The sum of the two integers.
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
add(x: )
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "add(_ x: Int, to: Int) -> Int",
|
||||
key.doc_comment: "Adds two integers.\n\n- Parameters:\n - x: The first integer to add.\n - y: The second integer to add.\n\nUsage:\n```swift\nadd(1, to: 2) // 3\n```\n\n- Returns: The sum of the two integers.",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 8
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 14,
|
||||
key.namelength: 7
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=7:15 %t/input.swift -- %t/input.swift > %t/actual_labelled.result
|
||||
// RUN: diff -u %t/expected_labelled.result %t/actual_labelled.result
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=11:18 %t/input.swift -- %t/input.swift > %t/actual_unlabelled.result
|
||||
// RUN: diff -u %t/expected_unlabelled.result %t/actual_unlabelled.result
|
||||
|
||||
//--- input.swift
|
||||
enum Barcode {
|
||||
case upc(numberSystem: Int, manufacturer: Int, product: Int, check: Int)
|
||||
case qrCode(String)
|
||||
}
|
||||
|
||||
func testLabeled() {
|
||||
Barcode.upc(, manufacturer: 85909, product: 51226, check: 3)
|
||||
}
|
||||
|
||||
func testUnlabled() {
|
||||
Barcode.qrCode()
|
||||
}
|
||||
|
||||
//--- expected_labelled.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "upc(numberSystem: Int, manufacturer: Int, product: Int, check: Int) -> Barcode",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "numberSystem",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 17
|
||||
},
|
||||
{
|
||||
key.name: "manufacturer",
|
||||
key.nameoffset: 23,
|
||||
key.namelength: 17
|
||||
},
|
||||
{
|
||||
key.name: "product",
|
||||
key.nameoffset: 42,
|
||||
key.namelength: 12
|
||||
},
|
||||
{
|
||||
key.name: "check",
|
||||
key.nameoffset: 56,
|
||||
key.namelength: 10
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
//--- expected_unlabelled.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "qrCode(String) -> Barcode",
|
||||
key.parameters: [
|
||||
{
|
||||
key.nameoffset: 7,
|
||||
key.namelength: 6
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=5:27 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
struct Person {
|
||||
init(name: String, age: Int, profession job: String) { }
|
||||
}
|
||||
|
||||
Person(name: "John", age: )
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "init(name: String, age: Int, profession: String)",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "name",
|
||||
key.nameoffset: 5,
|
||||
key.namelength: 12
|
||||
},
|
||||
{
|
||||
key.name: "age",
|
||||
key.nameoffset: 19,
|
||||
key.namelength: 8
|
||||
},
|
||||
{
|
||||
key.name: "job",
|
||||
key.nameoffset: 29,
|
||||
key.namelength: 18
|
||||
}
|
||||
],
|
||||
key.active_parameter: 1
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=5:23 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
struct Observable {
|
||||
var observer: (String, Int?, [AnyHashable: [Double?]]) async throws -> [Observable?]
|
||||
|
||||
func notify() async throws {
|
||||
observer("EVENT", , [:])
|
||||
}
|
||||
}
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "observer(String, Int?, [AnyHashable : [Double?]]) async throws -> [Observable?]",
|
||||
key.parameters: [
|
||||
{
|
||||
key.nameoffset: 9,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.nameoffset: 17,
|
||||
key.namelength: 4
|
||||
},
|
||||
{
|
||||
key.nameoffset: 23,
|
||||
key.namelength: 25
|
||||
}
|
||||
],
|
||||
key.active_parameter: 1
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=36:11 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
struct Adder {
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(oneTo x: inout Int) {
|
||||
x += 1
|
||||
}
|
||||
|
||||
func add<T: AdditiveArithmetic>(_ x: T, to y: T) -> T {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(first: Double!, second: Float, third: Int) -> Double {
|
||||
return first + Double(second) + Double(third)
|
||||
}
|
||||
|
||||
func add(arg1 param1: Double, arg2: Float, arg3 param3: Int) -> Double {
|
||||
return param1 + Double(arg2) + Double(param3)
|
||||
}
|
||||
|
||||
func add(numbers: Double...) -> Double {
|
||||
return numbers.reduce(into: 0) { $0 += $1 }
|
||||
}
|
||||
|
||||
func add(x: Int, y: Int, with adder: (Int, Int) -> Int) -> Int {
|
||||
return adder(x, y)
|
||||
}
|
||||
|
||||
func add(x: Int) -> (Int) -> Int {
|
||||
return { (y: Int) in x + y }
|
||||
}
|
||||
}
|
||||
|
||||
let adder = Adder()
|
||||
adder.add()
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "add(_ x: Int, to: Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 8
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 14,
|
||||
key.namelength: 7
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(oneTo: inout Int)",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 16
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ x: AdditiveArithmetic, to: AdditiveArithmetic) -> AdditiveArithmetic",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 23
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 29,
|
||||
key.namelength: 22
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(first: Double!, second: Float, third: Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "first",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 14
|
||||
},
|
||||
{
|
||||
key.name: "second",
|
||||
key.nameoffset: 20,
|
||||
key.namelength: 13
|
||||
},
|
||||
{
|
||||
key.name: "third",
|
||||
key.nameoffset: 35,
|
||||
key.namelength: 10
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(arg1: Double, arg2: Float, arg3: Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "param1",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 12
|
||||
},
|
||||
{
|
||||
key.name: "arg2",
|
||||
key.nameoffset: 18,
|
||||
key.namelength: 11
|
||||
},
|
||||
{
|
||||
key.name: "param3",
|
||||
key.nameoffset: 31,
|
||||
key.namelength: 9
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(numbers: Double...) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "numbers",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 18
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(x: Int, y: Int, with: (Int, Int) -> Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 12,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "adder",
|
||||
key.nameoffset: 20,
|
||||
key.namelength: 23
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(x: Int) -> (Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 6
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=8:15 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
struct Vector<Value> {
|
||||
init(elements: [Value]) { }
|
||||
|
||||
func dot(with other: Vector<Value>) -> Value { }
|
||||
}
|
||||
|
||||
let vec = Vector(elements: [1.0, 2.1, 3.4])
|
||||
vec.dot(with: )
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "dot(with: Vector<Double>) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "other",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 20
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=16:8 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
struct Matrix {
|
||||
subscript(row: Int, column: Int) -> Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
subscript(row r: Int) -> [Int] {
|
||||
return []
|
||||
}
|
||||
|
||||
subscript(column c: Int) -> [Int] {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
let matrix = Matrix()
|
||||
matrix[]
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "subscript(keyPath: KeyPath<Matrix, Value>) -> Value",
|
||||
key.parameters: [
|
||||
{
|
||||
key.nameoffset: 10,
|
||||
key.namelength: 31
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "subscript(row: Int, column: Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "row",
|
||||
key.nameoffset: 10,
|
||||
key.namelength: 8
|
||||
},
|
||||
{
|
||||
key.name: "column",
|
||||
key.nameoffset: 20,
|
||||
key.namelength: 11
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "subscript(row: Int) -> [Int]",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "r",
|
||||
key.nameoffset: 10,
|
||||
key.namelength: 8
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "subscript(column: Int) -> [Int]",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "c",
|
||||
key.nameoffset: 10,
|
||||
key.namelength: 11
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=5:37 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
struct `Raw Identifier` {
|
||||
func `some method :)`(`argument label!` `param label?`: Int) {}
|
||||
}
|
||||
|
||||
`Raw Identifier`().`some method :)`()
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "`some method :)`(`argument label!`: Int)",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "param label?",
|
||||
key.nameoffset: 17,
|
||||
key.namelength: 22
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=33:5 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
func add(_ x: Int, to y: Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(oneTo x: inout Int) {
|
||||
x += 1
|
||||
}
|
||||
|
||||
func add<T: AdditiveArithmetic>(_ x: T, to y: T) -> T {
|
||||
return x + y
|
||||
}
|
||||
|
||||
func add(first: Double!, second: Float, third: Int) -> Double {
|
||||
return first + Double(second) + Double(third)
|
||||
}
|
||||
|
||||
func add(arg1 param1: Double, arg2: Float, arg3 param3: Int) -> Double {
|
||||
return param1 + Double(arg2) + Double(param3)
|
||||
}
|
||||
|
||||
func add(numbers: Double...) -> Double {
|
||||
return numbers.reduce(into: 0) { $0 += $1 }
|
||||
}
|
||||
|
||||
func add(x: Int, y: Int, with adder: (Int, Int) -> Int) -> Int {
|
||||
return adder(x, y)
|
||||
}
|
||||
|
||||
func add(x: Int) -> (Int) -> Int {
|
||||
return { (y: Int) in x + y }
|
||||
}
|
||||
|
||||
add()
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "add(_ x: Int, to: Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 8
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 14,
|
||||
key.namelength: 7
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(oneTo: inout Int)",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 16
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(_ x: AdditiveArithmetic, to: AdditiveArithmetic) -> AdditiveArithmetic",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 23
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 29,
|
||||
key.namelength: 22
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(first: Double!, second: Float, third: Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "first",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 14
|
||||
},
|
||||
{
|
||||
key.name: "second",
|
||||
key.nameoffset: 20,
|
||||
key.namelength: 13
|
||||
},
|
||||
{
|
||||
key.name: "third",
|
||||
key.nameoffset: 35,
|
||||
key.namelength: 10
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(arg1: Double, arg2: Float, arg3: Int) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "param1",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 12
|
||||
},
|
||||
{
|
||||
key.name: "arg2",
|
||||
key.nameoffset: 18,
|
||||
key.namelength: 11
|
||||
},
|
||||
{
|
||||
key.name: "param3",
|
||||
key.nameoffset: 31,
|
||||
key.namelength: 9
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(numbers: Double...) -> Double",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "numbers",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 18
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(x: Int, y: Int, with: (Int, Int) -> Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 12,
|
||||
key.namelength: 6
|
||||
},
|
||||
{
|
||||
key.name: "adder",
|
||||
key.nameoffset: 20,
|
||||
key.namelength: 23
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
},
|
||||
{
|
||||
key.name: "add(x: Int) -> (Int) -> Int",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 6
|
||||
}
|
||||
],
|
||||
key.active_parameter: 0
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %sourcekitd-test -req=signaturehelp -pos=5:27 %t/input.swift -- %t/input.swift > %t/actual.result
|
||||
// RUN: diff -u %t/expected.result %t/actual.result
|
||||
|
||||
//--- input.swift
|
||||
func add<T>(x: T, y: T, with adder: (T, T) -> T) -> T where T: AdditiveArithmetic {
|
||||
return adder(x, y)
|
||||
}
|
||||
|
||||
add(x: "A", y: "B", with: )
|
||||
|
||||
//--- expected.result
|
||||
{
|
||||
key.signatures: [
|
||||
{
|
||||
key.name: "add(x: String, y: String, with: (String, String) -> String) -> String",
|
||||
key.parameters: [
|
||||
{
|
||||
key.name: "x",
|
||||
key.nameoffset: 4,
|
||||
key.namelength: 9
|
||||
},
|
||||
{
|
||||
key.name: "y",
|
||||
key.nameoffset: 15,
|
||||
key.namelength: 9
|
||||
},
|
||||
{
|
||||
key.name: "adder",
|
||||
key.nameoffset: 26,
|
||||
key.namelength: 32
|
||||
}
|
||||
],
|
||||
key.active_parameter: 2
|
||||
}
|
||||
],
|
||||
key.active_signature: 0
|
||||
}
|
||||
@@ -35,6 +35,12 @@ namespace llvm {
|
||||
class MemoryBuffer;
|
||||
}
|
||||
|
||||
namespace swift {
|
||||
namespace ide {
|
||||
struct FormattedSignatureHelp;
|
||||
} // namespace ide
|
||||
} // namespace swift
|
||||
|
||||
namespace SourceKit {
|
||||
class GlobalConfig;
|
||||
using swift::ide::CancellableResult;
|
||||
@@ -1012,51 +1018,14 @@ public:
|
||||
virtual void cancelled() = 0;
|
||||
};
|
||||
|
||||
struct SignatureHelpResponse {
|
||||
struct Parameter {
|
||||
/// The offset of the parameter text in the signature text.
|
||||
unsigned Offset;
|
||||
|
||||
/// The length of the parameter text in the signature text.
|
||||
unsigned Length;
|
||||
|
||||
/// The documentation comment for the parameter.
|
||||
StringRef DocComment;
|
||||
|
||||
/// The internal parameter name.
|
||||
StringRef Name;
|
||||
|
||||
Parameter() {}
|
||||
};
|
||||
|
||||
struct Signature {
|
||||
/// The text describing the signature.
|
||||
StringRef Text;
|
||||
|
||||
/// The documentation comment for the signature.
|
||||
StringRef Doc;
|
||||
|
||||
/// The index of the active parameter if any.
|
||||
std::optional<unsigned> ActiveParam;
|
||||
|
||||
/// The parameters for the signature.
|
||||
ArrayRef<Parameter> Params;
|
||||
};
|
||||
|
||||
/// The index of the active signature.
|
||||
unsigned ActiveSignature;
|
||||
|
||||
/// The available signatures/overloads.
|
||||
ArrayRef<Signature> Signatures;
|
||||
};
|
||||
|
||||
class SignatureHelpConsumer {
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
virtual ~SignatureHelpConsumer() {}
|
||||
|
||||
virtual void handleResult(const SignatureHelpResponse &Result) = 0;
|
||||
virtual void
|
||||
handleResult(const swift::ide::FormattedSignatureHelp &Result) = 0;
|
||||
virtual void setReusingASTContext(bool flag) = 0;
|
||||
virtual void failed(StringRef ErrDescription) = 0;
|
||||
virtual void cancelled() = 0;
|
||||
|
||||
@@ -12,193 +12,14 @@
|
||||
|
||||
#include "SwiftASTManager.h"
|
||||
#include "SwiftLangSupport.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/IDE/CodeCompletionResultPrinter.h"
|
||||
#include "swift/IDE/CodeCompletionStringBuilder.h"
|
||||
#include "swift/IDE/CommentConversion.h"
|
||||
#include "swift/IDE/SignatureHelp.h"
|
||||
#include "swift/IDE/SignatureHelpFormatter.h"
|
||||
#include "swift/IDETool/IDEInspectionInstance.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace SourceKit;
|
||||
using namespace swift;
|
||||
using namespace ide;
|
||||
|
||||
using ChunkKind = CodeCompletionString::Chunk::ChunkKind;
|
||||
|
||||
namespace {
|
||||
struct SignatureInfo {
|
||||
StringRef Text;
|
||||
StringRef DocComment;
|
||||
std::optional<unsigned> ActiveParam;
|
||||
SmallVector<SourceKit::SignatureHelpResponse::Parameter, 1> Params;
|
||||
|
||||
SignatureInfo() {}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
/// \returns Array of parameters of \p VD accounting for implicitly curried
|
||||
/// instance methods.
|
||||
static ArrayRef<const ParamDecl *>
|
||||
getParameterArray(const ValueDecl *VD, bool IsImplicitlyCurried,
|
||||
const ParamDecl *&Scratch) {
|
||||
if (!VD)
|
||||
return {};
|
||||
|
||||
if (IsImplicitlyCurried) {
|
||||
auto *FD = dyn_cast<AbstractFunctionDecl>(VD);
|
||||
assert(FD && FD->hasImplicitSelfDecl());
|
||||
|
||||
Scratch = FD->getImplicitSelfDecl();
|
||||
return ArrayRef(&Scratch, 1);
|
||||
}
|
||||
|
||||
if (auto *ParamList = VD->getParameterList())
|
||||
return ParamList->getArray();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static CodeCompletionString *createSignatureString(
|
||||
llvm::BumpPtrAllocator &Allocator, ValueDecl *FD, AnyFunctionType *AFT,
|
||||
const DeclContext *DC, GenericSignature GenericSig, bool IsSubscript,
|
||||
bool IsMember, bool IsImplicitlyCurried, bool IsSecondApply) {
|
||||
CodeCompletionStringBuilder StringBuilder(
|
||||
Allocator, /*AnnotateResults=*/false,
|
||||
/*UnderscoreEmptyArgumentLabel=*/!IsSubscript,
|
||||
/*FullParameterFlags=*/true);
|
||||
|
||||
DeclBaseName BaseName;
|
||||
|
||||
if (!IsSecondApply && FD) {
|
||||
BaseName = FD->getBaseName();
|
||||
} else if (IsSubscript) {
|
||||
BaseName = DeclBaseName::createSubscript();
|
||||
}
|
||||
|
||||
if (!BaseName.empty())
|
||||
StringBuilder.addValueBaseName(BaseName, IsMember);
|
||||
|
||||
StringBuilder.addLeftParen();
|
||||
|
||||
const ParamDecl *ParamScratch;
|
||||
StringBuilder.addCallArgumentPatterns(
|
||||
AFT->getParams(),
|
||||
getParameterArray(FD, IsImplicitlyCurried, ParamScratch), DC, GenericSig,
|
||||
DefaultArgumentOutputMode::All, /*includeDefaultValues=*/true);
|
||||
|
||||
StringBuilder.addRightParen();
|
||||
|
||||
if (!IsImplicitlyCurried) {
|
||||
// For a second apply, we don't pass the declaration to avoid adding
|
||||
// incorrect rethrows and reasync which are only usable in a single apply.
|
||||
StringBuilder.addEffectsSpecifiers(
|
||||
AFT,
|
||||
/*AFD=*/IsSecondApply ? nullptr
|
||||
: dyn_cast_or_null<AbstractFunctionDecl>(FD));
|
||||
}
|
||||
|
||||
if (FD && FD->isImplicitlyUnwrappedOptional()) {
|
||||
StringBuilder.addTypeAnnotationForImplicitlyUnwrappedOptional(
|
||||
AFT->getResult(), DC, GenericSig);
|
||||
} else {
|
||||
StringBuilder.addTypeAnnotation(AFT->getResult(), DC, GenericSig);
|
||||
}
|
||||
|
||||
return StringBuilder.createCompletionString();
|
||||
}
|
||||
|
||||
static StringRef copyAndClearString(llvm::BumpPtrAllocator &Allocator,
|
||||
SmallVectorImpl<char> &Str) {
|
||||
auto Ref = StringRef(Str.data(), Str.size()).copy(Allocator);
|
||||
Str.clear();
|
||||
return Ref;
|
||||
}
|
||||
|
||||
static void getSignatureInfo(const DeclContext *DC, const Signature &Sig,
|
||||
SignatureInfo &Info,
|
||||
llvm::BumpPtrAllocator &Allocator) {
|
||||
auto *FD = Sig.FuncD;
|
||||
auto *AFT = Sig.FuncTy;
|
||||
|
||||
bool IsConstructor = false;
|
||||
GenericSignature genericSig;
|
||||
if (FD) {
|
||||
IsConstructor = isa<ConstructorDecl>(FD);
|
||||
|
||||
if (auto *GC = FD->getAsGenericContext())
|
||||
genericSig = GC->getGenericSignature();
|
||||
}
|
||||
|
||||
auto *SignatureString =
|
||||
createSignatureString(Allocator, FD, AFT, DC, genericSig, Sig.IsSubscript,
|
||||
/*IsMember=*/bool(Sig.BaseType),
|
||||
Sig.IsImplicitlyCurried, Sig.IsSecondApply);
|
||||
|
||||
llvm::SmallString<512> SS;
|
||||
llvm::raw_svector_ostream OS(SS);
|
||||
|
||||
bool SkipResult = AFT->getResult()->isVoid() || IsConstructor;
|
||||
|
||||
auto Chunks = SignatureString->getChunks();
|
||||
auto C = Chunks.begin();
|
||||
while (C != Chunks.end()) {
|
||||
if (C->is(ChunkKind::TypeAnnotation) && SkipResult) {
|
||||
++C;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (C->is(ChunkKind::TypeAnnotation))
|
||||
OS << " -> ";
|
||||
|
||||
if (C->is(ChunkKind::CallArgumentBegin)) {
|
||||
unsigned NestingLevel = C->getNestingLevel();
|
||||
++C;
|
||||
|
||||
auto &P = Info.Params.emplace_back();
|
||||
P.Offset = SS.size();
|
||||
|
||||
do {
|
||||
if (!C->is(ChunkKind::CallArgumentClosureType) && C->hasText())
|
||||
OS << C->getText();
|
||||
|
||||
++C;
|
||||
} while (C != Chunks.end() && !C->endsPreviousNestedGroup(NestingLevel));
|
||||
|
||||
P.Length = SS.size() - P.Offset;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (C->hasText())
|
||||
OS << C->getText();
|
||||
|
||||
++C;
|
||||
}
|
||||
|
||||
Info.Text = copyAndClearString(Allocator, SS);
|
||||
Info.ActiveParam = Sig.ParamIdx;
|
||||
|
||||
// Parameter names.
|
||||
const ParamDecl *ParamScratch;
|
||||
auto ParamDecls =
|
||||
getParameterArray(FD, Sig.IsImplicitlyCurried, ParamScratch);
|
||||
|
||||
if (!ParamDecls.empty()) {
|
||||
for (unsigned i = 0; i < Info.Params.size(); ++i) {
|
||||
Info.Params[i].Name = ParamDecls[i]->getParameterName().str();
|
||||
}
|
||||
}
|
||||
|
||||
// Documentation.
|
||||
if (FD) {
|
||||
ide::getRawDocumentationComment(FD, OS);
|
||||
|
||||
Info.DocComment = copyAndClearString(Allocator, SS);
|
||||
}
|
||||
}
|
||||
|
||||
static void deliverResults(SourceKit::SignatureHelpConsumer &SKConsumer,
|
||||
CancellableResult<SignatureHelpResults> Result) {
|
||||
switch (Result.getKind()) {
|
||||
@@ -212,29 +33,9 @@ static void deliverResults(SourceKit::SignatureHelpConsumer &SKConsumer,
|
||||
}
|
||||
|
||||
llvm::BumpPtrAllocator Allocator;
|
||||
SmallVector<SignatureInfo, 4> Infos;
|
||||
SignatureHelpFormatter Formatter(Allocator);
|
||||
|
||||
for (auto &Sig : Result->Result->Signatures) {
|
||||
Infos.emplace_back();
|
||||
auto &Info = Infos.back();
|
||||
|
||||
getSignatureInfo(Result->Result->DC, Sig, Info, Allocator);
|
||||
}
|
||||
|
||||
SourceKit::SignatureHelpResponse SKResult;
|
||||
SmallVector<SourceKit::SignatureHelpResponse::Signature, 8> SKSignatures;
|
||||
|
||||
for (auto &Info : Infos) {
|
||||
SKSignatures.push_back(
|
||||
{Info.Text, Info.DocComment, Info.ActiveParam, Info.Params});
|
||||
}
|
||||
|
||||
SKResult.Signatures = SKSignatures;
|
||||
|
||||
// TODO(a7medev): Select active signature and param.
|
||||
SKResult.ActiveSignature = 0;
|
||||
|
||||
SKConsumer.handleResult(SKResult);
|
||||
SKConsumer.handleResult(Formatter.format(*Result->Result));
|
||||
break;
|
||||
}
|
||||
case CancellableResultKind::Failure:
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "swift/Basic/LLVMInitialize.h"
|
||||
#include "swift/Basic/Statistic.h"
|
||||
#include "swift/Basic/Version.h"
|
||||
#include "swift/IDE/SignatureHelpFormatter.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
@@ -3645,7 +3646,8 @@ signatureHelp(StringRef PrimaryFilePath, int64_t Offset,
|
||||
public:
|
||||
Consumer(ResponseBuilder Builder) : SKResult(Builder.getDictionary()) {}
|
||||
|
||||
void handleResult(const SignatureHelpResponse &Result) override {
|
||||
void
|
||||
handleResult(const swift::ide::FormattedSignatureHelp &Result) override {
|
||||
SKResult.set(KeyActiveSignature, Result.ActiveSignature);
|
||||
|
||||
auto Signatures = SKResult.setArray(KeySignatures);
|
||||
@@ -3658,8 +3660,8 @@ signatureHelp(StringRef PrimaryFilePath, int64_t Offset,
|
||||
if (auto ActiveParam = Signature.ActiveParam)
|
||||
SignatureElem.set(KeyActiveParameter, ActiveParam.value());
|
||||
|
||||
if (!Signature.Doc.empty())
|
||||
SignatureElem.set(KeyDocComment, Signature.Doc);
|
||||
if (!Signature.DocComment.empty())
|
||||
SignatureElem.set(KeyDocComment, Signature.DocComment);
|
||||
|
||||
auto Params = SignatureElem.setArray(KeyParameters);
|
||||
|
||||
@@ -3671,9 +3673,6 @@ signatureHelp(StringRef PrimaryFilePath, int64_t Offset,
|
||||
|
||||
ParamElem.set(KeyNameOffset, Param.Offset);
|
||||
ParamElem.set(KeyNameLength, Param.Length);
|
||||
|
||||
if (!Param.DocComment.empty())
|
||||
ParamElem.set(KeyDocComment, Param.DocComment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
#include "swift/IDE/IDERequests.h"
|
||||
#include "swift/IDE/ModuleInterfacePrinting.h"
|
||||
#include "swift/IDE/REPLCodeCompletion.h"
|
||||
#include "swift/IDE/SignatureHelp.h"
|
||||
#include "swift/IDE/SignatureHelpFormatter.h"
|
||||
#include "swift/IDE/SourceEntityWalker.h"
|
||||
#include "swift/IDE/SyntaxModel.h"
|
||||
#include "swift/IDE/TypeContextInfo.h"
|
||||
@@ -117,6 +119,7 @@ enum class ActionType {
|
||||
Range,
|
||||
TypeContextInfo,
|
||||
ConformingMethodList,
|
||||
SignatureHelp,
|
||||
};
|
||||
|
||||
class NullDebuggerClient : public DebuggerClient {
|
||||
@@ -251,7 +254,9 @@ Action(llvm::cl::desc("Mode:"), llvm::cl::init(ActionType::None),
|
||||
"Print types for all expressions in the file"),
|
||||
clEnumValN(ActionType::ConformingMethodList,
|
||||
"conforming-methods",
|
||||
"Perform conforming method analysis for expression")));
|
||||
"Perform conforming method analysis for expression"),
|
||||
clEnumValN(ActionType::SignatureHelp, "signature-help",
|
||||
"Perform signature help")));
|
||||
|
||||
static llvm::cl::opt<std::string>
|
||||
SourceFilename("source-filename", llvm::cl::desc("Name of the source file"),
|
||||
@@ -1451,6 +1456,99 @@ printCodeCompletionLookedupTypeNames(ArrayRef<NullTerminatedStringRef> names,
|
||||
OS << "]\n";
|
||||
}
|
||||
|
||||
static void printWithEscaping(StringRef Str, llvm::raw_ostream &OS) {
|
||||
for (char C : Str) {
|
||||
switch (C) {
|
||||
case '\n':
|
||||
OS << "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
OS << "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
OS << "\\t";
|
||||
break;
|
||||
case '\v':
|
||||
OS << "\\v";
|
||||
break;
|
||||
case '\f':
|
||||
OS << "\\f";
|
||||
break;
|
||||
default:
|
||||
OS << C;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void printSignatureHelpResultsImpl(const FormattedSignatureHelp &Result,
|
||||
llvm::raw_ostream &OS) {
|
||||
OS << "Begin signatures, " << Result.Signatures.size() << " items\n";
|
||||
|
||||
for (unsigned i = 0; i < Result.Signatures.size(); ++i) {
|
||||
const auto &Signature = Result.Signatures[i];
|
||||
if (i == Result.ActiveSignature) {
|
||||
OS << "Signature[Active]: ";
|
||||
} else {
|
||||
OS << "Signature: ";
|
||||
}
|
||||
|
||||
StringRef signatureText = Signature.Text;
|
||||
|
||||
unsigned currentPos = 0;
|
||||
for (unsigned j = 0; j < Signature.Params.size(); ++j) {
|
||||
const auto &Param = Signature.Params[j];
|
||||
|
||||
if (Param.Offset > currentPos) {
|
||||
OS << signatureText.substr(currentPos, Param.Offset - currentPos);
|
||||
}
|
||||
|
||||
OS << "<param";
|
||||
if (!Param.Name.empty()) {
|
||||
OS << " name=\"" << Param.Name << '"';
|
||||
}
|
||||
if (Signature.ActiveParam && *Signature.ActiveParam == j) {
|
||||
OS << " active";
|
||||
}
|
||||
OS << ">";
|
||||
OS << signatureText.substr(Param.Offset, Param.Length);
|
||||
OS << "</param>";
|
||||
|
||||
currentPos = Param.Offset + Param.Length;
|
||||
}
|
||||
|
||||
if (currentPos < signatureText.size()) {
|
||||
OS << signatureText.substr(currentPos);
|
||||
}
|
||||
|
||||
if (!Signature.DocComment.empty()) {
|
||||
OS << "; Documentation=";
|
||||
printWithEscaping(Signature.DocComment, OS);
|
||||
}
|
||||
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
OS << "End signatures\n";
|
||||
}
|
||||
|
||||
static int printSignatureHelpResults(
|
||||
CancellableResult<SignatureHelpResults> CancellableResult) {
|
||||
llvm::raw_fd_ostream &OS = llvm::outs();
|
||||
return printResult<SignatureHelpResults>(
|
||||
CancellableResult, [&](const SignatureHelpResults &Results) {
|
||||
if (Results.Result) {
|
||||
llvm::BumpPtrAllocator Allocator;
|
||||
SignatureHelpFormatter Formatter(Allocator);
|
||||
auto FormattedResult = Formatter.format(*Results.Result);
|
||||
printSignatureHelpResultsImpl(FormattedResult, OS);
|
||||
} else {
|
||||
OS << "No signature help results\n";
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
static int printCodeCompletionResults(
|
||||
CancellableResult<CodeCompleteResult> CancellableResult,
|
||||
bool IncludeKeywords, bool IncludeComments, bool IncludeSourceText,
|
||||
@@ -1468,6 +1566,27 @@ static int printCodeCompletionResults(
|
||||
});
|
||||
}
|
||||
|
||||
static int doSignatureHelp(const CompilerInvocation &InitInvok,
|
||||
StringRef SourceFilename,
|
||||
StringRef SecondSourceFileName,
|
||||
StringRef SignatureHelpToken,
|
||||
bool SignatureHelpDiagnostics) {
|
||||
return performWithCompletionLikeOperationParams(
|
||||
InitInvok, SourceFilename, SecondSourceFileName, SignatureHelpToken,
|
||||
SignatureHelpDiagnostics,
|
||||
[&](CompletionLikeOperationParams Params) -> bool {
|
||||
IDEInspectionInstance Inst(std::make_shared<PluginRegistry>());
|
||||
int ExitCode = 2;
|
||||
Inst.signatureHelp(Params.Invocation, Params.Args, Params.FileSystem,
|
||||
Params.CompletionBuffer, Params.Offset, Params.DiagC,
|
||||
/*CancellationFlag=*/nullptr,
|
||||
[&](CancellableResult<SignatureHelpResults> Result) {
|
||||
ExitCode = printSignatureHelpResults(Result);
|
||||
});
|
||||
return ExitCode;
|
||||
});
|
||||
}
|
||||
|
||||
static int
|
||||
doCodeCompletion(const CompilerInvocation &InitInvok, StringRef SourceFilename,
|
||||
StringRef SecondSourceFileName, StringRef CodeCompletionToken,
|
||||
@@ -3469,19 +3588,6 @@ public:
|
||||
ASTCommentPrinter(SourceManager &SM, XMLValidator &TheXMLValidator)
|
||||
: OS(llvm::outs()), SM(SM), TheXMLValidator(TheXMLValidator) {}
|
||||
|
||||
void printWithEscaping(StringRef Str) {
|
||||
for (char C : Str) {
|
||||
switch (C) {
|
||||
case '\n': OS << "\\n"; break;
|
||||
case '\r': OS << "\\r"; break;
|
||||
case '\t': OS << "\\t"; break;
|
||||
case '\v': OS << "\\v"; break;
|
||||
case '\f': OS << "\\f"; break;
|
||||
default: OS << C; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printDeclName(const ValueDecl *VD) {
|
||||
if (auto *NTD = dyn_cast<NominalTypeDecl>(VD->getDeclContext())) {
|
||||
Identifier Id = NTD->getName();
|
||||
@@ -3554,7 +3660,7 @@ public:
|
||||
}
|
||||
OS << "[";
|
||||
for (auto &SRC : RC.Comments)
|
||||
printWithEscaping(SRC.RawText);
|
||||
printWithEscaping(SRC.RawText, OS);
|
||||
OS << "]";
|
||||
}
|
||||
|
||||
@@ -3565,7 +3671,7 @@ public:
|
||||
return;
|
||||
}
|
||||
OS << "[";
|
||||
printWithEscaping(Brief);
|
||||
printWithEscaping(Brief, OS);
|
||||
OS << "]";
|
||||
}
|
||||
|
||||
@@ -3581,7 +3687,7 @@ public:
|
||||
return;
|
||||
}
|
||||
OS << "[";
|
||||
printWithEscaping(XML);
|
||||
printWithEscaping(XML, OS);
|
||||
OS << "]";
|
||||
|
||||
auto Status = TheXMLValidator.validate(XML);
|
||||
@@ -4856,6 +4962,16 @@ int main(int argc, char *argv[]) {
|
||||
options::ConformingMethodListExpectedTypes, PrintOpts);
|
||||
break;
|
||||
|
||||
case ActionType::SignatureHelp:
|
||||
if (options::CodeCompletionToken.empty()) {
|
||||
llvm::errs() << "signature help token name required\n";
|
||||
return 1;
|
||||
}
|
||||
ExitCode = doSignatureHelp(
|
||||
InitInvok, options::SourceFilename, options::SecondSourceFilename,
|
||||
options::CodeCompletionToken, options::CodeCompletionDiagnostics);
|
||||
break;
|
||||
|
||||
case ActionType::SyntaxColoring:
|
||||
ExitCode = doSyntaxColoring(InitInvok,
|
||||
options::SourceFilename,
|
||||
|
||||
Reference in New Issue
Block a user