Files
swift-mirror/include/swift/AST/AvailabilitySpec.h
Ankit Aggarwal 92d09f4e19 Extend @available to support PackageDescription
<rdar://problem/46548531> Extend @available to support PackageDescription

This introduces a new private availability kind "_PackageDescription" to
allow availability testing by an arbitary version that can be passed
using a new command-line flag "-swiftpm-manifest-version". The semantics
are exactly same as Swift version specific availability. In longer term,
it maybe possible to remove this enhancement once there is
a language-level availability support for 3rd party libraries.

Motivation:

Swift packages are configured using a Package.swift manifest file. The
manifest file uses a library called PackageDescription, which contains
various settings that can be configured for a package. The new additions
in the PackageDescription APIs are gated behind a "tools version" that
every manifest must declare. This means, packages don't automatically
get access to the new APIs. They need to update their declared tools
version in order to use the new API. This is basically similar to the
minimum deployment target version we have for our OSes.

This gating is important for allowing packages to maintain backwards
compatibility. SwiftPM currently checks for API usages at runtime in
order to implement this gating. This works reasonably well but can lead
to a poor experience with features like code-completion and module
interface generation in IDEs and editors (that use sourcekit-lsp) as
SwiftPM has no control over these features.
2018-12-08 09:38:40 +05:30

188 lines
6.7 KiB
C++

//===--- AvailabilitySpec.h - Swift Availability Query ASTs -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the availability specification AST classes.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_AVAILABILITY_SPEC_H
#define SWIFT_AST_AVAILABILITY_SPEC_H
#include "swift/AST/Identifier.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/AST/PlatformKind.h"
#include "llvm/Support/VersionTuple.h"
namespace swift {
class ASTContext;
enum class VersionComparison { GreaterThanEqual };
enum class AvailabilitySpecKind {
/// A platform-version constraint of the form "PlatformName X.Y.Z"
PlatformVersionConstraint,
/// A wildcard constraint, spelled '*', that is equivalent
/// to CurrentPlatformName >= MinimumDeploymentTargetVersion
OtherPlatform,
/// A language-version constraint of the form "swift X.Y.Z"
LanguageVersionConstraint,
/// A PackageDescription version constraint of the form "_PackageDescription X.Y.Z"
PackageDescriptionVersionConstraint,
};
/// The root class for specifications of API availability in availability
/// queries.
class AvailabilitySpec {
AvailabilitySpecKind Kind;
public:
AvailabilitySpec(AvailabilitySpecKind Kind) : Kind(Kind) {}
AvailabilitySpecKind getKind() const { return Kind; }
SourceRange getSourceRange() const;
void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(AvailabilitySpec));
void *operator new(size_t Bytes) throw() = delete;
void operator delete(void *Data) throw() = delete;
};
/// An availability specification that guards execution based on the
/// run-time platform and version, e.g., OS X >= 10.10.
class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
PlatformKind Platform;
SourceLoc PlatformLoc;
llvm::VersionTuple Version;
SourceRange VersionSrcRange;
public:
PlatformVersionConstraintAvailabilitySpec(PlatformKind Platform,
SourceLoc PlatformLoc,
llvm::VersionTuple Version,
SourceRange VersionSrcRange)
: AvailabilitySpec(AvailabilitySpecKind::PlatformVersionConstraint),
Platform(Platform),
PlatformLoc(PlatformLoc), Version(Version),
VersionSrcRange(VersionSrcRange) {}
/// The required platform.
PlatformKind getPlatform() const { return Platform; }
SourceLoc getPlatformLoc() const { return PlatformLoc; }
// The platform version to compare against.
llvm::VersionTuple getVersion() const { return Version; }
SourceRange getVersionSrcRange() const { return VersionSrcRange; }
SourceRange getSourceRange() const;
void print(raw_ostream &OS, unsigned Indent) const;
static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::PlatformVersionConstraint;
}
void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(PlatformVersionConstraintAvailabilitySpec)){
return AvailabilitySpec::operator new(Bytes, C, Alignment);
}
};
/// An availability specification that guards execution based on the
/// compile-time platform agnostic version, e.g., swift >= 3.0.1,
/// package-description >= 4.0.
class PlatformAgnosticVersionConstraintAvailabilitySpec : public AvailabilitySpec {
SourceLoc PlatformAgnosticNameLoc;
llvm::VersionTuple Version;
SourceRange VersionSrcRange;
public:
PlatformAgnosticVersionConstraintAvailabilitySpec(
AvailabilitySpecKind AvailabilitySpecKind,
SourceLoc PlatformAgnosticNameLoc, llvm::VersionTuple Version,
SourceRange VersionSrcRange)
: AvailabilitySpec(AvailabilitySpecKind),
PlatformAgnosticNameLoc(PlatformAgnosticNameLoc), Version(Version),
VersionSrcRange(VersionSrcRange) {
assert(AvailabilitySpecKind == AvailabilitySpecKind::LanguageVersionConstraint ||
AvailabilitySpecKind == AvailabilitySpecKind::PackageDescriptionVersionConstraint);
}
SourceLoc getPlatformAgnosticNameLoc() const { return PlatformAgnosticNameLoc; }
// The platform version to compare against.
llvm::VersionTuple getVersion() const { return Version; }
SourceRange getVersionSrcRange() const { return VersionSrcRange; }
SourceRange getSourceRange() const;
bool isLanguageVersionSpecific() const {
return getKind() == AvailabilitySpecKind::LanguageVersionConstraint;
}
void print(raw_ostream &OS, unsigned Indent) const;
static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::LanguageVersionConstraint ||
Spec->getKind() == AvailabilitySpecKind::PackageDescriptionVersionConstraint;
}
void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(PlatformAgnosticVersionConstraintAvailabilitySpec)){
return AvailabilitySpec::operator new(Bytes, C, Alignment);
}
};
/// A wildcard availability specification that guards execution
/// by checking that the run-time version is greater than the minimum
/// deployment target. This specification is designed to ease porting
/// to new platforms. Because new platforms typically branch from
/// existing platforms, the wildcard allows an #available() check to do the
/// "right" thing (executing the guarded branch) on the new platform without
/// requiring a modification to every availability guard in the program. Note
/// that we still do compile-time availability checking with '*', so the
/// compiler will still catch references to potentially unavailable symbols.
class OtherPlatformAvailabilitySpec : public AvailabilitySpec {
SourceLoc StarLoc;
public:
OtherPlatformAvailabilitySpec(SourceLoc StarLoc)
: AvailabilitySpec(AvailabilitySpecKind::OtherPlatform),
StarLoc(StarLoc) {}
SourceRange getSourceRange() const { return SourceRange(StarLoc, StarLoc); }
void print(raw_ostream &OS, unsigned Indent) const;
static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::OtherPlatform;
}
void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(OtherPlatformAvailabilitySpec)) {
return AvailabilitySpec::operator new(Bytes, C, Alignment);
}
};
} // end namespace swift
#endif