Skip to content

Commit 6c015ca

Browse files
authored
Merge pull request swiftlang#35665 from beccadax/i-have-some-notes-for-you
Add support for access notes
2 parents 69d251a + ef97f5c commit 6c015ca

26 files changed

+1381
-38
lines changed

include/swift/AST/AccessNotes.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//===--- AccessNotes.h - Access Notes ---------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 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+
// Implements access notes, which allow certain modifiers or attributes to be
14+
// added to the declarations in a module.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef ACCESSNOTES_H
19+
#define ACCESSNOTES_H
20+
21+
#include "swift/AST/Identifier.h"
22+
#include "swift/AST/StorageImpl.h"
23+
#include "swift/Basic/NullablePtr.h"
24+
#include "llvm/Support/Error.h"
25+
#include "llvm/Support/MemoryBuffer.h"
26+
#include "llvm/Support/raw_ostream.h"
27+
#include <set>
28+
#include <string>
29+
#include <vector>
30+
31+
namespace swift {
32+
class ASTContext;
33+
class ValueDecl;
34+
35+
/// The name of the declaration an access note should be applied to.
36+
///
37+
/// Grammatically, this is equivalent to a \c ParsedDeclName, but supports a
38+
/// subset of that type's features.
39+
class AccessNoteDeclName {
40+
public:
41+
/// The names of the parent/contextual declarations containing the declaration
42+
/// the access note should apply to.
43+
std::vector<Identifier> parentNames;
44+
45+
/// The name of the declaration the access note should be applied to. (For
46+
/// accessors, this is actually the name of the storage it's attached to.)
47+
DeclName name;
48+
49+
/// For accessors, the kind of accessor; for non-accessors, \c None.
50+
Optional<AccessorKind> accessorKind;
51+
52+
AccessNoteDeclName(ASTContext &ctx, StringRef str);
53+
AccessNoteDeclName();
54+
55+
/// If true, an access note with this name should apply to \p VD.
56+
bool matches(ValueDecl *VD) const;
57+
58+
/// If true, the name is empty and invalid.
59+
bool empty() const;
60+
61+
void print(llvm::raw_ostream &os) const;
62+
SWIFT_DEBUG_DUMP;
63+
};
64+
65+
/// An individual access note specifying modifications to a declaration.
66+
class AccessNote {
67+
public:
68+
/// The name of the declaration to modify.
69+
AccessNoteDeclName Name;
70+
71+
/// If \c true, add an @objc attribute; if \c false, delete an @objc
72+
/// attribute; if \c None, do nothing.
73+
Optional<bool> ObjC;
74+
75+
/// If \c true, add a dynamic modifier; if \c false, delete a dynamic
76+
/// modifier; if \c None, do nothing.
77+
Optional<bool> Dynamic;
78+
79+
/// If set, modify an @objc attribute to give it the specified \c ObjCName.
80+
/// If \c ObjC would otherwise be \c None, it will be set to \c true.
81+
Optional<ObjCSelector> ObjCName;
82+
83+
void dump(llvm::raw_ostream &os, int indent = 0) const;
84+
SWIFT_DEBUG_DUMP;
85+
};
86+
87+
/// A set of access notes with module-wide metadata about them.
88+
class AccessNotesFile {
89+
public:
90+
/// A human-readable string describing why the access notes are being applied.
91+
/// Inserted into diagnostics about access notes in the file.
92+
std::string Reason;
93+
94+
/// Access notes to apply to the module.
95+
std::vector<AccessNote> Notes;
96+
97+
/// Load the access notes from \p buffer, or \c None if they cannot be loaded.
98+
/// Diagnoses any parsing issues with the access notes file.
99+
static llvm::Optional<AccessNotesFile>
100+
load(ASTContext &ctx, const llvm::MemoryBuffer *buffer);
101+
102+
/// Look up the access note in this file, if any, which applies to \p VD.
103+
NullablePtr<const AccessNote> lookup(ValueDecl *VD) const;
104+
105+
void dump(llvm::raw_ostream &os) const;
106+
SWIFT_DEBUG_DUMP;
107+
};
108+
109+
}
110+
111+
#endif

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,5 +405,16 @@ WARNING(module_incompatible_with_skip_function_bodies,none,
405405
"-experimental-skip-*-function-bodies* flags; they have "
406406
"been automatically disabled", (StringRef))
407407

408+
WARNING(access_notes_file_io_error,none,
409+
"ignored access notes file at '%0' because it cannot be read: %1",
410+
(StringRef, StringRef))
411+
WARNING(error_in_access_notes_file,none,
412+
"ignored access notes file because it cannot be parsed: %0",
413+
(StringRef))
414+
REMARK(warning_in_access_notes_file,none,
415+
"ignored invalid content in access notes file: %0",
416+
(StringRef))
417+
418+
408419
#define UNDEFINE_DIAGNOSTIC_MACROS
409420
#include "DefineDiagnosticMacros.h"

include/swift/AST/DiagnosticsSema.def

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5653,5 +5653,35 @@ ERROR(atomics_ordering_must_be_constant, none,
56535653
"ordering argument must be a static method or property of %0",
56545654
(Identifier))
56555655

5656+
//------------------------------------------------------------------------------
5657+
// MARK: access notes
5658+
//------------------------------------------------------------------------------
5659+
5660+
REMARK(attr_added_by_access_note, none,
5661+
"access note for %0 adds %select{attribute|modifier}1 '%2' to this %3",
5662+
(StringRef, bool, StringRef, DescriptiveDeclKind))
5663+
NOTE(fixit_attr_added_by_access_note, none,
5664+
"add %select{attribute|modifier}0 explicitly to silence this warning",
5665+
(bool))
5666+
5667+
REMARK(attr_removed_by_access_note, none,
5668+
"access note for %0 removes %select{attribute|modifier}1 '%2' from "
5669+
"this %3",
5670+
(StringRef, bool, StringRef, DescriptiveDeclKind))
5671+
NOTE(fixit_attr_removed_by_access_note, none,
5672+
"remove %select{attribute|modifier}0 explicitly to silence this warning",
5673+
(bool))
5674+
5675+
REMARK(attr_objc_name_changed_by_access_note, none,
5676+
"access note for %0 changes the '@objc' name of this %1 to %2",
5677+
(StringRef, DescriptiveDeclKind, ObjCSelector))
5678+
NOTE(fixit_attr_objc_name_changed_by_access_note, none,
5679+
"change '@objc' name in source code explicitly to silence this warning",
5680+
())
5681+
REMARK(attr_objc_name_conflicts_with_access_note, none,
5682+
"access note for %0 changes the '@objc' name of this %1 to %2, but "
5683+
"source code specifies %3; the access note will be ignored",
5684+
(StringRef, DescriptiveDeclKind, ObjCSelector, ObjCSelector))
5685+
56565686
#define UNDEFINE_DIAGNOSTIC_MACROS
56575687
#include "DefineDiagnosticMacros.h"

include/swift/AST/Identifier.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,13 @@ class ObjCSelector {
820820
/// Construct an invalid ObjCSelector.
821821
ObjCSelector() : Storage() {}
822822

823+
/// Split \p string into selector pieces on colons to create an ObjCSelector.
824+
///
825+
/// This should not be used to parse selectors written directly in Swift
826+
/// source source code (e.g. the argument of an @objc attribute). Use the
827+
/// parser for that.
828+
static llvm::Optional<ObjCSelector> parse(ASTContext &ctx, StringRef string);
829+
823830
/// Convert to true if the decl name is valid.
824831
explicit operator bool() const { return (bool)Storage; }
825832

include/swift/AST/Module.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_MODULE_H
1818
#define SWIFT_MODULE_H
1919

20+
#include "swift/AST/AccessNotes.h"
2021
#include "swift/AST/Decl.h"
2122
#include "swift/AST/DeclContext.h"
2223
#include "swift/AST/Identifier.h"
@@ -249,6 +250,8 @@ class ModuleDecl : public DeclContext, public TypeDecl {
249250
/// \see EntryPointInfoTy
250251
EntryPointInfoTy EntryPointInfo;
251252

253+
AccessNotesFile accessNotes;
254+
252255
ModuleDecl(Identifier name, ASTContext &ctx, ImplicitImportInfo importInfo);
253256

254257
public:
@@ -279,6 +282,9 @@ class ModuleDecl : public DeclContext, public TypeDecl {
279282
/// imports.
280283
ImplicitImportList getImplicitImports() const;
281284

285+
AccessNotesFile &getAccessNotes() { return accessNotes; }
286+
const AccessNotesFile &getAccessNotes() const { return accessNotes; }
287+
282288
ArrayRef<FileUnit *> getFiles() {
283289
assert(!Files.empty() || failedToLoad());
284290
return Files;

include/swift/AST/TypeCheckRequests.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2312,6 +2312,25 @@ class SpecializeAttrTargetDeclRequest
23122312
bool isCached() const { return true; }
23132313
};
23142314

2315+
/// Looks up and applies the access note for a given declaration.
2316+
class ApplyAccessNoteRequest
2317+
: public SimpleRequest<ApplyAccessNoteRequest,
2318+
evaluator::SideEffect(ValueDecl *),
2319+
RequestFlags::Cached> {
2320+
public:
2321+
using SimpleRequest::SimpleRequest;
2322+
2323+
private:
2324+
friend SimpleRequest;
2325+
2326+
evaluator::SideEffect evaluate(Evaluator &evaluator, ValueDecl *VD) const;
2327+
2328+
public:
2329+
// Cached.
2330+
bool isCached() const { return true; }
2331+
};
2332+
2333+
23152334
class TypeCheckSourceFileRequest
23162335
: public SimpleRequest<
23172336
TypeCheckSourceFileRequest, evaluator::SideEffect(SourceFile *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ SWIFT_REQUEST(TypeChecker, AbstractGenericSignatureRequest,
2020
SmallVector<GenericTypeParamType *, 2>,
2121
SmallVector<Requirement, 2>),
2222
Cached, NoLocationInfo)
23+
SWIFT_REQUEST(TypeChecker, ApplyAccessNoteRequest,
24+
evaluator::SideEffect(ValueDecl *), Cached, NoLocationInfo)
2325
SWIFT_REQUEST(TypeChecker, AttachedResultBuilderRequest,
2426
CustomAttr *(ValueDecl *), Cached, NoLocationInfo)
2527
SWIFT_REQUEST(TypeChecker, AttachedPropertyWrapperTypeRequest,

include/swift/Basic/SourceManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class SourceManager {
7878
FileSystem = FS;
7979
}
8080

81-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() {
81+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const {
8282
return FileSystem;
8383
}
8484

include/swift/Frontend/Frontend.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,9 @@ class CompilerInstance {
467467
DiagnosticEngine &getDiags() { return Diagnostics; }
468468
const DiagnosticEngine &getDiags() const { return Diagnostics; }
469469

470-
llvm::vfs::FileSystem &getFileSystem() { return *SourceMgr.getFileSystem(); }
470+
llvm::vfs::FileSystem &getFileSystem() const {
471+
return *SourceMgr.getFileSystem();
472+
}
471473

472474
ASTContext &getASTContext() { return *Context; }
473475
const ASTContext &getASTContext() const { return *Context; }

include/swift/Frontend/FrontendOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ class FrontendOptions {
7070
/// The path to which we should store indexing data, if any.
7171
std::string IndexStorePath;
7272

73+
/// The path to load access notes from.
74+
std::string AccessNotesPath;
75+
7376
/// The path to look in when loading a module interface file, to see if a
7477
/// binary module has already been built for use by the compiler.
7578
std::string PrebuiltModuleCachePath;

0 commit comments

Comments
 (0)