mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -0,0 +1 @@
|
||||
func 1() {}
|
||||
@@ -0,0 +1,2 @@
|
||||
_ = unknown
|
||||
// code-completion at 2:1
|
||||
45
test/SourceKit/CompileNotifications/diagnostics.swift
Normal file
45
test/SourceKit/CompileNotifications/diagnostics.swift
Normal file
@@ -0,0 +1,45 @@
|
||||
// RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s | %FileCheck %s -check-prefix=NODIAGS
|
||||
// NODIAGS: key.notification: source.notification.compile-did-finish
|
||||
// NODIAGS-NEXT: key.diagnostics: [
|
||||
// NODIAGS-NEXT: ]
|
||||
|
||||
// RUN: %sourcekitd-test -req=track-compiles == -req=sema %S/Inputs/parse-error.swift -- %S/Inputs/parse-error.swift | %FileCheck %s -check-prefix=PARSE
|
||||
// PARSE: key.notification: source.notification.compile-did-finish
|
||||
// PARSE-NEXT: key.diagnostics: [
|
||||
// PARSE-NEXT: {
|
||||
// PARSE-NEXT: key.line: 1
|
||||
// PARSE-NEXT: key.column: 6
|
||||
// PARSE-NEXT: key.filepath: "{{.*}}parse-error.swift"
|
||||
// PARSE-NEXT: key.severity: source.diagnostic.severity.error
|
||||
// PARSE-NEXT: key.description: "function name
|
||||
// PARSE-NEXT: }
|
||||
// PARSE-NEXT: ]
|
||||
|
||||
// Diagnostic from other file.
|
||||
// RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s %S/Inputs/parse-error.swift | %FileCheck %s -check-prefix=PARSE
|
||||
|
||||
// RUN: %sourcekitd-test -req=track-compiles == -req=sema %S/Inputs/sema-error.swift -- %S/Inputs/sema-error.swift | %FileCheck %s -check-prefix=SEMA
|
||||
// SEMA: key.notification: source.notification.compile-did-finish
|
||||
// SEMA-NEXT: key.diagnostics: [
|
||||
// SEMA-NEXT: {
|
||||
// SEMA-NEXT: key.line: 1
|
||||
// SEMA-NEXT: key.column: 5
|
||||
// SEMA-NEXT: key.filepath: "{{.*}}sema-error.swift"
|
||||
// SEMA-NEXT: key.severity: source.diagnostic.severity.error
|
||||
// SEMA-NEXT: key.description: "use of
|
||||
// SEMA-NEXT: key.ranges: [
|
||||
|
||||
// RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s -Xcc -include -Xcc /doesnotexist | %FileCheck %s -check-prefix=CLANG_IMPORTER
|
||||
// CLANG_IMPORTER: key.notification: source.notification.compile-did-finish,
|
||||
// CLANG_IMPORTER-NEXT: key.diagnostics: [
|
||||
// CLANG_IMPORTER-NEXT: {
|
||||
// CLANG_IMPORTER-NEXT: key.line:
|
||||
// CLANG_IMPORTER-NEXT: key.column:
|
||||
// CLANG_IMPORTER-NEXT: key.filepath: "<{{.*}}>"
|
||||
// CLANG_IMPORTER-NEXT: key.severity: source.diagnostic.severity.error,
|
||||
// CLANG_IMPORTER-NEXT: key.description: {{.*}}not found
|
||||
|
||||
// Note: we're missing the "compiler is in code completion mode" diagnostic,
|
||||
// which is probably just as well.
|
||||
// RUN: %sourcekitd-test -req=track-compiles == -req=complete -offset=0 %s -- %s | %FileCheck %s -check-prefix=NODIAGS
|
||||
// RUN: %sourcekitd-test -req=track-compiles == -req=complete -pos=2:1 %S/Inputs/sema-error.swift -- %S/Inputs/sema-error.swift | %FileCheck %s -check-prefix=SEMA
|
||||
@@ -13,13 +13,17 @@
|
||||
#ifndef LLVM_SOURCEKIT_SUPPORT_TRACING_H
|
||||
#define LLVM_SOURCEKIT_SUPPORT_TRACING_H
|
||||
|
||||
#include "SourceKit/Core/LLVM.h"
|
||||
#include "SourceKit/Support/UIdent.h"
|
||||
#include "swift/Basic/OptionSet.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace SourceKit {
|
||||
struct DiagnosticEntryInfo;
|
||||
|
||||
namespace trace {
|
||||
|
||||
struct SwiftArguments {
|
||||
@@ -76,7 +80,8 @@ public:
|
||||
const StringPairs &OpArgs) = 0;
|
||||
|
||||
// Operation previously started with startXXX has finished
|
||||
virtual void operationFinished(uint64_t OpId, OperationKind OpKind) = 0;
|
||||
virtual void operationFinished(uint64_t OpId, OperationKind OpKind,
|
||||
ArrayRef<DiagnosticEntryInfo> Diagnostics) = 0;
|
||||
|
||||
/// Returns the set of operations this consumer is interested in.
|
||||
///
|
||||
@@ -99,7 +104,8 @@ uint64_t startOperation(OperationKind OpKind,
|
||||
const StringPairs &OpArgs = StringPairs());
|
||||
|
||||
// Operation previously started with startXXX has finished
|
||||
void operationFinished(uint64_t OpId, OperationKind OpKind);
|
||||
void operationFinished(uint64_t OpId, OperationKind OpKind,
|
||||
ArrayRef<DiagnosticEntryInfo> Diagnostics);
|
||||
|
||||
// Register trace consumer.
|
||||
void registerConsumer(TraceConsumer *Consumer);
|
||||
@@ -134,9 +140,9 @@ public:
|
||||
OpId = startOperation(OpKind, Inv, OpArgs);
|
||||
}
|
||||
|
||||
void finish() {
|
||||
void finish(ArrayRef<DiagnosticEntryInfo> Diagnostics = llvm::None) {
|
||||
if (OpId.hasValue()) {
|
||||
operationFinished(OpId.getValue(), OpKind);
|
||||
operationFinished(OpId.getValue(), OpKind, Diagnostics);
|
||||
OpId.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,11 +54,12 @@ uint64_t trace::startOperation(trace::OperationKind OpKind,
|
||||
}
|
||||
|
||||
// Operation previously started with startXXX has finished
|
||||
void trace::operationFinished(uint64_t OpId, trace::OperationKind OpKind) {
|
||||
void trace::operationFinished(uint64_t OpId, trace::OperationKind OpKind,
|
||||
ArrayRef<DiagnosticEntryInfo> Diagnostics) {
|
||||
if (trace::anyEnabled()) {
|
||||
llvm::sys::ScopedLock L(consumersLock);
|
||||
for (auto *consumer : consumers) {
|
||||
consumer->operationFinished(OpId, OpKind);
|
||||
consumer->operationFinished(OpId, OpKind, Diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -878,6 +878,12 @@ ASTUnitRef ASTProducer::createASTUnit(SwiftASTManager::Implementation &MgrImpl,
|
||||
// TypeResolver is set before.
|
||||
ASTRef->Impl.TypeResolver = createLazyResolver(CompIns.getASTContext());
|
||||
|
||||
if (TracedOp.enabled()) {
|
||||
SmallVector<DiagnosticEntryInfo, 8> Diagnostics;
|
||||
Consumer.getAllDiagnostics(Diagnostics);
|
||||
TracedOp.finish(Diagnostics);
|
||||
}
|
||||
|
||||
return ASTRef;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "CodeCompletionOrganizer.h"
|
||||
#include "SwiftASTManager.h"
|
||||
#include "SwiftLangSupport.h"
|
||||
#include "SwiftEditorDiagConsumer.h"
|
||||
#include "SourceKit/Support/Logging.h"
|
||||
#include "SourceKit/Support/UIdent.h"
|
||||
|
||||
@@ -138,6 +139,12 @@ static bool swiftCodeCompleteImpl(SwiftLangSupport &Lang,
|
||||
PrintingDiagnosticConsumer PrintDiags;
|
||||
CI.addDiagnosticConsumer(&PrintDiags);
|
||||
|
||||
EditorDiagConsumer TraceDiags;
|
||||
trace::TracedOperation TracedOp(trace::OperationKind::CodeCompletion);
|
||||
if (TracedOp.enabled()) {
|
||||
CI.addDiagnosticConsumer(&TraceDiags);
|
||||
}
|
||||
|
||||
CompilerInvocation Invocation;
|
||||
bool Failed = Lang.getASTManager().initCompilerInvocation(
|
||||
Invocation, Args, CI.getDiags(), InputFile->getBufferIdentifier(), Error);
|
||||
@@ -188,8 +195,6 @@ static bool swiftCodeCompleteImpl(SwiftLangSupport &Lang,
|
||||
|
||||
TracedInit.finish();
|
||||
|
||||
|
||||
trace::TracedOperation TracedOp(trace::OperationKind::CodeCompletion);
|
||||
if (TracedOp.enabled()) {
|
||||
trace::SwiftInvocation SwiftArgs;
|
||||
trace::initTraceInfo(SwiftArgs, InputFile->getBufferIdentifier(), Args);
|
||||
@@ -215,6 +220,13 @@ static bool swiftCodeCompleteImpl(SwiftLangSupport &Lang,
|
||||
&CompletionContext);
|
||||
CI.performSema();
|
||||
SwiftConsumer.clearContext();
|
||||
|
||||
if (TracedOp.enabled()) {
|
||||
SmallVector<DiagnosticEntryInfo, 8> Diagnostics;
|
||||
TraceDiags.getAllDiagnostics(Diagnostics);
|
||||
TracedOp.finish(Diagnostics);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,28 @@ using namespace SourceKit;
|
||||
using namespace swift;
|
||||
using namespace ide;
|
||||
|
||||
static std::vector<unsigned> getSortedBufferIDs(
|
||||
const llvm::DenseMap<unsigned, std::vector<DiagnosticEntryInfo>> &Map) {
|
||||
std::vector<unsigned> bufferIDs;
|
||||
bufferIDs.reserve(Map.size());
|
||||
for (auto I = Map.begin(), E = Map.end(); I != E; ++I) {
|
||||
bufferIDs.push_back(I->getFirst());
|
||||
}
|
||||
llvm::array_pod_sort(bufferIDs.begin(), bufferIDs.end());
|
||||
return bufferIDs;
|
||||
}
|
||||
|
||||
void EditorDiagConsumer::getAllDiagnostics(
|
||||
SmallVectorImpl<DiagnosticEntryInfo> &Result) {
|
||||
// Note: we cannot reuse InputBufIds because there may be diagnostics outside
|
||||
// the inputs. Instead, sort the extant buffers.
|
||||
auto bufferIDs = getSortedBufferIDs(BufferDiagnostics);
|
||||
for (unsigned bufferID : bufferIDs) {
|
||||
const auto &diags = BufferDiagnostics[bufferID];
|
||||
Result.append(diags.begin(), diags.end());
|
||||
}
|
||||
}
|
||||
|
||||
void EditorDiagConsumer::handleDiagnostic(
|
||||
SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
|
||||
StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
|
||||
@@ -92,15 +114,10 @@ void EditorDiagConsumer::handleDiagnostic(
|
||||
if (!isInputBufferID(BufferID)) {
|
||||
if (Info.ID == diag::error_from_clang.ID ||
|
||||
Info.ID == diag::warning_from_clang.ID ||
|
||||
Info.ID == diag::note_from_clang.ID) {
|
||||
Info.ID == diag::note_from_clang.ID ||
|
||||
!IsNote) {
|
||||
// Handle it as other diagnostics.
|
||||
} else {
|
||||
if (!IsNote) {
|
||||
LOG_WARN_FUNC("got swift diagnostic not pointing at input file, "
|
||||
"buffer name: " << SM.getIdentifierForBuffer(BufferID));
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: This is a note pointing to a synthesized declaration buffer for
|
||||
// a declaration coming from a module.
|
||||
// We should include the Decl* in the DiagnosticInfo and have a way for
|
||||
|
||||
@@ -62,6 +62,8 @@ public:
|
||||
return Diags;
|
||||
}
|
||||
|
||||
void getAllDiagnostics(SmallVectorImpl<DiagnosticEntryInfo> &Result);
|
||||
|
||||
bool hadErrorWithInvalidLoc() const { return HadInvalidLocError; }
|
||||
|
||||
bool hadAnyError() const { return HadAnyError; }
|
||||
|
||||
@@ -98,7 +98,9 @@ public:
|
||||
const StringPairs &OpArgs) override;
|
||||
|
||||
// Operation previously started with startXXX has finished
|
||||
void operationFinished(uint64_t OpId, OperationKind OpKind) override;
|
||||
void operationFinished(
|
||||
uint64_t OpId, OperationKind OpKind,
|
||||
ArrayRef<SourceKit::DiagnosticEntryInfo> Diagnostics) override;
|
||||
};
|
||||
|
||||
// Trace start of SourceKit operation
|
||||
@@ -117,7 +119,9 @@ void XpcTraceConsumer::operationStarted(uint64_t OpId,
|
||||
}
|
||||
|
||||
// Operation previously started with startXXX has finished
|
||||
void XpcTraceConsumer::operationFinished(uint64_t OpId, OperationKind OpKind) {
|
||||
void XpcTraceConsumer::operationFinished(
|
||||
uint64_t OpId, OperationKind OpKind,
|
||||
ArrayRef<SourceKit::DiagnosticEntryInfo> Diagnostics) {
|
||||
xpc_object_t Contents = xpc_array_create(nullptr, 0);
|
||||
append(Contents, trace::ActionKind::OperationFinished);
|
||||
append(Contents, OpId);
|
||||
|
||||
@@ -232,7 +232,7 @@ findRenameRanges(llvm::MemoryBuffer *InputBuf,
|
||||
static bool isSemanticEditorDisabled();
|
||||
|
||||
static void fillDictionaryForDiagnosticInfo(
|
||||
ResponseBuilder::Dictionary Elem, const DiagnosticEntryInfoBase &Info);
|
||||
ResponseBuilder::Dictionary Elem, const DiagnosticEntryInfo &Info);
|
||||
|
||||
static void enableCompileNotifications(bool value);
|
||||
|
||||
@@ -1466,30 +1466,7 @@ bool SKDocConsumer::handleDiagnostic(const DiagnosticEntryInfo &Info) {
|
||||
Arr = TopDict.setArray(KeyDiagnostics);
|
||||
|
||||
auto Elem = Arr.appendDictionary();
|
||||
UIdent SeverityUID;
|
||||
static UIdent UIDKindDiagWarning(KindDiagWarning.str());
|
||||
static UIdent UIDKindDiagError(KindDiagError.str());
|
||||
switch (Info.Severity) {
|
||||
case DiagnosticSeverityKind::Warning:
|
||||
SeverityUID = UIDKindDiagWarning;
|
||||
break;
|
||||
case DiagnosticSeverityKind::Error:
|
||||
SeverityUID = UIDKindDiagError;
|
||||
break;
|
||||
}
|
||||
|
||||
Elem.set(KeySeverity, SeverityUID);
|
||||
fillDictionaryForDiagnosticInfo(Elem, Info);
|
||||
|
||||
if (!Info.Notes.empty()) {
|
||||
auto NotesArr = Elem.setArray(KeyDiagnostics);
|
||||
for (auto &NoteDiag : Info.Notes) {
|
||||
auto NoteElem = NotesArr.appendDictionary();
|
||||
NoteElem.set(KeySeverity, KindDiagNote);
|
||||
fillDictionaryForDiagnosticInfo(NoteElem, NoteDiag);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2335,7 +2312,38 @@ bool SKEditorConsumer::recordFormattedText(StringRef Text) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fillDictionaryForDiagnosticInfoBase(
|
||||
ResponseBuilder::Dictionary Elem, const DiagnosticEntryInfoBase &Info);
|
||||
|
||||
static void fillDictionaryForDiagnosticInfo(
|
||||
ResponseBuilder::Dictionary Elem, const DiagnosticEntryInfo &Info) {
|
||||
|
||||
UIdent SeverityUID;
|
||||
static UIdent UIDKindDiagWarning(KindDiagWarning.str());
|
||||
static UIdent UIDKindDiagError(KindDiagError.str());
|
||||
switch (Info.Severity) {
|
||||
case DiagnosticSeverityKind::Warning:
|
||||
SeverityUID = UIDKindDiagWarning;
|
||||
break;
|
||||
case DiagnosticSeverityKind::Error:
|
||||
SeverityUID = UIDKindDiagError;
|
||||
break;
|
||||
}
|
||||
|
||||
Elem.set(KeySeverity, SeverityUID);
|
||||
fillDictionaryForDiagnosticInfoBase(Elem, Info);
|
||||
|
||||
if (!Info.Notes.empty()) {
|
||||
auto NotesArr = Elem.setArray(KeyDiagnostics);
|
||||
for (auto &NoteDiag : Info.Notes) {
|
||||
auto NoteElem = NotesArr.appendDictionary();
|
||||
NoteElem.set(KeySeverity, KindDiagNote);
|
||||
fillDictionaryForDiagnosticInfoBase(NoteElem, NoteDiag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fillDictionaryForDiagnosticInfoBase(
|
||||
ResponseBuilder::Dictionary Elem, const DiagnosticEntryInfoBase &Info) {
|
||||
|
||||
Elem.set(KeyDescription, Info.Description);
|
||||
@@ -2383,31 +2391,8 @@ bool SKEditorConsumer::handleDiagnostic(const DiagnosticEntryInfo &Info,
|
||||
Arr = Dict.setArray(KeyDiagnostics);
|
||||
|
||||
auto Elem = Arr.appendDictionary();
|
||||
UIdent SeverityUID;
|
||||
static UIdent UIDKindDiagWarning(KindDiagWarning.str());
|
||||
static UIdent UIDKindDiagError(KindDiagError.str());
|
||||
switch (Info.Severity) {
|
||||
case DiagnosticSeverityKind::Warning:
|
||||
SeverityUID = UIDKindDiagWarning;
|
||||
break;
|
||||
case DiagnosticSeverityKind::Error:
|
||||
SeverityUID = UIDKindDiagError;
|
||||
break;
|
||||
}
|
||||
|
||||
Elem.set(KeySeverity, SeverityUID);
|
||||
Elem.set(KeyDiagnosticStage, DiagStage);
|
||||
fillDictionaryForDiagnosticInfo(Elem, Info);
|
||||
|
||||
if (!Info.Notes.empty()) {
|
||||
auto NotesArr = Elem.setArray(KeyDiagnostics);
|
||||
for (auto &NoteDiag : Info.Notes) {
|
||||
auto NoteElem = NotesArr.appendDictionary();
|
||||
NoteElem.set(KeySeverity, KindDiagNote);
|
||||
fillDictionaryForDiagnosticInfo(NoteElem, NoteDiag);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2710,7 +2695,8 @@ public:
|
||||
void operationStarted(uint64_t OpId, trace::OperationKind OpKind,
|
||||
const trace::SwiftInvocation &Inv,
|
||||
const trace::StringPairs &OpArgs) override;
|
||||
void operationFinished(uint64_t OpId, trace::OperationKind OpKind) override;
|
||||
void operationFinished(uint64_t OpId, trace::OperationKind OpKind,
|
||||
ArrayRef<DiagnosticEntryInfo> Diagnostics) override;
|
||||
swift::OptionSet<trace::OperationKind> desiredOperations() override {
|
||||
return swift::OptionSet<trace::OperationKind>() |
|
||||
trace::OperationKind::PerformSema |
|
||||
@@ -2736,8 +2722,9 @@ void CompileTrackingConsumer::operationStarted(
|
||||
sourcekitd::postNotification(RespBuilder.createResponse());
|
||||
}
|
||||
|
||||
void CompileTrackingConsumer::operationFinished(uint64_t OpId,
|
||||
trace::OperationKind OpKind) {
|
||||
void CompileTrackingConsumer::operationFinished(
|
||||
uint64_t OpId, trace::OperationKind OpKind,
|
||||
ArrayRef<DiagnosticEntryInfo> Diagnostics) {
|
||||
if (!desiredOperations().contains(OpKind))
|
||||
return;
|
||||
|
||||
@@ -2746,7 +2733,11 @@ void CompileTrackingConsumer::operationFinished(uint64_t OpId,
|
||||
auto Dict = RespBuilder.getDictionary();
|
||||
Dict.set(KeyNotification, CompileDidFinishUID);
|
||||
Dict.set(KeyCompileID, std::to_string(OpId));
|
||||
// Diagnostics
|
||||
auto DiagArray = Dict.setArray(KeyDiagnostics);
|
||||
for (const auto &DiagInfo : Diagnostics) {
|
||||
fillDictionaryForDiagnosticInfo(DiagArray.appendDictionary(), DiagInfo);
|
||||
}
|
||||
|
||||
sourcekitd::postNotification(RespBuilder.createResponse());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user