Skip to content

Commit 7d9551c

Browse files
@_documentation now takes arguments 'visibility' and 'metadata'
1 parent 5795ae4 commit 7d9551c

23 files changed

+268
-108
lines changed

docs/ReferenceGuides/UnderscoredAttributes.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,26 @@ extension Text {
117117
}
118118
```
119119

120-
## `@_documentation(...)`
121-
122-
Adds a "documentation category" to the given symbol. The identifier in the
123-
attribute is added to the symbol graph in the `"category"` field of the symbol.
124-
125-
There are two special-case categories: `underscored` will treat the given symbol
126-
as having an underscored name regardless of its actual name, effectively marking
127-
it as `internal`. Conversely, the `ignoreUnderscored` category will do the
128-
opposite: A symbol with this category will appear in symbol graphs with its
129-
original visibility, regardless of whether it has an underscored name.
130-
131-
`@_documentation(underscored)` can also be applied to `@_exported import`
132-
statements to treat the re-exported symbols as `internal`, dropping them from
133-
public symbol graphs.
120+
## `@_documentation(metadata: ...)`
121+
122+
Adds "documentation metadata" to the symbol. The identifier in the attribute is
123+
added to the symbol graph in the `"metadata"` field of the symbol. This can be
124+
used to add an arbitrary grouping or other indicator to symbols for use in
125+
documentation.
126+
127+
## `@_documentation(visibility: ...)`
128+
129+
Forces the symbol to be treated as the given access level when checking
130+
visibility. This can be used to, for example, force a symbol with an underscored
131+
name to appear in `public` symbol graphs, or treat an otherwise-`public` symbol
132+
as being `internal` or `private` for the purposes of documentation, to hide it
133+
from `public` docs.
134+
135+
This can also be applied to `@_exported import` statements to only include the
136+
imported symbols in symbol graphs with the given minimum access level. For
137+
example, applying `@_documentation(visibility: internal)` to an `@_exported
138+
import` statement will hide the imported symbols from `public` symbol graphs and
139+
documentation, but show them on `internal` symbol graphs and documentation.
134140

135141
## `@_dynamicReplacement(for: targetFunc(label:))`
136142

include/swift/AST/Attr.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,9 @@ SIMPLE_DECL_ATTR(_alwaysEmitConformanceMetadata, AlwaysEmitConformanceMetadata,
746746
132)
747747

748748
DECL_ATTR(_documentation, Documentation,
749-
OnAnyDecl |
749+
OnAnyDecl | UserInaccessible |
750750
APIBreakingToAdd | APIStableToRemove | ABIStableToAdd | ABIStableToRemove,
751-
132)
751+
133)
752752

753753
// If you're adding a new underscored attribute here, please document it in
754754
// docs/ReferenceGuides/UnderscoredAttributes.md.

include/swift/AST/Attr.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,15 +2232,16 @@ class BackDeployAttr: public DeclAttribute {
22322232
class DocumentationAttr: public DeclAttribute {
22332233
public:
22342234
DocumentationAttr(SourceLoc AtLoc, SourceRange Range,
2235-
StringRef Category,
2235+
StringRef Metadata, Optional<AccessLevel> Visibility,
22362236
bool Implicit)
22372237
: DeclAttribute(DAK_Documentation, AtLoc, Range, Implicit),
2238-
Category(Category) {}
2238+
Metadata(Metadata), Visibility(Visibility) {}
22392239

2240-
DocumentationAttr(StringRef Category, bool Implicit)
2241-
: DocumentationAttr(SourceLoc(), SourceRange(), Category, Implicit) {}
2240+
DocumentationAttr(StringRef Metadata, Optional<AccessLevel> Visibility, bool Implicit)
2241+
: DocumentationAttr(SourceLoc(), SourceRange(), Metadata, Visibility, Implicit) {}
22422242

2243-
const StringRef Category;
2243+
const StringRef Metadata;
2244+
const Optional<AccessLevel> Visibility;
22442245

22452246
static bool classof(const DeclAttribute *DA) {
22462247
return DA->getKind() == DAK_Documentation;

include/swift/AST/DiagnosticsParse.def

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,9 +1464,6 @@ ERROR(attr_expected_string_literal,none,
14641464
ERROR(attr_expected_integer_literal,none,
14651465
"expected integer literal in '%0' attribute", (StringRef))
14661466

1467-
ERROR(attr_expected_identifier,none,
1468-
"expected identifier in '%0' attribute", (StringRef))
1469-
14701467
ERROR(attr_expected_option_such_as,none,
14711468
"expected '%0' option such as '%1'", (StringRef, StringRef))
14721469

@@ -1765,6 +1762,27 @@ WARNING(warn_attr_unsafe_removed,none,
17651762
"'%0' attribute has been removed in favor of @preconcurrency",
17661763
(StringRef))
17671764

1765+
// _documentation
1766+
ERROR(documentation_attr_expected_argument,none,
1767+
"@_documentation attribute expected 'visibility' or 'metadata' argument",
1768+
())
1769+
ERROR(documentation_attr_unknown_argument,none,
1770+
"unknown argument '%0', expected 'visibility' or 'metadata'",
1771+
(StringRef))
1772+
ERROR(documentation_attr_expected_access_level,none,
1773+
"@_documentation attribute's 'visibility' argument expected an access level",
1774+
())
1775+
ERROR(documentation_attr_unknown_access_level,none,
1776+
"unknown visibility '%0', expected an access level keyword",
1777+
(StringRef))
1778+
ERROR(documentation_attr_duplicate_visibility,none,
1779+
"cannot give more than one visibility to the same item", ())
1780+
ERROR(documentation_attr_metadata_expected_identifier,none,
1781+
"@_documentation attribute's 'metadata' argument expected a plain identifier",
1782+
())
1783+
ERROR(documentation_attr_duplicate_metadata,none,
1784+
"cannot give more than one metadata argument to the same item", ())
1785+
17681786
//------------------------------------------------------------------------------
17691787
// MARK: Generics parsing diagnostics
17701788
//------------------------------------------------------------------------------

include/swift/AST/Import.h

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef SWIFT_IMPORT_H
2020
#define SWIFT_IMPORT_H
2121

22+
#include "swift/AST/AttrKind.h"
2223
#include "swift/AST/Identifier.h"
2324
#include "swift/Basic/Located.h"
2425
#include "swift/Basic/OptionSet.h"
@@ -84,10 +85,6 @@ enum class ImportFlags {
8485
/// concurrency.
8586
Preconcurrency = 0x20,
8687

87-
/// The module is being exported, but its contents should not appear in a
88-
/// symbol graph.
89-
NoDoc = 0x40,
90-
9188
/// Used for DenseMap.
9289
Reserved = 0x80
9390
};
@@ -574,13 +571,18 @@ struct AttributedImport {
574571
/// is the source range covering the annotation.
575572
SourceRange preconcurrencyRange;
576573

574+
/// If the import declaration has a `@_documentation(visibility: <access>)`
575+
/// attribute, this is the given access level.
576+
Optional<AccessLevel> docVisibility;
577+
577578
AttributedImport(ModuleInfo module, SourceLoc importLoc = SourceLoc(),
578579
ImportOptions options = ImportOptions(),
579580
StringRef filename = {}, ArrayRef<Identifier> spiGroups = {},
580-
SourceRange preconcurrencyRange = {})
581+
SourceRange preconcurrencyRange = {},
582+
Optional<AccessLevel> docVisibility = None)
581583
: module(module), importLoc(importLoc), options(options),
582584
sourceFileArg(filename), spiGroups(spiGroups),
583-
preconcurrencyRange(preconcurrencyRange) {
585+
preconcurrencyRange(preconcurrencyRange), docVisibility(docVisibility) {
584586
assert(!(options.contains(ImportFlags::Exported) &&
585587
options.contains(ImportFlags::ImplementationOnly)) ||
586588
options.contains(ImportFlags::Reserved));
@@ -590,14 +592,15 @@ struct AttributedImport {
590592
AttributedImport(ModuleInfo module, AttributedImport<OtherModuleInfo> other)
591593
: AttributedImport(module, other.importLoc, other.options,
592594
other.sourceFileArg, other.spiGroups,
593-
other.preconcurrencyRange) { }
595+
other.preconcurrencyRange, other.docVisibility) { }
594596

595597
friend bool operator==(const AttributedImport<ModuleInfo> &lhs,
596598
const AttributedImport<ModuleInfo> &rhs) {
597599
return lhs.module == rhs.module &&
598600
lhs.options.toRaw() == rhs.options.toRaw() &&
599601
lhs.sourceFileArg == rhs.sourceFileArg &&
600-
lhs.spiGroups == rhs.spiGroups;
602+
lhs.spiGroups == rhs.spiGroups &&
603+
lhs.docVisibility == rhs.docVisibility;
601604
}
602605

603606
AttributedImport<ImportedModule> getLoaded(ModuleDecl *loadedModule) const {
@@ -749,14 +752,14 @@ struct DenseMapInfo<swift::AttributedImport<ModuleInfo>> {
749752
SourceLocDMI::getEmptyKey(),
750753
ImportOptionsDMI::getEmptyKey(),
751754
StringRefDMI::getEmptyKey(),
752-
{});
755+
{}, {}, None);
753756
}
754757
static inline AttributedImport getTombstoneKey() {
755758
return AttributedImport(ModuleInfoDMI::getTombstoneKey(),
756759
SourceLocDMI::getEmptyKey(),
757760
ImportOptionsDMI::getTombstoneKey(),
758761
StringRefDMI::getTombstoneKey(),
759-
{});
762+
{}, {}, None);
760763
}
761764
static inline unsigned getHashValue(const AttributedImport &import) {
762765
return detail::combineHashValue(
@@ -770,7 +773,8 @@ struct DenseMapInfo<swift::AttributedImport<ModuleInfo>> {
770773
return ModuleInfoDMI::isEqual(a.module, b.module) &&
771774
ImportOptionsDMI::isEqual(a.options, b.options) &&
772775
StringRefDMI::isEqual(a.sourceFileArg, b.sourceFileArg) &&
773-
a.spiGroups == b.spiGroups;
776+
a.spiGroups == b.spiGroups &&
777+
a.docVisibility == b.docVisibility;
774778
}
775779
};
776780
}

include/swift/AST/Module.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ inline SourceLoc extractNearestSourceLoc(const ModuleDecl *mod) {
952952
void collectParsedExportedImports(const ModuleDecl *M,
953953
SmallPtrSetImpl<ModuleDecl *> &Imports,
954954
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> &QualifiedImports,
955-
bool DropNoDoc = false);
955+
llvm::function_ref<bool(AttributedImport<ImportedModule>)> includeImport = nullptr);
956956

957957
} // end namespace swift
958958

include/swift/Parse/Parser.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,14 @@ class Parser {
10981098
bool parseBackDeployAttribute(DeclAttributes &Attributes, StringRef AttrName,
10991099
SourceLoc AtLoc, SourceLoc Loc);
11001100

1101+
/// Parse the @_documentation attribute.
1102+
ParserResult<DocumentationAttr> parseDocumentationAttribute(SourceLoc AtLoc,
1103+
SourceLoc Loc);
1104+
1105+
/// Parse a single argument from a @_documentation attribute.
1106+
bool parseDocumentationAttributeArgument(Optional<StringRef> &Metadata,
1107+
Optional<AccessLevel> &Visibility);
1108+
11011109
/// Parse a specific attribute.
11021110
ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
11031111
PatternBindingInitializer *&initContext,

include/swift/SymbolGraphGen/DocumentationCategory.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,31 @@
1515

1616
#include "swift/AST/Decl.h"
1717

18+
#include "llvm/Support/Compiler.h"
19+
1820
namespace swift {
1921
namespace symbolgraphgen {
2022

21-
static StringRef documentationCategoryForDecl(const Decl *D) {
23+
LLVM_ATTRIBUTE_USED
24+
static StringRef documentationMetadataForDecl(const Decl *D) {
2225
if (!D) return {};
2326

2427
if (const auto *DC = D->getAttrs().getAttribute<DocumentationAttr>()) {
25-
return DC->Category;
28+
return DC->Metadata;
2629
}
2730

2831
return {};
2932
}
3033

31-
static bool isUnderscoredDocumentationCategory(const Decl *D) {
32-
return documentationCategoryForDecl(D) == "underscored";
33-
}
34+
LLVM_ATTRIBUTE_USED
35+
static Optional<AccessLevel> documentationVisibilityForDecl(const Decl *D) {
36+
if (!D) return None;
37+
38+
if (const auto *DC = D->getAttrs().getAttribute<DocumentationAttr>()) {
39+
return DC->Visibility;
40+
}
3441

35-
static bool isIgnoreUnderscoredDocumentationCategory(const Decl *D) {
36-
return documentationCategoryForDecl(D) == "ignoreUnderscored";
42+
return None;
3743
}
3844

3945
} // namespace symbolgraphgen

lib/AST/Module.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,13 +795,13 @@ bool ModuleDecl::shouldCollectDisplayDecls() const {
795795
void swift::collectParsedExportedImports(const ModuleDecl *M,
796796
SmallPtrSetImpl<ModuleDecl *> &Imports,
797797
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> &QualifiedImports,
798-
bool DropNoDoc) {
798+
llvm::function_ref<bool(AttributedImport<ImportedModule>)> includeImport) {
799799
for (const FileUnit *file : M->getFiles()) {
800800
if (const SourceFile *source = dyn_cast<SourceFile>(file)) {
801801
if (source->hasImports()) {
802802
for (auto import : source->getImports()) {
803803
if (import.options.contains(ImportFlags::Exported) &&
804-
!(DropNoDoc && import.options.contains(ImportFlags::NoDoc)) &&
804+
(!includeImport || includeImport(import)) &&
805805
import.module.importedModule->shouldCollectDisplayDecls()) {
806806
auto *TheModule = import.module.importedModule;
807807

lib/AST/TypeCheckRequests.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,8 +1459,6 @@ void swift::simple_display(llvm::raw_ostream &out,
14591459

14601460
if (import.options.contains(ImportFlags::Exported))
14611461
out << " exported";
1462-
if (import.options.contains(ImportFlags::NoDoc))
1463-
out << " nodoc";
14641462
if (import.options.contains(ImportFlags::Testable))
14651463
out << " testable";
14661464
if (import.options.contains(ImportFlags::ImplementationOnly))

0 commit comments

Comments
 (0)