mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Another preposition splitting option: directional prepositions.
Swift SVN r15297
This commit is contained in:
@@ -31,7 +31,9 @@ namespace swift {
|
|||||||
/// Split before the last preposition.
|
/// Split before the last preposition.
|
||||||
BeforePreposition,
|
BeforePreposition,
|
||||||
/// Split after the last preposition.
|
/// Split after the last preposition.
|
||||||
AfterPreposition
|
AfterPreposition,
|
||||||
|
/// Split before directional prepositions, after other prepositions.
|
||||||
|
DirectionalPreposition,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A collection of options that affect the language dialect and
|
/// \brief A collection of options that affect the language dialect and
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ def enable_source_import : Flag<["-"], "enable-source-import">,
|
|||||||
def enable_objc_optional : Flag<["-"], "enable-objc-optional">,
|
def enable_objc_optional : Flag<["-"], "enable-objc-optional">,
|
||||||
HelpText<"Import Objective-C references using UncheckedOptional">;
|
HelpText<"Import Objective-C references using UncheckedOptional">;
|
||||||
|
|
||||||
|
def split_objc_selectors : Flag<["-"], "split-objc-selectors">,
|
||||||
|
HelpText<"Split imported Objective-C selectors based on prepositions">;
|
||||||
|
|
||||||
def split_objc_selectors_before : Flag<["-"], "split-objc-selectors-before">,
|
def split_objc_selectors_before : Flag<["-"], "split-objc-selectors-before">,
|
||||||
HelpText<"Split imported Objective-C selectors before the last preposition">;
|
HelpText<"Split imported Objective-C selectors before the last preposition">;
|
||||||
|
|
||||||
|
|||||||
@@ -580,11 +580,15 @@ splitSelectorPieceAt(StringRef selector, unsigned index,
|
|||||||
|
|
||||||
/// Determine whether the given word (which should have its first
|
/// Determine whether the given word (which should have its first
|
||||||
/// letter already capitalized) is a preposition.
|
/// letter already capitalized) is a preposition.
|
||||||
static bool isPreposition(StringRef word) {
|
///
|
||||||
return llvm::StringSwitch<bool>(word)
|
/// The stored boolean indicates whether the preposition has
|
||||||
#define PREPOSITION(Word) .Case(#Word, true)
|
/// direction.
|
||||||
|
static Optional<bool> isPreposition(StringRef word) {
|
||||||
|
return llvm::StringSwitch<Optional<bool>>(word)
|
||||||
|
#define DIRECTIONAL_PREPOSITION(Word) .Case(#Word, true)
|
||||||
|
#define PREPOSITION(Word) .Case(#Word, false)
|
||||||
#include "Prepositions.def"
|
#include "Prepositions.def"
|
||||||
.Default(false);
|
.Default(Nothing);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<StringRef, StringRef>
|
std::pair<StringRef, StringRef>
|
||||||
@@ -602,7 +606,6 @@ ClangImporter::Implementation::splitFirstSelectorPiece(
|
|||||||
unsigned selectorEnd = selector.size();
|
unsigned selectorEnd = selector.size();
|
||||||
unsigned wordStart = selector.size();
|
unsigned wordStart = selector.size();
|
||||||
unsigned wordEnd = wordStart;
|
unsigned wordEnd = wordStart;
|
||||||
bool splitBefore = SplitPrepositions == SelectorSplitKind::BeforePreposition;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Skip over any lowercase letters.
|
// Skip over any lowercase letters.
|
||||||
while (wordStart > 0 && clang::isLowercase(selector[wordStart-1]))
|
while (wordStart > 0 && clang::isLowercase(selector[wordStart-1]))
|
||||||
@@ -617,11 +620,29 @@ ClangImporter::Implementation::splitFirstSelectorPiece(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// If this word is a preposition, and it isn't the last word, split here.
|
// If this word is a preposition, and it isn't the last word, split here.
|
||||||
if (wordEnd != selectorEnd &&
|
if (wordEnd != selectorEnd) {
|
||||||
isPreposition(selector.substr(wordStart, wordEnd - wordStart))) {
|
if (auto isPrep = isPreposition(
|
||||||
return splitSelectorPieceAt(selector,
|
selector.substr(wordStart, wordEnd - wordStart))) {
|
||||||
splitBefore ? wordStart : wordEnd,
|
unsigned splitLocation;
|
||||||
buffer);
|
switch (SplitPrepositions) {
|
||||||
|
case SelectorSplitKind::None:
|
||||||
|
llvm_unreachable("not splitting selectors");
|
||||||
|
|
||||||
|
case SelectorSplitKind::BeforePreposition:
|
||||||
|
splitLocation = wordStart;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SelectorSplitKind::AfterPreposition:
|
||||||
|
splitLocation = wordEnd;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SelectorSplitKind::DirectionalPreposition:
|
||||||
|
splitLocation = *isPrep ? wordStart : wordEnd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return splitSelectorPieceAt(selector, splitLocation, buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for the next word.
|
// Look for the next word.
|
||||||
|
|||||||
@@ -16,14 +16,16 @@
|
|||||||
# error Define PREPOSITION(Word) before including this file.
|
# error Define PREPOSITION(Word) before including this file.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PREPOSITION(Abaft)
|
#ifndef DIRECTIONAL_PREPOSITION
|
||||||
PREPOSITION(Aboard)
|
# define DIRECTIONAL_PREPOSITION(Word) PREPOSITION(Word)
|
||||||
|
#endif
|
||||||
|
|
||||||
PREPOSITION(About)
|
PREPOSITION(About)
|
||||||
PREPOSITION(Above)
|
DIRECTIONAL_PREPOSITION(Above)
|
||||||
PREPOSITION(Absent)
|
PREPOSITION(Absent)
|
||||||
PREPOSITION(Across)
|
PREPOSITION(Across)
|
||||||
PREPOSITION(Afore)
|
DIRECTIONAL_PREPOSITION(Afore)
|
||||||
PREPOSITION(After)
|
DIRECTIONAL_PREPOSITION(After)
|
||||||
PREPOSITION(Against)
|
PREPOSITION(Against)
|
||||||
PREPOSITION(Along)
|
PREPOSITION(Along)
|
||||||
PREPOSITION(Alongside)
|
PREPOSITION(Alongside)
|
||||||
@@ -40,84 +42,70 @@ PREPOSITION(Aside)
|
|||||||
PREPOSITION(Astride)
|
PREPOSITION(Astride)
|
||||||
PREPOSITION(At)
|
PREPOSITION(At)
|
||||||
PREPOSITION(Athwart)
|
PREPOSITION(Athwart)
|
||||||
PREPOSITION(Atop)
|
DIRECTIONAL_PREPOSITION(Atop)
|
||||||
PREPOSITION(Barring)
|
PREPOSITION(Barring)
|
||||||
PREPOSITION(Before)
|
DIRECTIONAL_PREPOSITION(Before)
|
||||||
PREPOSITION(Behind)
|
DIRECTIONAL_PREPOSITION(Behind)
|
||||||
PREPOSITION(Below)
|
DIRECTIONAL_PREPOSITION(Below)
|
||||||
PREPOSITION(Beneath)
|
DIRECTIONAL_PREPOSITION(Beneath)
|
||||||
PREPOSITION(Beside)
|
PREPOSITION(Beside)
|
||||||
PREPOSITION(Besides)
|
PREPOSITION(Besides)
|
||||||
PREPOSITION(Between)
|
PREPOSITION(Between)
|
||||||
PREPOSITION(Betwixt)
|
PREPOSITION(Betwixt)
|
||||||
PREPOSITION(Beyond)
|
DIRECTIONAL_PREPOSITION(Beyond)
|
||||||
PREPOSITION(But)
|
|
||||||
PREPOSITION(By)
|
PREPOSITION(By)
|
||||||
PREPOSITION(Circa)
|
PREPOSITION(Circa)
|
||||||
PREPOSITION(Concerning)
|
PREPOSITION(Concerning)
|
||||||
PREPOSITION(Despite)
|
PREPOSITION(Despite)
|
||||||
PREPOSITION(Down)
|
DIRECTIONAL_PREPOSITION(Down)
|
||||||
PREPOSITION(During)
|
PREPOSITION(During)
|
||||||
PREPOSITION(Except)
|
PREPOSITION(Except)
|
||||||
PREPOSITION(Excluding)
|
PREPOSITION(Excluding)
|
||||||
PREPOSITION(Failing)
|
PREPOSITION(Failing)
|
||||||
PREPOSITION(Following)
|
DIRECTIONAL_PREPOSITION(Following)
|
||||||
PREPOSITION(For)
|
PREPOSITION(For)
|
||||||
PREPOSITION(Forenenst)
|
PREPOSITION(Forenenst)
|
||||||
PREPOSITION(From)
|
DIRECTIONAL_PREPOSITION(From)
|
||||||
PREPOSITION(Given)
|
PREPOSITION(Given)
|
||||||
PREPOSITION(In)
|
|
||||||
PREPOSITION(Including)
|
PREPOSITION(Including)
|
||||||
PREPOSITION(Inside)
|
DIRECTIONAL_PREPOSITION(Inside)
|
||||||
PREPOSITION(Into)
|
DIRECTIONAL_PREPOSITION(Into)
|
||||||
PREPOSITION(Lest)
|
PREPOSITION(Lest)
|
||||||
PREPOSITION(Like)
|
PREPOSITION(Like)
|
||||||
PREPOSITION(Mid)
|
DIRECTIONAL_PREPOSITION(Minus)
|
||||||
PREPOSITION(Midst)
|
DIRECTIONAL_PREPOSITION(Modulo)
|
||||||
PREPOSITION(Minus)
|
DIRECTIONAL_PREPOSITION(Near)
|
||||||
PREPOSITION(Modulo)
|
|
||||||
PREPOSITION(Near)
|
|
||||||
PREPOSITION(Next)
|
|
||||||
PREPOSITION(Notwithstanding)
|
PREPOSITION(Notwithstanding)
|
||||||
PREPOSITION(Of)
|
PREPOSITION(Of)
|
||||||
PREPOSITION(Off)
|
DIRECTIONAL_PREPOSITION(Onto)
|
||||||
PREPOSITION(On)
|
|
||||||
PREPOSITION(Onto)
|
|
||||||
PREPOSITION(Opposite)
|
PREPOSITION(Opposite)
|
||||||
PREPOSITION(Out)
|
DIRECTIONAL_PREPOSITION(Outside)
|
||||||
PREPOSITION(Outside)
|
|
||||||
PREPOSITION(Over)
|
PREPOSITION(Over)
|
||||||
PREPOSITION(Pace)
|
DIRECTIONAL_PREPOSITION(Past)
|
||||||
PREPOSITION(Past)
|
|
||||||
PREPOSITION(Per)
|
PREPOSITION(Per)
|
||||||
PREPOSITION(Plus)
|
DIRECTIONAL_PREPOSITION(Plus)
|
||||||
PREPOSITION(Pro)
|
|
||||||
PREPOSITION(Qua)
|
|
||||||
PREPOSITION(Regarding)
|
PREPOSITION(Regarding)
|
||||||
PREPOSITION(Round)
|
DIRECTIONAL_PREPOSITION(Since)
|
||||||
PREPOSITION(Sans)
|
|
||||||
PREPOSITION(Save)
|
|
||||||
PREPOSITION(Since)
|
|
||||||
PREPOSITION(Than)
|
PREPOSITION(Than)
|
||||||
PREPOSITION(Through)
|
PREPOSITION(Through)
|
||||||
PREPOSITION(Throughout)
|
PREPOSITION(Throughout)
|
||||||
PREPOSITION(Times)
|
DIRECTIONAL_PREPOSITION(Times)
|
||||||
PREPOSITION(To)
|
DIRECTIONAL_PREPOSITION(To)
|
||||||
PREPOSITION(Toward)
|
DIRECTIONAL_PREPOSITION(Toward)
|
||||||
PREPOSITION(Towards)
|
DIRECTIONAL_PREPOSITION(Towards)
|
||||||
PREPOSITION(Under)
|
DIRECTIONAL_PREPOSITION(Under)
|
||||||
PREPOSITION(Underneath)
|
DIRECTIONAL_PREPOSITION(Underneath)
|
||||||
PREPOSITION(Unlike)
|
PREPOSITION(Unlike)
|
||||||
PREPOSITION(Until)
|
DIRECTIONAL_PREPOSITION(Until)
|
||||||
PREPOSITION(Unto)
|
PREPOSITION(Unto)
|
||||||
PREPOSITION(Up)
|
DIRECTIONAL_PREPOSITION(Up)
|
||||||
PREPOSITION(Upon)
|
PREPOSITION(Upon)
|
||||||
PREPOSITION(Versus)
|
PREPOSITION(Versus)
|
||||||
PREPOSITION(Via)
|
PREPOSITION(Via)
|
||||||
PREPOSITION(Vs)
|
PREPOSITION(Vs)
|
||||||
PREPOSITION(With)
|
PREPOSITION(With)
|
||||||
PREPOSITION(Within)
|
DIRECTIONAL_PREPOSITION(Within)
|
||||||
PREPOSITION(Without)
|
DIRECTIONAL_PREPOSITION(Without)
|
||||||
PREPOSITION(Worth)
|
|
||||||
|
|
||||||
|
#undef DIRECTIONAL_PREPOSITION
|
||||||
#undef PREPOSITION
|
#undef PREPOSITION
|
||||||
|
|||||||
@@ -534,9 +534,12 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
|||||||
|
|
||||||
Opts.EnableObjCOptional = Args.hasArg(OPT_enable_objc_optional);
|
Opts.EnableObjCOptional = Args.hasArg(OPT_enable_objc_optional);
|
||||||
|
|
||||||
if (const Arg *A = Args.getLastArg(OPT_split_objc_selectors_before,
|
if (const Arg *A = Args.getLastArg(OPT_split_objc_selectors,
|
||||||
|
OPT_split_objc_selectors_before,
|
||||||
OPT_split_objc_selectors_after)) {
|
OPT_split_objc_selectors_after)) {
|
||||||
if (A->getOption().matches(OPT_split_objc_selectors_before))
|
if (A->getOption().matches(OPT_split_objc_selectors))
|
||||||
|
Opts.SplitPrepositions = SelectorSplitKind::DirectionalPreposition;
|
||||||
|
else if (A->getOption().matches(OPT_split_objc_selectors_before))
|
||||||
Opts.SplitPrepositions = SelectorSplitKind::BeforePreposition;
|
Opts.SplitPrepositions = SelectorSplitKind::BeforePreposition;
|
||||||
else
|
else
|
||||||
Opts.SplitPrepositions = SelectorSplitKind::AfterPreposition;
|
Opts.SplitPrepositions = SelectorSplitKind::AfterPreposition;
|
||||||
|
|||||||
376
test/ClangModules/objc_parse_split.swift
Normal file
376
test/ClangModules/objc_parse_split.swift
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
// RUN: rm -rf %t/clang-module-cache
|
||||||
|
// RUN: %swift %clang-importer-sdk -emit-sil -module-cache-path %t/clang-module-cache -I %S/Inputs/custom-modules -target x86_64-apple-darwin13 -split-objc-selectors %s -verify
|
||||||
|
// RUN: ls -lR %t/clang-module-cache | grep ObjectiveC.pcm
|
||||||
|
|
||||||
|
import AppKit
|
||||||
|
import objc_ext
|
||||||
|
import TestProtocols
|
||||||
|
|
||||||
|
func testAnyObject(obj: AnyObject) {
|
||||||
|
var optStr = obj.nsstringProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construction
|
||||||
|
func construction() {
|
||||||
|
var b = B()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtyping
|
||||||
|
func treatBAsA(b: B) -> A {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance method invocation
|
||||||
|
func instanceMethods(b: B) {
|
||||||
|
var i = b.method(1, withFloat:2.5)
|
||||||
|
i = i + b.method(1, withDouble:2.5)
|
||||||
|
|
||||||
|
// BOOL
|
||||||
|
b.setEnabled(true)
|
||||||
|
|
||||||
|
// SEL
|
||||||
|
b.performSelector("isEqual:", withObject:b)
|
||||||
|
|
||||||
|
// Renaming of redundant parameters.
|
||||||
|
b.performAdd(1, withValue:2, withValue2:3, withValue:4)
|
||||||
|
|
||||||
|
// Renaming of redundant parameters.
|
||||||
|
b.performMultiplyWith(value:1, value:2)
|
||||||
|
|
||||||
|
// Splitting does not split a preposition at the end
|
||||||
|
b.moveFor(5)
|
||||||
|
|
||||||
|
// Both class and instance methods exist.
|
||||||
|
b.description()
|
||||||
|
b.instanceTakesObjectClassTakesFloat(b)
|
||||||
|
b.instanceTakesObjectClassTakesFloat(2.0) // expected-error{{does not type-check}}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Class method invocation
|
||||||
|
func classMethods(b: B, other: NSObject) {
|
||||||
|
var i = B.classMethod()
|
||||||
|
i += B.classMethod(1)
|
||||||
|
i += B.classMethod(1, withInt:2)
|
||||||
|
|
||||||
|
i += b.classMethod() // expected-error{{'B' does not have a member named 'classMethod'}}
|
||||||
|
|
||||||
|
// Both class and instance methods exist.
|
||||||
|
B.description()
|
||||||
|
B.instanceTakesObjectClassTakesFloat(2.0)
|
||||||
|
B.instanceTakesObjectClassTakesFloat(other) // expected-error{{does not type-check}}
|
||||||
|
|
||||||
|
// Call an instance method of NSObject.
|
||||||
|
var c: AnyClass = B.myClass() // no-warning
|
||||||
|
c = b.myClass() // no-warning
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance method invocation on extensions
|
||||||
|
func instanceMethodsInExtensions(b: B) {
|
||||||
|
b.method(1, onCat1:2.5)
|
||||||
|
b.method(1, onExtA:2.5)
|
||||||
|
b.method(1, onExtB:2.5)
|
||||||
|
b.method(1, separateExtMethod:3.5)
|
||||||
|
|
||||||
|
let m1 = b.method:onCat1: // expected-error{{partial application of Objective-C method is not allowed}}
|
||||||
|
m1(1, 2.5)
|
||||||
|
|
||||||
|
let m2 = b.method:onExtA: // expected-error{{partial application of Objective-C method is not allowed}}
|
||||||
|
m2(1, 2.5)
|
||||||
|
|
||||||
|
let m3 = b.method:onExtB: // expected-error{{partial application of Objective-C method is not allowed}}
|
||||||
|
m3(1, 2.5)
|
||||||
|
|
||||||
|
let m4 = b.method:separateExtMethod: // expected-error{{partial application of Objective-C method is not allowed}}
|
||||||
|
m4(1, 2.5)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dynamicLookupMethod(b: AnyObject) {
|
||||||
|
if let m5 = b.method:separateExtMethod: {
|
||||||
|
m5(1, 2.5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
func properties(b: B) {
|
||||||
|
var i = b.counter
|
||||||
|
b.counter = i + 1
|
||||||
|
i = i + b.readCounter
|
||||||
|
b.readCounter = i + 1 // expected-error{{cannot assign to the result of this expression}}
|
||||||
|
|
||||||
|
b.setCounter(5) // expected-error{{'B' does not have a member named 'setCounter'}}
|
||||||
|
|
||||||
|
// Informal properties in Objective-C map to methods, not variables.
|
||||||
|
b.informalProp()
|
||||||
|
|
||||||
|
// An informal property cannot be made formal in a subclass. The
|
||||||
|
// formal property is simply ignored.
|
||||||
|
b.informalMadeFormal()
|
||||||
|
b.informalMadeFormal = i // expected-error{{cannot assign to the result of this expression}}
|
||||||
|
b.setInformalMadeFormal(5)
|
||||||
|
|
||||||
|
b.overriddenProp = 17
|
||||||
|
|
||||||
|
// Dynamic properties.
|
||||||
|
var obj : AnyObject = b
|
||||||
|
var optStr = obj.nsstringProperty
|
||||||
|
if optStr {
|
||||||
|
var s : String = optStr!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construction.
|
||||||
|
func newConstruction(a: A, aproxy: AProxy) {
|
||||||
|
var b : B = B()
|
||||||
|
b = B(17)
|
||||||
|
b = B(withInt:17)
|
||||||
|
b = B(withDouble:17.5, 3.14159)
|
||||||
|
b = B(BBB:b)
|
||||||
|
b = B(forWorldDomination:())
|
||||||
|
b = B(17, andDouble : 3.14159)
|
||||||
|
|
||||||
|
b = B.newWith(a:a)
|
||||||
|
B.alloc()._initFoo()
|
||||||
|
b.notAnInit()
|
||||||
|
|
||||||
|
// init methods are not imported by themselves.
|
||||||
|
b.initWithInt(17) // expected-error{{'B' does not have a member named 'initWithInt'}}
|
||||||
|
|
||||||
|
// init methods on non-NSObject-rooted classes
|
||||||
|
AProxy(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indexed subscripting
|
||||||
|
func indexedSubscripting(b: B, idx: Int, a: A) {
|
||||||
|
b[idx] = a
|
||||||
|
var a2 = (b[idx] as A)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyed subscripting
|
||||||
|
func keyedSubscripting(b: B, idx: A, a: A) {
|
||||||
|
b[a] = a
|
||||||
|
var a2 = (b[a] as A)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typed indexed subscripting
|
||||||
|
func checkHive(hive: Hive, b: B) {
|
||||||
|
var b2 = (hive.bees[5] as B)!
|
||||||
|
b2.method(1, withFloat:1.5)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protocols
|
||||||
|
func testProtocols(b: B, bp: BProto) {
|
||||||
|
var bp2 : BProto = b
|
||||||
|
var b2 : B = bp // expected-error{{'BProto' is not convertible to 'B'}}
|
||||||
|
bp.method(1, withFloat:2.5)
|
||||||
|
bp.method(1, withDouble:2.5) // expected-error{{expression does not type-check}}
|
||||||
|
bp2 = b.getAsProto()
|
||||||
|
|
||||||
|
var c1 : Cat1Proto = b
|
||||||
|
var bcat1 = b.getAsProtoWithCat()
|
||||||
|
c1 = bcat1
|
||||||
|
bcat1 = c1 // expected-error{{type 'Cat1Proto' does not conform to protocol 'BProto'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods only defined in a protocol
|
||||||
|
func testProtocolMethods(b: B) {
|
||||||
|
b.otherMethod(1, withFloat:3.14159)
|
||||||
|
b.p2Method()
|
||||||
|
b.initViaP2(3.14159, second:3.14159)
|
||||||
|
|
||||||
|
// Imported constructor.
|
||||||
|
var b2 = B(3.14159, second:3.14159)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testId(x: AnyObject) {
|
||||||
|
x.performSelector!("foo:", x)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MySubclass : B {
|
||||||
|
// Override a regular method.
|
||||||
|
@override func anotherMethodOnB() {}
|
||||||
|
|
||||||
|
// Override a category method
|
||||||
|
@override func anotherCategoryMethod() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDescription(array: NSArray) {
|
||||||
|
array.description()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method overriding with unfortunate ordering.
|
||||||
|
func overridingTest(srs: SuperRefsSub) {
|
||||||
|
var rs : RefedSub
|
||||||
|
rs.overridden()
|
||||||
|
}
|
||||||
|
|
||||||
|
func almostSubscriptableValueMismatch(as1: AlmostSubscriptable, a: A) {
|
||||||
|
// FIXME: Crummy diagnostic.
|
||||||
|
as1[a] // expected-error{{'AlmostSubscriptable' does not have a member named 'subscript'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func almostSubscriptableKeyMismatch(bc: BadCollection, key: NSString) {
|
||||||
|
// FIXME: We end up importing this as read-only due to the mismatch between
|
||||||
|
// getter/setter element types.
|
||||||
|
var v : AnyObject = bc[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
func almostSubscriptableKeyMismatchInherited(bc: BadCollectionChild,
|
||||||
|
key: String) {
|
||||||
|
var value : AnyObject = bc[key] // no-warning, inherited from parent
|
||||||
|
bc[key] = value // expected-error{{expression does not type-check}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func almostSubscriptableKeyMismatchInherited(roc: ReadOnlyCollectionChild,
|
||||||
|
key: String) {
|
||||||
|
var value : AnyObject = roc[key] // no-warning, inherited from parent
|
||||||
|
roc[key] = value // expected-error{{expression does not type-check}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use of 'Class' via dynamic lookup.
|
||||||
|
func classAnyObject(obj: NSObject) {
|
||||||
|
obj.myClass().description!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protocol conformances
|
||||||
|
class Wobbler : NSWobbling {
|
||||||
|
func wobble() { }
|
||||||
|
func returnMyself() -> Self { return self }
|
||||||
|
}
|
||||||
|
|
||||||
|
func optionalMemberAccess(w: NSWobbling) {
|
||||||
|
w.wobble()
|
||||||
|
w.wibble() // expected-error{{'() -> $T3' is not identical to '(() -> Void)?'}}
|
||||||
|
var x: AnyObject = w[5] // expected-error{{type 'AnyObject?' does not conform to protocol 'AnyObject'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func protocolInheritance(s: NSString) {
|
||||||
|
var coding: NSCoding = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func ivars(hive: Hive) {
|
||||||
|
hive.bees.description() // no-warning
|
||||||
|
hive.queen.description() // expected-error{{'Hive' does not have a member named 'queen'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NSObjectable : NSObjectProtocol {
|
||||||
|
@objc func description() -> AnyObject { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties with custom accessors
|
||||||
|
func customAccessors(hive: Hive, bee: B) {
|
||||||
|
println(hive.makingHoney)
|
||||||
|
println(hive.isMakingHoney()) // expected-error{{'Hive' does not have a member named 'isMakingHoney'}}
|
||||||
|
hive.setMakingHoney(true) // expected-error{{'Hive' does not have a member named 'setMakingHoney'}}
|
||||||
|
|
||||||
|
hive.guard.description() // okay
|
||||||
|
hive.guard.description!() // no-warning
|
||||||
|
hive.guard = bee // no-warning
|
||||||
|
}
|
||||||
|
|
||||||
|
// instancetype/Dynamic Self invocation.
|
||||||
|
func testDynamicSelf(queen: B, wobbler: NSWobbling) {
|
||||||
|
var hive = Hive()
|
||||||
|
|
||||||
|
// Factory method with instancetype result.
|
||||||
|
var hive1 = Hive.hiveWith(queen: queen)
|
||||||
|
hive1 = hive
|
||||||
|
hive = hive1
|
||||||
|
|
||||||
|
// Instance method with instancetype result.
|
||||||
|
var hive2 = hive.visit()
|
||||||
|
hive2 = hive
|
||||||
|
hive = hive2
|
||||||
|
|
||||||
|
// Instance method on a protocol with instancetype result.
|
||||||
|
var wobbler2 = wobbler.returnMyself()
|
||||||
|
var wobbler: NSWobbling = wobbler2
|
||||||
|
wobbler2 = wobbler
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRepeatedProtocolAdoption(w: NSWindow) {
|
||||||
|
w.description()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProtocolAdopter1 : FooProto {
|
||||||
|
var bar: CInt // no-warning
|
||||||
|
|
||||||
|
init() { bar = 5 }
|
||||||
|
}
|
||||||
|
class ProtocolAdopter2 : FooProto {
|
||||||
|
var bar: CInt {
|
||||||
|
get { return 42 }
|
||||||
|
set { /* do nothing! */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ProtocolAdopterBad1 : FooProto { // expected-error{{type 'ProtocolAdopterBad1' does not conform to protocol 'FooProto'}}
|
||||||
|
var bar: Int = 0 // expected-note{{candidate has non-matching type 'Int'}}
|
||||||
|
}
|
||||||
|
class ProtocolAdopterBad2 : FooProto { // expected-error{{type 'ProtocolAdopterBad2' does not conform to protocol 'FooProto'}}
|
||||||
|
let bar: CInt = 0 // expected-note{{candidate is not settable, but protocol requires it}}
|
||||||
|
}
|
||||||
|
class ProtocolAdopterBad3 : FooProto { // expected-error{{type 'ProtocolAdopterBad3' does not conform to protocol 'FooProto'}}
|
||||||
|
var bar: CInt { // expected-note{{candidate is not settable, but protocol requires it}}
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subclassing and designated initializers
|
||||||
|
func testNSInterestingDesignated() {
|
||||||
|
NSInterestingDesignated()
|
||||||
|
NSInterestingDesignated(withString:"hello")
|
||||||
|
NSInterestingDesignatedSub()
|
||||||
|
NSInterestingDesignatedSub(withString:"hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyDocument1 : NSDocument {
|
||||||
|
init() {
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMyDocument1() {
|
||||||
|
var md = MyDocument1()
|
||||||
|
md = MyDocument1(withURL: "http://llvm.org")
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyDocument2 : NSDocument {
|
||||||
|
init withURL(url: String) {
|
||||||
|
return super.init(withURL: url) // expected-error{{must call a designated initializer of the superclass 'NSDocument'}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyDocument3 : NSAwesomeDocument {
|
||||||
|
init() {
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMyDocument3() {
|
||||||
|
var md = MyDocument3()
|
||||||
|
md = MyDocument3(withURL: "http://llvm.org")
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyInterestingDesignated : NSInterestingDesignatedSub {
|
||||||
|
init withString(str: String) {
|
||||||
|
super.init(withString: str)
|
||||||
|
}
|
||||||
|
|
||||||
|
init withInt(i: Int) {
|
||||||
|
super.init() // expected-error{{must call a designated initializer of the superclass 'NSInterestingDesignatedSub'}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMyInterestingDesignated() {
|
||||||
|
var md = MyInterestingDesignated(withURL: "http://llvm.org")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNoReturn(a : NSAwesomeDocument) -> Int {
|
||||||
|
a.noReturnMethod(42)
|
||||||
|
return 17 // TODO: In principle, we should produce an unreachable code diagnostic here.
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitting(doc: NSDocument, url: NSURL) {
|
||||||
|
doc.copyDocument(fromURL: url, toURL: url)
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@
|
|||||||
@interface NSDocument : NSObject
|
@interface NSDocument : NSObject
|
||||||
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
||||||
- (instancetype)initWithURL:(NSString*)url;
|
- (instancetype)initWithURL:(NSString*)url;
|
||||||
|
|
||||||
|
- (void)copyDocumentFromURL:(NSURL*)fromURL toURL:(NSURL*)toURL;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface NSAwesomeDocument : NSDocument
|
@interface NSAwesomeDocument : NSDocument
|
||||||
|
|||||||
@@ -140,3 +140,6 @@ typedef NS_OPTIONS(NSUInteger, NSSingleOptions) {
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
|
#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
|
||||||
|
|
||||||
|
@interface NSURL : NSObject
|
||||||
|
@end
|
||||||
|
|||||||
Reference in New Issue
Block a user