Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum not working in custom initializer

I'm using an enum variable called BuildingType in a class initializer (of a class called Building).

This enum is defined outside the class because I want to use it also in other places.

The autocomplete for this enum is not working properly when initializing the variable typeOfBuilding.

Example code:

enum BuildingType {
    case Flat, House, Villa
}

class Building {
    var type : BuildingType = BuildingType.House
    var floors : Int = 1

    init(typeOfBuilding : BuildingType, numFloors : Int) {
        self.type = typeOfBuilding
        self.floors = numFloors
    }
}

var myBuilding : Building = Building(typeOfBuilding: BuildingType.Flat , numFloors: 3)

So if I type "... typeOfBuilding: BuildingType." (when initializing myBuilding) 'floors' and 'type' are shown, and not the enum values.

I must be doing something wrong here but what?

like image 245
etri Avatar asked Nov 09 '22 16:11

etri


1 Answers

This is a pretty weird bug

It occurs when you attempt to pass an enum into an argument of an initialiser, autocomplete will fail and instead of suggesting the enum cases after typing Enum., it will list the instance members of the class you’re calling the initialiser on. If you try and use the single dot syntax (.Case), autocomplete will also fail, but instead of displaying the list of instance members, it simply won't display anything.

I initially thought it may have had something to do with the naming of your enum and class (BuildingType & Building), but this is not the case.

This bug only appears to be present in initialisers with multiple arguments (one of which being an enum). I couldn’t reproduce this issue with single argument initialisers.

The reproducibility appears to depend on whether the initialiser is 'complete'. I'm considering an initialiser to be 'complete' if it has all argument names and values (except the enum) defined. For example:

// Incomplete (foo is one argument of many)
let baz = Baz(foo: Foo.

// Semi-Complete (before you assign the second parameter a value)
let baz = Baz(foo: Foo., string: <String Placeholder>)

// Complete
let baz = Baz(foo: Foo., string: "")

// Complete (note the lack of the last bracket)
let baz = Baz(param: 0, foo: Foo.

Here is my test setup (Xcode 7.3, Swift 2.2):

enum Foo {
    case Bar
}

class Baz {
    var iReallyShouldntBeDisplayedHere = 0
    init(foo:Foo, string:String) {}
    init(foo: Foo) {}
}

And here is a list of cases where I've found the bug does & doesn't occur:

// Enum is the only argument

// CORRECT: accepting the initialiser's autocomplete (so it's 'complete'), then typing "Foo." brings up autocomplete options for enum cases
let baz = Baz(foo: Foo.)

// CORRECT: typing the initialiser yourself (so it's 'incomplete'), then typing "Foo." in the first parameter brings up autocomplete options for enum cases
let baz2 = Baz(foo: Foo.


// Enum is one argument of many

// INCORRECT: accepting the initialiser's autocomplete (so it's 'semi-complete'), then typing "Foo." in the first parameter brings up Baz's instance members ("iReallyShouldntBeDisplayedHere")
let baz3 = Baz(foo: Foo., string: <String Placeholder>)

// CORRECT: typing the initialiser yourself (so it's 'incomplete'), and typing "Foo." in the first parameter brings up enum cases
let baz4 = Baz(foo: Foo.


// Single dot syntax (where enum is one argument of many)

// CORRECT: typing the initialiser yourself (so it's 'incomplete'), and typing "." in the first parameter brings up enum cases
let baz5 = Baz(foo:.

// CORRECT: accepting the initialiser's autocomplete (so it's 'semi-complete'), then typing "." in the first parameter brings up enum cases
let baz6 = Baz(foo:., string: <String Placeholder>)

// INCORRECT: modifying the foo: argument once the initialiser is 'complete' by typing "." in the first parameter doesn't generate the autocomplete list
let baz7 = Baz(foo:., string: "")

I also tried this where foo: is the last argument, but the initialiser always has to be complete in that case, so it always fails. I did try with initialisers that take 3 arguments, but it appears to have the same behaviour as an initialiser with 2 arguments.

If anyone knows of any more cases where this bug can be reproduced, I'd love to know!

like image 182
Hamish Avatar answered Nov 15 '22 04:11

Hamish