Skip to content

Conversation

marcelofabri
Copy link
Member

@marcelofabri marcelofabri commented May 27, 2020

Fixes #698

@SwiftGen-Eve
Copy link

SwiftGen-Eve commented May 27, 2020

1 Warning
⚠️ Big PR

Hey 👋 I'm Eve, the friendly bot watching over SwiftGen 🤖

Thanks a lot for your contribution!


Seems like everything is in order 👍 You did a good job here! 🤝

Generated by 🚫 Danger

Copy link
Collaborator

@AliSoftware AliSoftware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Looks good 👍
I just think we need to move some unit tests around to split YAML tests in 2 before merging though.

  • Currently, our Unit tests are only on Yaml, and we just have one .json fixture used by the Yaml tests. We should instead move that json fixture in its dedicated Tests/Fixtures/Resources/JSON folder, and maybe add one or two other JSONs (like maybe one whose root is a dict, another with an array instead…)
  • Then add a Tests/SwiftGenKitTests/JsonTests.swift test file and move the func testJSON() test case (from YamlTests.swift) in there (as well as create 1 or 2 more test cases for 1 or 2 other JSON fixtures?)
    • You'll have to add an entry to the Fixtures.Directory (see TestsHelper.swift), and create the corresponding subdirectory in Fixtures/StencilContexts for the JSON contexts to be generated there for the tests
    • Then be sure to change the sub: parameter in the implementation of testJSON() to use that new Fixture.Directory.json
    • Once you've done those changes, use the SwiftGenKit - Generate Contexts Xcode scheme to automatically re-generate the unit test fixture files
    • Tip: I suggest you to delete the content of the Fixtures/StencilContexts/Yaml before running that scheme, so that any file that is not needed (especially configuration.yml context generated from configuration.json input file will likely have to be deleted from the Yaml StencilContext subdir) will not stay there and only the necessary files will be re-created
  • Finally, split the YAML-Demo page in the demo Playground in 2 separate pages, extracting the JSON example in its own page

Copy link
Member

@djbe djbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just couple of small things, rest seems good (assuming it's mostly a copy&paste from the yaml parser).

@djbe djbe added this to the 6.2.1 milestone May 27, 2020
@djbe
Copy link
Member

djbe commented May 27, 2020

Tagging this 6.2.1 for now, unless it's done before we create the 6.2.0 PR.

@marcelofabri
Copy link
Member Author

Finally, split the YAML-Demo page in the demo Playground in 2 separate pages, extracting the JSON example in its own page

I didn't quite understand the playground. Is that embedded code generated by SwiftGen automatically?

@djbe
Copy link
Member

djbe commented May 27, 2020

Currently we copy code from one of the generated files (for the output tests), and sometimes process them a bit as needed (to keep the pages as minimal as possible)

@marcelofabri
Copy link
Member Author

Currently we copy code from one of the generated files (for the output tests), and sometimes process them a bit as needed (to keep the pages as minimal as possible)

hmm, do we need to make any changes here then? since the generated code will be the same, I don't see why we need to update the playgrounds

@djbe
Copy link
Member

djbe commented May 27, 2020

If the test changes that @AliSoftware mentioned are implemented, then that'll mean that the resources and generated code will change (and we'll have a separate JSON page instead of 1 for both JSON & YAML). We'll get to that when we've covered the test changes.

@marcelofabri
Copy link
Member Author

If the test changes that @AliSoftware mentioned are implemented, then that'll mean that the resources and generated code will change (and we'll have a separate JSON page instead of 1 for both JSON & YAML). We'll get to that when we've covered the test changes.

i've updated the tests, but the thing is that the template tests still are using ymls. I don't think this is too much of a deal right now, so I wonder if we can do this clean up later (as we update the templates to use document, for example)

@AliSoftware AliSoftware mentioned this pull request May 28, 2020
8 tasks
@AliSoftware
Copy link
Collaborator

Ok, for the playground that's my bad, I missed that we already had a JSON-Demo page it seems. So no new page to create there and probably nothing much to change.

I think I confused this with the case of some playground pages in which we do have multiple examples in a single playground page (for example the Plist-Demo page… hell even the JSON-Demo page… where we have 2 examples in these pages, one to show the code for inline-swift4 templates and the other for runtime-swift4. For some reason that memory of this made me think for a minute that we had a Yaml-Demo page with 2 examples too, one for Yaml one for JSON… but that's not the case (and wouldn't make sense since indeed the outputs are the same for both anyway), and we already have the Json and Yaml demos separate in playground

The only thing you could include in that PR regarding playground changes is to update the examples – for example the Yaml-Demo page contains internal enum Configuration in its examples while after your change the generated code in tests (and the file in Fixtures/Generated/JSON/…) doesn't contain that anymore (since that file has move to JSON fixtures and is not used in Yaml tests. Technically, the playground page is not incorrect, but it could be confusing to someone looking both at the test generated fixtures and the playground 🤷 not a bit deal though

Copy link
Collaborator

@AliSoftware AliSoftware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latest changes seems to address everything, except that comment below about the tiny change left in TemplatesTests/; once this is addressed I think we'll be ready to merge! 🎉

@marcelofabri
Copy link
Member Author

Looks like the tests are failing because the template is not stable anymore, the order of the keys is changing between runs:

 internal enum JSONFiles {
-  internal static let items: [[String: Any]] = [[AnyHashable("id"): "1", AnyHashable("name"): "Anna"], [AnyHashable("name"): "Bob", AnyHashable("id"): "2"]]
+  internal static let items: [[String: Any]] = [[AnyHashable("name"): "Anna", AnyHashable("id"): "1"], [AnyHashable("name"): "Bob", AnyHashable("id"): "2"]]
 }

This is not surprising given that Dictionary doesn't have stable keys. I wonder why this wasn't a problem before (and if there's an easy way to fix it).

@AliSoftware
Copy link
Collaborator

AliSoftware commented May 28, 2020

Ah, this has indeed been a problem in other places in the past.

This is why we order most of the content alphabetically in most of the places. Like the order of the entries in .strings is sorted before being output (see StringsContext.swift)

We might need to do the same for the JSON content then. Indeed not sure why this was not a problem before.

Maybe it was sheer luck that the order on macOS (our dev machines) and Linux (CI) were the same in the past implementation. Maybe it was due to some implementation details of Yams when parsing the file.

In any case the fact is that JSONSerialization is not deterministic in the keys orders (as expected for a dictionary) so we'll likely need to add some sorting indeed when building the context. The bad news is that we'll need to do that sorting on embedded dicts recursively too, to ensure consistency at all levels of the JSON structure being parsed… (we might want to add just another fixture that contains some deeper JSON structure to test that part btw)

@AliSoftware
Copy link
Collaborator

PS: in case you were thinking of using the special build setting that we can use in Xcode to make Dictionary hashes be stable across runs for testing purposes, this is not really a solution since we also need to generate stable outputs in production, not just during tests, so that the generated code is also stable when the user runs swiftgen on every build via a script build phase

@djbe
Copy link
Member

djbe commented May 29, 2020

Note on that "sorting of keys" issue:
This was actually adressed in Stencil itself (stencilproject/Stencil#242), it'll sort dictionaries before iterating if it detects a [String: Any].

What has changed that defeats that check? And is there something that can be adressed in Stencil? I'm preparing a release there, so we can include a fix if needed.

@marcelofabri
Copy link
Member Author

Note on that "sorting of keys" issue:
This was actually adressed in Stencil itself (stencilproject/Stencil#242), it'll sort dictionaries before iterating if it detects a [String: Any].

What has changed that defeats that check? And is there something that can be adressed in Stencil? I'm preparing a release there, so we can include a fix if needed.

so I think the issue is not the order in the template, but the order inside a template variable

@djbe
Copy link
Member

djbe commented May 29, 2020

The template outputs variables using a for loop:
https://github.com/SwiftGen/SwiftGen/blob/develop/templates/json/inline-swift5.stencil#L63

@marcelofabri marcelofabri requested a review from djbe June 23, 2020 20:36
Copy link
Member

@djbe djbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to update the docs at Documentation/SwiftGenKit Contexts/JSON.md. Note that this currently is a symlink to the Yaml.md file

Marcelo Fabri and others added 2 commits June 23, 2020 16:45
@marcelofabri marcelofabri requested a review from djbe June 23, 2020 23:50
Copy link
Member

@djbe djbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub is being difficult, so can't point to the right line, but:
In the json context documentation, you can remove the documents part (plural), we don't usually document deprecated properties in the Docs.

@djbe djbe mentioned this pull request Jun 24, 2020
12 tasks
Copy link
Member

@djbe djbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allright this looks pretty complete to me. Maybe @AliSoftware wants to do a last pass, otherwise we can merge this. The (functional) change itself is pretty small after all.

@djbe djbe changed the title Use JSONSerialization to parse JSON instead of Yams JSON: use JSONSerialization instead of Yams Jun 24, 2020
@AliSoftware
Copy link
Collaborator

AliSoftware commented Jun 24, 2020

idk what's up with GitHub this evening. Can't post a PR review nor comment inline either.

Documentation/SwiftGenKit Contexts/Json.md, line 5

typo: s/mutiple/multiple/ + wording s/each file/each file's content/

-The JSON parser accepts mutiple files or directories (which it'll recursively search). Each file will be loaded into the context, but the parser will also generate metadata about the structure of the file.
+The JSON parser accepts multiple files or directories (which it'll recursively search). Each file's content will be loaded into the context; but the parser will also generate metadata about the structure of the file content.

This diff actually needs to be applied to Documentation/SwiftGenKit Contexts/Yaml.md as well

Documentation/SwiftGenKit Contexts/Json.md, line 38

I know @djbe said in an earlier feedback that we don't document deprecated keys in contexts, but then it looks strange to have that documents: key in the example while it not being documented in the previous section…

imho we should either document that documents: key and mention it's deprecated, or omit it from the example (even if that makes the example not completely true to what is actually generated because of retro-compatibility until SwiftGen 7) so that it's less confusing.

Tests/TemplatesTests/JsonTests.swift

nit: It seems like Contexts.all only refers to ["empty", "all"] and doesn't reference configuration and array contexts. That might be fine (maybe we don't want to test all the cases everywhere and pollute the tests too much) but then we might consider renaming that variable to something other than all? commonTestSet or something?

@AliSoftware
Copy link
Collaborator

btw wondering if we should merge this in develop as soon as we officially approve it, or if we should wait to have a fix for #712 before we merge that transition to JSONSerialization. I know the issue with #712 was already present before that PR though, but wondering if that already-existing issue will start to become way more common and thus more problematic if we merge that migration to JSONSerialization 🤔

@djbe
Copy link
Member

djbe commented Jun 24, 2020

There are issues with the inline templates in general:

Seeing as those are already present in the current & older releases, I don't think this PR should be held back because of them.

@AliSoftware
Copy link
Collaborator

Ok, updated my previous comment with my latest feedback. Mainly just a typo and a question about including documents key or not in docs example

# Conflicts:
#	Tests/Fixtures/Generated/JSON/inline-swift4/all-customName.swift
#	Tests/Fixtures/Generated/JSON/inline-swift4/all-forceFileNameEnum.swift
#	Tests/Fixtures/Generated/JSON/inline-swift4/all-publicAccess.swift
#	Tests/Fixtures/Generated/JSON/inline-swift4/all.swift
#	Tests/Fixtures/Generated/JSON/inline-swift5/all-customName.swift
#	Tests/Fixtures/Generated/JSON/inline-swift5/all-forceFileNameEnum.swift
#	Tests/Fixtures/Generated/JSON/inline-swift5/all-publicAccess.swift
#	Tests/Fixtures/Generated/JSON/inline-swift5/all.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift4/all-customname.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift4/all-forceFileNameEnum.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift4/all-preservePath.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift4/all-publicAccess.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift4/all.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift5/all-customname.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift5/all-forceFileNameEnum.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift5/all-preservePath.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift5/all-publicAccess.swift
#	Tests/Fixtures/Generated/JSON/runtime-swift5/all.swift
@djbe
Copy link
Member

djbe commented Jun 24, 2020

I'm merging everything and processing the feedback (+ fixing the typos in other places).

Note: @AliSoftware we already use the all context in other parsers, if we rename it here, we should rename it everywhere. And TBH we can delegate that to another PR.

@AliSoftware
Copy link
Collaborator

AliSoftware commented Jun 24, 2020

I'm merging everything and processing the feedback (+ fixing the typos in other places).

👍 cool. I see that you fixed s/mutiple/multiple/ in those other places, but did not apply the same s/each file/each file's content/ fix everywhere tho 😅

Note: @AliSoftware we already use the all context in other parsers, if we rename it here, we should rename it everywhere. And TBH we can delegate that to another PR.

Ah, right. Let's keep Context.all then 👍

just another nit: I've also noticed that we seem to use inconsistent case in fine names for Documentation/SwiftGenKit Parsers vs Documentation/Parsers (Json.md vs json.md for example). (sorry, I'm quite nitpicky lately, that's just my perfectionist side speaking… hope you don't take it the wrong way 😬)

@djbe djbe merged commit aa81dbd into SwiftGen:develop Jun 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants