Merge remote-tracking branch 'origin/main' into rebranch

This commit is contained in:
swift-ci
2025-09-29 06:15:20 -07:00
39 changed files with 826 additions and 1484 deletions

View 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

View File

@@ -19,6 +19,7 @@ add_swift_host_library(swiftIDE STATIC
CompletionOverrideLookup.cpp
ConformingMethodList.cpp
SignatureHelp.cpp
SignatureHelpFormatter.cpp
CursorInfo.cpp
ExprCompletion.cpp
ExprContextAnalysis.cpp

View File

@@ -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;

View File

@@ -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"

View File

@@ -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;

View 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);
}

View File

@@ -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

View 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
}

View 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
}

View 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>)

View 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.

View 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
}

View 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>)

View 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?]
}
}

View 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

View 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

View 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]

View 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>)

View 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

View 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

View 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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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:

View File

@@ -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);
}
}
}

View File

@@ -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,