johnno1962 / InjectionApp

Issue Tracking Repo for Injection as an App
MIT License
111 stars 7 forks source link

Learnt Compile Failed on extensions #18

Open loganj opened 7 years ago

loganj commented 7 years ago

I have an extension on a nested extension, defined across three files:

// Foo.swift
class Foo {
}
// Bar.swift
extension Foo {
  final class Bar {
  }
}
// Baz.swift
extension Foo.Bar {
}

XCode is able to build and run my project just fine, but Injection fails to compile with Bar is not a member type of 'Foo'.

I believe this is probably due to a bug in the Swift compiler wherein input file order affects (breaks) compilation. If I look at XCode's Build Phases, under Compile Sources I see the files listed in the expected relative order:

...
Foo.swift
...
Bar.swift
...
Baz.swift
...

If I look at Injection's filelist.txt, I see the reverse:

...
Baz.swift
...
Bar.swift
...
Foo.swift
...

I doubt there's a fix here, other than to list files in the same order that XCode does. That'd be ideal for ensuring consistency with XCode, regardless of this issue, but I have no idea whether it's possible.

johnno1962 commented 7 years ago

Very Interesting.. Could you send me a small example project which doesn’t inject a particular file? injection at johnholdsworth.com

johnno1962 commented 7 years ago

I can’t even get those three files to compile :( - btw it’s not clear you can inject extensions.

loganj commented 7 years ago

Sorry, those files were meant to be sketches. I'll try to get an example project together. The change I made (and tried to inject) is actually not in any of those three files, interestingly. They just fail the build.

Curious though: is it possible to list the files in the same order XCode does? Or do you only get an unordered set?

johnno1962 commented 7 years ago

The list comes out of a JSON file. I’m not sure if it will be possible to replicate it’s ordering: https://github.com/johnno1962/injectionforxcode/blob/master/InjectionPluginLite/injectSource.pl#L268

loganj commented 7 years ago

You're going to hate me, but I think that JSON file might actually be an answer. It contains a map, keyed on Swift source files. Under each source file there's a swift-dependencies key pointing to a *.swiftdeps file.

The swiftdeps file contains a couple of useful pieces of information about the source file: a list of symbols it provides, and a list of symbols it needs.

One could use that information to construct a DAG, and then a correctly ordered file list would be topological ordering of that graph.

It still might not be the same ordering as XCode though.

loganj commented 7 years ago

... or maybe the right thing to do is to just supply that same file to swiftc via -output-file-map, and let swiftc sort it out?