├── .babelrc ├── .eslintrc.json ├── .flake8 ├── .flowconfig ├── .github ├── dependabot.yml └── workflows │ ├── ci.yml │ └── pre-commit-autoupdate.yml ├── .gitignore ├── .nvmrc ├── .pre-commit-config.yaml ├── .prettierrc ├── CHANGES.md ├── LICENSE ├── Makefile ├── README.md ├── bin └── ast_to_js ├── config └── ast_to_js.webpack.config.js ├── json_codegen ├── __init__.py ├── astlib │ ├── __init__.py │ ├── javascript.py │ └── python.py ├── cli.py ├── core.py ├── generators │ ├── __init__.py │ ├── flow.py │ ├── javascript_flow.py │ ├── python3.py │ └── python3_marshmallow │ │ ├── __init__.py │ │ ├── generator.py │ │ ├── object_generator.py │ │ └── utils.py ├── js_utils.py └── types.py ├── package.json ├── poetry.lock ├── pyproject.toml ├── scripts ├── ast_to_js.js └── build_js_ast.js ├── tests ├── __init__.py ├── astlib │ ├── __init__.py │ └── javascript_test.py ├── cli_test.py ├── fixtures │ ├── flow │ │ ├── additional_properties_with_ref.ast.json │ │ ├── additional_properties_with_ref.template.js │ │ ├── array_items_ref.ast.json │ │ ├── array_items_ref.template.js │ │ ├── array_items_ref_as_alias.ast.json │ │ ├── array_items_ref_as_alias.template.js │ │ ├── array_items_ref_as_scalar.ast.json │ │ ├── array_items_ref_as_scalar.template.js │ │ ├── array_property_default.ast.json │ │ ├── array_property_default.template.js │ │ ├── boolean_property.ast.json │ │ ├── boolean_property.template.js │ │ ├── boolean_property_default.ast.json │ │ ├── boolean_property_default.template.js │ │ ├── definition_of_primitive_alias.ast.json │ │ ├── definition_of_primitive_alias.template.js │ │ ├── definition_without_title.ast.json │ │ ├── definition_without_title.template.js │ │ ├── integer_property.ast.json │ │ ├── integer_property.template.js │ │ ├── integer_property_default.ast.json │ │ ├── integer_property_default.template.js │ │ ├── object_property.ast.json │ │ ├── object_property.template.js │ │ ├── object_property_default.ast.json │ │ ├── object_property_default.template.js │ │ ├── simple.ast.json │ │ ├── simple.template.js │ │ ├── string_property_default.ast.json │ │ ├── string_property_default.template.js │ │ ├── with_mixed_properties.ast.json │ │ ├── with_mixed_properties.template.js │ │ ├── with_nested_object.ast.json │ │ ├── with_nested_object.template.js │ │ ├── with_property.ast.json │ │ ├── with_property.template.js │ │ ├── with_required_property.ast.json │ │ └── with_required_property.template.js │ ├── generators │ │ ├── class_not_found_generator.py │ │ └── custom_generator.py │ ├── javascript_flow │ │ ├── additional_properties_with_ref.ast.json │ │ ├── additional_properties_with_ref.template.js │ │ ├── array_items_ref.ast.json │ │ ├── array_items_ref.template.js │ │ ├── array_items_ref_as_alias.ast.json │ │ ├── array_items_ref_as_alias.template.js │ │ ├── array_items_ref_as_scalar.ast.json │ │ ├── array_items_ref_as_scalar.template.js │ │ ├── array_property_default.ast.json │ │ ├── array_property_default.template.js │ │ ├── boolean_property.ast.json │ │ ├── boolean_property.template.js │ │ ├── boolean_property_default.ast.json │ │ ├── boolean_property_default.template.js │ │ ├── definition_of_primitive_alias.ast.json │ │ ├── definition_of_primitive_alias.template.js │ │ ├── definition_without_title.ast.json │ │ ├── definition_without_title.template.js │ │ ├── integer_property.ast.json │ │ ├── integer_property.template.js │ │ ├── integer_property_default.ast.json │ │ ├── integer_property_default.template.js │ │ ├── object_property.ast.json │ │ ├── object_property.template.js │ │ ├── object_property_default.ast.json │ │ ├── object_property_default.template.js │ │ ├── simple.ast.json │ │ ├── simple.template.js │ │ ├── string_property_default.ast.json │ │ ├── string_property_default.template.js │ │ ├── with_mixed_properties.ast.json │ │ ├── with_mixed_properties.template.js │ │ ├── with_nested_object.ast.json │ │ ├── with_nested_object.template.js │ │ ├── with_property.ast.json │ │ ├── with_property.template.js │ │ ├── with_required_property.ast.json │ │ └── with_required_property.template.js │ ├── python3 │ │ ├── additional_properties_with_ref.py │ │ ├── array_items_ref.py │ │ ├── array_items_ref_as_alias.py │ │ ├── array_items_ref_as_scalar.py │ │ ├── array_property_default.py │ │ ├── boolean_property.py │ │ ├── boolean_property_default.py │ │ ├── definition_of_primitive_alias.py │ │ ├── definition_without_title.py │ │ ├── integer_property.py │ │ ├── integer_property_default.py │ │ ├── object_property.py │ │ ├── object_property_default.py │ │ ├── simple.py │ │ ├── string_property_default.py │ │ ├── with_mixed_properties.py │ │ ├── with_nested_object.py │ │ ├── with_property.py │ │ └── with_required_property.py │ ├── python3_marshmallow │ │ ├── array_items_ref.py │ │ ├── array_property_default.py │ │ ├── boolean_property_default.py │ │ ├── definition_of_primitive_alias.py │ │ ├── definition_without_title.py │ │ ├── integer_property_default.py │ │ ├── object_property_default.py │ │ ├── simple.py │ │ ├── string_property_default.py │ │ ├── with_mixed_properties.py │ │ ├── with_nested_object.py │ │ ├── with_property.py │ │ └── with_required_property.py │ └── schemas │ │ ├── additional_properties_with_ref.schema.json │ │ ├── array_items_ref.schema.json │ │ ├── array_items_ref_as_alias.schema.json │ │ ├── array_items_ref_as_scalar.schema.json │ │ ├── array_property_default.schema.json │ │ ├── boolean_property.schema.json │ │ ├── boolean_property_default.schema.json │ │ ├── definition_of_primitive_alias.schema.json │ │ ├── definition_without_title.schema.json │ │ ├── integer_property.schema.json │ │ ├── integer_property_default.schema.json │ │ ├── object_property.schema.json │ │ ├── object_property_default.schema.json │ │ ├── simple.schema.json │ │ ├── string_property_default.schema.json │ │ ├── with_mixed_properties.schema.json │ │ ├── with_nested_object.schema.json │ │ ├── with_property.schema.json │ │ └── with_required_property.schema.json ├── generator_flow_test.py ├── generator_javascript_flow_test.py ├── generator_python3_marshmallow_test.py ├── generator_python3_test.py └── generators │ ├── __init__.py │ └── core_test.py └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/preset-flow" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:flowtype/recommended" 9 | ], 10 | "parser": "babel-eslint", 11 | "parserOptions": { 12 | "sourceType": "module" 13 | }, 14 | "plugins": [ 15 | "flowtype" 16 | ], 17 | "rules": { 18 | "indent": [ 19 | "error", 20 | 2 21 | ], 22 | "linebreak-style": [ 23 | "error", 24 | "unix" 25 | ], 26 | "quotes": [ 27 | "error", 28 | "double" 29 | ], 30 | "semi": [ 31 | "error", 32 | "always" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 99 3 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [lints] 8 | 9 | [options] 10 | 11 | [strict] 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "pip" 9 | directory: "/" 10 | schedule: 11 | interval: "monthly" 12 | - package-ecosystem: "npm" 13 | directory: "/" 14 | schedule: 15 | interval: "monthly" 16 | - package-ecosystem: "github-actions" 17 | directory: "/" 18 | schedule: 19 | interval: "weekly" 20 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Unit testing, formatting & linting 2 | on: [push] 3 | 4 | jobs: 5 | linting: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v4 9 | - uses: actions/setup-python@v5 10 | with: 11 | python-version: "3.11" 12 | - name: Cache multiple paths 13 | uses: actions/cache@v4 14 | with: 15 | path: | 16 | ~/.cache/pip 17 | ~/.cache/pre-commit 18 | key: ${{ runner.os }}-3.11-${{ hashFiles('**/.pre-commit-config.yaml') }} 19 | - run: pip install pre-commit 20 | - run: pre-commit run -a 21 | 22 | testing-python: 23 | runs-on: ubuntu-latest 24 | continue-on-error: ${{ matrix.experimental }} 25 | strategy: 26 | matrix: 27 | astor: 28 | - "0.7.0" 29 | - "0.8.0" 30 | python-version: 31 | - "3.7" 32 | experimental: 33 | - false 34 | # include: 35 | # - python-version: "3.8" 36 | # astor: "0.8.0" 37 | # experimental: true 38 | # - python-version: "3.9" 39 | # astor: "0.8.0" 40 | # experimental: true 41 | # - python-version: "3.10" 42 | # astor: "0.8.0" 43 | # experimental: true 44 | steps: 45 | - uses: actions/checkout@v4 46 | - uses: actions/setup-python@v5 47 | with: 48 | python-version: ${{ matrix.python-version }} 49 | - name: Cache multiple paths 50 | uses: actions/cache@v4 51 | with: 52 | path: | 53 | ~/.cache/pip 54 | key: ${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.astor }}-${{ hashFiles('**/poetry.lock') }} 55 | - run: pip install poetry~=1.3.1 56 | - run: poetry install 57 | - run: poetry run pip install "astor~=${{ matrix.astor }}" 58 | - run: poetry run pytest -vv tests 59 | 60 | testing-node: 61 | runs-on: ubuntu-latest 62 | strategy: 63 | matrix: 64 | node: 65 | - "14" 66 | - "16" 67 | - "18" 68 | steps: 69 | - uses: actions/checkout@v4 70 | - uses: actions/setup-node@v4 71 | with: 72 | node-version: ${{ matrix.node }} 73 | cache: "yarn" 74 | - run: yarn 75 | - run: yarn run build:test:js 76 | - run: yarn run code:format:check 77 | 78 | publish_package: 79 | runs-on: ubuntu-latest 80 | needs: 81 | - linting 82 | - testing-python 83 | - testing-node 84 | if: startsWith(github.ref, 'refs/tags') 85 | steps: 86 | - uses: actions/checkout@v4 87 | - uses: actions/setup-python@v5 88 | with: 89 | python-version: "3.7" 90 | - name: Cache multiple paths 91 | uses: actions/cache@v4 92 | with: 93 | path: | 94 | ~/.cache/pip 95 | key: ${{ runner.os }}-3.7-${{ hashFiles('**/poetry.lock') }} 96 | - run: pip install poetry 97 | - run: poetry build 98 | # From https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#publishing-the-distribution-to-pypi-and-testpypi 99 | - name: Publish distribution 📦 to PyPI 100 | uses: pypa/gh-action-pypi-publish@master 101 | with: 102 | password: ${{ secrets.PYPI_API_TOKEN }} 103 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit-autoupdate.yml: -------------------------------------------------------------------------------- 1 | name: Pre-commit auto-update 2 | 3 | on: 4 | # every Monday at midnight 5 | schedule: 6 | - cron: "0 0 * * 1" 7 | # on demand 8 | workflow_dispatch: 9 | 10 | jobs: 11 | pre-commit-autoupdate: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-python@v5 16 | with: 17 | python-version: "3.11" 18 | - name: Cache multiple paths 19 | uses: actions/cache@v4 20 | with: 21 | path: | 22 | ~/.cache/pip 23 | ~/.cache/pre-commit 24 | key: ${{ runner.os }}-3.11-${{ hashFiles('**/.pre-commit-config.yaml') }} 25 | - uses: browniebroke/pre-commit-autoupdate-action@main 26 | - uses: peter-evans/create-pull-request@v7 27 | with: 28 | token: ${{ secrets.GITHUB_TOKEN }} 29 | branch: update/pre-commit-hooks 30 | title: Update pre-commit hooks 31 | commit-message: "chore: update pre-commit hooks" 32 | body: Update versions of pre-commit hooks to latest version. 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | pip-wheel-metadata/ 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | .hypothesis/ 49 | .pytest_cache/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | db.sqlite3 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .env 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | env.bak/ 92 | venv.bak/ 93 | 94 | # Spyder project settings 95 | .spyderproject 96 | .spyproject 97 | 98 | # Rope project settings 99 | .ropeproject 100 | 101 | # mkdocs documentation 102 | /site 103 | 104 | # mypy 105 | .mypy_cache/ 106 | 107 | # JavaScript 108 | node_modules 109 | flow-typed 110 | 111 | # OS X 112 | .DS_Store 113 | 114 | # VSCode 115 | .vscode 116 | 117 | # testmon 118 | .testmondata 119 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v14 2 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python3.11 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.6.0 6 | hooks: 7 | - id: check-case-conflict 8 | - id: check-docstring-first 9 | - id: check-executables-have-shebangs 10 | - id: check-json 11 | - id: check-merge-conflict 12 | - id: check-yaml 13 | - id: check-shebang-scripts-are-executable 14 | - id: check-toml 15 | - id: debug-statements 16 | - id: detect-private-key 17 | - id: end-of-file-fixer 18 | - id: mixed-line-ending 19 | - id: name-tests-test 20 | entry: name-tests-test --pytest 21 | files: (^|/)tests/(?!fixtures/).+\.py$ 22 | exclude: ^.*(fixtures|data).py$ 23 | - id: pretty-format-json 24 | args: 25 | - --autofix 26 | - id: trailing-whitespace 27 | - repo: https://github.com/myint/autoflake 28 | rev: v2.3.1 29 | hooks: 30 | - id: autoflake 31 | args: 32 | [ 33 | "--in-place", 34 | "--remove-all-unused-imports", 35 | "--remove-unused-variable", 36 | "--expand-star-imports", 37 | "--remove-duplicate-keys", 38 | ] 39 | - repo: https://github.com/pycqa/flake8 40 | rev: 7.1.0 41 | hooks: 42 | - id: flake8 43 | additional_dependencies: 44 | - flake8-bugbear 45 | - flake8-datetime-utcnow-plugin 46 | - repo: https://github.com/asottile/pyupgrade 47 | rev: v3.16.0 48 | hooks: 49 | - id: pyupgrade 50 | args: 51 | - "--py37-plus" 52 | - "--keep-runtime-typing" 53 | - repo: meta 54 | hooks: 55 | - id: check-hooks-apply 56 | - repo: https://github.com/pycqa/isort 57 | rev: 5.13.2 58 | hooks: 59 | - id: isort 60 | - repo: https://github.com/pycqa/bandit 61 | rev: 1.7.9 62 | hooks: 63 | - id: bandit 64 | args: 65 | - "-r" 66 | - "-q" 67 | - "--exclude" 68 | - "tests" 69 | - repo: https://github.com/pycqa/bandit 70 | rev: 1.7.9 71 | hooks: 72 | - id: bandit 73 | args: 74 | - "-r" 75 | - "-q" 76 | - "-lll" 77 | - "tests" 78 | - repo: https://github.com/psf/black 79 | rev: 24.4.2 80 | hooks: 81 | - id: black 82 | - repo: https://github.com/pre-commit/pygrep-hooks 83 | rev: v1.10.0 84 | hooks: 85 | - id: python-use-type-annotations 86 | - id: python-check-blanket-noqa 87 | - id: python-check-blanket-type-ignore 88 | - id: python-check-mock-methods 89 | - id: python-no-log-warn 90 | - id: python-no-eval 91 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "printWidth": 120 4 | } 5 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.6.0 4 | 5 | ### Backward incompatible changes 6 | 7 | - dropped generatino of Python 2 code 8 | 9 | ## v0.4.6 10 | 11 | ### Trivial/internal changes 12 | 13 | - In the generated code for Python 3 classes don't inherit from `object` 14 | - Migrated to Poetry as package management 15 | 16 | ## v0.4.5 17 | 18 | ### Bug fixes 19 | 20 | - [#27](https://github.com/expobrain/json-schema-codegen/pull/27) Fixes generation of proper nullable scalars and objects 21 | 22 | ## v0.4.4 23 | 24 | ### Bug fixes 25 | 26 | - [#30](https://github.com/expobrain/json-schema-codegen/pull/30) Nested objects had an ahrdoced name instead of the reference's name 27 | 28 | ## v0.4.3.1 29 | 30 | ### Bug fixes 31 | 32 | - [#28](https://github.com/expobrain/json-schema-codegen/pull/28) Value is not coerced to object 33 | 34 | ## v0.4.2 35 | 36 | ### Bug fixes 37 | 38 | - [#26](https://github.com/expobrain/json-schema-codegen/pull/26) Required fields were not honored in Python generators 39 | 40 | ## v0.4.1 41 | 42 | ### Bug fixes 43 | 44 | - [#25](https://github.com/expobrain/json-schema-codegen/pull/25) Fixed error when object type without default value 45 | 46 | ## v0.4.0 47 | 48 | ### Breaking changes 49 | 50 | - [#23](https://github.com/expobrain/json-schema-codegen/pull/23) Use list validation in the schemas to generate lists instead of generating them from a tuple validation. See https://json-schema.org/understanding-json-schema/reference/array.html#items. 51 | 52 | ### New features 53 | 54 | - [#24](https://github.com/expobrain/json-schema-codegen/pull/24) Added generation of pure Python 3 compatible code 55 | 56 | ### Trivial/internal changes 57 | 58 | - [#21](https://github.com/expobrain/json-schema-codegen/pull/21) Fixed anchors in README 59 | - [#22](https://github.com/expobrain/json-schema-codegen/pull/22) Various internal improvements and fixes 60 | 61 | ## v0.3.0 62 | 63 | ### Backward imcompatible changes 64 | 65 | - [#20](https://github.com/expobrain/json-schema-codegen/pull/20) Renamed `python3` code generator into `python3+marshmallow` 66 | 67 | ### Trivial/internal changes 68 | 69 | - [#19](https://github.com/expobrain/json-schema-codegen/pull/19) Removed `pathlib2` as a dependency 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Daniele Esposti 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .SILENT: mypy 2 | 3 | mypy: 4 | poetry run mypy . 5 | 6 | install: 7 | poetry install --sync 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/expobrain/json-schema-codegen.svg?branch=master)](https://travis-ci.org/expobrain/json-schema-codegen) 2 | 3 | # json-schema-codegen 4 | 5 | Generate code from JSON schema files. 6 | 7 | # Table of contents 8 | 9 | - [Introduction](#introduction) 10 | - [Currently supported languages](#currently-supported-languages) 11 | - [Requirements](#requirements) 12 | - [Installation](#installation) 13 | - [Usage](#usage) 14 | - [Code generation](#code-generation) 15 | - [Python3](#python-3) 16 | - [Python3+Marshmallow](#python-3marshmallow) 17 | - [JavaScript+Flow and Flow](#javascriptflow-and-flow) 18 | - [Contribute](#contribute) 19 | 20 | # Introduction 21 | 22 | This is a command line tool to take a [json-schema](http://json-schema.org/) file and generate code automatically. 23 | 24 | For instance this `json-schema` definition: 25 | 26 | ```json 27 | { 28 | "$schema": "http://json-schema.org/draft-04/schema#", 29 | "title": "Test", 30 | "type": "object", 31 | "properties": { 32 | "id": { "type": "integer" } 33 | } 34 | } 35 | ``` 36 | 37 | will generate this Python code: 38 | 39 | ```python 40 | class Test(object): 41 | def __init__(self, data=None): 42 | data = data or {} 43 | 44 | self.id = data.get("id") 45 | ``` 46 | 47 | or this JavaScript+Flow code: 48 | 49 | ```javascript 50 | export class Test { 51 | id: ?number; 52 | 53 | constructor(data: Object = {}) { 54 | this.id = data.id; 55 | } 56 | } 57 | ``` 58 | 59 | Currently this tool generates code for Python and JavaScript with [Flow](https://flow.org/) annotations but it can be extended to generate code for any language. 60 | 61 | The code generation is divided in two stages: 62 | 63 | 1. generate the [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) for the target language from the `json-schema` file 64 | 1. convert the AST into the target language 65 | 66 | This allows the tool to be language agnostic, that is it just needs to generate the AST in JSON format for the target language and then a language specific tool will convert this AST into proper code. 67 | 68 | # Currently supported languages 69 | 70 | List of currently supported languages: 71 | 72 | - Python 3.7+ 73 | - JavaScript ES7+ with Flow annotations 74 | - pure Flow annotations 75 | 76 | # Requirements 77 | 78 | - Python 3.6 / 3.7 79 | - Node v12 80 | 81 | # Installation 82 | 83 | Until this [pull request](https://github.com/pypa/setuptools/pull/1389) in [`setuptools`](https://pypi.org/project/setuptools/) is fixed, the only way to install `json-schema-codegen` is to clone the repo: 84 | 85 | ```shell 86 | git clone https://github.com/expobrain/json-schema-codegen.git 87 | ``` 88 | 89 | # Usage 90 | 91 | ```shell 92 | usage: json_codegen.py [-h] [--prefix PREFIX] [--language LANGUAGE] 93 | [--output OUTPUT] 94 | schema 95 | 96 | positional arguments: 97 | schema Definition of the PRD as JSON schema 98 | 99 | optional arguments: 100 | -h, --help show this help message and exit 101 | --prefix PREFIX, -p PREFIX 102 | Optional prefix for generated classes 103 | --language LANGUAGE, -l LANGUAGE 104 | Output language. Default is python 105 | --output OUTPUT, -o OUTPUT 106 | Output filename for the generated code 107 | ``` 108 | 109 | # Code generation 110 | 111 | ## Python 3 112 | 113 | The egenerator of pure Python 3 compatible code: 114 | 115 | ```shell 116 | json_codegen --language python3 --output 117 | ``` 118 | 119 | ## Python 3+Marshmallow 120 | 121 | The generation of Python 3's code with [Marshmallow](https://marshmallow.readthedocs.io/en/2.x-line/) support is integrated into the tool so it needs just a single invocation: 122 | 123 | ```shell 124 | json_codegen --language python3+marshmallow --output 125 | ``` 126 | 127 | ## JavaScript+Flow and Flow 128 | 129 | Generating JavaScript+Flow and Flow code involves two steps, generating the AST: 130 | 131 | ```shell 132 | json_codegen --language [javascript+flow|flow] --output 133 | ``` 134 | 135 | and generating the code from the AST: 136 | 137 | ```shell 138 | bin/ast_to_js 139 | ``` 140 | -------------------------------------------------------------------------------- /config/ast_to_js.webpack.config.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | /** 4 | * Courtesy of https://github.com/yarnpkg/yarn/blob/master/scripts/build-webpack.js 5 | */ 6 | 7 | const path = require("path"); 8 | 9 | const webpack = require("webpack"); 10 | const ProgressBarPlugin = require("progress-bar-webpack-plugin"); 11 | const CaseSensitivePathsPlugin = require("case-sensitive-paths-webpack-plugin"); 12 | 13 | const basedir = path.join(__dirname, ".."); 14 | 15 | // Use the real node __dirname and __filename in order to get Yarn's source 16 | // files on the user's system. See constants.js 17 | const nodeOptions = { 18 | __filename: false, 19 | __dirname: false, 20 | }; 21 | 22 | module.exports = { 23 | target: "node", 24 | node: nodeOptions, 25 | mode: "production", 26 | entry: { ast_to_js: path.join(basedir, "scripts", "ast_to_js.js") }, 27 | module: { 28 | rules: [ 29 | { 30 | test: /\.js$/, 31 | exclude: /node_modules/, 32 | loader: "babel-loader", 33 | }, 34 | ], 35 | }, 36 | plugins: [ 37 | new webpack.LoaderOptionsPlugin({ 38 | options: { 39 | minimize: true, 40 | }, 41 | }), 42 | new ProgressBarPlugin(), 43 | new CaseSensitivePathsPlugin(), 44 | new webpack.BannerPlugin({ 45 | banner: "#!/usr/bin/env node", 46 | raw: true, 47 | }), 48 | ], 49 | output: { 50 | filename: `[name]`, 51 | path: path.join(basedir, "bin"), 52 | libraryTarget: "commonjs2", 53 | }, 54 | }; 55 | -------------------------------------------------------------------------------- /json_codegen/__init__.py: -------------------------------------------------------------------------------- 1 | from json_codegen.core import ( # noqa: F401 2 | GeneratorNotFoundException, 3 | load_external_generator, 4 | load_schema, 5 | ) 6 | -------------------------------------------------------------------------------- /json_codegen/astlib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expobrain/json-schema-codegen/f4c8306a4bc6925607aaff95a5fc68aa01469454/json_codegen/astlib/__init__.py -------------------------------------------------------------------------------- /json_codegen/astlib/python.py: -------------------------------------------------------------------------------- 1 | from ast import * # noqa: F401,F403 2 | -------------------------------------------------------------------------------- /json_codegen/cli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from argparse import ArgumentParser 5 | from pathlib import Path 6 | 7 | from json_codegen import generators 8 | from json_codegen.core import load_external_generator, load_schema 9 | 10 | sys.path.append((Path(__file__).parent.resolve() / "..").as_posix()) 11 | 12 | 13 | LANGUAGES = { 14 | "python3": generators.Python3Generator, 15 | "python3+marshmallow": generators.Python3MarshmallowGenerator, 16 | "javascript+flow": generators.JavaScriptFlowGenerator, 17 | "flow": generators.FlowGenerator, 18 | } 19 | 20 | 21 | def get_generator(language): 22 | try: 23 | return LANGUAGES[language] 24 | except KeyError: 25 | raise ValueError(f"Language {language} not supported") 26 | 27 | 28 | def main(): 29 | # Validating parameters 30 | parser = ArgumentParser(description="Generates code from a JSON-schema definition") 31 | parser.add_argument("--prefix", "-p", help="Optional prefix for generated classes") 32 | parser.add_argument( 33 | "--output", "-o", help="Output filename for the generated code. Default is stdout" 34 | ) 35 | parser.add_argument( 36 | "--generator", 37 | "-g", 38 | help=( 39 | "Path to an external custom code generator. " 40 | "When used the option --language will be ignored." 41 | ), 42 | ) 43 | parser.add_argument("schema", help="Definition of the PRD as JSON schema") 44 | parser.add_argument( 45 | "--language", 46 | "-l", 47 | choices=LANGUAGES, 48 | help=( 49 | "Output language. " 50 | "This option will be ignored if the --generator option is used. " 51 | "Default is python3" 52 | ), 53 | ) 54 | 55 | args = parser.parse_args() 56 | 57 | # Load schema 58 | with open(args.schema) as f: 59 | schema = load_schema(f.read()) 60 | 61 | # Generate code 62 | if args.generator: 63 | generator = load_external_generator(args.generator) 64 | else: 65 | generator = get_generator(args.language) 66 | 67 | code = generator(schema, prefix=args.prefix).generate().as_code() 68 | 69 | # Output code 70 | if args.output: 71 | with open(args.output, "w") as f: 72 | f.write(code) 73 | else: 74 | sys.stdout.write(code) 75 | sys.stdout.write("\n") 76 | 77 | 78 | if __name__ == "__main__": 79 | main() 80 | -------------------------------------------------------------------------------- /json_codegen/core.py: -------------------------------------------------------------------------------- 1 | import importlib.util 2 | import json 3 | from collections import OrderedDict 4 | from pathlib import Path 5 | from typing import Iterable 6 | 7 | 8 | class GeneratorNotFoundException(Exception): 9 | pass 10 | 11 | 12 | def load_external_generator(filename: Path): 13 | module_name = filename.stem 14 | klass_name = "".join(s.capitalize() for s in module_name.split("_")) 15 | filename_str = str(filename) 16 | 17 | spec = importlib.util.spec_from_file_location(module_name, filename_str) 18 | module = importlib.util.module_from_spec(spec) 19 | spec.loader.exec_module(module) 20 | 21 | try: 22 | return getattr(module, klass_name) 23 | except AttributeError: 24 | raise GeneratorNotFoundException(f"Class {klass_name} not found in {filename}") 25 | 26 | 27 | def load_schema(schema_str): 28 | return json.loads(schema_str, object_pairs_hook=OrderedDict) 29 | 30 | 31 | class SchemaParser: 32 | def __init__(self, schema, *args, **kwds): 33 | self.schema = schema 34 | self.prefix = kwds.get("prefix") or "" 35 | self.definitions = OrderedDict() 36 | 37 | self.__parse_definitions() 38 | 39 | def __parse_definitions(self): 40 | definitions = self.schema.get("definitions", {}) 41 | 42 | for key, definition in definitions.items(): 43 | new_key = f"#/definitions/{key}" 44 | new_definition = dict(definition) 45 | 46 | if "title" not in new_definition: 47 | new_definition["title"] = key 48 | 49 | self.definitions[new_key] = new_definition 50 | 51 | def apply_prefix(self, definition): 52 | title = definition.get("title") 53 | 54 | if title is None: 55 | return definition 56 | 57 | new_title = "{}{}".format(self.prefix, definition["title"]) 58 | new_definition = dict(definition, title=new_title) 59 | 60 | return new_definition 61 | 62 | def definition_is_primitive_alias(self, definition): 63 | return definition.get("type") != "object" or len(definition.get("properties", {})) == 0 64 | 65 | def get_root_definition(self): 66 | return self.apply_prefix(self.schema) 67 | 68 | def get_klass_definitions(self) -> Iterable: 69 | return ( 70 | self.apply_prefix(d) 71 | for d in self.definitions.values() 72 | if not self.definition_is_primitive_alias(d) 73 | ) 74 | 75 | def get_type_aliases(self): 76 | return (d for d in self.definitions.values() if self.definition_is_primitive_alias(d)) 77 | 78 | 79 | class BaseGenerator: 80 | _body = None 81 | 82 | def generate(self): 83 | return self 84 | 85 | def as_code(self): 86 | raise NotImplementedError(self) 87 | 88 | def as_ast(self): 89 | raise NotImplementedError(self) 90 | -------------------------------------------------------------------------------- /json_codegen/generators/__init__.py: -------------------------------------------------------------------------------- 1 | from json_codegen.generators.flow import FlowGenerator # noqa: F401 2 | from json_codegen.generators.javascript_flow import ( # noqa: F401 3 | JavaScriptFlowGenerator, 4 | ) 5 | from json_codegen.generators.python3 import Python3Generator # noqa: F401 6 | from json_codegen.generators.python3_marshmallow import ( # noqa: F401 7 | Python3MarshmallowGenerator, 8 | ) 9 | -------------------------------------------------------------------------------- /json_codegen/generators/flow.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from json_codegen.astlib import javascript as ast 4 | from json_codegen.core import BaseGenerator, SchemaParser 5 | from json_codegen.js_utils import get_type_annotation 6 | 7 | 8 | class FlowGenerator(SchemaParser, BaseGenerator): 9 | def generate(self): 10 | # Generates type aliases 11 | self._body = [] 12 | 13 | for definition in self.get_type_aliases(): 14 | self._body.append(self.type_alias(definition)) 15 | 16 | # Generates definitions 17 | for definition in self.get_klass_definitions(): 18 | self._body.append(self.klass(definition)) 19 | 20 | # Generate root definition 21 | root_definition = self.get_root_definition() 22 | 23 | if "title" in root_definition: 24 | self._body.append(self.klass(root_definition)) 25 | 26 | # Add leading comment 27 | if len(self._body): 28 | self._body[0]["leadingComments"] = [ast.CommentLine("@flow")] 29 | 30 | return self 31 | 32 | def type_alias(self, definition): 33 | aliased_type = get_type_annotation(self.definitions, definition, required=True) 34 | type_alias = ast.DeclareTypeAlias( 35 | id_=ast.Identifier(definition["title"]), right=aliased_type 36 | ) 37 | 38 | return type_alias 39 | 40 | def klass(self, definition): 41 | # Build class property Flow definition 42 | klass_annotations = [] 43 | required = definition.get("required", ()) 44 | properties = definition.get("properties", {}) 45 | 46 | for key in sorted(properties.keys()): 47 | # Add property type definition 48 | property_ = properties[key] 49 | is_required = key in required 50 | has_default = "default" in property_ 51 | 52 | property_annotation = get_type_annotation( 53 | self.definitions, property_, required=(is_required or has_default) 54 | ) 55 | property_def = ast.ObjectTypeProperty( 56 | key=ast.Identifier(key), value=property_annotation, force_variance=True 57 | ) 58 | klass_annotations.append(property_def) 59 | 60 | # Add class constructor 61 | if len(properties): 62 | klass_annotations.append(self.klass_constructor()) 63 | 64 | # Return class definition 65 | klass = ast.DeclareTypeAlias( 66 | id_=ast.Identifier(definition["title"]), 67 | right=ast.ObjectTypeAnnotation(klass_annotations), 68 | ) 69 | 70 | return klass 71 | 72 | def klass_constructor(self): 73 | return ast.ObjectTypeProperty( 74 | key=ast.Identifier("constructor"), 75 | value=ast.FunctionTypeAnnotation( 76 | params=[ 77 | ast.FunctionTypeParam( 78 | ast.Identifier("data"), 79 | type_annotation=ast.NullableTypeAnnotation( 80 | ast.GenericTypeAnnotation(ast.Identifier("Object")) 81 | ), 82 | ) 83 | ], 84 | return_type=ast.VoidTypeAnnotation(), 85 | ), 86 | method=True, 87 | ) 88 | 89 | def as_ast(self): 90 | return ast.File(program=ast.Program(body=self._body), comments=[ast.CommentLine("@flow")]) 91 | 92 | def as_code(self): 93 | return json.dumps(self.as_ast(), indent=2) 94 | -------------------------------------------------------------------------------- /json_codegen/generators/python3_marshmallow/__init__.py: -------------------------------------------------------------------------------- 1 | from json_codegen.generators.python3_marshmallow.generator import ( # noqa: F401 2 | Python3MarshmallowGenerator, 3 | ) 4 | -------------------------------------------------------------------------------- /json_codegen/generators/python3_marshmallow/utils.py: -------------------------------------------------------------------------------- 1 | import ast 2 | from re import search 3 | from typing import List 4 | 5 | marshmallow_type_map = { 6 | "integer": "Integer", 7 | "string": "String", 8 | "boolean": "Boolean", 9 | "array": "List", 10 | "number": "Number", 11 | "object": "Dict", 12 | } 13 | 14 | python_type_map = { 15 | "Integer": "int", 16 | "String": "str", 17 | "Boolean": "bool", 18 | "List": "List", 19 | "Number": "float", 20 | "Dict": "dict", 21 | } 22 | 23 | 24 | def upper_first_letter(s): 25 | """ 26 | Assumes custom types of two words are defined as customType 27 | such that the class name is CustomTypeSchema 28 | """ 29 | return s[0].upper() + s[1:] 30 | 31 | 32 | def class_name(s, strict=True) -> str: 33 | name = search("^(.*)Schema$", s) 34 | if name is not None: 35 | return name.group(1) 36 | else: 37 | if strict: 38 | raise ValueError("Cannot form class name from schema") 39 | else: 40 | return None 41 | 42 | 43 | class Annotations: 44 | def __init__(self, node): 45 | self.node: List[ast.stmt] = node 46 | self.nested_type: bool = self._is_nested_type() 47 | self.type: str = self.type_annotation() 48 | 49 | def type_annotation(self): 50 | """ 51 | Gets the type hint for a marshmallow field 52 | """ 53 | # If the keyword required has been supplied, wrap the type hint 54 | # in `Optional`. As the class is generated, `required=False` does 55 | # not occur 56 | for node in ast.walk(self.node): 57 | if isinstance(node, ast.keyword) and node.arg in ["required", "default"]: 58 | optional = False 59 | break 60 | else: 61 | optional = True 62 | 63 | for node in ast.walk(self.node): 64 | if isinstance(node, ast.Attribute) and node.value.id == "fields_": 65 | # If the type is not a `List`, return either the type (primitive or custom) 66 | type_ = python_type_map.get(node.attr, upper_first_letter(node.attr)) 67 | 68 | if type_ != "List": 69 | return self.annotation(type_, list_=False, optional=optional) 70 | elif self.nested_type is not None: 71 | return self.annotation([self.nested_type], list_=True, optional=optional) 72 | else: 73 | return self.annotation(["Any"], list_=True, optional=optional) 74 | 75 | if isinstance(node, ast.Call) and node.func.attr == "Nested": 76 | # If the type is a List, wrap the subtype with `List` 77 | subtype = [class_name(n.id) for n in node.args] 78 | 79 | if len(subtype) != 1: 80 | raise ValueError("Nested Schema called with more than 1 type") 81 | 82 | return self.annotation(subtype, list_=True, optional=optional) 83 | 84 | else: 85 | raise NotImplementedError("Unexpected node type") 86 | 87 | def _is_nested_type(self): 88 | for node in ast.walk(self.node): 89 | if isinstance(node, ast.Call) and node.func.attr == "Nested" and len(node.args) > 0: 90 | return class_name(node.args[0].id) 91 | 92 | def _annotation_optional(self, type_, optional=False): 93 | if optional: 94 | return ast.Subscript( 95 | value=ast.Name(id="Optional"), slice=ast.Index(value=ast.Name(id=type_)) 96 | ) 97 | else: 98 | return ast.Name(id=type_) 99 | 100 | def _annotation_list(self, type_): 101 | return ast.Subscript( 102 | value=ast.Name(id="List"), slice=ast.Index(value=ast.Name(id=type_[0])) 103 | ) 104 | 105 | def annotation(self, type_, list_, optional): 106 | if list_: 107 | type_ = self._annotation_list(type_) 108 | if optional: 109 | type_ = self._annotation_optional(type_, optional) 110 | 111 | if not (list_ or optional): 112 | return ast.Name(id=type_) 113 | else: 114 | return type_ 115 | -------------------------------------------------------------------------------- /json_codegen/js_utils.py: -------------------------------------------------------------------------------- 1 | from json_codegen.astlib import javascript as ast 2 | from json_codegen.types import DefinitionType, PropertyType 3 | 4 | 5 | def get_object_type_annotation(definitions: DefinitionType, property_: PropertyType) -> ast.AST: 6 | additionalProperties = property_.get("additionalProperties") 7 | 8 | if additionalProperties: 9 | annotation = ast.ObjectTypeAnnotation( 10 | properties=[], 11 | indexers=[ 12 | ast.ObjectTypeIndexer( 13 | id_=ast.Identifier("key"), 14 | key=ast.StringTypeAnnotation(), 15 | value=get_type_annotation(definitions, additionalProperties, required=True), 16 | ) 17 | ], 18 | ) 19 | elif "oneOf" in property_: 20 | annotation = get_oneof_type_annotion(definitions, property_) 21 | else: 22 | annotation = ast.GenericTypeAnnotation(ast.Identifier("Object")) 23 | 24 | return annotation 25 | 26 | 27 | def get_single_type_annotation(definitions: DefinitionType, property_: PropertyType) -> ast.AST: 28 | # If no property definition, use any 29 | if property_ is None: 30 | return ast.AnyTypeAnnotation() 31 | 32 | # Parse type 33 | type_name = property_.get("type") 34 | ref_key = property_.get("$ref") 35 | 36 | if type_name is None and ref_key is None: 37 | return ast.AnyTypeAnnotation() 38 | elif type_name in ("integer", "number"): 39 | return ast.NumberTypeAnnotation() 40 | elif type_name == "string": 41 | return ast.StringTypeAnnotation() 42 | elif type_name == "boolean": 43 | return ast.BooleanTypeAnnotation() 44 | elif type_name == "object": 45 | return get_object_type_annotation(definitions, property_) 46 | elif type_name == "array": 47 | items_definition = property_.get("items") 48 | parameter = get_single_type_annotation(definitions, items_definition) 49 | 50 | return ast.GenericTypeAnnotation( 51 | ast.Identifier("Array"), type_parameters=ast.TypeParameterInstantiation([parameter]) 52 | ) 53 | elif ref_key is not None: 54 | definition = definitions[ref_key] 55 | 56 | return ast.GenericTypeAnnotation(ast.Identifier(definition["title"])) 57 | 58 | # Nothing matches 59 | raise NotImplementedError(f"{definitions}: {property_}") 60 | 61 | 62 | def get_union_type_annotation(definitions, types): 63 | return [get_single_type_annotation(definitions, t) for t in types] 64 | 65 | 66 | def get_type_annotation( 67 | definitions: DefinitionType, property_: PropertyType, required: bool = False 68 | ) -> ast.AST: 69 | # Check for oneOf 70 | if "oneOf" in property_: 71 | annotation = get_oneof_type_annotion(definitions, property_) 72 | else: 73 | annotation = get_single_type_annotation(definitions, property_) 74 | 75 | if not required: 76 | annotation = ast.NullableTypeAnnotation(annotation) 77 | 78 | return annotation 79 | 80 | 81 | def get_oneof_type_annotion(definitions: DefinitionType, property_: PropertyType) -> ast.AST: 82 | annotations = get_union_type_annotation(definitions, property_.get("oneOf")) 83 | 84 | if len(annotations) == 1: 85 | annotation = annotations[0] 86 | elif len(annotations) > 1: 87 | annotation = ast.UnionTypeAnnotation(annotations) 88 | 89 | return annotation 90 | -------------------------------------------------------------------------------- /json_codegen/types.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, NewType 2 | 3 | DefinitionType = NewType("DefinitionType", Dict) 4 | PropertyType = NewType("PropertyType", Dict) 5 | PropertiesType = NewType("PropertiesType", List[PropertyType]) 6 | RequiredType = NewType("RequiredType", List[str]) 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@babel/cli": "^7.23.9", 4 | "@babel/core": "^7.24.5", 5 | "@babel/generator": "^7.24.6", 6 | "@babel/node": "^7.24.7", 7 | "@babel/preset-env": "^7.24.7", 8 | "@babel/preset-flow": "^7.24.1", 9 | "babel-eslint": "^10.1.0", 10 | "babel-loader": "^9.1.3", 11 | "babylon": "7.0.0-beta.47", 12 | "case-sensitive-paths-webpack-plugin": "^2.4.0", 13 | "eslint": "^8.56.0", 14 | "eslint-plugin-flowtype": "^8.0.2", 15 | "eslint-plugin-react": "^7.34.2", 16 | "flow-bin": "^0.229.2", 17 | "prettier": "^3.3.2", 18 | "progress-bar-webpack-plugin": "^2.1.0", 19 | "webpack": "^5.90.3", 20 | "webpack-cli": "^5.1.4" 21 | }, 22 | "license": "MIT", 23 | "name": "json_codegen", 24 | "scripts": { 25 | "build:bin": "webpack --config config/ast_to_js.webpack.config.js && chmod +x bin/ast_to_js", 26 | "build:test:js": "babel-node scripts/build_js_ast.js && npm run code:format tests/**/*.json", 27 | "code:format": "prettier --write *.md **/*.js", 28 | "code:format:check": "prettier --check *.md **/*.js" 29 | }, 30 | "version": "0.1.0" 31 | } 32 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 99 3 | target-version = ["py37", "py38", "py39", "py310", "py311"] 4 | exclude = ''' 5 | /( 6 | \.git|node_modules|\.venv 7 | )/ 8 | ''' 9 | 10 | [tool.poetry] 11 | name = "json_codegen" 12 | description = "Generate code from JSON schema files." 13 | keywords = ["python", "javascript", "json-schema", "codegen"] 14 | version = "0.6.0" 15 | authors = ["Daniele Esposti "] 16 | license = "MIT" 17 | readme = "README.md" 18 | packages = [{ include = "json_codegen" }] 19 | include = ["bin/ast_to_js"] 20 | 21 | [tool.poetry.dependencies] 22 | python = "^3.7,<3.8" 23 | astor = ">=0.7.1" 24 | 25 | [tool.poetry.scripts] 26 | json_codegen = "json_codegen.cli.main:cli" 27 | 28 | [tool.poetry.group.dev.dependencies] 29 | pytest = "^7.2.1" 30 | pytest-clarity = "^1.0.1" 31 | bandit = "^1.7.4" 32 | pytest-testmon = ">=1.4.5,<3.0.0" 33 | pytest-timeout = "^2.1.0" 34 | pytest-cov = "^4.0.0" 35 | mypy = ">=0.991,<1.5" 36 | marshmallow = ">=2,<4" 37 | black = ">=22.12,<24.0" 38 | 39 | [build-system] 40 | requires = ["poetry-core>=1.0.0", "setuptools>=40.1.0"] 41 | build-backend = "poetry.core.masonry.api" 42 | 43 | [tool.mypy] 44 | exclude = ".venv/" 45 | check_untyped_defs = true 46 | disallow_incomplete_defs = true 47 | warn_unused_configs = true 48 | warn_unused_ignores = true 49 | disallow_subclassing_any = true 50 | disallow_untyped_defs = true 51 | no_implicit_optional = true 52 | warn_redundant_casts = true 53 | warn_return_any = true 54 | 55 | [[tool.mypy.overrides]] 56 | module = "astor" 57 | ignore_missing_imports = true 58 | 59 | [[tool.mypy.overrides]] 60 | module = "marshmallow" 61 | ignore_missing_imports = true 62 | 63 | [tool.isort] 64 | profile = "black" 65 | float_to_top = true 66 | skip_glob = ".venv" 67 | 68 | [tool.pytest.ini_options] 69 | timeout = 10 70 | -------------------------------------------------------------------------------- /scripts/ast_to_js.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import fs from "fs"; 4 | 5 | import generate from "@babel/generator"; 6 | 7 | const generateOptions = { 8 | compact: false, 9 | }; 10 | 11 | const generateCode = (s: string): string => { 12 | const ast = JSON.parse(s); 13 | const { code } = generate(ast, generateOptions); 14 | 15 | return code; 16 | }; 17 | 18 | if (process.stdin.isTTY) { 19 | // Executed as standalone 20 | if (process.argv.length < 4) { 21 | // eslint-disable-next-line no-console 22 | console.log("Usage: ast_to_js "); 23 | process.exit(1); 24 | } 25 | 26 | const inputAst = process.argv[2]; 27 | const outputJs = process.argv[3]; 28 | 29 | fs.readFile(inputAst, (err: ?Error, data: Buffer) => { 30 | if (err) { 31 | // eslint-disable-next-line no-console 32 | console.error(err); 33 | process.exit(1); 34 | } 35 | 36 | const code = generateCode(data.toString()); 37 | 38 | fs.writeFile(outputJs, code, { encoding: "utf-8" }, (err: ?Error) => { 39 | if (err) { 40 | // eslint-disable-next-line no-console 41 | console.error(err); 42 | process.exit(1); 43 | } 44 | }); 45 | }); 46 | } else { 47 | // Executed inside a pipe 48 | let buffer = ""; 49 | 50 | process.stdin.setEncoding("utf8"); 51 | 52 | process.stdin.on("readable", () => { 53 | const chunk = process.stdin.read(); 54 | 55 | if (chunk !== null) { 56 | buffer += chunk.toString(); 57 | } 58 | }); 59 | 60 | process.stdin.on("end", () => { 61 | const code = generateCode(buffer); 62 | 63 | process.stdout.write(code); 64 | }); 65 | } 66 | -------------------------------------------------------------------------------- /scripts/build_js_ast.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import path from "path"; 4 | import fs from "fs"; 5 | 6 | import * as babylon from "babylon"; 7 | 8 | const BASE_AST_DIR = path.join(__dirname, "..", "tests", "fixtures"); 9 | const TEMPLATE_EXT = ".template.js"; 10 | const PRIMITIVES = ["boolean", "string", "number"]; 11 | const AST_LOCATION_KEYS = ["loc", "start", "end", "parenStart"]; 12 | 13 | const parserOptions = { 14 | sourceType: "module", 15 | plugins: ["flow"], 16 | }; 17 | 18 | const removeLocationData = (obj: Object) => { 19 | return ( 20 | Object.entries(obj) 21 | // eslint-disable-next-line no-unused-vars 22 | .filter(([key, value]) => !AST_LOCATION_KEYS.includes(key)) 23 | .map(([key, value]) => { 24 | if (value !== null) { 25 | if (Array.isArray(value)) { 26 | value = value.map((v: any) => (PRIMITIVES.includes(typeof v) ? v : removeLocationData(v))); 27 | } else if (!PRIMITIVES.includes(typeof value)) { 28 | value = removeLocationData(((value: any): Object)); 29 | } 30 | } 31 | 32 | return [key, value]; 33 | }) 34 | .reduce((acc, [key, value]) => { 35 | acc[key] = value; 36 | 37 | return acc; 38 | }, {}) 39 | ); 40 | }; 41 | 42 | const buildAst = (astDir: string) => { 43 | fs.readdir(astDir, (err: ?Error, filenames: Array) => { 44 | if (err) { 45 | throw err; 46 | } 47 | 48 | filenames 49 | .map((filename) => path.join(astDir, filename)) 50 | .filter((filename) => filename.endsWith(TEMPLATE_EXT) && fs.statSync(filename).isFile()) 51 | .forEach((filename: string) => { 52 | fs.readFile(filename, "utf8", (er: ?Error, sourceCode: string) => { 53 | const parsedAst = babylon.parse(sourceCode, parserOptions); 54 | const cleanAst = removeLocationData(parsedAst); 55 | 56 | const content = JSON.stringify(cleanAst, null, 2); 57 | const newFilename = path.join(astDir, path.basename(filename, TEMPLATE_EXT) + ".ast.json"); 58 | 59 | // eslint-disable-next-line no-console 60 | console.log(`writing ${newFilename}`); 61 | 62 | fs.writeFile(newFilename, content, (err: ?Error) => { 63 | if (err) { 64 | throw err; 65 | } 66 | }); 67 | }); 68 | }); 69 | }); 70 | }; 71 | 72 | ["javascript_flow", "flow"].map((v) => path.join(BASE_AST_DIR, v)).forEach(buildAst); 73 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | sys.path.append(os.path.join(os.path.dirname(__file__), "..")) 5 | -------------------------------------------------------------------------------- /tests/astlib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expobrain/json-schema-codegen/f4c8306a4bc6925607aaff95a5fc68aa01469454/tests/astlib/__init__.py -------------------------------------------------------------------------------- /tests/astlib/javascript_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from json_codegen.astlib.javascript import ( 4 | AnyTypeAnnotation, 5 | CommentLine, 6 | Identifier, 7 | NumericLiteral, 8 | ObjectTypeProperty, 9 | StringLiteral, 10 | TypeCastExpression, 11 | UnaryExpression, 12 | ) 13 | 14 | 15 | @pytest.mark.parametrize( 16 | "name, type_annotation, expected", 17 | [ 18 | ["test", None, {"type": "Identifier", "name": "test"}], 19 | [ 20 | "test", 21 | AnyTypeAnnotation(), 22 | { 23 | "type": "Identifier", 24 | "name": "test", 25 | "typeAnnotation": {"type": "AnyTypeAnnotation"}, 26 | }, 27 | ], 28 | ], 29 | ) 30 | def test_Identifier(name, type_annotation, expected): 31 | result = Identifier(name, type_annotation=type_annotation) 32 | 33 | assert result == expected 34 | 35 | 36 | @pytest.mark.parametrize( 37 | "key, value, force_variance, expected", 38 | [ 39 | [ 40 | Identifier("test"), 41 | AnyTypeAnnotation(), 42 | False, 43 | { 44 | "type": "ObjectTypeProperty", 45 | "key": {"type": "Identifier", "name": "test"}, 46 | "value": {"type": "AnyTypeAnnotation"}, 47 | "static": False, 48 | "kind": "init", 49 | "method": False, 50 | "optional": False, 51 | }, 52 | ], 53 | [ 54 | Identifier("test"), 55 | AnyTypeAnnotation(), 56 | True, 57 | { 58 | "type": "ObjectTypeProperty", 59 | "key": {"type": "Identifier", "name": "test"}, 60 | "value": {"type": "AnyTypeAnnotation"}, 61 | "static": False, 62 | "kind": "init", 63 | "method": False, 64 | "optional": False, 65 | "variance": None, 66 | }, 67 | ], 68 | ], 69 | ) 70 | def test_ObjectTypeProperty(key, value, force_variance, expected): 71 | result = ObjectTypeProperty(key, value, force_variance=force_variance) 72 | 73 | assert result == expected 74 | 75 | 76 | @pytest.mark.parametrize( 77 | "value, expected", 78 | [ 79 | ["my_comment", {"type": "CommentLine", "value": " my_comment"}], 80 | [" my_comment", {"type": "CommentLine", "value": " my_comment"}], 81 | ["my_comment ", {"type": "CommentLine", "value": " my_comment"}], 82 | ], 83 | ) 84 | def test_CommentLine(value, expected): 85 | result = CommentLine(value) 86 | 87 | assert result == expected 88 | 89 | 90 | @pytest.mark.parametrize( 91 | "expression, type_annotation, extra, expected", 92 | [ 93 | [ 94 | Identifier("test"), 95 | AnyTypeAnnotation(), 96 | None, 97 | { 98 | "type": "TypeCastExpression", 99 | "expression": {"type": "Identifier", "name": "test"}, 100 | "typeAnnotation": {"type": "AnyTypeAnnotation"}, 101 | "extra": {"parenthesized": True}, 102 | }, 103 | ] 104 | ], 105 | ) 106 | def test_TypeCastExpression(expression, type_annotation, extra, expected): 107 | result = TypeCastExpression(expression, type_annotation, extra=extra) 108 | 109 | assert result == expected 110 | 111 | 112 | @pytest.mark.parametrize( 113 | "extra, expected", 114 | [ 115 | [ 116 | None, 117 | { 118 | "type": "UnaryExpression", 119 | "operator": None, 120 | "prefix": True, 121 | "argument": None, 122 | "extra": {"parenthesizedArgument": False}, 123 | }, 124 | ] 125 | ], 126 | ) 127 | def test_UnaryExpression(extra, expected): 128 | result = UnaryExpression(extra=extra) 129 | 130 | assert result == expected 131 | 132 | 133 | @pytest.mark.parametrize( 134 | "value, expected", 135 | [[42, {"type": "NumericLiteral", "value": 42, "extra": {"rawValue": 42, "raw": "42"}}]], 136 | ) 137 | def test_NumericLiteral(value, expected): 138 | result = NumericLiteral(value) 139 | 140 | assert result == expected 141 | 142 | 143 | @pytest.mark.parametrize( 144 | "value, expected", 145 | [ 146 | [ 147 | "test", 148 | { 149 | "type": "StringLiteral", 150 | "value": "test", 151 | "extra": {"rawValue": "test", "raw": '"test"'}, 152 | }, 153 | ] 154 | ], 155 | ) 156 | def test_StringLiteral(value, expected): 157 | result = StringLiteral(value) 158 | 159 | assert result == expected 160 | -------------------------------------------------------------------------------- /tests/cli_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from json_codegen import cli 4 | from json_codegen.core import BaseGenerator 5 | 6 | 7 | def test_langages(): 8 | languages = set(cli.LANGUAGES.keys()) 9 | expected = {"python3", "python3+marshmallow", "javascript+flow", "flow"} 10 | 11 | assert languages == expected 12 | 13 | 14 | @pytest.mark.parametrize("language", cli.LANGUAGES.keys()) 15 | def test_get_generator(language): 16 | generator = cli.get_generator(language) 17 | 18 | assert issubclass(generator, BaseGenerator) 19 | -------------------------------------------------------------------------------- /tests/fixtures/flow/additional_properties_with_ref.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Value", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "v", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NullableTypeAnnotation", 38 | "typeAnnotation": { 39 | "type": "NumberTypeAnnotation" 40 | } 41 | }, 42 | "variance": null 43 | }, 44 | { 45 | "key": { 46 | "name": "constructor", 47 | "type": "Identifier" 48 | }, 49 | "kind": "init", 50 | "method": true, 51 | "optional": false, 52 | "static": false, 53 | "type": "ObjectTypeProperty", 54 | "value": { 55 | "params": [ 56 | { 57 | "name": { 58 | "name": "data", 59 | "type": "Identifier" 60 | }, 61 | "optional": false, 62 | "type": "FunctionTypeParam", 63 | "typeAnnotation": { 64 | "type": "NullableTypeAnnotation", 65 | "typeAnnotation": { 66 | "id": { 67 | "name": "Object", 68 | "type": "Identifier" 69 | }, 70 | "type": "GenericTypeAnnotation", 71 | "typeParameters": null 72 | } 73 | } 74 | } 75 | ], 76 | "rest": null, 77 | "returnType": { 78 | "type": "VoidTypeAnnotation" 79 | }, 80 | "type": "FunctionTypeAnnotation", 81 | "typeParameters": null 82 | } 83 | } 84 | ], 85 | "type": "ObjectTypeAnnotation" 86 | }, 87 | "type": "DeclareTypeAlias", 88 | "typeParameters": null 89 | }, 90 | { 91 | "id": { 92 | "name": "Test", 93 | "type": "Identifier" 94 | }, 95 | "right": { 96 | "callProperties": [], 97 | "exact": false, 98 | "indexers": [], 99 | "properties": [ 100 | { 101 | "key": { 102 | "name": "x", 103 | "type": "Identifier" 104 | }, 105 | "kind": "init", 106 | "method": false, 107 | "optional": false, 108 | "static": false, 109 | "type": "ObjectTypeProperty", 110 | "value": { 111 | "callProperties": [], 112 | "exact": false, 113 | "indexers": [ 114 | { 115 | "id": { 116 | "name": "key", 117 | "type": "Identifier" 118 | }, 119 | "key": { 120 | "type": "StringTypeAnnotation" 121 | }, 122 | "static": false, 123 | "type": "ObjectTypeIndexer", 124 | "value": { 125 | "id": { 126 | "name": "Value", 127 | "type": "Identifier" 128 | }, 129 | "type": "GenericTypeAnnotation", 130 | "typeParameters": null 131 | }, 132 | "variance": null 133 | } 134 | ], 135 | "properties": [], 136 | "type": "ObjectTypeAnnotation" 137 | }, 138 | "variance": null 139 | }, 140 | { 141 | "key": { 142 | "name": "constructor", 143 | "type": "Identifier" 144 | }, 145 | "kind": "init", 146 | "method": true, 147 | "optional": false, 148 | "static": false, 149 | "type": "ObjectTypeProperty", 150 | "value": { 151 | "params": [ 152 | { 153 | "name": { 154 | "name": "data", 155 | "type": "Identifier" 156 | }, 157 | "optional": false, 158 | "type": "FunctionTypeParam", 159 | "typeAnnotation": { 160 | "type": "NullableTypeAnnotation", 161 | "typeAnnotation": { 162 | "id": { 163 | "name": "Object", 164 | "type": "Identifier" 165 | }, 166 | "type": "GenericTypeAnnotation", 167 | "typeParameters": null 168 | } 169 | } 170 | } 171 | ], 172 | "rest": null, 173 | "returnType": { 174 | "type": "VoidTypeAnnotation" 175 | }, 176 | "type": "FunctionTypeAnnotation", 177 | "typeParameters": null 178 | } 179 | } 180 | ], 181 | "type": "ObjectTypeAnnotation" 182 | }, 183 | "type": "DeclareTypeAlias", 184 | "typeParameters": null 185 | } 186 | ], 187 | "directives": [], 188 | "sourceType": "module", 189 | "type": "Program" 190 | }, 191 | "type": "File" 192 | } 193 | -------------------------------------------------------------------------------- /tests/fixtures/flow/additional_properties_with_ref.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Value = { 4 | v: ?number, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | 9 | declare type Test = { 10 | x: { [key: string]: Value }, 11 | 12 | constructor(data: ?Object): void, 13 | }; 14 | -------------------------------------------------------------------------------- /tests/fixtures/flow/array_items_ref.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "MyType", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "v", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NullableTypeAnnotation", 38 | "typeAnnotation": { 39 | "type": "NumberTypeAnnotation" 40 | } 41 | }, 42 | "variance": null 43 | }, 44 | { 45 | "key": { 46 | "name": "constructor", 47 | "type": "Identifier" 48 | }, 49 | "kind": "init", 50 | "method": true, 51 | "optional": false, 52 | "static": false, 53 | "type": "ObjectTypeProperty", 54 | "value": { 55 | "params": [ 56 | { 57 | "name": { 58 | "name": "data", 59 | "type": "Identifier" 60 | }, 61 | "optional": false, 62 | "type": "FunctionTypeParam", 63 | "typeAnnotation": { 64 | "type": "NullableTypeAnnotation", 65 | "typeAnnotation": { 66 | "id": { 67 | "name": "Object", 68 | "type": "Identifier" 69 | }, 70 | "type": "GenericTypeAnnotation", 71 | "typeParameters": null 72 | } 73 | } 74 | } 75 | ], 76 | "rest": null, 77 | "returnType": { 78 | "type": "VoidTypeAnnotation" 79 | }, 80 | "type": "FunctionTypeAnnotation", 81 | "typeParameters": null 82 | } 83 | } 84 | ], 85 | "type": "ObjectTypeAnnotation" 86 | }, 87 | "type": "DeclareTypeAlias", 88 | "typeParameters": null 89 | }, 90 | { 91 | "id": { 92 | "name": "Test", 93 | "type": "Identifier" 94 | }, 95 | "right": { 96 | "callProperties": [], 97 | "exact": false, 98 | "indexers": [], 99 | "properties": [ 100 | { 101 | "key": { 102 | "name": "x", 103 | "type": "Identifier" 104 | }, 105 | "kind": "init", 106 | "method": false, 107 | "optional": false, 108 | "static": false, 109 | "type": "ObjectTypeProperty", 110 | "value": { 111 | "id": { 112 | "name": "Array", 113 | "type": "Identifier" 114 | }, 115 | "type": "GenericTypeAnnotation", 116 | "typeParameters": { 117 | "params": [ 118 | { 119 | "id": { 120 | "name": "MyType", 121 | "type": "Identifier" 122 | }, 123 | "type": "GenericTypeAnnotation", 124 | "typeParameters": null 125 | } 126 | ], 127 | "type": "TypeParameterInstantiation" 128 | } 129 | }, 130 | "variance": null 131 | }, 132 | { 133 | "key": { 134 | "name": "constructor", 135 | "type": "Identifier" 136 | }, 137 | "kind": "init", 138 | "method": true, 139 | "optional": false, 140 | "static": false, 141 | "type": "ObjectTypeProperty", 142 | "value": { 143 | "params": [ 144 | { 145 | "name": { 146 | "name": "data", 147 | "type": "Identifier" 148 | }, 149 | "optional": false, 150 | "type": "FunctionTypeParam", 151 | "typeAnnotation": { 152 | "type": "NullableTypeAnnotation", 153 | "typeAnnotation": { 154 | "id": { 155 | "name": "Object", 156 | "type": "Identifier" 157 | }, 158 | "type": "GenericTypeAnnotation", 159 | "typeParameters": null 160 | } 161 | } 162 | } 163 | ], 164 | "rest": null, 165 | "returnType": { 166 | "type": "VoidTypeAnnotation" 167 | }, 168 | "type": "FunctionTypeAnnotation", 169 | "typeParameters": null 170 | } 171 | } 172 | ], 173 | "type": "ObjectTypeAnnotation" 174 | }, 175 | "type": "DeclareTypeAlias", 176 | "typeParameters": null 177 | } 178 | ], 179 | "directives": [], 180 | "sourceType": "module", 181 | "type": "Program" 182 | }, 183 | "type": "File" 184 | } 185 | -------------------------------------------------------------------------------- /tests/fixtures/flow/array_items_ref.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type MyType = { 4 | v: ?number, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | 9 | declare type Test = { 10 | x: Array, 11 | 12 | constructor(data: ?Object): void, 13 | }; 14 | -------------------------------------------------------------------------------- /tests/fixtures/flow/array_items_ref_as_alias.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "MyType", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "type": "StringTypeAnnotation" 23 | }, 24 | "type": "DeclareTypeAlias", 25 | "typeParameters": null 26 | }, 27 | { 28 | "id": { 29 | "name": "Test", 30 | "type": "Identifier" 31 | }, 32 | "right": { 33 | "callProperties": [], 34 | "exact": false, 35 | "indexers": [], 36 | "properties": [ 37 | { 38 | "key": { 39 | "name": "x", 40 | "type": "Identifier" 41 | }, 42 | "kind": "init", 43 | "method": false, 44 | "optional": false, 45 | "static": false, 46 | "type": "ObjectTypeProperty", 47 | "value": { 48 | "id": { 49 | "name": "Array", 50 | "type": "Identifier" 51 | }, 52 | "type": "GenericTypeAnnotation", 53 | "typeParameters": { 54 | "params": [ 55 | { 56 | "id": { 57 | "name": "MyType", 58 | "type": "Identifier" 59 | }, 60 | "type": "GenericTypeAnnotation", 61 | "typeParameters": null 62 | } 63 | ], 64 | "type": "TypeParameterInstantiation" 65 | } 66 | }, 67 | "variance": null 68 | }, 69 | { 70 | "key": { 71 | "name": "constructor", 72 | "type": "Identifier" 73 | }, 74 | "kind": "init", 75 | "method": true, 76 | "optional": false, 77 | "static": false, 78 | "type": "ObjectTypeProperty", 79 | "value": { 80 | "params": [ 81 | { 82 | "name": { 83 | "name": "data", 84 | "type": "Identifier" 85 | }, 86 | "optional": false, 87 | "type": "FunctionTypeParam", 88 | "typeAnnotation": { 89 | "type": "NullableTypeAnnotation", 90 | "typeAnnotation": { 91 | "id": { 92 | "name": "Object", 93 | "type": "Identifier" 94 | }, 95 | "type": "GenericTypeAnnotation", 96 | "typeParameters": null 97 | } 98 | } 99 | } 100 | ], 101 | "rest": null, 102 | "returnType": { 103 | "type": "VoidTypeAnnotation" 104 | }, 105 | "type": "FunctionTypeAnnotation", 106 | "typeParameters": null 107 | } 108 | } 109 | ], 110 | "type": "ObjectTypeAnnotation" 111 | }, 112 | "type": "DeclareTypeAlias", 113 | "typeParameters": null 114 | } 115 | ], 116 | "directives": [], 117 | "sourceType": "module", 118 | "type": "Program" 119 | }, 120 | "type": "File" 121 | } 122 | -------------------------------------------------------------------------------- /tests/fixtures/flow/array_items_ref_as_alias.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type MyType = string; 4 | 5 | declare type Test = { 6 | x: Array, 7 | 8 | constructor(data: ?Object): void, 9 | }; 10 | -------------------------------------------------------------------------------- /tests/fixtures/flow/array_items_ref_as_scalar.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "id": { 38 | "name": "Array", 39 | "type": "Identifier" 40 | }, 41 | "type": "GenericTypeAnnotation", 42 | "typeParameters": { 43 | "params": [ 44 | { 45 | "type": "StringTypeAnnotation" 46 | } 47 | ], 48 | "type": "TypeParameterInstantiation" 49 | } 50 | }, 51 | "variance": null 52 | }, 53 | { 54 | "key": { 55 | "name": "constructor", 56 | "type": "Identifier" 57 | }, 58 | "kind": "init", 59 | "method": true, 60 | "optional": false, 61 | "static": false, 62 | "type": "ObjectTypeProperty", 63 | "value": { 64 | "params": [ 65 | { 66 | "name": { 67 | "name": "data", 68 | "type": "Identifier" 69 | }, 70 | "optional": false, 71 | "type": "FunctionTypeParam", 72 | "typeAnnotation": { 73 | "type": "NullableTypeAnnotation", 74 | "typeAnnotation": { 75 | "id": { 76 | "name": "Object", 77 | "type": "Identifier" 78 | }, 79 | "type": "GenericTypeAnnotation", 80 | "typeParameters": null 81 | } 82 | } 83 | } 84 | ], 85 | "rest": null, 86 | "returnType": { 87 | "type": "VoidTypeAnnotation" 88 | }, 89 | "type": "FunctionTypeAnnotation", 90 | "typeParameters": null 91 | } 92 | } 93 | ], 94 | "type": "ObjectTypeAnnotation" 95 | }, 96 | "type": "DeclareTypeAlias", 97 | "typeParameters": null 98 | } 99 | ], 100 | "directives": [], 101 | "sourceType": "module", 102 | "type": "Program" 103 | }, 104 | "type": "File" 105 | } 106 | -------------------------------------------------------------------------------- /tests/fixtures/flow/array_items_ref_as_scalar.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: Array, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/array_property_default.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "id": { 38 | "name": "Array", 39 | "type": "Identifier" 40 | }, 41 | "type": "GenericTypeAnnotation", 42 | "typeParameters": { 43 | "params": [ 44 | { 45 | "type": "AnyTypeAnnotation" 46 | } 47 | ], 48 | "type": "TypeParameterInstantiation" 49 | } 50 | }, 51 | "variance": null 52 | }, 53 | { 54 | "key": { 55 | "name": "constructor", 56 | "type": "Identifier" 57 | }, 58 | "kind": "init", 59 | "method": true, 60 | "optional": false, 61 | "static": false, 62 | "type": "ObjectTypeProperty", 63 | "value": { 64 | "params": [ 65 | { 66 | "name": { 67 | "name": "data", 68 | "type": "Identifier" 69 | }, 70 | "optional": false, 71 | "type": "FunctionTypeParam", 72 | "typeAnnotation": { 73 | "type": "NullableTypeAnnotation", 74 | "typeAnnotation": { 75 | "id": { 76 | "name": "Object", 77 | "type": "Identifier" 78 | }, 79 | "type": "GenericTypeAnnotation", 80 | "typeParameters": null 81 | } 82 | } 83 | } 84 | ], 85 | "rest": null, 86 | "returnType": { 87 | "type": "VoidTypeAnnotation" 88 | }, 89 | "type": "FunctionTypeAnnotation", 90 | "typeParameters": null 91 | } 92 | } 93 | ], 94 | "type": "ObjectTypeAnnotation" 95 | }, 96 | "type": "DeclareTypeAlias", 97 | "typeParameters": null 98 | } 99 | ], 100 | "directives": [], 101 | "sourceType": "module", 102 | "type": "Program" 103 | }, 104 | "type": "File" 105 | } 106 | -------------------------------------------------------------------------------- /tests/fixtures/flow/array_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: Array, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/boolean_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NullableTypeAnnotation", 38 | "typeAnnotation": { 39 | "type": "BooleanTypeAnnotation" 40 | } 41 | }, 42 | "variance": null 43 | }, 44 | { 45 | "key": { 46 | "name": "constructor", 47 | "type": "Identifier" 48 | }, 49 | "kind": "init", 50 | "method": true, 51 | "optional": false, 52 | "static": false, 53 | "type": "ObjectTypeProperty", 54 | "value": { 55 | "params": [ 56 | { 57 | "name": { 58 | "name": "data", 59 | "type": "Identifier" 60 | }, 61 | "optional": false, 62 | "type": "FunctionTypeParam", 63 | "typeAnnotation": { 64 | "type": "NullableTypeAnnotation", 65 | "typeAnnotation": { 66 | "id": { 67 | "name": "Object", 68 | "type": "Identifier" 69 | }, 70 | "type": "GenericTypeAnnotation", 71 | "typeParameters": null 72 | } 73 | } 74 | } 75 | ], 76 | "rest": null, 77 | "returnType": { 78 | "type": "VoidTypeAnnotation" 79 | }, 80 | "type": "FunctionTypeAnnotation", 81 | "typeParameters": null 82 | } 83 | } 84 | ], 85 | "type": "ObjectTypeAnnotation" 86 | }, 87 | "type": "DeclareTypeAlias", 88 | "typeParameters": null 89 | } 90 | ], 91 | "directives": [], 92 | "sourceType": "module", 93 | "type": "Program" 94 | }, 95 | "type": "File" 96 | } 97 | -------------------------------------------------------------------------------- /tests/fixtures/flow/boolean_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: ?boolean, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/boolean_property_default.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "BooleanTypeAnnotation" 38 | }, 39 | "variance": null 40 | }, 41 | { 42 | "key": { 43 | "name": "constructor", 44 | "type": "Identifier" 45 | }, 46 | "kind": "init", 47 | "method": true, 48 | "optional": false, 49 | "static": false, 50 | "type": "ObjectTypeProperty", 51 | "value": { 52 | "params": [ 53 | { 54 | "name": { 55 | "name": "data", 56 | "type": "Identifier" 57 | }, 58 | "optional": false, 59 | "type": "FunctionTypeParam", 60 | "typeAnnotation": { 61 | "type": "NullableTypeAnnotation", 62 | "typeAnnotation": { 63 | "id": { 64 | "name": "Object", 65 | "type": "Identifier" 66 | }, 67 | "type": "GenericTypeAnnotation", 68 | "typeParameters": null 69 | } 70 | } 71 | } 72 | ], 73 | "rest": null, 74 | "returnType": { 75 | "type": "VoidTypeAnnotation" 76 | }, 77 | "type": "FunctionTypeAnnotation", 78 | "typeParameters": null 79 | } 80 | } 81 | ], 82 | "type": "ObjectTypeAnnotation" 83 | }, 84 | "type": "DeclareTypeAlias", 85 | "typeParameters": null 86 | } 87 | ], 88 | "directives": [], 89 | "sourceType": "module", 90 | "type": "Program" 91 | }, 92 | "type": "File" 93 | } 94 | -------------------------------------------------------------------------------- /tests/fixtures/flow/boolean_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: boolean, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/definition_of_primitive_alias.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "MyNumber", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "type": "NumberTypeAnnotation" 23 | }, 24 | "type": "DeclareTypeAlias", 25 | "typeParameters": null 26 | }, 27 | { 28 | "id": { 29 | "name": "MyString", 30 | "type": "Identifier" 31 | }, 32 | "right": { 33 | "type": "StringTypeAnnotation" 34 | }, 35 | "type": "DeclareTypeAlias", 36 | "typeParameters": null 37 | }, 38 | { 39 | "id": { 40 | "name": "MyUnion", 41 | "type": "Identifier" 42 | }, 43 | "right": { 44 | "type": "UnionTypeAnnotation", 45 | "types": [ 46 | { 47 | "type": "StringTypeAnnotation" 48 | }, 49 | { 50 | "type": "BooleanTypeAnnotation" 51 | } 52 | ] 53 | }, 54 | "type": "DeclareTypeAlias", 55 | "typeParameters": null 56 | } 57 | ], 58 | "directives": [], 59 | "sourceType": "module", 60 | "type": "Program" 61 | }, 62 | "type": "File" 63 | } 64 | -------------------------------------------------------------------------------- /tests/fixtures/flow/definition_of_primitive_alias.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type MyString = string; 4 | 5 | declare type MyNumber = number; 6 | 7 | declare type MyUnion = string | boolean; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/definition_without_title.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "NoTitle", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NullableTypeAnnotation", 38 | "typeAnnotation": { 39 | "type": "StringTypeAnnotation" 40 | } 41 | }, 42 | "variance": null 43 | }, 44 | { 45 | "key": { 46 | "name": "constructor", 47 | "type": "Identifier" 48 | }, 49 | "kind": "init", 50 | "method": true, 51 | "optional": false, 52 | "static": false, 53 | "type": "ObjectTypeProperty", 54 | "value": { 55 | "params": [ 56 | { 57 | "name": { 58 | "name": "data", 59 | "type": "Identifier" 60 | }, 61 | "optional": false, 62 | "type": "FunctionTypeParam", 63 | "typeAnnotation": { 64 | "type": "NullableTypeAnnotation", 65 | "typeAnnotation": { 66 | "id": { 67 | "name": "Object", 68 | "type": "Identifier" 69 | }, 70 | "type": "GenericTypeAnnotation", 71 | "typeParameters": null 72 | } 73 | } 74 | } 75 | ], 76 | "rest": null, 77 | "returnType": { 78 | "type": "VoidTypeAnnotation" 79 | }, 80 | "type": "FunctionTypeAnnotation", 81 | "typeParameters": null 82 | } 83 | } 84 | ], 85 | "type": "ObjectTypeAnnotation" 86 | }, 87 | "type": "DeclareTypeAlias", 88 | "typeParameters": null 89 | } 90 | ], 91 | "directives": [], 92 | "sourceType": "module", 93 | "type": "Program" 94 | }, 95 | "type": "File" 96 | } 97 | -------------------------------------------------------------------------------- /tests/fixtures/flow/definition_without_title.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type NoTitle = { 4 | x: ?string, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/integer_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NullableTypeAnnotation", 38 | "typeAnnotation": { 39 | "type": "NumberTypeAnnotation" 40 | } 41 | }, 42 | "variance": null 43 | }, 44 | { 45 | "key": { 46 | "name": "constructor", 47 | "type": "Identifier" 48 | }, 49 | "kind": "init", 50 | "method": true, 51 | "optional": false, 52 | "static": false, 53 | "type": "ObjectTypeProperty", 54 | "value": { 55 | "params": [ 56 | { 57 | "name": { 58 | "name": "data", 59 | "type": "Identifier" 60 | }, 61 | "optional": false, 62 | "type": "FunctionTypeParam", 63 | "typeAnnotation": { 64 | "type": "NullableTypeAnnotation", 65 | "typeAnnotation": { 66 | "id": { 67 | "name": "Object", 68 | "type": "Identifier" 69 | }, 70 | "type": "GenericTypeAnnotation", 71 | "typeParameters": null 72 | } 73 | } 74 | } 75 | ], 76 | "rest": null, 77 | "returnType": { 78 | "type": "VoidTypeAnnotation" 79 | }, 80 | "type": "FunctionTypeAnnotation", 81 | "typeParameters": null 82 | } 83 | } 84 | ], 85 | "type": "ObjectTypeAnnotation" 86 | }, 87 | "type": "DeclareTypeAlias", 88 | "typeParameters": null 89 | } 90 | ], 91 | "directives": [], 92 | "sourceType": "module", 93 | "type": "Program" 94 | }, 95 | "type": "File" 96 | } 97 | -------------------------------------------------------------------------------- /tests/fixtures/flow/integer_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: ?number, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/integer_property_default.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NumberTypeAnnotation" 38 | }, 39 | "variance": null 40 | }, 41 | { 42 | "key": { 43 | "name": "constructor", 44 | "type": "Identifier" 45 | }, 46 | "kind": "init", 47 | "method": true, 48 | "optional": false, 49 | "static": false, 50 | "type": "ObjectTypeProperty", 51 | "value": { 52 | "params": [ 53 | { 54 | "name": { 55 | "name": "data", 56 | "type": "Identifier" 57 | }, 58 | "optional": false, 59 | "type": "FunctionTypeParam", 60 | "typeAnnotation": { 61 | "type": "NullableTypeAnnotation", 62 | "typeAnnotation": { 63 | "id": { 64 | "name": "Object", 65 | "type": "Identifier" 66 | }, 67 | "type": "GenericTypeAnnotation", 68 | "typeParameters": null 69 | } 70 | } 71 | } 72 | ], 73 | "rest": null, 74 | "returnType": { 75 | "type": "VoidTypeAnnotation" 76 | }, 77 | "type": "FunctionTypeAnnotation", 78 | "typeParameters": null 79 | } 80 | } 81 | ], 82 | "type": "ObjectTypeAnnotation" 83 | }, 84 | "type": "DeclareTypeAlias", 85 | "typeParameters": null 86 | } 87 | ], 88 | "directives": [], 89 | "sourceType": "module", 90 | "type": "Program" 91 | }, 92 | "type": "File" 93 | } 94 | -------------------------------------------------------------------------------- /tests/fixtures/flow/integer_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: number, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/object_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NullableTypeAnnotation", 38 | "typeAnnotation": { 39 | "id": { 40 | "name": "Object", 41 | "type": "Identifier" 42 | }, 43 | "type": "GenericTypeAnnotation", 44 | "typeParameters": null 45 | } 46 | }, 47 | "variance": null 48 | }, 49 | { 50 | "key": { 51 | "name": "constructor", 52 | "type": "Identifier" 53 | }, 54 | "kind": "init", 55 | "method": true, 56 | "optional": false, 57 | "static": false, 58 | "type": "ObjectTypeProperty", 59 | "value": { 60 | "params": [ 61 | { 62 | "name": { 63 | "name": "data", 64 | "type": "Identifier" 65 | }, 66 | "optional": false, 67 | "type": "FunctionTypeParam", 68 | "typeAnnotation": { 69 | "type": "NullableTypeAnnotation", 70 | "typeAnnotation": { 71 | "id": { 72 | "name": "Object", 73 | "type": "Identifier" 74 | }, 75 | "type": "GenericTypeAnnotation", 76 | "typeParameters": null 77 | } 78 | } 79 | } 80 | ], 81 | "rest": null, 82 | "returnType": { 83 | "type": "VoidTypeAnnotation" 84 | }, 85 | "type": "FunctionTypeAnnotation", 86 | "typeParameters": null 87 | } 88 | } 89 | ], 90 | "type": "ObjectTypeAnnotation" 91 | }, 92 | "type": "DeclareTypeAlias", 93 | "typeParameters": null 94 | } 95 | ], 96 | "directives": [], 97 | "sourceType": "module", 98 | "type": "Program" 99 | }, 100 | "type": "File" 101 | } 102 | -------------------------------------------------------------------------------- /tests/fixtures/flow/object_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: ?Object, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/object_property_default.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "id": { 38 | "name": "Object", 39 | "type": "Identifier" 40 | }, 41 | "type": "GenericTypeAnnotation", 42 | "typeParameters": null 43 | }, 44 | "variance": null 45 | }, 46 | { 47 | "key": { 48 | "name": "constructor", 49 | "type": "Identifier" 50 | }, 51 | "kind": "init", 52 | "method": true, 53 | "optional": false, 54 | "static": false, 55 | "type": "ObjectTypeProperty", 56 | "value": { 57 | "params": [ 58 | { 59 | "name": { 60 | "name": "data", 61 | "type": "Identifier" 62 | }, 63 | "optional": false, 64 | "type": "FunctionTypeParam", 65 | "typeAnnotation": { 66 | "type": "NullableTypeAnnotation", 67 | "typeAnnotation": { 68 | "id": { 69 | "name": "Object", 70 | "type": "Identifier" 71 | }, 72 | "type": "GenericTypeAnnotation", 73 | "typeParameters": null 74 | } 75 | } 76 | } 77 | ], 78 | "rest": null, 79 | "returnType": { 80 | "type": "VoidTypeAnnotation" 81 | }, 82 | "type": "FunctionTypeAnnotation", 83 | "typeParameters": null 84 | } 85 | } 86 | ], 87 | "type": "ObjectTypeAnnotation" 88 | }, 89 | "type": "DeclareTypeAlias", 90 | "typeParameters": null 91 | } 92 | ], 93 | "directives": [], 94 | "sourceType": "module", 95 | "type": "Program" 96 | }, 97 | "type": "File" 98 | } 99 | -------------------------------------------------------------------------------- /tests/fixtures/flow/object_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: Object, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/simple.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [], 26 | "type": "ObjectTypeAnnotation" 27 | }, 28 | "type": "DeclareTypeAlias", 29 | "typeParameters": null 30 | } 31 | ], 32 | "directives": [], 33 | "sourceType": "module", 34 | "type": "Program" 35 | }, 36 | "type": "File" 37 | } 38 | -------------------------------------------------------------------------------- /tests/fixtures/flow/simple.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = {}; 4 | -------------------------------------------------------------------------------- /tests/fixtures/flow/string_property_default.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "StringTypeAnnotation" 38 | }, 39 | "variance": null 40 | }, 41 | { 42 | "key": { 43 | "name": "constructor", 44 | "type": "Identifier" 45 | }, 46 | "kind": "init", 47 | "method": true, 48 | "optional": false, 49 | "static": false, 50 | "type": "ObjectTypeProperty", 51 | "value": { 52 | "params": [ 53 | { 54 | "name": { 55 | "name": "data", 56 | "type": "Identifier" 57 | }, 58 | "optional": false, 59 | "type": "FunctionTypeParam", 60 | "typeAnnotation": { 61 | "type": "NullableTypeAnnotation", 62 | "typeAnnotation": { 63 | "id": { 64 | "name": "Object", 65 | "type": "Identifier" 66 | }, 67 | "type": "GenericTypeAnnotation", 68 | "typeParameters": null 69 | } 70 | } 71 | } 72 | ], 73 | "rest": null, 74 | "returnType": { 75 | "type": "VoidTypeAnnotation" 76 | }, 77 | "type": "FunctionTypeAnnotation", 78 | "typeParameters": null 79 | } 80 | } 81 | ], 82 | "type": "ObjectTypeAnnotation" 83 | }, 84 | "type": "DeclareTypeAlias", 85 | "typeParameters": null 86 | } 87 | ], 88 | "directives": [], 89 | "sourceType": "module", 90 | "type": "Program" 91 | }, 92 | "type": "File" 93 | } 94 | -------------------------------------------------------------------------------- /tests/fixtures/flow/string_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | x: string, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/with_mixed_properties.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "id", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NumberTypeAnnotation" 38 | }, 39 | "variance": null 40 | }, 41 | { 42 | "key": { 43 | "name": "name", 44 | "type": "Identifier" 45 | }, 46 | "kind": "init", 47 | "method": false, 48 | "optional": false, 49 | "static": false, 50 | "type": "ObjectTypeProperty", 51 | "value": { 52 | "type": "NullableTypeAnnotation", 53 | "typeAnnotation": { 54 | "type": "StringTypeAnnotation" 55 | } 56 | }, 57 | "variance": null 58 | }, 59 | { 60 | "key": { 61 | "name": "constructor", 62 | "type": "Identifier" 63 | }, 64 | "kind": "init", 65 | "method": true, 66 | "optional": false, 67 | "static": false, 68 | "type": "ObjectTypeProperty", 69 | "value": { 70 | "params": [ 71 | { 72 | "name": { 73 | "name": "data", 74 | "type": "Identifier" 75 | }, 76 | "optional": false, 77 | "type": "FunctionTypeParam", 78 | "typeAnnotation": { 79 | "type": "NullableTypeAnnotation", 80 | "typeAnnotation": { 81 | "id": { 82 | "name": "Object", 83 | "type": "Identifier" 84 | }, 85 | "type": "GenericTypeAnnotation", 86 | "typeParameters": null 87 | } 88 | } 89 | } 90 | ], 91 | "rest": null, 92 | "returnType": { 93 | "type": "VoidTypeAnnotation" 94 | }, 95 | "type": "FunctionTypeAnnotation", 96 | "typeParameters": null 97 | } 98 | } 99 | ], 100 | "type": "ObjectTypeAnnotation" 101 | }, 102 | "type": "DeclareTypeAlias", 103 | "typeParameters": null 104 | } 105 | ], 106 | "directives": [], 107 | "sourceType": "module", 108 | "type": "Program" 109 | }, 110 | "type": "File" 111 | } 112 | -------------------------------------------------------------------------------- /tests/fixtures/flow/with_mixed_properties.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | id: number, 5 | name: ?string, 6 | 7 | constructor(data: ?Object): void, 8 | }; 9 | -------------------------------------------------------------------------------- /tests/fixtures/flow/with_nested_object.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Nested", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "x", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NullableTypeAnnotation", 38 | "typeAnnotation": { 39 | "type": "StringTypeAnnotation" 40 | } 41 | }, 42 | "variance": null 43 | }, 44 | { 45 | "key": { 46 | "name": "constructor", 47 | "type": "Identifier" 48 | }, 49 | "kind": "init", 50 | "method": true, 51 | "optional": false, 52 | "static": false, 53 | "type": "ObjectTypeProperty", 54 | "value": { 55 | "params": [ 56 | { 57 | "name": { 58 | "name": "data", 59 | "type": "Identifier" 60 | }, 61 | "optional": false, 62 | "type": "FunctionTypeParam", 63 | "typeAnnotation": { 64 | "type": "NullableTypeAnnotation", 65 | "typeAnnotation": { 66 | "id": { 67 | "name": "Object", 68 | "type": "Identifier" 69 | }, 70 | "type": "GenericTypeAnnotation", 71 | "typeParameters": null 72 | } 73 | } 74 | } 75 | ], 76 | "rest": null, 77 | "returnType": { 78 | "type": "VoidTypeAnnotation" 79 | }, 80 | "type": "FunctionTypeAnnotation", 81 | "typeParameters": null 82 | } 83 | } 84 | ], 85 | "type": "ObjectTypeAnnotation" 86 | }, 87 | "type": "DeclareTypeAlias", 88 | "typeParameters": null 89 | }, 90 | { 91 | "id": { 92 | "name": "Test", 93 | "type": "Identifier" 94 | }, 95 | "right": { 96 | "callProperties": [], 97 | "exact": false, 98 | "indexers": [], 99 | "properties": [ 100 | { 101 | "key": { 102 | "name": "nested", 103 | "type": "Identifier" 104 | }, 105 | "kind": "init", 106 | "method": false, 107 | "optional": false, 108 | "static": false, 109 | "type": "ObjectTypeProperty", 110 | "value": { 111 | "type": "NullableTypeAnnotation", 112 | "typeAnnotation": { 113 | "id": { 114 | "name": "Nested", 115 | "type": "Identifier" 116 | }, 117 | "type": "GenericTypeAnnotation", 118 | "typeParameters": null 119 | } 120 | }, 121 | "variance": null 122 | }, 123 | { 124 | "key": { 125 | "name": "constructor", 126 | "type": "Identifier" 127 | }, 128 | "kind": "init", 129 | "method": true, 130 | "optional": false, 131 | "static": false, 132 | "type": "ObjectTypeProperty", 133 | "value": { 134 | "params": [ 135 | { 136 | "name": { 137 | "name": "data", 138 | "type": "Identifier" 139 | }, 140 | "optional": false, 141 | "type": "FunctionTypeParam", 142 | "typeAnnotation": { 143 | "type": "NullableTypeAnnotation", 144 | "typeAnnotation": { 145 | "id": { 146 | "name": "Object", 147 | "type": "Identifier" 148 | }, 149 | "type": "GenericTypeAnnotation", 150 | "typeParameters": null 151 | } 152 | } 153 | } 154 | ], 155 | "rest": null, 156 | "returnType": { 157 | "type": "VoidTypeAnnotation" 158 | }, 159 | "type": "FunctionTypeAnnotation", 160 | "typeParameters": null 161 | } 162 | } 163 | ], 164 | "type": "ObjectTypeAnnotation" 165 | }, 166 | "type": "DeclareTypeAlias", 167 | "typeParameters": null 168 | } 169 | ], 170 | "directives": [], 171 | "sourceType": "module", 172 | "type": "Program" 173 | }, 174 | "type": "File" 175 | } 176 | -------------------------------------------------------------------------------- /tests/fixtures/flow/with_nested_object.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Nested = { 4 | x: ?string, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | 9 | declare type Test = { 10 | nested: ?Nested, 11 | 12 | constructor(data: ?Object): void, 13 | }; 14 | -------------------------------------------------------------------------------- /tests/fixtures/flow/with_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "id", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NullableTypeAnnotation", 38 | "typeAnnotation": { 39 | "type": "NumberTypeAnnotation" 40 | } 41 | }, 42 | "variance": null 43 | }, 44 | { 45 | "key": { 46 | "name": "constructor", 47 | "type": "Identifier" 48 | }, 49 | "kind": "init", 50 | "method": true, 51 | "optional": false, 52 | "static": false, 53 | "type": "ObjectTypeProperty", 54 | "value": { 55 | "params": [ 56 | { 57 | "name": { 58 | "name": "data", 59 | "type": "Identifier" 60 | }, 61 | "optional": false, 62 | "type": "FunctionTypeParam", 63 | "typeAnnotation": { 64 | "type": "NullableTypeAnnotation", 65 | "typeAnnotation": { 66 | "id": { 67 | "name": "Object", 68 | "type": "Identifier" 69 | }, 70 | "type": "GenericTypeAnnotation", 71 | "typeParameters": null 72 | } 73 | } 74 | } 75 | ], 76 | "rest": null, 77 | "returnType": { 78 | "type": "VoidTypeAnnotation" 79 | }, 80 | "type": "FunctionTypeAnnotation", 81 | "typeParameters": null 82 | } 83 | } 84 | ], 85 | "type": "ObjectTypeAnnotation" 86 | }, 87 | "type": "DeclareTypeAlias", 88 | "typeParameters": null 89 | } 90 | ], 91 | "directives": [], 92 | "sourceType": "module", 93 | "type": "Program" 94 | }, 95 | "type": "File" 96 | } 97 | -------------------------------------------------------------------------------- /tests/fixtures/flow/with_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | id: ?number, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/flow/with_required_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "id": { 12 | "name": "Test", 13 | "type": "Identifier" 14 | }, 15 | "leadingComments": [ 16 | { 17 | "type": "CommentLine", 18 | "value": " @flow" 19 | } 20 | ], 21 | "right": { 22 | "callProperties": [], 23 | "exact": false, 24 | "indexers": [], 25 | "properties": [ 26 | { 27 | "key": { 28 | "name": "id", 29 | "type": "Identifier" 30 | }, 31 | "kind": "init", 32 | "method": false, 33 | "optional": false, 34 | "static": false, 35 | "type": "ObjectTypeProperty", 36 | "value": { 37 | "type": "NumberTypeAnnotation" 38 | }, 39 | "variance": null 40 | }, 41 | { 42 | "key": { 43 | "name": "constructor", 44 | "type": "Identifier" 45 | }, 46 | "kind": "init", 47 | "method": true, 48 | "optional": false, 49 | "static": false, 50 | "type": "ObjectTypeProperty", 51 | "value": { 52 | "params": [ 53 | { 54 | "name": { 55 | "name": "data", 56 | "type": "Identifier" 57 | }, 58 | "optional": false, 59 | "type": "FunctionTypeParam", 60 | "typeAnnotation": { 61 | "type": "NullableTypeAnnotation", 62 | "typeAnnotation": { 63 | "id": { 64 | "name": "Object", 65 | "type": "Identifier" 66 | }, 67 | "type": "GenericTypeAnnotation", 68 | "typeParameters": null 69 | } 70 | } 71 | } 72 | ], 73 | "rest": null, 74 | "returnType": { 75 | "type": "VoidTypeAnnotation" 76 | }, 77 | "type": "FunctionTypeAnnotation", 78 | "typeParameters": null 79 | } 80 | } 81 | ], 82 | "type": "ObjectTypeAnnotation" 83 | }, 84 | "type": "DeclareTypeAlias", 85 | "typeParameters": null 86 | } 87 | ], 88 | "directives": [], 89 | "sourceType": "module", 90 | "type": "Program" 91 | }, 92 | "type": "File" 93 | } 94 | -------------------------------------------------------------------------------- /tests/fixtures/flow/with_required_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | declare type Test = { 4 | id: number, 5 | 6 | constructor(data: ?Object): void, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/fixtures/generators/class_not_found_generator.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expobrain/json-schema-codegen/f4c8306a4bc6925607aaff95a5fc68aa01469454/tests/fixtures/generators/class_not_found_generator.py -------------------------------------------------------------------------------- /tests/fixtures/generators/custom_generator.py: -------------------------------------------------------------------------------- 1 | from json_codegen.core import BaseGenerator 2 | 3 | 4 | class CustomGenerator(BaseGenerator): 5 | pass 6 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/additional_properties_with_ref.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Value { 4 | v: ?number; 5 | 6 | constructor(data: Object = {}) { 7 | this.v = data.v; 8 | } 9 | } 10 | 11 | export class Test { 12 | x: { [key: string]: Value }; 13 | 14 | constructor(data: Object = {}) { 15 | this.x = Object.entries(data.x).reduce((acc, entry) => { 16 | const [key: string, value: Object] = (entry: any); 17 | const newValue = new Value(value); 18 | 19 | acc[key] = newValue; 20 | 21 | return acc; 22 | }, {}); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/array_items_ref.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class MyType { 4 | v: ?number; 5 | 6 | constructor(data: Object = {}) { 7 | this.v = data.v; 8 | } 9 | } 10 | 11 | export class Test { 12 | x: Array; 13 | 14 | constructor(data: Object = {}) { 15 | this.x = Array.isArray(data.x) ? data.x.map((v) => MyType(v)) : []; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/array_items_ref_as_alias.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: Array; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = Array.isArray(data.x) ? data.x : []; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/array_items_ref_as_scalar.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: Array; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = Array.isArray(data.x) ? data.x : []; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/array_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: Array; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = Array.isArray(data.x) ? data.x : [42]; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/boolean_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "x", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "NullableTypeAnnotation", 26 | "typeAnnotation": { 27 | "type": "BooleanTypeAnnotation" 28 | } 29 | } 30 | }, 31 | "value": null, 32 | "variance": null 33 | }, 34 | { 35 | "async": false, 36 | "body": { 37 | "body": [ 38 | { 39 | "expression": { 40 | "left": { 41 | "computed": false, 42 | "object": { 43 | "type": "ThisExpression" 44 | }, 45 | "property": { 46 | "name": "x", 47 | "type": "Identifier" 48 | }, 49 | "type": "MemberExpression" 50 | }, 51 | "operator": "=", 52 | "right": { 53 | "computed": false, 54 | "object": { 55 | "name": "data", 56 | "type": "Identifier" 57 | }, 58 | "property": { 59 | "name": "x", 60 | "type": "Identifier" 61 | }, 62 | "type": "MemberExpression" 63 | }, 64 | "type": "AssignmentExpression" 65 | }, 66 | "type": "ExpressionStatement" 67 | } 68 | ], 69 | "directives": [], 70 | "type": "BlockStatement" 71 | }, 72 | "computed": false, 73 | "generator": false, 74 | "id": null, 75 | "key": { 76 | "name": "constructor", 77 | "type": "Identifier" 78 | }, 79 | "kind": "constructor", 80 | "params": [ 81 | { 82 | "left": { 83 | "name": "data", 84 | "type": "Identifier", 85 | "typeAnnotation": { 86 | "type": "TypeAnnotation", 87 | "typeAnnotation": { 88 | "id": { 89 | "name": "Object", 90 | "type": "Identifier" 91 | }, 92 | "type": "GenericTypeAnnotation", 93 | "typeParameters": null 94 | } 95 | } 96 | }, 97 | "right": { 98 | "properties": [], 99 | "type": "ObjectExpression" 100 | }, 101 | "type": "AssignmentPattern" 102 | } 103 | ], 104 | "static": false, 105 | "type": "ClassMethod" 106 | } 107 | ], 108 | "type": "ClassBody" 109 | }, 110 | "id": { 111 | "name": "Test", 112 | "type": "Identifier" 113 | }, 114 | "superClass": null, 115 | "type": "ClassDeclaration" 116 | }, 117 | "exportKind": "value", 118 | "leadingComments": [ 119 | { 120 | "type": "CommentLine", 121 | "value": " @flow" 122 | } 123 | ], 124 | "source": null, 125 | "specifiers": [], 126 | "type": "ExportNamedDeclaration" 127 | } 128 | ], 129 | "directives": [], 130 | "sourceType": "module", 131 | "type": "Program" 132 | }, 133 | "type": "File" 134 | } 135 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/boolean_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: ?boolean; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = data.x; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/boolean_property_default.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "x", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "BooleanTypeAnnotation" 26 | } 27 | }, 28 | "value": null, 29 | "variance": null 30 | }, 31 | { 32 | "async": false, 33 | "body": { 34 | "body": [ 35 | { 36 | "expression": { 37 | "left": { 38 | "computed": false, 39 | "object": { 40 | "type": "ThisExpression" 41 | }, 42 | "property": { 43 | "name": "x", 44 | "type": "Identifier" 45 | }, 46 | "type": "MemberExpression" 47 | }, 48 | "operator": "=", 49 | "right": { 50 | "alternate": { 51 | "type": "BooleanLiteral", 52 | "value": true 53 | }, 54 | "consequent": { 55 | "computed": false, 56 | "object": { 57 | "name": "data", 58 | "type": "Identifier" 59 | }, 60 | "property": { 61 | "name": "x", 62 | "type": "Identifier" 63 | }, 64 | "type": "MemberExpression" 65 | }, 66 | "test": { 67 | "left": { 68 | "argument": { 69 | "computed": false, 70 | "object": { 71 | "name": "data", 72 | "type": "Identifier" 73 | }, 74 | "property": { 75 | "name": "x", 76 | "type": "Identifier" 77 | }, 78 | "type": "MemberExpression" 79 | }, 80 | "extra": { 81 | "parenthesizedArgument": false 82 | }, 83 | "operator": "typeof", 84 | "prefix": true, 85 | "type": "UnaryExpression" 86 | }, 87 | "operator": "===", 88 | "right": { 89 | "extra": { 90 | "raw": "\"boolean\"", 91 | "rawValue": "boolean" 92 | }, 93 | "type": "StringLiteral", 94 | "value": "boolean" 95 | }, 96 | "type": "BinaryExpression" 97 | }, 98 | "type": "ConditionalExpression" 99 | }, 100 | "type": "AssignmentExpression" 101 | }, 102 | "type": "ExpressionStatement" 103 | } 104 | ], 105 | "directives": [], 106 | "type": "BlockStatement" 107 | }, 108 | "computed": false, 109 | "generator": false, 110 | "id": null, 111 | "key": { 112 | "name": "constructor", 113 | "type": "Identifier" 114 | }, 115 | "kind": "constructor", 116 | "params": [ 117 | { 118 | "left": { 119 | "name": "data", 120 | "type": "Identifier", 121 | "typeAnnotation": { 122 | "type": "TypeAnnotation", 123 | "typeAnnotation": { 124 | "id": { 125 | "name": "Object", 126 | "type": "Identifier" 127 | }, 128 | "type": "GenericTypeAnnotation", 129 | "typeParameters": null 130 | } 131 | } 132 | }, 133 | "right": { 134 | "properties": [], 135 | "type": "ObjectExpression" 136 | }, 137 | "type": "AssignmentPattern" 138 | } 139 | ], 140 | "static": false, 141 | "type": "ClassMethod" 142 | } 143 | ], 144 | "type": "ClassBody" 145 | }, 146 | "id": { 147 | "name": "Test", 148 | "type": "Identifier" 149 | }, 150 | "superClass": null, 151 | "type": "ClassDeclaration" 152 | }, 153 | "exportKind": "value", 154 | "leadingComments": [ 155 | { 156 | "type": "CommentLine", 157 | "value": " @flow" 158 | } 159 | ], 160 | "source": null, 161 | "specifiers": [], 162 | "type": "ExportNamedDeclaration" 163 | } 164 | ], 165 | "directives": [], 166 | "sourceType": "module", 167 | "type": "Program" 168 | }, 169 | "type": "File" 170 | } 171 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/boolean_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: boolean; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = typeof data.x === "boolean" ? data.x : true; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/definition_of_primitive_alias.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [], 3 | "program": { 4 | "body": [], 5 | "directives": [], 6 | "sourceType": "module", 7 | "type": "Program" 8 | }, 9 | "type": "File" 10 | } 11 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/definition_of_primitive_alias.template.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expobrain/json-schema-codegen/f4c8306a4bc6925607aaff95a5fc68aa01469454/tests/fixtures/javascript_flow/definition_of_primitive_alias.template.js -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/definition_without_title.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "x", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "NullableTypeAnnotation", 26 | "typeAnnotation": { 27 | "type": "StringTypeAnnotation" 28 | } 29 | } 30 | }, 31 | "value": null, 32 | "variance": null 33 | }, 34 | { 35 | "async": false, 36 | "body": { 37 | "body": [ 38 | { 39 | "expression": { 40 | "left": { 41 | "computed": false, 42 | "object": { 43 | "type": "ThisExpression" 44 | }, 45 | "property": { 46 | "name": "x", 47 | "type": "Identifier" 48 | }, 49 | "type": "MemberExpression" 50 | }, 51 | "operator": "=", 52 | "right": { 53 | "computed": false, 54 | "object": { 55 | "name": "data", 56 | "type": "Identifier" 57 | }, 58 | "property": { 59 | "name": "x", 60 | "type": "Identifier" 61 | }, 62 | "type": "MemberExpression" 63 | }, 64 | "type": "AssignmentExpression" 65 | }, 66 | "type": "ExpressionStatement" 67 | } 68 | ], 69 | "directives": [], 70 | "type": "BlockStatement" 71 | }, 72 | "computed": false, 73 | "generator": false, 74 | "id": null, 75 | "key": { 76 | "name": "constructor", 77 | "type": "Identifier" 78 | }, 79 | "kind": "constructor", 80 | "params": [ 81 | { 82 | "left": { 83 | "name": "data", 84 | "type": "Identifier", 85 | "typeAnnotation": { 86 | "type": "TypeAnnotation", 87 | "typeAnnotation": { 88 | "id": { 89 | "name": "Object", 90 | "type": "Identifier" 91 | }, 92 | "type": "GenericTypeAnnotation", 93 | "typeParameters": null 94 | } 95 | } 96 | }, 97 | "right": { 98 | "properties": [], 99 | "type": "ObjectExpression" 100 | }, 101 | "type": "AssignmentPattern" 102 | } 103 | ], 104 | "static": false, 105 | "type": "ClassMethod" 106 | } 107 | ], 108 | "type": "ClassBody" 109 | }, 110 | "id": { 111 | "name": "NoTitle", 112 | "type": "Identifier" 113 | }, 114 | "superClass": null, 115 | "type": "ClassDeclaration" 116 | }, 117 | "exportKind": "value", 118 | "leadingComments": [ 119 | { 120 | "type": "CommentLine", 121 | "value": " @flow" 122 | } 123 | ], 124 | "source": null, 125 | "specifiers": [], 126 | "type": "ExportNamedDeclaration" 127 | } 128 | ], 129 | "directives": [], 130 | "sourceType": "module", 131 | "type": "Program" 132 | }, 133 | "type": "File" 134 | } 135 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/definition_without_title.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class NoTitle { 4 | x: ?string; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = data.x; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/integer_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "x", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "NullableTypeAnnotation", 26 | "typeAnnotation": { 27 | "type": "NumberTypeAnnotation" 28 | } 29 | } 30 | }, 31 | "value": null, 32 | "variance": null 33 | }, 34 | { 35 | "async": false, 36 | "body": { 37 | "body": [ 38 | { 39 | "expression": { 40 | "left": { 41 | "computed": false, 42 | "object": { 43 | "type": "ThisExpression" 44 | }, 45 | "property": { 46 | "name": "x", 47 | "type": "Identifier" 48 | }, 49 | "type": "MemberExpression" 50 | }, 51 | "operator": "=", 52 | "right": { 53 | "computed": false, 54 | "object": { 55 | "name": "data", 56 | "type": "Identifier" 57 | }, 58 | "property": { 59 | "name": "x", 60 | "type": "Identifier" 61 | }, 62 | "type": "MemberExpression" 63 | }, 64 | "type": "AssignmentExpression" 65 | }, 66 | "type": "ExpressionStatement" 67 | } 68 | ], 69 | "directives": [], 70 | "type": "BlockStatement" 71 | }, 72 | "computed": false, 73 | "generator": false, 74 | "id": null, 75 | "key": { 76 | "name": "constructor", 77 | "type": "Identifier" 78 | }, 79 | "kind": "constructor", 80 | "params": [ 81 | { 82 | "left": { 83 | "name": "data", 84 | "type": "Identifier", 85 | "typeAnnotation": { 86 | "type": "TypeAnnotation", 87 | "typeAnnotation": { 88 | "id": { 89 | "name": "Object", 90 | "type": "Identifier" 91 | }, 92 | "type": "GenericTypeAnnotation", 93 | "typeParameters": null 94 | } 95 | } 96 | }, 97 | "right": { 98 | "properties": [], 99 | "type": "ObjectExpression" 100 | }, 101 | "type": "AssignmentPattern" 102 | } 103 | ], 104 | "static": false, 105 | "type": "ClassMethod" 106 | } 107 | ], 108 | "type": "ClassBody" 109 | }, 110 | "id": { 111 | "name": "Test", 112 | "type": "Identifier" 113 | }, 114 | "superClass": null, 115 | "type": "ClassDeclaration" 116 | }, 117 | "exportKind": "value", 118 | "leadingComments": [ 119 | { 120 | "type": "CommentLine", 121 | "value": " @flow" 122 | } 123 | ], 124 | "source": null, 125 | "specifiers": [], 126 | "type": "ExportNamedDeclaration" 127 | } 128 | ], 129 | "directives": [], 130 | "sourceType": "module", 131 | "type": "Program" 132 | }, 133 | "type": "File" 134 | } 135 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/integer_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: ?number; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = data.x; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/integer_property_default.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "x", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "NumberTypeAnnotation" 26 | } 27 | }, 28 | "value": null, 29 | "variance": null 30 | }, 31 | { 32 | "async": false, 33 | "body": { 34 | "body": [ 35 | { 36 | "expression": { 37 | "left": { 38 | "computed": false, 39 | "object": { 40 | "type": "ThisExpression" 41 | }, 42 | "property": { 43 | "name": "x", 44 | "type": "Identifier" 45 | }, 46 | "type": "MemberExpression" 47 | }, 48 | "operator": "=", 49 | "right": { 50 | "alternate": { 51 | "extra": { 52 | "raw": "42", 53 | "rawValue": 42 54 | }, 55 | "type": "NumericLiteral", 56 | "value": 42 57 | }, 58 | "consequent": { 59 | "computed": false, 60 | "object": { 61 | "name": "data", 62 | "type": "Identifier" 63 | }, 64 | "property": { 65 | "name": "x", 66 | "type": "Identifier" 67 | }, 68 | "type": "MemberExpression" 69 | }, 70 | "test": { 71 | "arguments": [ 72 | { 73 | "computed": false, 74 | "object": { 75 | "name": "data", 76 | "type": "Identifier" 77 | }, 78 | "property": { 79 | "name": "x", 80 | "type": "Identifier" 81 | }, 82 | "type": "MemberExpression" 83 | } 84 | ], 85 | "callee": { 86 | "computed": false, 87 | "object": { 88 | "name": "Number", 89 | "type": "Identifier" 90 | }, 91 | "property": { 92 | "name": "isInteger", 93 | "type": "Identifier" 94 | }, 95 | "type": "MemberExpression" 96 | }, 97 | "type": "CallExpression" 98 | }, 99 | "type": "ConditionalExpression" 100 | }, 101 | "type": "AssignmentExpression" 102 | }, 103 | "type": "ExpressionStatement" 104 | } 105 | ], 106 | "directives": [], 107 | "type": "BlockStatement" 108 | }, 109 | "computed": false, 110 | "generator": false, 111 | "id": null, 112 | "key": { 113 | "name": "constructor", 114 | "type": "Identifier" 115 | }, 116 | "kind": "constructor", 117 | "params": [ 118 | { 119 | "left": { 120 | "name": "data", 121 | "type": "Identifier", 122 | "typeAnnotation": { 123 | "type": "TypeAnnotation", 124 | "typeAnnotation": { 125 | "id": { 126 | "name": "Object", 127 | "type": "Identifier" 128 | }, 129 | "type": "GenericTypeAnnotation", 130 | "typeParameters": null 131 | } 132 | } 133 | }, 134 | "right": { 135 | "properties": [], 136 | "type": "ObjectExpression" 137 | }, 138 | "type": "AssignmentPattern" 139 | } 140 | ], 141 | "static": false, 142 | "type": "ClassMethod" 143 | } 144 | ], 145 | "type": "ClassBody" 146 | }, 147 | "id": { 148 | "name": "Test", 149 | "type": "Identifier" 150 | }, 151 | "superClass": null, 152 | "type": "ClassDeclaration" 153 | }, 154 | "exportKind": "value", 155 | "leadingComments": [ 156 | { 157 | "type": "CommentLine", 158 | "value": " @flow" 159 | } 160 | ], 161 | "source": null, 162 | "specifiers": [], 163 | "type": "ExportNamedDeclaration" 164 | } 165 | ], 166 | "directives": [], 167 | "sourceType": "module", 168 | "type": "Program" 169 | }, 170 | "type": "File" 171 | } 172 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/integer_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: number; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = Number.isInteger(data.x) ? data.x : 42; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/object_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "x", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "NullableTypeAnnotation", 26 | "typeAnnotation": { 27 | "id": { 28 | "name": "Object", 29 | "type": "Identifier" 30 | }, 31 | "type": "GenericTypeAnnotation", 32 | "typeParameters": null 33 | } 34 | } 35 | }, 36 | "value": null, 37 | "variance": null 38 | }, 39 | { 40 | "async": false, 41 | "body": { 42 | "body": [ 43 | { 44 | "expression": { 45 | "left": { 46 | "computed": false, 47 | "object": { 48 | "type": "ThisExpression" 49 | }, 50 | "property": { 51 | "name": "x", 52 | "type": "Identifier" 53 | }, 54 | "type": "MemberExpression" 55 | }, 56 | "operator": "=", 57 | "right": { 58 | "computed": false, 59 | "object": { 60 | "name": "data", 61 | "type": "Identifier" 62 | }, 63 | "property": { 64 | "name": "x", 65 | "type": "Identifier" 66 | }, 67 | "type": "MemberExpression" 68 | }, 69 | "type": "AssignmentExpression" 70 | }, 71 | "type": "ExpressionStatement" 72 | } 73 | ], 74 | "directives": [], 75 | "type": "BlockStatement" 76 | }, 77 | "computed": false, 78 | "generator": false, 79 | "id": null, 80 | "key": { 81 | "name": "constructor", 82 | "type": "Identifier" 83 | }, 84 | "kind": "constructor", 85 | "params": [ 86 | { 87 | "left": { 88 | "name": "data", 89 | "type": "Identifier", 90 | "typeAnnotation": { 91 | "type": "TypeAnnotation", 92 | "typeAnnotation": { 93 | "id": { 94 | "name": "Object", 95 | "type": "Identifier" 96 | }, 97 | "type": "GenericTypeAnnotation", 98 | "typeParameters": null 99 | } 100 | } 101 | }, 102 | "right": { 103 | "properties": [], 104 | "type": "ObjectExpression" 105 | }, 106 | "type": "AssignmentPattern" 107 | } 108 | ], 109 | "static": false, 110 | "type": "ClassMethod" 111 | } 112 | ], 113 | "type": "ClassBody" 114 | }, 115 | "id": { 116 | "name": "Test", 117 | "type": "Identifier" 118 | }, 119 | "superClass": null, 120 | "type": "ClassDeclaration" 121 | }, 122 | "exportKind": "value", 123 | "leadingComments": [ 124 | { 125 | "type": "CommentLine", 126 | "value": " @flow" 127 | } 128 | ], 129 | "source": null, 130 | "specifiers": [], 131 | "type": "ExportNamedDeclaration" 132 | } 133 | ], 134 | "directives": [], 135 | "sourceType": "module", 136 | "type": "Program" 137 | }, 138 | "type": "File" 139 | } 140 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/object_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: ?Object; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = data.x; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/object_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: Object; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = data.x !== null && typeof data.x === "object" ? data.x : { x: 42 }; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/simple.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [], 14 | "type": "ClassBody" 15 | }, 16 | "id": { 17 | "name": "Test", 18 | "type": "Identifier" 19 | }, 20 | "superClass": null, 21 | "type": "ClassDeclaration" 22 | }, 23 | "exportKind": "value", 24 | "leadingComments": [ 25 | { 26 | "type": "CommentLine", 27 | "value": " @flow" 28 | } 29 | ], 30 | "source": null, 31 | "specifiers": [], 32 | "type": "ExportNamedDeclaration" 33 | } 34 | ], 35 | "directives": [], 36 | "sourceType": "module", 37 | "type": "Program" 38 | }, 39 | "type": "File" 40 | } 41 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/simple.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test {} 4 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/string_property_default.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "x", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "StringTypeAnnotation" 26 | } 27 | }, 28 | "value": null, 29 | "variance": null 30 | }, 31 | { 32 | "async": false, 33 | "body": { 34 | "body": [ 35 | { 36 | "expression": { 37 | "left": { 38 | "computed": false, 39 | "object": { 40 | "type": "ThisExpression" 41 | }, 42 | "property": { 43 | "name": "x", 44 | "type": "Identifier" 45 | }, 46 | "type": "MemberExpression" 47 | }, 48 | "operator": "=", 49 | "right": { 50 | "alternate": { 51 | "extra": { 52 | "raw": "\"42\"", 53 | "rawValue": "42" 54 | }, 55 | "type": "StringLiteral", 56 | "value": "42" 57 | }, 58 | "consequent": { 59 | "computed": false, 60 | "object": { 61 | "name": "data", 62 | "type": "Identifier" 63 | }, 64 | "property": { 65 | "name": "x", 66 | "type": "Identifier" 67 | }, 68 | "type": "MemberExpression" 69 | }, 70 | "test": { 71 | "left": { 72 | "argument": { 73 | "computed": false, 74 | "object": { 75 | "name": "data", 76 | "type": "Identifier" 77 | }, 78 | "property": { 79 | "name": "x", 80 | "type": "Identifier" 81 | }, 82 | "type": "MemberExpression" 83 | }, 84 | "extra": { 85 | "parenthesizedArgument": false 86 | }, 87 | "operator": "typeof", 88 | "prefix": true, 89 | "type": "UnaryExpression" 90 | }, 91 | "operator": "===", 92 | "right": { 93 | "extra": { 94 | "raw": "\"string\"", 95 | "rawValue": "string" 96 | }, 97 | "type": "StringLiteral", 98 | "value": "string" 99 | }, 100 | "type": "BinaryExpression" 101 | }, 102 | "type": "ConditionalExpression" 103 | }, 104 | "type": "AssignmentExpression" 105 | }, 106 | "type": "ExpressionStatement" 107 | } 108 | ], 109 | "directives": [], 110 | "type": "BlockStatement" 111 | }, 112 | "computed": false, 113 | "generator": false, 114 | "id": null, 115 | "key": { 116 | "name": "constructor", 117 | "type": "Identifier" 118 | }, 119 | "kind": "constructor", 120 | "params": [ 121 | { 122 | "left": { 123 | "name": "data", 124 | "type": "Identifier", 125 | "typeAnnotation": { 126 | "type": "TypeAnnotation", 127 | "typeAnnotation": { 128 | "id": { 129 | "name": "Object", 130 | "type": "Identifier" 131 | }, 132 | "type": "GenericTypeAnnotation", 133 | "typeParameters": null 134 | } 135 | } 136 | }, 137 | "right": { 138 | "properties": [], 139 | "type": "ObjectExpression" 140 | }, 141 | "type": "AssignmentPattern" 142 | } 143 | ], 144 | "static": false, 145 | "type": "ClassMethod" 146 | } 147 | ], 148 | "type": "ClassBody" 149 | }, 150 | "id": { 151 | "name": "Test", 152 | "type": "Identifier" 153 | }, 154 | "superClass": null, 155 | "type": "ClassDeclaration" 156 | }, 157 | "exportKind": "value", 158 | "leadingComments": [ 159 | { 160 | "type": "CommentLine", 161 | "value": " @flow" 162 | } 163 | ], 164 | "source": null, 165 | "specifiers": [], 166 | "type": "ExportNamedDeclaration" 167 | } 168 | ], 169 | "directives": [], 170 | "sourceType": "module", 171 | "type": "Program" 172 | }, 173 | "type": "File" 174 | } 175 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/string_property_default.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | x: string; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = typeof data.x === "string" ? data.x : "42"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/with_mixed_properties.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "id", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "NumberTypeAnnotation" 26 | } 27 | }, 28 | "value": null, 29 | "variance": null 30 | }, 31 | { 32 | "computed": false, 33 | "key": { 34 | "name": "name", 35 | "type": "Identifier" 36 | }, 37 | "static": false, 38 | "type": "ClassProperty", 39 | "typeAnnotation": { 40 | "type": "TypeAnnotation", 41 | "typeAnnotation": { 42 | "type": "NullableTypeAnnotation", 43 | "typeAnnotation": { 44 | "type": "StringTypeAnnotation" 45 | } 46 | } 47 | }, 48 | "value": null, 49 | "variance": null 50 | }, 51 | { 52 | "async": false, 53 | "body": { 54 | "body": [ 55 | { 56 | "expression": { 57 | "left": { 58 | "computed": false, 59 | "object": { 60 | "type": "ThisExpression" 61 | }, 62 | "property": { 63 | "name": "id", 64 | "type": "Identifier" 65 | }, 66 | "type": "MemberExpression" 67 | }, 68 | "operator": "=", 69 | "right": { 70 | "computed": false, 71 | "object": { 72 | "name": "data", 73 | "type": "Identifier" 74 | }, 75 | "property": { 76 | "name": "id", 77 | "type": "Identifier" 78 | }, 79 | "type": "MemberExpression" 80 | }, 81 | "type": "AssignmentExpression" 82 | }, 83 | "type": "ExpressionStatement" 84 | }, 85 | { 86 | "expression": { 87 | "left": { 88 | "computed": false, 89 | "object": { 90 | "type": "ThisExpression" 91 | }, 92 | "property": { 93 | "name": "name", 94 | "type": "Identifier" 95 | }, 96 | "type": "MemberExpression" 97 | }, 98 | "operator": "=", 99 | "right": { 100 | "computed": false, 101 | "object": { 102 | "name": "data", 103 | "type": "Identifier" 104 | }, 105 | "property": { 106 | "name": "name", 107 | "type": "Identifier" 108 | }, 109 | "type": "MemberExpression" 110 | }, 111 | "type": "AssignmentExpression" 112 | }, 113 | "type": "ExpressionStatement" 114 | } 115 | ], 116 | "directives": [], 117 | "type": "BlockStatement" 118 | }, 119 | "computed": false, 120 | "generator": false, 121 | "id": null, 122 | "key": { 123 | "name": "constructor", 124 | "type": "Identifier" 125 | }, 126 | "kind": "constructor", 127 | "params": [ 128 | { 129 | "left": { 130 | "name": "data", 131 | "type": "Identifier", 132 | "typeAnnotation": { 133 | "type": "TypeAnnotation", 134 | "typeAnnotation": { 135 | "id": { 136 | "name": "Object", 137 | "type": "Identifier" 138 | }, 139 | "type": "GenericTypeAnnotation", 140 | "typeParameters": null 141 | } 142 | } 143 | }, 144 | "right": { 145 | "properties": [], 146 | "type": "ObjectExpression" 147 | }, 148 | "type": "AssignmentPattern" 149 | } 150 | ], 151 | "static": false, 152 | "type": "ClassMethod" 153 | } 154 | ], 155 | "type": "ClassBody" 156 | }, 157 | "id": { 158 | "name": "Test", 159 | "type": "Identifier" 160 | }, 161 | "superClass": null, 162 | "type": "ClassDeclaration" 163 | }, 164 | "exportKind": "value", 165 | "leadingComments": [ 166 | { 167 | "type": "CommentLine", 168 | "value": " @flow" 169 | } 170 | ], 171 | "source": null, 172 | "specifiers": [], 173 | "type": "ExportNamedDeclaration" 174 | } 175 | ], 176 | "directives": [], 177 | "sourceType": "module", 178 | "type": "Program" 179 | }, 180 | "type": "File" 181 | } 182 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/with_mixed_properties.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | id: number; 5 | name: ?string; 6 | 7 | constructor(data: Object = {}) { 8 | this.id = data.id; 9 | this.name = data.name; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/with_nested_object.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Nested { 4 | x: ?string; 5 | 6 | constructor(data: Object = {}) { 7 | this.x = data.x; 8 | } 9 | } 10 | 11 | export class Test { 12 | nested: ?Nested; 13 | 14 | constructor(data: Object = {}) { 15 | this.nested = data.nested ? new Nested(data.nested) : undefined; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/with_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "id", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "NullableTypeAnnotation", 26 | "typeAnnotation": { 27 | "type": "NumberTypeAnnotation" 28 | } 29 | } 30 | }, 31 | "value": null, 32 | "variance": null 33 | }, 34 | { 35 | "async": false, 36 | "body": { 37 | "body": [ 38 | { 39 | "expression": { 40 | "left": { 41 | "computed": false, 42 | "object": { 43 | "type": "ThisExpression" 44 | }, 45 | "property": { 46 | "name": "id", 47 | "type": "Identifier" 48 | }, 49 | "type": "MemberExpression" 50 | }, 51 | "operator": "=", 52 | "right": { 53 | "computed": false, 54 | "object": { 55 | "name": "data", 56 | "type": "Identifier" 57 | }, 58 | "property": { 59 | "name": "id", 60 | "type": "Identifier" 61 | }, 62 | "type": "MemberExpression" 63 | }, 64 | "type": "AssignmentExpression" 65 | }, 66 | "type": "ExpressionStatement" 67 | } 68 | ], 69 | "directives": [], 70 | "type": "BlockStatement" 71 | }, 72 | "computed": false, 73 | "generator": false, 74 | "id": null, 75 | "key": { 76 | "name": "constructor", 77 | "type": "Identifier" 78 | }, 79 | "kind": "constructor", 80 | "params": [ 81 | { 82 | "left": { 83 | "name": "data", 84 | "type": "Identifier", 85 | "typeAnnotation": { 86 | "type": "TypeAnnotation", 87 | "typeAnnotation": { 88 | "id": { 89 | "name": "Object", 90 | "type": "Identifier" 91 | }, 92 | "type": "GenericTypeAnnotation", 93 | "typeParameters": null 94 | } 95 | } 96 | }, 97 | "right": { 98 | "properties": [], 99 | "type": "ObjectExpression" 100 | }, 101 | "type": "AssignmentPattern" 102 | } 103 | ], 104 | "static": false, 105 | "type": "ClassMethod" 106 | } 107 | ], 108 | "type": "ClassBody" 109 | }, 110 | "id": { 111 | "name": "Test", 112 | "type": "Identifier" 113 | }, 114 | "superClass": null, 115 | "type": "ClassDeclaration" 116 | }, 117 | "exportKind": "value", 118 | "leadingComments": [ 119 | { 120 | "type": "CommentLine", 121 | "value": " @flow" 122 | } 123 | ], 124 | "source": null, 125 | "specifiers": [], 126 | "type": "ExportNamedDeclaration" 127 | } 128 | ], 129 | "directives": [], 130 | "sourceType": "module", 131 | "type": "Program" 132 | }, 133 | "type": "File" 134 | } 135 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/with_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | id: ?number; 5 | 6 | constructor(data: Object = {}) { 7 | this.id = data.id; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/with_required_property.ast.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "CommentLine", 5 | "value": " @flow" 6 | } 7 | ], 8 | "program": { 9 | "body": [ 10 | { 11 | "declaration": { 12 | "body": { 13 | "body": [ 14 | { 15 | "computed": false, 16 | "key": { 17 | "name": "id", 18 | "type": "Identifier" 19 | }, 20 | "static": false, 21 | "type": "ClassProperty", 22 | "typeAnnotation": { 23 | "type": "TypeAnnotation", 24 | "typeAnnotation": { 25 | "type": "NumberTypeAnnotation" 26 | } 27 | }, 28 | "value": null, 29 | "variance": null 30 | }, 31 | { 32 | "async": false, 33 | "body": { 34 | "body": [ 35 | { 36 | "expression": { 37 | "left": { 38 | "computed": false, 39 | "object": { 40 | "type": "ThisExpression" 41 | }, 42 | "property": { 43 | "name": "id", 44 | "type": "Identifier" 45 | }, 46 | "type": "MemberExpression" 47 | }, 48 | "operator": "=", 49 | "right": { 50 | "computed": false, 51 | "object": { 52 | "name": "data", 53 | "type": "Identifier" 54 | }, 55 | "property": { 56 | "name": "id", 57 | "type": "Identifier" 58 | }, 59 | "type": "MemberExpression" 60 | }, 61 | "type": "AssignmentExpression" 62 | }, 63 | "type": "ExpressionStatement" 64 | } 65 | ], 66 | "directives": [], 67 | "type": "BlockStatement" 68 | }, 69 | "computed": false, 70 | "generator": false, 71 | "id": null, 72 | "key": { 73 | "name": "constructor", 74 | "type": "Identifier" 75 | }, 76 | "kind": "constructor", 77 | "params": [ 78 | { 79 | "left": { 80 | "name": "data", 81 | "type": "Identifier", 82 | "typeAnnotation": { 83 | "type": "TypeAnnotation", 84 | "typeAnnotation": { 85 | "id": { 86 | "name": "Object", 87 | "type": "Identifier" 88 | }, 89 | "type": "GenericTypeAnnotation", 90 | "typeParameters": null 91 | } 92 | } 93 | }, 94 | "right": { 95 | "properties": [], 96 | "type": "ObjectExpression" 97 | }, 98 | "type": "AssignmentPattern" 99 | } 100 | ], 101 | "static": false, 102 | "type": "ClassMethod" 103 | } 104 | ], 105 | "type": "ClassBody" 106 | }, 107 | "id": { 108 | "name": "Test", 109 | "type": "Identifier" 110 | }, 111 | "superClass": null, 112 | "type": "ClassDeclaration" 113 | }, 114 | "exportKind": "value", 115 | "leadingComments": [ 116 | { 117 | "type": "CommentLine", 118 | "value": " @flow" 119 | } 120 | ], 121 | "source": null, 122 | "specifiers": [], 123 | "type": "ExportNamedDeclaration" 124 | } 125 | ], 126 | "directives": [], 127 | "sourceType": "module", 128 | "type": "Program" 129 | }, 130 | "type": "File" 131 | } 132 | -------------------------------------------------------------------------------- /tests/fixtures/javascript_flow/with_required_property.template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export class Test { 4 | id: number; 5 | 6 | constructor(data: Object = {}) { 7 | this.id = data.id; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/additional_properties_with_ref.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Value: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.v: Optional[int] = data.get("v") 10 | 11 | 12 | class Test: 13 | def __init__(self, data: Optional[Dict] = None): 14 | data = data or {} 15 | 16 | self.x: Dict[str, Value] = { 17 | k: Value(v) for k, v in ({} if data.get("x") is None else data.get("x")).iteritems() 18 | } 19 | -------------------------------------------------------------------------------- /tests/fixtures/python3/array_items_ref.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class MyType: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.v: Optional[float] = data.get("v") 10 | 11 | 12 | class Test: 13 | def __init__(self, data: Optional[Dict] = None): 14 | data = data or {} 15 | 16 | self.x: List[MyType] = [ 17 | MyType(v) for v in ([] if data.get("x") is None else data.get("x")) 18 | ] 19 | -------------------------------------------------------------------------------- /tests/fixtures/python3/array_items_ref_as_alias.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: List[str] = [] if data.get("x") is None else data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/array_items_ref_as_scalar.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: List[str] = [] if data.get("x") is None else data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/array_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: List[Any] = [42] if data.get("x") is None else data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/boolean_property.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: Optional[bool] = data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/boolean_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: bool = True if data.get("x") is None else data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/definition_of_primitive_alias.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | -------------------------------------------------------------------------------- /tests/fixtures/python3/definition_without_title.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class NoTitle: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: Optional[str] = data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/integer_property.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: Optional[int] = data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/integer_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: int = 42 if data.get("x") is None else data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/object_property.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: Optional[Dict] = data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/object_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: Dict = {"x": 42} if data.get("x") is None else data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/simple.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | pass 7 | -------------------------------------------------------------------------------- /tests/fixtures/python3/string_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: str = "42" if data.get("x") is None else data.get("x") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/with_mixed_properties.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.id: int = data["id"] 10 | self.name: Optional[str] = data.get("name") 11 | -------------------------------------------------------------------------------- /tests/fixtures/python3/with_nested_object.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Nested: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.x: Optional[str] = data.get("x") 10 | 11 | 12 | class Test: 13 | def __init__(self, data: Optional[Dict] = None): 14 | data = data or {} 15 | 16 | self.nested: Optional[Nested] = ( 17 | None if data.get("nested") is None else Nested(data.get("nested")) 18 | ) 19 | -------------------------------------------------------------------------------- /tests/fixtures/python3/with_property.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.id: Optional[int] = data.get("id") 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3/with_required_property.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from typing import Dict, Optional, List, Any # noqa: F401 3 | 4 | 5 | class Test: 6 | def __init__(self, data: Optional[Dict] = None): 7 | data = data or {} 8 | 9 | self.id: int = data["id"] 10 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/array_items_ref.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class MyTypeSchema(Schema): 7 | v = fields_.Number() 8 | 9 | 10 | class MyType: 11 | def __init__(self, mytype: dict): 12 | self.v: Optional[float] = mytype.get("v") 13 | 14 | def to_json(self): 15 | return MyTypeSchema(strict=True).dumps(self).data 16 | 17 | def to_dict(self): 18 | return MyTypeSchema(strict=True).dump(self).data 19 | 20 | @staticmethod 21 | def from_json(json: str, only=None): 22 | return MyTypeSchema(strict=True, only=only).loads(json).data 23 | 24 | 25 | class TestSchema(Schema): 26 | x = fields_.List(fields_.Nested(MyTypeSchema), required=True, default=[]) 27 | 28 | @post_load 29 | def make_test(self, test): 30 | return Test(test) 31 | 32 | 33 | class Test: 34 | def __init__(self, test: dict): 35 | self.x: List[MyType] = [MyType(el) for el in test.get("x", {})] 36 | 37 | def to_json(self): 38 | return TestSchema(strict=True).dumps(self).data 39 | 40 | def to_dict(self): 41 | return TestSchema(strict=True).dump(self).data 42 | 43 | @staticmethod 44 | def from_json(json: str, only=None): 45 | return TestSchema(strict=True, only=only).loads(json).data 46 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/array_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | x = fields_.List(fields_.Field(), default=[42]) 8 | 9 | @post_load 10 | def make_test(self, test): 11 | return Test(test) 12 | 13 | 14 | class Test: 15 | def __init__(self, test: dict): 16 | self.x: List[Any] = test.get("x", [42]) 17 | 18 | def to_json(self): 19 | return TestSchema(strict=True).dumps(self).data 20 | 21 | def to_dict(self): 22 | return TestSchema(strict=True).dump(self).data 23 | 24 | @staticmethod 25 | def from_json(json: str, only=None): 26 | return TestSchema(strict=True, only=only).loads(json).data 27 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/boolean_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | x = fields_.Boolean(default=True) 8 | 9 | @post_load 10 | def make_test(self, test): 11 | return Test(test) 12 | 13 | 14 | class Test: 15 | def __init__(self, test: dict): 16 | self.x: bool = test.get("x", True) 17 | 18 | def to_json(self): 19 | return TestSchema(strict=True).dumps(self).data 20 | 21 | def to_dict(self): 22 | return TestSchema(strict=True).dump(self).data 23 | 24 | @staticmethod 25 | def from_json(json: str, only=None): 26 | return TestSchema(strict=True, only=only).loads(json).data 27 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/definition_of_primitive_alias.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/definition_without_title.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class NoTitleSchema(Schema): 7 | x = fields_.String() 8 | 9 | 10 | class NoTitle: 11 | def __init__(self, notitle: dict): 12 | self.x: Optional[str] = notitle.get("x") 13 | 14 | def to_json(self): 15 | return NoTitleSchema(strict=True).dumps(self).data 16 | 17 | def to_dict(self): 18 | return NoTitleSchema(strict=True).dump(self).data 19 | 20 | @staticmethod 21 | def from_json(json: str, only=None): 22 | return NoTitleSchema(strict=True, only=only).loads(json).data 23 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/integer_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | x = fields_.Integer(default=42) 8 | 9 | @post_load 10 | def make_test(self, test): 11 | return Test(test) 12 | 13 | 14 | class Test: 15 | def __init__(self, test: dict): 16 | self.x: int = test.get("x", 42) 17 | 18 | def to_json(self): 19 | return TestSchema(strict=True).dumps(self).data 20 | 21 | def to_dict(self): 22 | return TestSchema(strict=True).dump(self).data 23 | 24 | @staticmethod 25 | def from_json(json: str, only=None): 26 | return TestSchema(strict=True, only=only).loads(json).data 27 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/object_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | x = fields_.Dict(default={"x": 42}) 8 | 9 | @post_load 10 | def make_test(self, test): 11 | return Test(test) 12 | 13 | 14 | class Test: 15 | def __init__(self, test: dict): 16 | self.x: dict = test.get("x", {"x": 42}) 17 | 18 | def to_json(self): 19 | return TestSchema(strict=True).dumps(self).data 20 | 21 | def to_dict(self): 22 | return TestSchema(strict=True).dump(self).data 23 | 24 | @staticmethod 25 | def from_json(json: str, only=None): 26 | return TestSchema(strict=True, only=only).loads(json).data 27 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/simple.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | pass 8 | 9 | @post_load 10 | def make_test(self, test): 11 | return Test(test) 12 | 13 | 14 | class Test: 15 | def __init__(self, test: dict): 16 | pass 17 | 18 | def to_json(self): 19 | return TestSchema(strict=True).dumps(self).data 20 | 21 | def to_dict(self): 22 | return TestSchema(strict=True).dump(self).data 23 | 24 | @staticmethod 25 | def from_json(json: str, only=None): 26 | return TestSchema(strict=True, only=only).loads(json).data 27 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/string_property_default.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | x = fields_.String(default="42") 8 | 9 | @post_load 10 | def make_test(self, test): 11 | return Test(test) 12 | 13 | 14 | class Test: 15 | def __init__(self, test: dict): 16 | self.x: str = test.get("x", "42") 17 | 18 | def to_json(self): 19 | return TestSchema(strict=True).dumps(self).data 20 | 21 | def to_dict(self): 22 | return TestSchema(strict=True).dump(self).data 23 | 24 | @staticmethod 25 | def from_json(json: str, only=None): 26 | return TestSchema(strict=True, only=only).loads(json).data 27 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/with_mixed_properties.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | id = fields_.Integer(required=True) 8 | name = fields_.String() 9 | 10 | @post_load 11 | def make_test(self, test): 12 | return Test(test) 13 | 14 | 15 | class Test: 16 | def __init__(self, test: dict): 17 | self.id: int = test["id"] 18 | self.name: Optional[str] = test.get("name") 19 | 20 | def to_json(self): 21 | return TestSchema(strict=True).dumps(self).data 22 | 23 | def to_dict(self): 24 | return TestSchema(strict=True).dump(self).data 25 | 26 | @staticmethod 27 | def from_json(json: str, only=None): 28 | return TestSchema(strict=True, only=only).loads(json).data 29 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/with_nested_object.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class NestedSchema(Schema): 7 | x = fields_.String() 8 | 9 | 10 | class Nested: 11 | def __init__(self, nested: dict): 12 | self.x: Optional[str] = nested.get("x") 13 | 14 | def to_json(self): 15 | return NestedSchema(strict=True).dumps(self).data 16 | 17 | def to_dict(self): 18 | return NestedSchema(strict=True).dump(self).data 19 | 20 | @staticmethod 21 | def from_json(json: str, only=None): 22 | return NestedSchema(strict=True, only=only).loads(json).data 23 | 24 | 25 | class TestSchema(Schema): 26 | nested = fields_.Dict() 27 | 28 | @post_load 29 | def make_test(self, test): 30 | return Test(test) 31 | 32 | 33 | class Test: 34 | def __init__(self, test: dict): 35 | self.nested: Optional[dict] = test.get("nested") 36 | 37 | def to_json(self): 38 | return TestSchema(strict=True).dumps(self).data 39 | 40 | def to_dict(self): 41 | return TestSchema(strict=True).dump(self).data 42 | 43 | @staticmethod 44 | def from_json(json: str, only=None): 45 | return TestSchema(strict=True, only=only).loads(json).data 46 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/with_property.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | id = fields_.Integer() 8 | 9 | @post_load 10 | def make_test(self, test): 11 | return Test(test) 12 | 13 | 14 | class Test: 15 | def __init__(self, test: dict): 16 | self.id: Optional[int] = test.get("id") 17 | 18 | def to_json(self): 19 | return TestSchema(strict=True).dumps(self).data 20 | 21 | def to_dict(self): 22 | return TestSchema(strict=True).dump(self).data 23 | 24 | @staticmethod 25 | def from_json(json: str, only=None): 26 | return TestSchema(strict=True, only=only).loads(json).data 27 | -------------------------------------------------------------------------------- /tests/fixtures/python3_marshmallow/with_required_property.py: -------------------------------------------------------------------------------- 1 | # isort: skip_file 2 | from marshmallow import Schema, fields as fields_, post_load # noqa: F401 3 | from typing import Optional, List, Any # noqa: F401 4 | 5 | 6 | class TestSchema(Schema): 7 | id = fields_.Integer(required=True) 8 | 9 | @post_load 10 | def make_test(self, test): 11 | return Test(test) 12 | 13 | 14 | class Test: 15 | def __init__(self, test: dict): 16 | self.id: int = test["id"] 17 | 18 | def to_json(self): 19 | return TestSchema(strict=True).dumps(self).data 20 | 21 | def to_dict(self): 22 | return TestSchema(strict=True).dump(self).data 23 | 24 | @staticmethod 25 | def from_json(json: str, only=None): 26 | return TestSchema(strict=True, only=only).loads(json).data 27 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/additional_properties_with_ref.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "definitions": { 4 | "Value": { 5 | "properties": { 6 | "v": { 7 | "type": "integer" 8 | } 9 | }, 10 | "title": "Value", 11 | "type": "object" 12 | } 13 | }, 14 | "properties": { 15 | "x": { 16 | "additionalProperties": { 17 | "$ref": "#/definitions/Value" 18 | }, 19 | "default": {}, 20 | "type": "object" 21 | } 22 | }, 23 | "title": "Test", 24 | "type": "object" 25 | } 26 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/array_items_ref.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "definitions": { 4 | "MyType": { 5 | "properties": { 6 | "v": { 7 | "type": "number" 8 | } 9 | }, 10 | "type": "object" 11 | } 12 | }, 13 | "properties": { 14 | "x": { 15 | "default": [], 16 | "items": { 17 | "oneOf": [ 18 | { 19 | "$ref": "#/definitions/MyType" 20 | } 21 | ], 22 | "type": "object" 23 | }, 24 | "type": "array" 25 | } 26 | }, 27 | "required": [ 28 | "x" 29 | ], 30 | "title": "Test", 31 | "type": "object" 32 | } 33 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/array_items_ref_as_alias.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "definitions": { 4 | "MyType": { 5 | "type": "string" 6 | } 7 | }, 8 | "properties": { 9 | "x": { 10 | "default": [], 11 | "items": { 12 | "oneOf": [ 13 | { 14 | "$ref": "#/definitions/MyType" 15 | } 16 | ], 17 | "type": "object" 18 | }, 19 | "type": "array" 20 | } 21 | }, 22 | "required": [ 23 | "x" 24 | ], 25 | "title": "Test", 26 | "type": "object" 27 | } 28 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/array_items_ref_as_scalar.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "default": [], 6 | "items": { 7 | "type": "string" 8 | }, 9 | "type": "array" 10 | } 11 | }, 12 | "required": [ 13 | "x" 14 | ], 15 | "title": "Test", 16 | "type": "object" 17 | } 18 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/array_property_default.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "default": [ 6 | 42 7 | ], 8 | "type": "array" 9 | } 10 | }, 11 | "title": "Test", 12 | "type": "object" 13 | } 14 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/boolean_property.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "type": "boolean" 6 | } 7 | }, 8 | "title": "Test", 9 | "type": "object" 10 | } 11 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/boolean_property_default.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "default": true, 6 | "type": "boolean" 7 | } 8 | }, 9 | "title": "Test", 10 | "type": "object" 11 | } 12 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/definition_of_primitive_alias.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "definitions": { 4 | "MyNumber": { 5 | "type": "number" 6 | }, 7 | "MyString": { 8 | "type": "string" 9 | }, 10 | "MyUnion": { 11 | "oneOf": [ 12 | { 13 | "type": "string" 14 | }, 15 | { 16 | "type": "boolean" 17 | } 18 | ] 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/definition_without_title.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "definitions": { 4 | "NoTitle": { 5 | "properties": { 6 | "x": { 7 | "type": "string" 8 | } 9 | }, 10 | "type": "object" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/integer_property.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "type": "integer" 6 | } 7 | }, 8 | "title": "Test", 9 | "type": "object" 10 | } 11 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/integer_property_default.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "default": 42, 6 | "type": "integer" 7 | } 8 | }, 9 | "title": "Test", 10 | "type": "object" 11 | } 12 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/object_property.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "type": "object" 6 | } 7 | }, 8 | "title": "Test", 9 | "type": "object" 10 | } 11 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/object_property_default.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "default": { 6 | "x": 42 7 | }, 8 | "type": "object" 9 | } 10 | }, 11 | "title": "Test", 12 | "type": "object" 13 | } 14 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/simple.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "Test", 4 | "type": "object" 5 | } 6 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/string_property_default.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "x": { 5 | "default": "42", 6 | "type": "string" 7 | } 8 | }, 9 | "title": "Test", 10 | "type": "object" 11 | } 12 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/with_mixed_properties.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "id": { 5 | "type": "integer" 6 | }, 7 | "name": { 8 | "type": "string" 9 | } 10 | }, 11 | "required": [ 12 | "id" 13 | ], 14 | "title": "Test", 15 | "type": "object" 16 | } 17 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/with_nested_object.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "definitions": { 4 | "Nested": { 5 | "properties": { 6 | "x": { 7 | "type": "string" 8 | } 9 | }, 10 | "title": "Nested", 11 | "type": "object" 12 | } 13 | }, 14 | "properties": { 15 | "nested": { 16 | "oneOf": [ 17 | { 18 | "$ref": "#/definitions/Nested" 19 | } 20 | ], 21 | "type": "object" 22 | } 23 | }, 24 | "title": "Test" 25 | } 26 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/with_property.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "id": { 5 | "type": "integer" 6 | } 7 | }, 8 | "title": "Test", 9 | "type": "object" 10 | } 11 | -------------------------------------------------------------------------------- /tests/fixtures/schemas/with_required_property.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "properties": { 4 | "id": { 5 | "type": "integer" 6 | } 7 | }, 8 | "required": [ 9 | "id" 10 | ], 11 | "title": "Test", 12 | "type": "object" 13 | } 14 | -------------------------------------------------------------------------------- /tests/generator_flow_test.py: -------------------------------------------------------------------------------- 1 | import ast 2 | import json 3 | from pathlib import Path 4 | 5 | import astor 6 | import pytest 7 | 8 | from json_codegen import load_schema 9 | from json_codegen.generators.flow import FlowGenerator 10 | 11 | SCHEMAS_DIR = Path(__file__).parent / "fixtures" / "schemas" 12 | FIXTURES_DIR = Path(__file__).parent / "fixtures" / "flow" 13 | 14 | expected_init_py = astor.dump_tree(ast.Module(body=[])) 15 | 16 | test_params = sorted(pytest.param(f, id=f.name) for f in SCHEMAS_DIR.glob("*.schema.json")) 17 | 18 | 19 | def load_fixture(name): 20 | filename = FIXTURES_DIR / (name + ".ast.json") 21 | 22 | return astor.parse_file(filename) 23 | 24 | 25 | @pytest.mark.parametrize("schema_filename", (test_params)) 26 | def test_generate(schema_filename): 27 | fixture_filename = FIXTURES_DIR / (schema_filename.name.split(".")[0] + ".ast.json") 28 | 29 | schema = load_schema(schema_filename.read_text()) 30 | 31 | generator = FlowGenerator(schema) 32 | result = generator.generate().as_ast() 33 | 34 | expected = json.loads(fixture_filename.read_text()) 35 | 36 | assert result == expected 37 | -------------------------------------------------------------------------------- /tests/generator_javascript_flow_test.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | 4 | import astor 5 | import pytest 6 | 7 | from json_codegen import load_schema 8 | from json_codegen.generators.javascript_flow import JavaScriptFlowGenerator 9 | 10 | SCHEMAS_DIR = Path(__file__).parent / "fixtures" / "schemas" 11 | FIXTURES_DIR = Path(__file__).parent / "fixtures" / "javascript_flow" 12 | 13 | test_params = sorted(pytest.param(f, id=f.name) for f in SCHEMAS_DIR.glob("*.schema.json")) 14 | 15 | 16 | def load_fixture(name): 17 | filename = FIXTURES_DIR / (name + ".ast.json") 18 | 19 | return astor.parse_file(filename) 20 | 21 | 22 | @pytest.mark.parametrize("schema_filename", (test_params)) 23 | def test_generate(schema_filename): 24 | fixture_filename = FIXTURES_DIR / (schema_filename.name.split(".")[0] + ".ast.json") 25 | 26 | schema = load_schema(schema_filename.read_text()) 27 | 28 | generator = JavaScriptFlowGenerator(schema) 29 | result = generator.generate().as_ast() 30 | 31 | expected = json.loads(fixture_filename.read_text()) 32 | 33 | assert result == expected 34 | -------------------------------------------------------------------------------- /tests/generator_python3_marshmallow_test.py: -------------------------------------------------------------------------------- 1 | import ast 2 | import os 3 | import warnings 4 | from pathlib import Path 5 | 6 | import astor 7 | import pytest 8 | 9 | from json_codegen import load_schema 10 | from json_codegen.generators.python3_marshmallow import Python3MarshmallowGenerator 11 | 12 | SCHEMAS_DIR = Path(__file__).parent / "fixtures" / "schemas" 13 | FIXTURES_DIR = Path(__file__).parent / "fixtures" / "python3_marshmallow" 14 | 15 | expected_init_py = astor.dump_tree(ast.Module(body=[])) 16 | 17 | test_params = sorted(pytest.param(f, id=f.name) for f in SCHEMAS_DIR.glob("*.schema.json")) 18 | 19 | 20 | def load_fixture(name): 21 | filename = FIXTURES_DIR / (name + ".py") 22 | 23 | return astor.parse_file(filename) 24 | 25 | 26 | @pytest.mark.parametrize("schema_filename", (test_params)) 27 | def test_generate(schema_filename): 28 | fixture_filename = FIXTURES_DIR / (schema_filename.name.split(".")[0] + ".py") 29 | 30 | schema = load_schema(schema_filename.read_text()) 31 | 32 | try: 33 | fixture = astor.parse_file(fixture_filename) 34 | except FileNotFoundError: 35 | warnings.warn( 36 | f"Fixture not implemented yet: {os.path.basename(fixture_filename)}", stacklevel=2 37 | ) 38 | return 39 | 40 | generator = Python3MarshmallowGenerator(schema) 41 | result = generator.generate().as_ast() 42 | 43 | result_ast = astor.dump_tree(result) 44 | expected = astor.dump_tree(fixture) 45 | 46 | print(astor.to_source(result)) 47 | 48 | assert result_ast == expected 49 | -------------------------------------------------------------------------------- /tests/generator_python3_test.py: -------------------------------------------------------------------------------- 1 | import ast 2 | from pathlib import Path 3 | 4 | import astor 5 | import pytest 6 | 7 | from json_codegen import load_schema 8 | from json_codegen.generators.python3 import Python3Generator 9 | 10 | SCHEMAS_DIR = Path(__file__).parent / "fixtures" / "schemas" 11 | FIXTURES_DIR = Path(__file__).parent / "fixtures" / "python3" 12 | 13 | expected_init_py = astor.dump_tree(ast.Module(body=[])) 14 | 15 | test_params = sorted(pytest.param(f, id=f.name) for f in SCHEMAS_DIR.glob("*.schema.json")) 16 | 17 | 18 | def load_fixture(name): 19 | filename = FIXTURES_DIR / (name + ".py") 20 | 21 | return astor.parse_file(filename) 22 | 23 | 24 | @pytest.mark.parametrize("schema_filename", (test_params)) 25 | def test_generate(schema_filename): 26 | fixture_filename = FIXTURES_DIR / (schema_filename.name.split(".")[0] + ".py") 27 | 28 | schema = load_schema(schema_filename.read_text()) 29 | fixture = astor.parse_file(fixture_filename) 30 | 31 | generator = Python3Generator(schema) 32 | result = generator.generate().as_ast() 33 | 34 | result_ast = astor.dump_tree(result) 35 | expected = astor.dump_tree(fixture) 36 | 37 | print(astor.to_source(result)) 38 | 39 | assert result_ast == expected 40 | -------------------------------------------------------------------------------- /tests/generators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expobrain/json-schema-codegen/f4c8306a4bc6925607aaff95a5fc68aa01469454/tests/generators/__init__.py -------------------------------------------------------------------------------- /tests/generators/core_test.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import pytest 4 | 5 | from json_codegen.core import ( 6 | BaseGenerator, 7 | GeneratorNotFoundException, 8 | load_external_generator, 9 | ) 10 | 11 | fixture_dir = Path(__file__).parents[1] / "fixtures" / "generators" 12 | 13 | 14 | def test_load_external_generator(): 15 | filename = fixture_dir / "custom_generator.py" 16 | 17 | generator = load_external_generator(filename) 18 | 19 | assert issubclass(generator, BaseGenerator) 20 | 21 | 22 | def test_load_external_generator_class_not_found(): 23 | filename = fixture_dir / "class_not_found_generator.py" 24 | 25 | with pytest.raises(GeneratorNotFoundException): 26 | load_external_generator(filename) 27 | 28 | 29 | def test_load_external_generator_file_not_found(): 30 | filename = fixture_dir / "file_not_found_generator.py" 31 | 32 | with pytest.raises(FileNotFoundError): 33 | load_external_generator(filename) 34 | --------------------------------------------------------------------------------