Skip to content

Commit f8751d4

Browse files
committed
[CodeCompletion] Provide known module source file information
* 'CodeCompletionContext' now has 'requiresSourceFileInfo()' flag * When 'true', 'SourceFiles' is populated. * 'SourceFiles' is a list of pairs of a known module source file path and its up-to-date-ness * Clients (i.e. 'CodeCompletionConsumer') can retrieve it from 'CodeCompletionContext' in 'handleResults' * Each completion item now has 'SourceFilePath' property * C-APIs to get those informations
1 parent d6eec88 commit f8751d4

File tree

14 files changed

+383
-59
lines changed

14 files changed

+383
-59
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@ class CodeCompletionResult {
633633
private:
634634
CodeCompletionString *CompletionString;
635635
StringRef ModuleName;
636+
StringRef SourceFilePath;
636637
StringRef BriefDocComment;
637638
ArrayRef<StringRef> AssociatedUSRs;
638639
ArrayRef<std::pair<StringRef, StringRef>> DocWords;
@@ -740,7 +741,7 @@ class CodeCompletionResult {
740741
CodeCompletionFlair Flair, unsigned NumBytesToErase,
741742
CodeCompletionString *CompletionString,
742743
CodeCompletionDeclKind DeclKind, bool IsSystem,
743-
StringRef ModuleName,
744+
StringRef ModuleName, StringRef SourceFilePath,
744745
CodeCompletionResult::NotRecommendedReason NotRecReason,
745746
StringRef BriefDocComment,
746747
ArrayRef<StringRef> AssociatedUSRs,
@@ -749,10 +750,11 @@ class CodeCompletionResult {
749750
CodeCompletionOperatorKind KnownOperatorKind)
750751
: Kind(ResultKind::Declaration),
751752
KnownOperatorKind(unsigned(KnownOperatorKind)),
752-
SemanticContext(unsigned(SemanticContext)), Flair(unsigned(Flair.toRaw())),
753-
NotRecommended(unsigned(NotRecReason)), IsSystem(IsSystem),
754-
NumBytesToErase(NumBytesToErase), CompletionString(CompletionString),
755-
ModuleName(ModuleName), BriefDocComment(BriefDocComment),
753+
SemanticContext(unsigned(SemanticContext)),
754+
Flair(unsigned(Flair.toRaw())), NotRecommended(unsigned(NotRecReason)),
755+
IsSystem(IsSystem), NumBytesToErase(NumBytesToErase),
756+
CompletionString(CompletionString), ModuleName(ModuleName),
757+
SourceFilePath(SourceFilePath), BriefDocComment(BriefDocComment),
756758
AssociatedUSRs(AssociatedUSRs), DocWords(DocWords),
757759
TypeDistance(TypeDistance) {
758760
AssociatedKind = static_cast<unsigned>(DeclKind);
@@ -853,6 +855,16 @@ class CodeCompletionResult {
853855
return DocWords;
854856
}
855857

858+
void setSourceFilePath(StringRef value) {
859+
SourceFilePath = value;
860+
}
861+
862+
/// Returns the source file path where the associated decl was declared.
863+
/// Returns an empty string if the information is not available.
864+
StringRef getSourceFilePath() const {
865+
return SourceFilePath;
866+
}
867+
856868
/// Print a debug representation of the code completion result to \p OS.
857869
void printPrefix(raw_ostream &OS) const;
858870
SWIFT_DEBUG_DUMP;
@@ -865,6 +877,15 @@ class CodeCompletionResult {
865877
static bool getDeclIsSystem(const Decl *D);
866878
};
867879

880+
/// A pair of a file path and its up-to-date-ness.
881+
struct SourceFileAndUpToDate {
882+
StringRef FilePath;
883+
bool IsUpToDate;
884+
885+
SourceFileAndUpToDate(StringRef FilePath, bool IsUpToDate)
886+
: FilePath(FilePath), IsUpToDate(IsUpToDate) {}
887+
};
888+
868889
struct CodeCompletionResultSink {
869890
using AllocatorPtr = std::shared_ptr<llvm::BumpPtrAllocator>;
870891

@@ -877,11 +898,13 @@ struct CodeCompletionResultSink {
877898

878899
/// Whether to annotate the results with XML.
879900
bool annotateResult = false;
901+
bool requiresSourceFileInfo = false;
880902

881903
/// Whether to emit object literals if desired.
882904
bool includeObjectLiterals = true;
883905

884906
std::vector<CodeCompletionResult *> Results;
907+
std::vector<SourceFileAndUpToDate> SourceFiles;
885908

886909
/// A single-element cache for module names stored in Allocator, keyed by a
887910
/// clang::Module * or swift::ModuleDecl *.
@@ -950,7 +973,10 @@ class CodeCompletionContext {
950973
: Cache(Cache) {}
951974

952975
void setAnnotateResult(bool flag) { CurrentResults.annotateResult = flag; }
953-
bool getAnnotateResult() { return CurrentResults.annotateResult; }
976+
bool getAnnotateResult() const { return CurrentResults.annotateResult; }
977+
978+
void setRequiresSourceFileInfo(bool flag) { CurrentResults.requiresSourceFileInfo = flag; }
979+
bool requiresSourceFileInfo() const { return CurrentResults.requiresSourceFileInfo; }
954980

955981
void setIncludeObjectLiterals(bool flag) {
956982
CurrentResults.includeObjectLiterals = flag;
@@ -1006,6 +1032,7 @@ class PrintingCodeCompletionConsumer
10061032
bool IncludeKeywords;
10071033
bool IncludeComments;
10081034
bool PrintAnnotatedDescription;
1035+
bool RequiresSourceFileInfo = false;
10091036

10101037
public:
10111038
PrintingCodeCompletionConsumer(llvm::raw_ostream &OS,
@@ -1017,8 +1044,8 @@ class PrintingCodeCompletionConsumer
10171044
IncludeComments(IncludeComments),
10181045
PrintAnnotatedDescription(PrintAnnotatedDescription) {}
10191046

1020-
void handleResults(CodeCompletionContext &context) override;
1021-
void handleResults(MutableArrayRef<CodeCompletionResult *> Results);
1047+
void handleResults(CodeCompletionContext &context) override;
1048+
void handleResults(MutableArrayRef<CodeCompletionResult *> Results);
10221049
};
10231050

10241051
/// Create a factory for code completion callbacks.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===--- ModuleSourceFileInfo.h ---------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_IDE_MODULESOURCEFILEINFO_H
14+
#define SWIFT_IDE_MODULESOURCEFILEINFO_H
15+
16+
#include "swift/AST/RawComment.h"
17+
#include "swift/Basic/BasicSourceInfo.h"
18+
#include "swift/Basic/LLVM.h"
19+
20+
namespace swift {
21+
class ASTContext;
22+
class Decl;
23+
namespace ide {
24+
25+
/// Get the source file path where \p D is declared. Returns an empty string
26+
/// if the information is not available.
27+
StringRef getSourceFilePathForDecl(const Decl *D);
28+
29+
/// Check if the source file of \p info is up-to-date.
30+
/// * \c true if the mtime and the size are the same.
31+
/// * \c true if the interface has hasn't changed.
32+
/// * \c false otherwise.
33+
bool isSourceFileUpToDate(const BasicSourceFileInfo &info, ASTContext &Ctx);
34+
35+
36+
} // namespace ide
37+
} // namespace swift
38+
39+
#endif // SWIFT_IDE_MODULESOURCEFILEINFO_H

lib/IDE/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_swift_host_library(swiftIDE STATIC
1111
FuzzyStringMatcher.cpp
1212
Refactoring.cpp
1313
ModuleInterfacePrinting.cpp
14+
ModuleSourceFileInfo.cpp
1415
REPLCodeCompletion.cpp
1516
SwiftSourceDocInfo.cpp
1617
SyntaxModel.cpp

lib/IDE/CodeCompletion.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "swift/Frontend/FrontendOptions.h"
3434
#include "swift/IDE/CodeCompletionCache.h"
3535
#include "swift/IDE/CodeCompletionResultPrinter.h"
36+
#include "swift/IDE/ModuleSourceFileInfo.h"
3637
#include "swift/IDE/Utils.h"
3738
#include "swift/Parse/CodeCompletionCallbacks.h"
3839
#include "swift/Sema/IDETypeChecking.h"
@@ -1320,11 +1321,14 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
13201321
}
13211322
}
13221323

1323-
return new (*Sink.Allocator) CodeCompletionResult(
1324+
CodeCompletionResult *result = new (*Sink.Allocator) CodeCompletionResult(
13241325
SemanticContext, Flair, NumBytesToErase, CCS, AssociatedDecl,
13251326
ModuleName, NotRecReason, copyString(*Sink.Allocator, BriefComment),
13261327
copyAssociatedUSRs(*Sink.Allocator, AssociatedDecl),
13271328
copyArray(*Sink.Allocator, CommentWords), ExpectedTypeRelation);
1329+
if (!result->isSystem())
1330+
result->setSourceFilePath(getSourceFilePathForDecl(AssociatedDecl));
1331+
return result;
13281332
}
13291333

13301334
case CodeCompletionResult::ResultKind::Keyword:
@@ -6558,6 +6562,37 @@ static void postProcessResults(MutableArrayRef<CodeCompletionResult *> results,
65586562
}
65596563
}
65606564

6565+
static void copyAllKnownSourceFileInfo(
6566+
ASTContext &Ctx, CodeCompletionResultSink &Sink) {
6567+
assert(Sink.SourceFiles.empty());
6568+
6569+
SmallVector<ModuleDecl *, 8> loadedModules;
6570+
loadedModules.reserve(Ctx.getNumLoadedModules());
6571+
for (auto &entry : Ctx.getLoadedModules())
6572+
loadedModules.push_back(entry.second);
6573+
6574+
auto &result = Sink.SourceFiles;
6575+
for (auto *M : loadedModules) {
6576+
// We don't need to check system modules.
6577+
if (M->isSystemModule())
6578+
continue;
6579+
6580+
M->collectBasicSourceFileInfo([&](const BasicSourceFileInfo &info) {
6581+
if (info.getFilePath().empty())
6582+
return;
6583+
6584+
bool isUpToDate = false;
6585+
if (info.isFromSourceFile()) {
6586+
// 'SourceFile' is always "up-to-date" because we've just loaded.
6587+
isUpToDate = true;
6588+
} else {
6589+
isUpToDate = isSourceFileUpToDate(info, Ctx);
6590+
}
6591+
result.emplace_back(copyString(*Sink.Allocator, info.getFilePath()), isUpToDate);
6592+
});
6593+
}
6594+
}
6595+
65616596
static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
65626597
CompletionLookup &Lookup,
65636598
DeclContext *DC,
@@ -6677,6 +6712,10 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
66776712
CompletionContext.CodeCompletionKind, DC,
66786713
/*Sink=*/nullptr);
66796714

6715+
if (CompletionContext.requiresSourceFileInfo())
6716+
copyAllKnownSourceFileInfo(SF.getASTContext(),
6717+
CompletionContext.getResultSink());
6718+
66806719
Consumer.handleResultsAndModules(CompletionContext, RequestedModules, DC);
66816720
}
66826721

@@ -7378,6 +7417,16 @@ void CodeCompletionCallbacksImpl::doneParsing() {
73787417

73797418
void PrintingCodeCompletionConsumer::handleResults(
73807419
CodeCompletionContext &context) {
7420+
if (context.requiresSourceFileInfo() &&
7421+
!context.getResultSink().SourceFiles.empty()) {
7422+
OS << "Known module source files\n";
7423+
for (auto &entry : context.getResultSink().SourceFiles) {
7424+
OS << (entry.IsUpToDate ? " + " : " - ");
7425+
OS << entry.FilePath;
7426+
OS << "\n";
7427+
}
7428+
this->RequiresSourceFileInfo = true;
7429+
}
73817430
auto results = context.takeResults();
73827431
handleResults(results);
73837432
}
@@ -7414,6 +7463,13 @@ void PrintingCodeCompletionConsumer::handleResults(
74147463
OS << "; comment=" << comment;
74157464
}
74167465

7466+
if (RequiresSourceFileInfo) {
7467+
StringRef sourceFilePath = Result->getSourceFilePath();
7468+
if (!sourceFilePath.empty()) {
7469+
OS << "; source=" << sourceFilePath;
7470+
}
7471+
}
7472+
74177473
OS << "\n";
74187474
}
74197475
OS << "End completions\n";

0 commit comments

Comments
 (0)