mirror of
https://github.com/valitydev/thrift.git
synced 2024-11-06 10:25:18 +00:00
commit
85cab54341
33
.github/dependabot.yml
vendored
Normal file
33
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: monthly
|
||||
- package-ecosystem: "gradle"
|
||||
directory: "/lib/java"
|
||||
schedule:
|
||||
interval: monthly
|
||||
- package-ecosystem: "gradle"
|
||||
directory: "/lib/kotlin"
|
||||
schedule:
|
||||
interval: monthly
|
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@ -3,7 +3,7 @@
|
||||
|
||||
<!-- We recommend you review the checklist/tips before submitting a pull request. -->
|
||||
|
||||
- [ ] Did you create an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket? (not required for trivial changes)
|
||||
- [ ] Did you create an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket? ([Request account here](https://selfserve.apache.org/jira-account.html), not required for trivial changes)
|
||||
- [ ] If a ticket exists: Does your pull request title follow the pattern "THRIFT-NNNN: describe my issue"?
|
||||
- [ ] Did you squash your changes to a single commit? (not required, but preferred)
|
||||
- [ ] Did you do your best to avoid breaking changes? If one was needed, did you label the Jira ticket with "Breaking-Change"?
|
||||
|
338
.github/workflows/build.yml
vendored
338
.github/workflows/build.yml
vendored
@ -9,13 +9,42 @@ on:
|
||||
|
||||
env:
|
||||
BUILD_DEPS: automake bison flex git libboost-all-dev libevent-dev libssl-dev libtool make pkg-config
|
||||
CONFIG_ARGS_FOR_LIBS: >
|
||||
--disable-debug
|
||||
--disable-tests
|
||||
--disable-dependency-tracking
|
||||
--without-cpp
|
||||
--without-c_glib
|
||||
--without-java
|
||||
--without-kotlin
|
||||
--without-python
|
||||
--without-py3
|
||||
--without-ruby
|
||||
--without-haxe
|
||||
--without-netstd
|
||||
--without-perl
|
||||
--without-php
|
||||
--without-php_extension
|
||||
--without-dart
|
||||
--without-erlang
|
||||
--without-go
|
||||
--without-d
|
||||
--without-nodejs
|
||||
--without-nodets
|
||||
--without-lua
|
||||
--without-rs
|
||||
--without-swift
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# TODO windows and macos
|
||||
compiler:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-20.04]
|
||||
os: [ubuntu-20.04, ubuntu-22.04]
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@ -49,18 +78,78 @@ jobs:
|
||||
path: compiler/cpp/thrift
|
||||
retention-days: 3
|
||||
|
||||
lib-go:
|
||||
needs: compiler
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
go:
|
||||
- '1.20'
|
||||
- '1.21'
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -yq
|
||||
sudo apt-get install -y --no-install-recommends $BUILD_DEPS
|
||||
|
||||
- name: Run bootstrap
|
||||
run: ./bootstrap.sh
|
||||
|
||||
- name: Run configure
|
||||
run: |
|
||||
./configure $(echo $CONFIG_ARGS_FOR_LIBS | sed 's/without-go/with-go/')
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: thrift-compiler
|
||||
path: compiler/cpp
|
||||
|
||||
- name: Run thrift-compiler
|
||||
run: |
|
||||
chmod a+x compiler/cpp/thrift
|
||||
compiler/cpp/thrift -version
|
||||
|
||||
- name: Run make for go
|
||||
run: make -C lib/go
|
||||
|
||||
- name: Run make check for lib/go
|
||||
run: make -C lib/go check
|
||||
|
||||
- name: Run make check for test/go
|
||||
run: make -C test/go check
|
||||
|
||||
- name: Run make precross for go test
|
||||
run: make -C test/go precross
|
||||
|
||||
- name: Upload go precross artifacts
|
||||
if: matrix.go == '1.21'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: go-precross
|
||||
if-no-files-found: error
|
||||
path: |
|
||||
test/go/bin/*
|
||||
retention-days: 3
|
||||
|
||||
lib-java-kotlin:
|
||||
needs: compiler
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
GRADLE_VERSION: 7.4.2
|
||||
GRADLE_VERSION: "8.0.2"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
cache: "gradle"
|
||||
|
||||
- name: Install dependencies
|
||||
@ -72,7 +161,7 @@ jobs:
|
||||
- name: Setup gradle
|
||||
run: |
|
||||
wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip
|
||||
(echo "29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -)
|
||||
(echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -)
|
||||
unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip
|
||||
sudo mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle
|
||||
sudo ln -s /usr/local/gradle/bin/gradle /usr/local/bin
|
||||
@ -93,31 +182,7 @@ jobs:
|
||||
|
||||
- name: Run configure
|
||||
run: |
|
||||
./configure \
|
||||
--disable-debug \
|
||||
--disable-tests \
|
||||
--disable-dependency-tracking \
|
||||
--without-cpp \
|
||||
--without-c_glib \
|
||||
--with-java \
|
||||
--with-kotlin \
|
||||
--without-python \
|
||||
--without-py3 \
|
||||
--without-ruby \
|
||||
--without-haxe \
|
||||
--without-netstd \
|
||||
--without-perl \
|
||||
--without-php \
|
||||
--without-php_extension \
|
||||
--without-dart \
|
||||
--without-erlang \
|
||||
--without-go \
|
||||
--without-d \
|
||||
--without-nodejs \
|
||||
--without-nodets \
|
||||
--without-lua \
|
||||
--without-rs \
|
||||
--without-swift
|
||||
./configure $(echo $CONFIG_ARGS_FOR_LIBS | sed 's/without-java/with-java/' | sed 's/without-kotlin/with-kotlin/')
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
@ -181,22 +246,198 @@ jobs:
|
||||
lib/kotlin/cross-test-server/build/install/TestServer/
|
||||
retention-days: 3
|
||||
|
||||
cross-test:
|
||||
needs:
|
||||
- lib-java-kotlin
|
||||
lib-swift:
|
||||
needs: compiler
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v3
|
||||
|
||||
- name: Run bootstrap
|
||||
run: ./bootstrap.sh
|
||||
|
||||
- name: Run configure
|
||||
run: |
|
||||
./configure $(echo $CONFIG_ARGS_FOR_LIBS | sed 's/without-swift/with-swift/')
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: thrift-compiler
|
||||
path: compiler/cpp
|
||||
|
||||
- name: Run thrift-compiler
|
||||
run: |
|
||||
chmod a+x compiler/cpp/thrift
|
||||
compiler/cpp/thrift -version
|
||||
|
||||
- name: Run make precross for swift
|
||||
run: make -C test/swift precross
|
||||
|
||||
- name: Upload swift precross artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: swift-precross
|
||||
if-no-files-found: error
|
||||
path: |
|
||||
test/swift/CrossTests/.build/x86_64-unknown-linux-gnu/debug/TestServer
|
||||
test/swift/CrossTests/.build/x86_64-unknown-linux-gnu/debug/TestClient
|
||||
retention-days: 3
|
||||
|
||||
lib-rust:
|
||||
needs: compiler
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
TOOLCHAIN_VERSION: 1.61.0
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -yq
|
||||
sudo apt-get install -y --no-install-recommends curl $BUILD_DEPS
|
||||
|
||||
- name: Setup cargo
|
||||
run: |
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
rustup update
|
||||
rustup install $TOOLCHAIN_VERSION
|
||||
rustup default $TOOLCHAIN_VERSION
|
||||
rustup --version
|
||||
cargo --version
|
||||
rustc --version
|
||||
|
||||
- name: Run bootstrap
|
||||
run: ./bootstrap.sh
|
||||
|
||||
- name: Run configure
|
||||
run: |
|
||||
./configure $(echo $CONFIG_ARGS_FOR_LIBS | sed 's/without-rs/with-rs/')
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: thrift-compiler
|
||||
path: compiler/cpp
|
||||
|
||||
- name: Run thrift-compiler
|
||||
run: |
|
||||
chmod a+x compiler/cpp/thrift
|
||||
compiler/cpp/thrift -version
|
||||
|
||||
- name: Run make for rust
|
||||
run: make -C lib/rs
|
||||
|
||||
- name: Run make check for rust
|
||||
run: make -C lib/rs check
|
||||
|
||||
- name: Run make test for rust
|
||||
run: make -C lib/rs/test check
|
||||
|
||||
- name: Run make precross for test rust
|
||||
run: make -C test/rs precross
|
||||
|
||||
- name: Upload rust precross artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: rs-precross
|
||||
if-no-files-found: error
|
||||
path: |
|
||||
test/rs/bin/test_server
|
||||
test/rs/bin/test_client
|
||||
retention-days: 3
|
||||
|
||||
- name: Run make test_recursive for rust
|
||||
run: make -C lib/rs/test_recursive check
|
||||
|
||||
lib-python:
|
||||
needs: compiler
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.x"
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -yq
|
||||
sudo apt-get install -y --no-install-recommends $BUILD_DEPS
|
||||
sudo apt-get install -y --no-install-recommends curl openssl ca-certificates
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Python setup
|
||||
run: |
|
||||
python -m pip install --upgrade pip setuptools wheel flake8 tornado twisted zope.interface
|
||||
python --version
|
||||
pip --version
|
||||
|
||||
- name: Run bootstrap
|
||||
run: ./bootstrap.sh
|
||||
|
||||
- name: Run configure 3.x
|
||||
if: matrix.python-version == '3.x'
|
||||
run: |
|
||||
./configure $(echo $CONFIG_ARGS_FOR_LIBS | sed 's/without-py3/with-py3/')
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: thrift-compiler
|
||||
path: compiler/cpp
|
||||
|
||||
- name: Run thrift-compiler
|
||||
run: |
|
||||
chmod a+x compiler/cpp/thrift
|
||||
compiler/cpp/thrift -version
|
||||
|
||||
- name: Run make for python
|
||||
run: make -C lib/py
|
||||
|
||||
- name: Run make install for python
|
||||
run: sudo make -C lib/py install
|
||||
|
||||
# - name: Run make install-exec-hook for python
|
||||
# run: sudo make -C lib/py install-exec-hook
|
||||
|
||||
- name: Run make check for python
|
||||
run: make -C lib/py check
|
||||
|
||||
cross-test:
|
||||
needs:
|
||||
- lib-java-kotlin
|
||||
- lib-swift
|
||||
- lib-rust
|
||||
- lib-go
|
||||
- lib-python
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
server_lang: ['java', 'kotlin', 'go', 'rs', 'swift']
|
||||
# we always use comma join as many client langs as possible, to reduce the number of jobs
|
||||
client_lang: ['java,kotlin', 'go,rs', 'swift']
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: temurin
|
||||
# here we intentionally use java 8 so that we also verify java 11 compiles to version 8
|
||||
# here we intentionally use an older version so that we also verify Java 17 compiles to it
|
||||
java-version: 8
|
||||
cache: "gradle"
|
||||
|
||||
- name: Install openssl and certificates (for SSL tests)
|
||||
run: |
|
||||
sudo apt-get update -yq
|
||||
sudo apt-get install -y --no-install-recommends openssl ca-certificates
|
||||
|
||||
- name: Download java precross artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
@ -209,23 +450,43 @@ jobs:
|
||||
name: kotlin-precross
|
||||
path: lib/kotlin
|
||||
|
||||
- name: Download swift precross artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: swift-precross
|
||||
path: test/swift/CrossTests/.build/x86_64-unknown-linux-gnu/debug
|
||||
|
||||
- name: Download rust precross artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: rs-precross
|
||||
path: test/rs/bin
|
||||
|
||||
- name: Download go precross artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: go-precross
|
||||
path: test/go/bin
|
||||
|
||||
- name: Set back executable flags
|
||||
run: |
|
||||
chmod a+x \
|
||||
lib/java/build/run* \
|
||||
lib/kotlin/cross-test-client/build/install/TestClient/bin/* \
|
||||
lib/kotlin/cross-test-server/build/install/TestServer/bin/*
|
||||
lib/kotlin/cross-test-server/build/install/TestServer/bin/* \
|
||||
test/swift/CrossTests/.build/x86_64-unknown-linux-gnu/debug/* \
|
||||
test/rs/bin/* \
|
||||
test/go/bin/*
|
||||
|
||||
- name: Run cross test
|
||||
env:
|
||||
THRIFT_CROSSTEST_CONCURRENCY: 4
|
||||
PRECROSS_LANGS: java,kotlin
|
||||
run: |
|
||||
python test/test.py \
|
||||
--retry-count 5 \
|
||||
--skip-known-failures \
|
||||
--server $PRECROSS_LANGS \
|
||||
--client $PRECROSS_LANGS
|
||||
--server ${{ matrix.server_lang }} \
|
||||
--client ${{ matrix.client_lang }}
|
||||
|
||||
- name: Upload log files from failed cross test runs
|
||||
uses: actions/upload-artifact@v3
|
||||
@ -234,3 +495,4 @@ jobs:
|
||||
name: cross-test-log
|
||||
path: test/log/
|
||||
retention-days: 3
|
||||
|
||||
|
3
.github/workflows/cmake.yml
vendored
3
.github/workflows/cmake.yml
vendored
@ -9,6 +9,9 @@ on:
|
||||
env:
|
||||
BUILD_DEPS: bison flex g++ libboost-all-dev libevent-dev libssl-dev make cmake
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
compiler:
|
||||
runs-on: ubuntu-20.04
|
||||
|
22
.gitignore
vendored
22
.gitignore
vendored
@ -49,6 +49,7 @@ test-driver
|
||||
erl_crash.dump
|
||||
project.lock.json
|
||||
|
||||
.Dockerfile.sha512
|
||||
.sonar
|
||||
.DS_Store
|
||||
.svn
|
||||
@ -201,9 +202,9 @@ project.lock.json
|
||||
/lib/delphi/*.local
|
||||
/lib/delphi/*.identcache
|
||||
/lib/delphi/test/skip/bin
|
||||
/lib/delphi/test/serializer/*.dat
|
||||
/lib/delphi/test/serializer/**/*.dat
|
||||
/lib/delphi/test/serializer/bin
|
||||
/lib/delphi/test/thrift-testing
|
||||
/lib/delphi/test/thrift-testing/*.thrift
|
||||
/lib/delphi/**/*.identcache
|
||||
/lib/delphi/**/*.local
|
||||
/lib/delphi/**/*.dcu
|
||||
@ -224,6 +225,9 @@ project.lock.json
|
||||
/lib/haxe/test/data.tmp
|
||||
/lib/hs/dist
|
||||
/lib/java/.gradle
|
||||
/lib/java/gradle/wrapper
|
||||
/lib/java/gradlew
|
||||
/lib/java/gradlew.bat
|
||||
/lib/java/android/.gradle
|
||||
/lib/java/build
|
||||
/lib/java/out
|
||||
@ -285,7 +289,7 @@ project.lock.json
|
||||
/lib/go/src
|
||||
/lib/go/test/fuzz/gopathfuzz
|
||||
/lib/go/test/gopath/
|
||||
/lib/go/test/ThriftTest.thrift
|
||||
/lib/go/test/ThriftTest*.thrift
|
||||
/lib/nodets/test-compiled/
|
||||
/lib/ocaml/_build/
|
||||
/lib/ocaml/_tags
|
||||
@ -355,7 +359,7 @@ project.lock.json
|
||||
/test/erl/_build/
|
||||
/test/erl/rebar.lock
|
||||
/test/go/bin/
|
||||
/test/go/ThriftTest.thrift
|
||||
/test/go/ThriftTest*.thrift
|
||||
/test/go/gopath
|
||||
/test/go/pkg/
|
||||
/test/go/src/code.google.com/
|
||||
@ -388,6 +392,7 @@ project.lock.json
|
||||
/test/rs/target/
|
||||
/test/rs/*.iml
|
||||
/test/rs/**/*.iml
|
||||
/test/swift/CrossTests/.build
|
||||
/lib/cl/backport-update.zip
|
||||
/lib/cl/lib
|
||||
/tutorial/cl/quicklisp.lisp
|
||||
@ -441,3 +446,12 @@ project.lock.json
|
||||
/tutorial/netstd/Server/Properties/launchSettings.json
|
||||
/tutorial/netstd/Client/Properties/launchSettings.json
|
||||
/ylwrap
|
||||
|
||||
# Unit test generated artifacts
|
||||
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
compiler/cpp/tests/*.cmake
|
||||
compiler/cpp/tests/Testing/
|
||||
compiler/cpp/tests/bin/
|
||||
compiler/cpp/tests/*.a
|
||||
|
32
.travis.yml
32
.travis.yml
@ -17,7 +17,7 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
# build Apache Thrift on Travis CI - https://travis-ci.org/
|
||||
# build Apache Thrift on Travis CI - https://travis-ci.com/
|
||||
|
||||
#
|
||||
# Docker Integration
|
||||
@ -26,7 +26,7 @@
|
||||
|
||||
sudo: required
|
||||
# https://docs.travis-ci.com/user/reference/linux
|
||||
dist: xenial
|
||||
dist: focal
|
||||
language: cpp
|
||||
|
||||
services:
|
||||
@ -61,13 +61,18 @@ jobs:
|
||||
- stage: docker
|
||||
script: true
|
||||
env:
|
||||
- JOB="Docker Build ubuntu-xenial 16.04 LTS"
|
||||
- DISTRO=ubuntu-xenial
|
||||
- JOB="Docker Build ubuntu-bionic 18.04 LTS"
|
||||
- DISTRO=ubuntu-bionic
|
||||
- TRAVIS_BUILD_STAGE=docker
|
||||
- script: true
|
||||
env:
|
||||
- JOB="Docker Build ubuntu-bionic 18.04 LTS"
|
||||
- DISTRO=ubuntu-bionic
|
||||
- JOB="Docker Build ubuntu-focal 20.04 LTS"
|
||||
- DISTRO=ubuntu-focal
|
||||
- TRAVIS_BUILD_STAGE=docker
|
||||
- script: true
|
||||
env:
|
||||
- JOB="Docker Build ubuntu-jammy 22.04 LTS"
|
||||
- DISTRO=ubuntu-jammy
|
||||
- TRAVIS_BUILD_STAGE=docker
|
||||
|
||||
# ========================= stage: thrift =======================
|
||||
@ -112,15 +117,24 @@ jobs:
|
||||
|
||||
# ------------------------- phase: autotools --------------------
|
||||
# TODO: Remove them once migrated to CMake
|
||||
|
||||
# TODO fix the missing python2 deps or get rid of python2
|
||||
# - script: build/docker/run.sh
|
||||
# env:
|
||||
# - JOB="Autotools (Ubuntu Jammy)"
|
||||
# - DISTRO=ubuntu-jammy
|
||||
# - SCRIPT="autotools.sh"
|
||||
|
||||
- script: build/docker/run.sh
|
||||
env:
|
||||
- JOB="Autotools (Ubuntu Bionic)"
|
||||
- JOB="Autotools (Ubuntu Focal)"
|
||||
- DISTRO=ubuntu-focal
|
||||
- SCRIPT="autotools.sh"
|
||||
|
||||
- script: build/docker/run.sh
|
||||
env:
|
||||
- JOB="Autotools (Ubuntu Xenial)"
|
||||
- DISTRO=ubuntu-xenial
|
||||
- JOB="Autotools (Ubuntu Bionic)"
|
||||
- DISTRO=ubuntu-bionic
|
||||
- SCRIPT="autotools.sh"
|
||||
|
||||
# ------------------------- phase: cmake ------------------------
|
||||
|
@ -19,14 +19,14 @@
|
||||
the "Thrift" project.
|
||||
2. nuget setApiKey <your-api-key>
|
||||
3. nuget pack ApacheThrift.nuspec -Symbols -SymbolPackageFormat snupkg
|
||||
4. nuget push ApacheThrift.0.17.0.nupkg -Source https://api.nuget.org/v3/index.json
|
||||
4. nuget push ApacheThrift.0.19.0.nupkg -Source https://api.nuget.org/v3/index.json
|
||||
-->
|
||||
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>ApacheThrift</id>
|
||||
<version>0.17.0</version>
|
||||
<title>Apache Thrift 0.17.0</title>
|
||||
<version>0.19.0</version>
|
||||
<title>Apache Thrift 0.19.0</title>
|
||||
<authors>Apache Thrift Developers</authors>
|
||||
<owners>Apache Software Foundation</owners>
|
||||
<license type="expression">Apache-2.0</license>
|
||||
@ -36,7 +36,7 @@
|
||||
<description>
|
||||
Contains runtime libraries from lib/netstd for netstandard2.0 framework development.
|
||||
</description>
|
||||
<repository type="GitHub" url="https://github.com/apache/thrift" branch="release/0.17.0" />
|
||||
<repository type="GitHub" url="https://github.com/apache/thrift" branch="release/0.19.0" />
|
||||
<tags>Apache Thrift RPC</tags>
|
||||
</metadata>
|
||||
<files>
|
||||
|
179
CHANGES.md
179
CHANGES.md
@ -1,5 +1,184 @@
|
||||
# Apache Thrift Changelog
|
||||
|
||||
## 0.19.0
|
||||
|
||||
### Known Open Issues (Blocker or Critical)
|
||||
|
||||
- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++ library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
|
||||
- [THRIFT-5468](https://issues.apache.org/jira/browse/THRIFT-5468) - Swift service generator doesn't support oneway
|
||||
- [THRIFT-5654](https://issues.apache.org/jira/browse/THRIFT-5654) - LNK4042 and LNK2019 in go_validator_generator.cc
|
||||
|
||||
## Build Process
|
||||
|
||||
- [THRIFT-5701](https://issues.apache.org/jira/browse/THRIFT-5701) - Add dependabot
|
||||
|
||||
## C++
|
||||
|
||||
- [THRIFT-5725](https://issues.apache.org/jira/browse/THRIFT-5725) - Thrift SSL server stops working if the file descriptor returned is zero
|
||||
- [THRIFT-5716](https://issues.apache.org/jira/browse/THRIFT-5716) - TMemoryBuffer resizing might shrink the buffer size due to uint32_t overflow
|
||||
|
||||
## Compiler (General)
|
||||
|
||||
- [THRIFT-5690](https://issues.apache.org/jira/browse/THRIFT-5690) - Constant expects type to be defined before
|
||||
|
||||
## Delphi
|
||||
|
||||
- [THRIFT-5686](https://issues.apache.org/jira/browse/THRIFT-5686) - Add comparer and capacity arguments to container classes
|
||||
|
||||
## Go
|
||||
- [THRIFT-5731](https://issues.apache.org/jira/browse/THRIFT-5731) - Handle ErrAbandonRequest automatically
|
||||
|
||||
|
||||
## Haxe
|
||||
|
||||
- [THRIFT-5717](https://issues.apache.org/jira/browse/THRIFT-5717) - uuid sets and map keys may throw on some Haxe targets
|
||||
- [THRIFT-5704](https://issues.apache.org/jira/browse/THRIFT-5704) - Superfluous block scope in generated write() code
|
||||
- [THRIFT-5703](https://issues.apache.org/jira/browse/THRIFT-5703) - Haxe 4.30 emits "Local variable retval used without being initialized" on generated code
|
||||
- [THRIFT-5692](https://issues.apache.org/jira/browse/THRIFT-5692) - Support for deprecated methods (via annotation)
|
||||
- [THRIFT-5707](https://issues.apache.org/jira/browse/THRIFT-5707) - deprecation warning fixes for @:extern and @:enum
|
||||
|
||||
## Java
|
||||
|
||||
- [THRIFT-5700](https://issues.apache.org/jira/browse/THRIFT-5700) - Migration to JakartaEE and Apache HttpComponents 5
|
||||
- [THRIFT-5711](https://issues.apache.org/jira/browse/THRIFT-5711) - FutureClient does not extend when service extends from another service
|
||||
- [THRIFT-5702](https://issues.apache.org/jira/browse/THRIFT-5702) - Support Java 8
|
||||
- [THRIFT-5696](https://issues.apache.org/jira/browse/THRIFT-5696) - TByteBuffer.java does not allow non-default TConfiguration
|
||||
- [THRIFT-5653](https://issues.apache.org/jira/browse/THRIFT-5653) - Fix Java UUID typeid
|
||||
|
||||
|
||||
## JavaScript
|
||||
|
||||
- [THRIFT-5674](https://issues.apache.org/jira/browse/THRIFT-5674) - Server implementation exceptions are not sent to client in ES6 promise-style invocation
|
||||
|
||||
## netstd
|
||||
|
||||
- [THRIFT-5684](https://issues.apache.org/jira/browse/THRIFT-5684) - Upgrade to net7.0
|
||||
|
||||
## Node.js
|
||||
|
||||
- [THRIFT-5710](https://issues.apache.org/jira/browse/THRIFT-5710) - NodeJS header transport leaks headers between all instances
|
||||
|
||||
## PHP
|
||||
|
||||
- [THRIFT-5723](https://issues.apache.org/jira/browse/THRIFT-5723) - Php8.1 fix warnings
|
||||
|
||||
## Swift
|
||||
|
||||
- [THRIFT-5714](https://issues.apache.org/jira/browse/THRIFT-5714) - add TJSONProtocol support in thrift-swift
|
||||
|
||||
|
||||
## 0.18.1
|
||||
|
||||
### Known Open Issues (Blocker or Critical)
|
||||
|
||||
- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++ library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
|
||||
- [THRIFT-5468](https://issues.apache.org/jira/browse/THRIFT-5468) - Swift service generator doesn't support oneway
|
||||
|
||||
### Reopened issues
|
||||
|
||||
- [THRIFT-5601](https://issues.apache.org/jira/browse/THRIFT-5601) - Typedef after first use causes incorrect go code
|
||||
|
||||
### Go
|
||||
|
||||
- [THRIFT-5685](https://issues.apache.org/jira/browse/THRIFT-5685) - Compiler generates wrong go code for forward defined types in optional fields
|
||||
- [THRIFT-5679](https://issues.apache.org/jira/browse/THRIFT-5679) - libthrift-0.17.0 has wrong version numbers in MANIFEST.MF
|
||||
|
||||
|
||||
|
||||
## 0.18.0
|
||||
|
||||
### Known Open Issues (Blocker or Critical)
|
||||
|
||||
- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++ library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
|
||||
- [THRIFT-5468](https://issues.apache.org/jira/browse/THRIFT-5468) - Swift service generator doesn't support oneway
|
||||
|
||||
### Compiler (General)
|
||||
|
||||
- [THRIFT-5587](https://issues.apache.org/jira/browse/THRIFT-5587) - Introduce uuid as additional builtin type
|
||||
- [THRIFT-5591](https://issues.apache.org/jira/browse/THRIFT-5591) - Add uuid type to IDL and implement reference code
|
||||
- [THRIFT-5626](https://issues.apache.org/jira/browse/THRIFT-5626) - Parser should not confuse data types and field names
|
||||
- [THRIFT-5627](https://issues.apache.org/jira/browse/THRIFT-5627) - More consistent syntax for cpp_type
|
||||
- [THRIFT-5652](https://issues.apache.org/jira/browse/THRIFT-5652) - IDL uuid literals can be improved
|
||||
- [THRIFT-5669](https://issues.apache.org/jira/browse/THRIFT-5669) - "required" keyword is illegal in a "throws" clause
|
||||
|
||||
### C++
|
||||
|
||||
- [THRIFT-5661](https://issues.apache.org/jira/browse/THRIFT-5661) - TOutput: add zephyr-specific strerror_s implementation
|
||||
- [THRIFT-5658](https://issues.apache.org/jira/browse/THRIFT-5658) - TProtocol: support zephyr byteorder
|
||||
- [THRIFT-5659](https://issues.apache.org/jira/browse/THRIFT-5659) - protocol: declare when methods override
|
||||
|
||||
### D language
|
||||
|
||||
- [THRIFT-5647](https://issues.apache.org/jira/browse/THRIFT-5647) - Fix undeclared identifier ECONNRESET on macOS
|
||||
|
||||
### Delphi
|
||||
|
||||
- [THRIFT-5618](https://issues.apache.org/jira/browse/THRIFT-5618) - More consistent naming of container classes
|
||||
- [THRIFT-5620](https://issues.apache.org/jira/browse/THRIFT-5620) - Option to force usage of COM types to allow for cross-module references
|
||||
- [THRIFT-5656](https://issues.apache.org/jira/browse/THRIFT-5656) - Escape Delphi keywords with '&' prefix instead of '_' suffix
|
||||
- [THRIFT-5619](https://issues.apache.org/jira/browse/THRIFT-5619) - make sure CheckReadBytesAvailable() and CountConsumedMessageBytes() handle negative sizes properly
|
||||
- [THRIFT-5622](https://issues.apache.org/jira/browse/THRIFT-5622) - Garbled test output with multithreaded clients
|
||||
- [THRIFT-5625](https://issues.apache.org/jira/browse/THRIFT-5625) - SysUtils.TGuidHelper collides with ThriftUtils.TGuidHelper
|
||||
|
||||
### Erlang
|
||||
|
||||
- [THRIFT-5636](https://issues.apache.org/jira/browse/THRIFT-5636) - Broken client in erlang client library
|
||||
|
||||
### Go
|
||||
|
||||
- [THRIFT-5601](https://issues.apache.org/jira/browse/THRIFT-5601) - Typedef after first use causes incorrect go code
|
||||
- [THRIFT-5650](https://issues.apache.org/jira/browse/THRIFT-5650) - Add UUID support in go
|
||||
|
||||
### Haxe
|
||||
|
||||
- [THRIFT-5593](https://issues.apache.org/jira/browse/THRIFT-5593) - Implement uuid for hx
|
||||
|
||||
### Java
|
||||
- [THRIFT-3956](https://issues.apache.org/jira/browse/THRIFT-3956) - Java keywords that are legal in IDL can lead to generated code that will not compile
|
||||
- [THRIFT-4655](https://issues.apache.org/jira/browse/THRIFT-4655) - Parser fails on the word "from"
|
||||
- [THRIFT-5631](https://issues.apache.org/jira/browse/THRIFT-5631) - Execution failed for task ':generateBeanJava'.
|
||||
- [THRIFT-5632](https://issues.apache.org/jira/browse/THRIFT-5632) - Fix java lib pmd main offending errors
|
||||
|
||||
### Kotlin
|
||||
|
||||
- [THRIFT-5646](https://issues.apache.org/jira/browse/THRIFT-5646) - Kotlin library should check to see if Gradle is present
|
||||
|
||||
### netstd
|
||||
|
||||
- [THRIFT-5610](https://issues.apache.org/jira/browse/THRIFT-5610) - Inconsistent constructors TSocketTransport
|
||||
- [THRIFT-5623](https://issues.apache.org/jira/browse/THRIFT-5623) - ref to disposed instance should be set to null
|
||||
- [THRIFT-5624](https://issues.apache.org/jira/browse/THRIFT-5624) - suboptimal performance of the c# named pipe server transport in multithread servers
|
||||
- [THRIFT-5628](https://issues.apache.org/jira/browse/THRIFT-5628) - MaxMessageSize is never reset on a read buffer
|
||||
- [THRIFT-5639](https://issues.apache.org/jira/browse/THRIFT-5639) - ToString() should use InvariantCulture
|
||||
|
||||
### OCaml
|
||||
|
||||
- [THRIFT-5208](https://issues.apache.org/jira/browse/THRIFT-5208) - OCaml codegen exception pattern match syntax error
|
||||
- [THRIFT-5642](https://issues.apache.org/jira/browse/THRIFT-5642) - OCaml in docker build environment is broken
|
||||
|
||||
### Python
|
||||
|
||||
- [THRIFT-5617](https://issues.apache.org/jira/browse/THRIFT-5617) - T(SSL)Socket TCP keep-alive incorrectly applies SO_KEEPALIVE to IPPROTO_TCP
|
||||
|
||||
### Rust
|
||||
|
||||
- [THRIFT-5124](https://issues.apache.org/jira/browse/THRIFT-5124) - Cannot use reserved language keyword
|
||||
- [THRIFT-5606](https://issues.apache.org/jira/browse/THRIFT-5606) - Wrong indent for const double
|
||||
- [THRIFT-5600](https://issues.apache.org/jira/browse/THRIFT-5600) - Upgrade rust toolchain to 1.61 and edition 2021
|
||||
- [THRIFT-5643](https://issues.apache.org/jira/browse/THRIFT-5643) - Please publish latest version of the Rust lib to crates.io
|
||||
|
||||
### Swift
|
||||
|
||||
- [THRIFT-5629](https://issues.apache.org/jira/browse/THRIFT-5629) - Add UUID support for Swift
|
||||
- [THRIFT-4547](https://issues.apache.org/jira/browse/THRIFT-4547) - Finish the conversion to native swift (LANGUAGES.md, cross test)
|
||||
- [THRIFT-5621](https://issues.apache.org/jira/browse/THRIFT-5621) - Create Swift Tutorial
|
||||
- [THRIFT-5630](https://issues.apache.org/jira/browse/THRIFT-5630) - Swift TSocketServer not working on Linux
|
||||
|
||||
### Website
|
||||
|
||||
- [THRIFT-5634](https://issues.apache.org/jira/browse/THRIFT-5634) - thrift docs picture was broken
|
||||
|
||||
|
||||
## 0.17.0
|
||||
|
||||
### Known Open Issues (Blocker or Critical)
|
||||
|
@ -28,7 +28,7 @@ endif()
|
||||
|
||||
# PACKAGE_VERSION is used by cpack scripts currently
|
||||
# Both thrift_VERSION and PACKAGE_VERSION should be the same for now
|
||||
set(thrift_VERSION "0.17.0")
|
||||
set(thrift_VERSION "0.19.0")
|
||||
set(PACKAGE_VERSION ${thrift_VERSION})
|
||||
|
||||
project("thrift" VERSION ${PACKAGE_VERSION})
|
||||
|
302
LANGUAGES.md
302
LANGUAGES.md
@ -66,289 +66,289 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/c_glib/README.md">C (glib)</a></td>
|
||||
<!-- Since -----------------><td>0.6.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Language Levels -------><td>2.48.2</td><td>2.56.4</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22C%20glib%20-%20Compiler%22%2C%20%22C%20glib%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">C (glib)</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/cpp/README.md">C++</a></td>
|
||||
<!-- Since -----------------><td>0.2.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Language Levels -------><td colspan=2>C++11</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22C%2B%2B%20-%20Compiler%22%2C%20%22C%2B%2B%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">C++</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/cl/README.md">Common LISP</a></td>
|
||||
<!-- Since -----------------><td>0.12.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>SBCL 1.4.x</td><td>SBCL 1.5.3</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Common%20LISP%20-%20Compiler%22%2C%20%22Common%20LISP%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Common LISP</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/d/README.md">Dlang</a></td>
|
||||
<!-- Since -----------------><td>0.9.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>2.087.0</td><td>2.087.0</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22D%20-%20Compiler%22%2C%20%22D%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">D</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/dart/README.md">Dart</a></td>
|
||||
<!-- Since -----------------><td>0.10.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>2.0.0</td><td>2.4.0</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Dart%20-%20Compiler%22%2C%20%22Dart%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Dart</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/delphi/README.md">Delphi</a></td>
|
||||
<!-- Since -----------------><td>0.8.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>2010</td><td>Sydney 10.4.1</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cgrn.png" alt="Yes"/><td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>2010</td><td>Alexandria 11.2</td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Delphi%20-%20Compiler%22%2C%20%22Delphi%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Delphi</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/netstd/README.md">.NET Standard</a></td>
|
||||
<!-- Since -----------------><td>0.13.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td colspan=2>.NET 4.5+, .NET Standard 2.x, .NET 5.0</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cgrn.png" alt="Yes"/><td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td colspan=2>.NET Standard 2.x, .NET 6</td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22netstd%20-%20Compiler%22%2C%20%22netstd%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">.NET Standard</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/erl/README.md">Erlang</a></td>
|
||||
<!-- Since -----------------><td>0.3.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>18.3</td><td>22.0</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Erlang%20-%20Compiler%22%2C%20%22Erlang%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Erlang</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/go/README.md">Go</a></td>
|
||||
<!-- Since -----------------><td>0.7.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>1.18.5</td><td>1.19</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>1.20</td><td>1.21</td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Go%20-%20Compiler%22%2C%20%22Go%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Go</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/haxe/README.md">Haxe</a></td>
|
||||
<!-- Since -----------------><td>0.9.3</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>4.1.5</td><td>4.2.1</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>4.1.5</td><td>4.2.5</td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Haxe%20-%20Compiler%22%2C%20%22Haxe%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Haxe</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/java/README.md">Java (SE)</a></td>
|
||||
<!-- Since -----------------><td>0.2.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Language Levels -------><td>1.8.0_151</td><td>11.0.3</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Language Levels -------><td>11</td><td>19</td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Java%20-%20Compiler%22%2C%20%22Java%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Java SE</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/javame/README.md">Java (ME)</a></td>
|
||||
<!-- Since -----------------><td>0.5.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td colspan=2>unknown</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22JavaME%20-%20Compiler%22%2C%20%22JavaME%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Java ME</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/js/README.md">Javascript</a></td>
|
||||
<!-- Since -----------------><td>0.3.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>ES5</td><td>ES6</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Javascript%20-%20Compiler%22%2C%20%22Javascript%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Javascript</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/lua/README.md">Lua</a></td>
|
||||
<!-- Since -----------------><td>0.9.2</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>5.1.5</td><td>5.2.4</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Lua%20-%20Compiler%22%2C%20%22Lua%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Lua</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/nodejs/README.md">node.js</a></td>
|
||||
<!-- Since -----------------><td>0.6.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>10.x</td><td>10.x</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Node.js%20-%20Compiler%22%2C%20%22Node.js%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">node.js</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/nodets/README.md">node.ts</a></td>
|
||||
<!-- Since -----------------><td>0.12.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>3.1.6</td><td></td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22TypeScript%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">node.ts</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/ocaml/README.md">OCaml</a></td>
|
||||
<!-- Since -----------------><td>0.2.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td colspan=2>4.04.0</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22OCaml%20-%20Compiler%22%2C%20%22OCaml%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">OCaml</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/perl/README.md">Perl</a></td>
|
||||
<!-- Since -----------------><td>0.2.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>5.22.1</td><td>5.26.1</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Perl%20-%20Compiler%22%2C%20%22Perl%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Perl</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/php/README.md">PHP</a></td>
|
||||
<!-- Since -----------------><td>0.2.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>7.0.22</td><td>7.2.19</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22PHP%20-%20Compiler%22%2C%20%22PHP%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">PHP</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/py/README.md">Python</a></td>
|
||||
<!-- Since -----------------><td>0.2.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Language Levels -------><td>2.7.12, 3.5.2</td><td>2.7.15, 3.6.8</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Python%20-%20Compiler%22%2C%20%22Python%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Python</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/rb/README.md">Ruby</a></td>
|
||||
<!-- Since -----------------><td>0.2.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>2.3.1p112</td><td>2.5.1p57</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Ruby%20-%20Compiler%22%2C%20%22Ruby%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Ruby</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/rs/README.md">Rust</a></td>
|
||||
<!-- Since -----------------><td>0.11.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>1.40.0</td><td>1.xx.x</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td>1.61.0</td><td>1.xx.x</td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Rust%20-%20Compiler%22%2C%20%22Rust%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Rust</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/st/README.md">Smalltalk</a></td>
|
||||
<!-- Since -----------------><td>0.2.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td colspan=2>unknown</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Smalltalk%20-%20Compiler%22%2C%20%22Smalltalk%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Smalltalk</a></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td align=left><a href="https://github.com/apache/thrift/blob/master/lib/swift/README.md">Swift</a></td>
|
||||
<!-- Since -----------------><td>0.12.0</td>
|
||||
<!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td colspan=2>4.2.1</td>
|
||||
<!-- Field types -----------><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Build Systems ---------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Language Levels -------><td colspan=2>5.7</td>
|
||||
<!-- Field types -----------><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Low-Level Transports --><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Transport Wrappers ----><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td>
|
||||
<!-- Protocols -------------><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<!-- Servers ---------------><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cred.png" alt=""/></td><td><img src="/doc/images/cgrn.png" alt="Yes"/></td>
|
||||
<td align=left><a href="https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20component%20in%20(%22Swift%20-%20Compiler%22%2C%20%22Swift%20-%20Library%22)%20and%20status%20not%20in%20(fixed%2C%20resolved%2C%20closed)">Swift</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -78,7 +78,7 @@ empty :=
|
||||
space := $(empty) $(empty)
|
||||
comma := ,
|
||||
|
||||
CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_NETSTD@ @MAYBE_NODETS@ @MAYBE_KOTLIN@
|
||||
CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_NETSTD@ @MAYBE_NODETS@ @MAYBE_KOTLIN@ @MAYBE_SWIFT@
|
||||
CROSS_LANGS_COMMA_SEPARATED = $(subst $(space),$(comma),$(CROSS_LANGS))
|
||||
|
||||
if WITH_PY3
|
||||
@ -157,7 +157,6 @@ EXTRA_DIST = \
|
||||
doc \
|
||||
dub.json \
|
||||
go.mod \
|
||||
go.sum \
|
||||
jitpack.yml \
|
||||
LANGUAGES.md \
|
||||
LICENSE \
|
||||
|
@ -35,8 +35,8 @@ Status
|
||||
|
||||
| Branch | Travis | Appveyor | Coverity Scan | codecov.io | Website |
|
||||
| :----- | :----- | :------- | :------------ | :--------- | :------ |
|
||||
| [`master`](https://github.com/apache/thrift/tree/master) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=master)](https://travis-ci.org/apache/thrift/branches) | [![Build status](https://ci.appveyor.com/api/projects/status/github/apache/thrift?branch=master&svg=true)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/thrift/history) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/1345/badge.svg)](https://scan.coverity.com/projects/thrift) | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://thrift.apache.org/) |
|
||||
| [`0.14.0`](https://github.com/apache/thrift/tree/0.14.0) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=0.14.0)](https://travis-ci.org/apache/thrift/branches) | | | | |
|
||||
| [`master`](https://github.com/apache/thrift/tree/master) | [![Build Status](https://api.travis-ci.com/apache/thrift.svg?branch=master)](https://app.travis-ci.com/apache/thrift/branches) | [![Build status](https://ci.appveyor.com/api/projects/status/github/apache/thrift?branch=master&svg=true)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/thrift/history) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/1345/badge.svg)](https://scan.coverity.com/projects/thrift) | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://thrift.apache.org/) |
|
||||
| [`0.17.0`](https://github.com/apache/thrift/tree/0.17.0) | [![Build Status](https://api.travis-ci.com/apache/thrift.svg?branch=0.17.0)](https://app.travis-ci.com/apache/thrift/branches) | | | | |
|
||||
|
||||
Releases
|
||||
========
|
||||
|
@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'Thrift'
|
||||
s.version = '0.17.0'
|
||||
s.version = '0.19.0'
|
||||
s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC."
|
||||
s.description = <<-DESC
|
||||
The Apache Thrift scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages.
|
||||
@ -10,6 +10,6 @@ The Apache Thrift scalable cross-language software framework for networked servi
|
||||
s.author = { 'Apache Thrift Developers' => 'dev@thrift.apache.org' }
|
||||
s.ios.deployment_target = '9.0'
|
||||
s.osx.deployment_target = '10.10'
|
||||
s.source = { :git => 'https://github.com/apache/thrift.git', :tag => 'v0.17.0' }
|
||||
s.source = { :git => 'https://github.com/apache/thrift.git', :tag => 'v0.19.0' }
|
||||
s.source_files = 'lib/swift/Sources/*.swift'
|
||||
end
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
# build Apache Thrift on AppVeyor - https://ci.appveyor.com
|
||||
|
||||
version: '0.17.0.{build}'
|
||||
version: '0.19.0.{build}'
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "thrift",
|
||||
"version": "0.17.0",
|
||||
"version": "0.19.0",
|
||||
"homepage": "https://github.com/apache/thrift.git",
|
||||
"authors": [
|
||||
"Apache Thrift <dev@thrift.apache.org>"
|
||||
|
@ -40,5 +40,6 @@ if (NOT CYGWIN)
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ThriftConfig.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/ThriftConfigVersion.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/FindLibevent.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_DIR}/thrift")
|
||||
endif()
|
||||
|
@ -24,7 +24,9 @@ set(THRIFT_VERSION @thrift_VERSION@)
|
||||
set_and_check(THRIFT_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
|
||||
set_and_check(THRIFT_CMAKE_DIR "@PACKAGE_CMAKE_INSTALL_DIR@")
|
||||
set_and_check(THRIFT_BIN_DIR "@PACKAGE_BIN_INSTALL_DIR@")
|
||||
if(NOT DEFINED THRIFT_COMPILER)
|
||||
set(THRIFT_COMPILER "${THRIFT_BIN_DIR}/thrift@CMAKE_EXECUTABLE_SUFFIX@")
|
||||
endif()
|
||||
|
||||
if (NOT TARGET thrift::thrift)
|
||||
include("${THRIFT_CMAKE_DIR}/thriftTargets.cmake")
|
||||
@ -57,7 +59,19 @@ if(@OPENSSL_FOUND@ AND @WITH_OPENSSL@)
|
||||
endif()
|
||||
|
||||
if(@Libevent_FOUND@ AND @WITH_LIBEVENT@)
|
||||
if(DEFINED CMAKE_MODULE_PATH)
|
||||
set(THRIFT_CMAKE_MODULE_PATH_OLD ${CMAKE_MODULE_PATH})
|
||||
else()
|
||||
unset(THRIFT_CMAKE_MODULE_PATH_OLD)
|
||||
endif()
|
||||
set(CMAKE_MODULE_PATH "${THRIFT_CMAKE_DIR}")
|
||||
find_dependency(Libevent)
|
||||
if(DEFINED THRIFT_CMAKE_MODULE_PATH_OLD)
|
||||
set(CMAKE_MODULE_PATH ${THRIFT_CMAKE_MODULE_PATH_OLD})
|
||||
unset(THRIFT_CMAKE_MODULE_PATH_OLD)
|
||||
else()
|
||||
unset(CMAKE_MODULE_PATH)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_required_components(Thrift)
|
||||
|
@ -52,9 +52,9 @@ coverage.
|
||||
|
||||
### Ubuntu ###
|
||||
|
||||
* bionic (stable, current)
|
||||
* artful (previous stable)
|
||||
* xenial (legacy)
|
||||
* focal (stable, current)
|
||||
* bionic (previous stable)
|
||||
* jammy (next stable, WIP)
|
||||
|
||||
## Unsupported Containers ##
|
||||
|
||||
@ -172,17 +172,18 @@ Last updated: October 1, 2017
|
||||
| C++ gcc | 5.4.0 | 7.4.0 | |
|
||||
| C++ clang | 3.8 | 6.0 | |
|
||||
| C# (mono) | 4.2.1.0 | 4.6.2.7 | |
|
||||
| c_glib | 2.48.2 | 2.56.4 | |
|
||||
| c\_glib | 2.48.2 | 2.56.4 | |
|
||||
| cl (sbcl) | | 1.5.3 | |
|
||||
| d | 2.087.0 | 2.087.0 | |
|
||||
| dart | 2.0.0 | 2.4.0 | |
|
||||
| delphi | | | Not in CI |
|
||||
| erlang | OTP-18 | OTP-23 | |
|
||||
| go | 1.15.10 | 1.16.2 | |
|
||||
| haxe | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 |
|
||||
| java | 1.8.0_191 | 11.0.3 | |
|
||||
| java | 1.8.0\_191 | 17 | |
|
||||
| js | Node.js 6.17.1, V8 5.1.281.111, npm 3.10.10 | Node.js 10.18.0, V8 6.8.275.32, npm 6.13.4 | |
|
||||
| lua | | 5.2.4 | Lua 5.3: see THRIFT-4386 |
|
||||
| netstd | 6.0 | 6.0 | |
|
||||
| netstd | 7.0 | 7.0 | |
|
||||
| nodejs | 6.16.0 | 10.16.0 | |
|
||||
| ocaml | | 4.05.0 | THRIFT-4517: ocaml 4.02.3 on xenial appears broken |
|
||||
| perl | 5.22.1 | 5.26.1 | |
|
||||
@ -190,6 +191,6 @@ Last updated: October 1, 2017
|
||||
| python | 2.7.12 | 2.7.15 | |
|
||||
| python3 | 3.5.2 | 3.6.8 | |
|
||||
| ruby | 2.3.1p112 | 2.5.1p57 | |
|
||||
| rust | 1.40.0 | 1.40.0 | |
|
||||
| rust | 1.61.0 | 1.61.0 | |
|
||||
| smalltalk | | | Not in CI |
|
||||
| swift | | 5.1.4 | |
|
||||
|
@ -102,10 +102,10 @@ ENV PATH /usr/lib/dart/bin:$PATH
|
||||
# project isn't ready for this quite yet:
|
||||
# RUN apt-get install -y --no-install-recommends \
|
||||
# `# dotnet core dependencies` \
|
||||
# dotnet-sdk-6.0 \
|
||||
# dotnet-runtime-6.0 \
|
||||
# aspnetcore-runtime-6.0 \
|
||||
# dotnet-apphost-pack-6.0
|
||||
# dotnet-sdk-7.0 \
|
||||
# dotnet-runtime-7.0 \
|
||||
# aspnetcore-runtime-7.0 \
|
||||
# dotnet-apphost-pack-7.0
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Erlang dependencies` \
|
||||
|
@ -85,6 +85,17 @@ RUN apt-get install -y --no-install-recommends \
|
||||
qtbase5-dev \
|
||||
qtbase5-dev-tools
|
||||
|
||||
ENV SBCL_VERSION 1.4.5
|
||||
RUN \
|
||||
`# Common Lisp (sbcl) dependencies` \
|
||||
curl --version && \
|
||||
curl -O -J -L https://kent.dl.sourceforge.net/project/sbcl/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
|
||||
tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
|
||||
cd sbcl-${SBCL_VERSION}-x86-64-linux && \
|
||||
./install.sh && \
|
||||
sbcl --version && \
|
||||
rm -rf sbcl*
|
||||
|
||||
ENV D_VERSION 2.080.0
|
||||
ENV DMD_DEB dmd_2.080.0-0_amd64.deb
|
||||
RUN \
|
||||
@ -109,10 +120,10 @@ ENV PATH /usr/lib/dart/bin:$PATH
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# dotnet core dependencies` \
|
||||
dotnet-sdk-6.0 \
|
||||
dotnet-runtime-6.0 \
|
||||
aspnetcore-runtime-6.0 \
|
||||
dotnet-apphost-pack-6.0
|
||||
dotnet-sdk-7.0 \
|
||||
dotnet-runtime-7.0 \
|
||||
aspnetcore-runtime-7.0 \
|
||||
dotnet-apphost-pack-7.0
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Erlang dependencies` \
|
||||
|
@ -89,6 +89,18 @@ RUN apt-get install -y --no-install-recommends \
|
||||
qtbase5-dev \
|
||||
qtbase5-dev-tools
|
||||
|
||||
ENV SBCL_VERSION 1.5.3
|
||||
RUN \
|
||||
`# Common Lisp (sbcl) dependencies` \
|
||||
curl --version && \
|
||||
curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \
|
||||
tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
|
||||
cd sbcl-${SBCL_VERSION}-x86-64-linux && \
|
||||
./install.sh && \
|
||||
sbcl --version && \
|
||||
cd .. && \
|
||||
rm -rf sbcl*
|
||||
|
||||
ENV D_VERSION 2.087.0
|
||||
ENV DMD_DEB dmd_2.087.0-0_amd64.deb
|
||||
RUN \
|
||||
@ -114,10 +126,10 @@ ENV PATH /usr/lib/dart/bin:$PATH
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# dotnet core dependencies` \
|
||||
dotnet-sdk-6.0 \
|
||||
dotnet-runtime-6.0 \
|
||||
aspnetcore-runtime-6.0 \
|
||||
dotnet-apphost-pack-6.0
|
||||
dotnet-sdk-7.0 \
|
||||
dotnet-runtime-7.0 \
|
||||
aspnetcore-runtime-7.0 \
|
||||
dotnet-apphost-pack-7.0
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Erlang dependencies` \
|
||||
@ -148,7 +160,7 @@ RUN apt-get install -y --no-install-recommends \
|
||||
haxelib setup --always /usr/share/haxe/lib && \
|
||||
haxelib install --always hxcpp 2>&1 > /dev/null
|
||||
|
||||
ENV GRADLE_VERSION="7.4.2"
|
||||
ENV GRADLE_VERSION="8.0.2"
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Java dependencies` \
|
||||
ant \
|
||||
@ -157,7 +169,7 @@ RUN apt-get install -y --no-install-recommends \
|
||||
openjdk-11-jdk-headless && \
|
||||
`# Gradle` \
|
||||
wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
(echo "29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \
|
||||
(echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \
|
||||
unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \
|
||||
ln -s /usr/local/gradle/bin/gradle /usr/local/bin
|
||||
@ -242,7 +254,7 @@ RUN apt-get install -y --no-install-recommends \
|
||||
ruby-bundler
|
||||
|
||||
# Rust dependencies
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.40.0 -y
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y
|
||||
ENV PATH /root/.cargo/bin:$PATH
|
||||
|
||||
# Swift on Linux for cross tests
|
@ -115,10 +115,10 @@ ENV PATH /usr/lib/dart/bin:$PATH
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# dotnet core dependencies` \
|
||||
dotnet-sdk-6.0 \
|
||||
dotnet-runtime-6.0 \
|
||||
aspnetcore-runtime-6.0 \
|
||||
dotnet-apphost-pack-6.0
|
||||
dotnet-sdk-7.0 \
|
||||
dotnet-runtime-7.0 \
|
||||
aspnetcore-runtime-7.0 \
|
||||
dotnet-apphost-pack-7.0
|
||||
|
||||
# Erlang dependencies
|
||||
ARG ERLANG_OTP_VERSION=18.3.4.11
|
||||
@ -155,7 +155,7 @@ RUN apt-get install -y --no-install-recommends \
|
||||
haxelib install --always hxcpp 3.4.64 2>&1 > /dev/null
|
||||
# note: hxcpp 3.4.185 (latest) no longer ships static libraries, and caused a build failure
|
||||
|
||||
ENV GRADLE_VERSION="7.4.2"
|
||||
ENV GRADLE_VERSION="8.0.2"
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Java dependencies` \
|
||||
ant \
|
||||
@ -165,7 +165,7 @@ RUN apt-get install -y --no-install-recommends \
|
||||
unzip && \
|
||||
`# Gradle` \
|
||||
wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
(echo "29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \
|
||||
(echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \
|
||||
unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \
|
||||
ln -s /usr/local/gradle/bin/gradle /usr/local/bin
|
||||
@ -249,7 +249,7 @@ RUN apt-get install -y --no-install-recommends \
|
||||
ruby-bundler
|
||||
|
||||
# Rust dependencies
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.40.0 -y
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y
|
||||
|
||||
# Locale(s) for cpp unit tests
|
||||
RUN apt-get install -y --no-install-recommends \
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -ev
|
||||
|
||||
mkdir ~/.m2
|
||||
mkdir -p ~/.m2
|
||||
tee >~/.m2/settings.xml <<EOF
|
||||
<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0'>
|
||||
<mirrors>
|
||||
|
@ -16,12 +16,12 @@
|
||||
#
|
||||
|
||||
FROM buildpack-deps:bionic-scm
|
||||
MAINTAINER Apache Thrift <dev@thrift.apache.org>
|
||||
LABEL MAINTAINER='Apache Thrift <dev@thrift.apache.org>'
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
### Add apt repos
|
||||
|
||||
RUN apt-get update && \
|
||||
RUN apt-get update -yq && \
|
||||
apt-get dist-upgrade -y && \
|
||||
apt-get install -y --no-install-recommends --fix-missing \
|
||||
apt \
|
||||
@ -87,6 +87,18 @@ RUN apt-get install -y --no-install-recommends \
|
||||
qtbase5-dev \
|
||||
qtbase5-dev-tools
|
||||
|
||||
ENV SBCL_VERSION 1.5.3
|
||||
RUN \
|
||||
`# Common Lisp (sbcl) dependencies` \
|
||||
curl --version && \
|
||||
curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \
|
||||
tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
|
||||
cd sbcl-${SBCL_VERSION}-x86-64-linux && \
|
||||
./install.sh && \
|
||||
sbcl --version && \
|
||||
cd .. && \
|
||||
rm -rf sbcl*
|
||||
|
||||
ENV D_VERSION 2.087.0
|
||||
ENV DMD_DEB dmd_2.087.0-0_amd64.deb
|
||||
RUN \
|
||||
@ -112,10 +124,10 @@ ENV PATH /usr/lib/dart/bin:$PATH
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# dotnet core dependencies` \
|
||||
dotnet-sdk-6.0 \
|
||||
dotnet-runtime-6.0 \
|
||||
aspnetcore-runtime-6.0 \
|
||||
dotnet-apphost-pack-6.0
|
||||
dotnet-sdk-7.0 \
|
||||
dotnet-runtime-7.0 \
|
||||
aspnetcore-runtime-7.0 \
|
||||
dotnet-apphost-pack-7.0
|
||||
|
||||
# Erlang dependencies
|
||||
ARG ERLANG_OTP_VERSION=23.3.4.11
|
||||
@ -132,9 +144,9 @@ RUN apt-get install -y --no-install-recommends \
|
||||
libglib2.0-dev
|
||||
|
||||
# golang
|
||||
ENV GOLANG_VERSION 1.19
|
||||
ENV GOLANG_VERSION 1.19.5
|
||||
ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
|
||||
ENV GOLANG_DOWNLOAD_SHA256 464b6b66591f6cf055bc5df90a9750bf5fbc9d038722bb84a9d56a2bea974be6
|
||||
ENV GOLANG_DOWNLOAD_SHA256 36519702ae2fd573c9869461990ae550c8c0d955cd28d2827a6b159fda81ff95
|
||||
RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \
|
||||
echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \
|
||||
tar -C /usr/local -xzf golang.tar.gz && \
|
||||
@ -149,16 +161,16 @@ RUN apt-get install -y --no-install-recommends \
|
||||
haxelib setup --always /usr/share/haxe/lib && \
|
||||
haxelib install --always hxcpp 2>&1 > /dev/null
|
||||
|
||||
ENV GRADLE_VERSION="7.4.2"
|
||||
ENV GRADLE_VERSION="8.0.2"
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Java dependencies` \
|
||||
ant \
|
||||
ant-optional \
|
||||
maven \
|
||||
openjdk-11-jdk-headless && \
|
||||
openjdk-17-jdk-headless && \
|
||||
`# Gradle` \
|
||||
wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
(echo "29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \
|
||||
(echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \
|
||||
unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \
|
||||
ln -s /usr/local/gradle/bin/gradle /usr/local/bin
|
||||
@ -242,15 +254,23 @@ RUN apt-get install -y --no-install-recommends \
|
||||
ruby-bundler
|
||||
|
||||
# Rust dependencies
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.40.0 -y
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y
|
||||
ENV PATH /root/.cargo/bin:$PATH
|
||||
|
||||
# Swift on Linux for cross tests
|
||||
RUN cd / && \
|
||||
wget --quiet https://swift.org/builds/swift-5.1.4-release/ubuntu1804/swift-5.1.4-RELEASE/swift-5.1.4-RELEASE-ubuntu18.04.tar.gz && \
|
||||
tar xf swift-5.1.4-RELEASE-ubuntu18.04.tar.gz --strip-components=1 && \
|
||||
rm swift-5.1.4-RELEASE-ubuntu18.04.tar.gz && \
|
||||
swift --version
|
||||
RUN apt-get install -yq \
|
||||
libedit-dev \
|
||||
libz3-dev \
|
||||
libpython-dev \
|
||||
libxml2-dev && \
|
||||
cd / && \
|
||||
wget --quiet https://download.swift.org/swift-5.7-release/ubuntu1804/swift-5.7-RELEASE/swift-5.7-RELEASE-ubuntu18.04.tar.gz && \
|
||||
tar xf swift-5.7-RELEASE-ubuntu18.04.tar.gz && \
|
||||
mv swift-5.7-RELEASE-ubuntu18.04 /usr/share/swift && \
|
||||
rm swift-5.7-RELEASE-ubuntu18.04.tar.gz
|
||||
|
||||
ENV PATH /usr/share/swift/usr/bin:$PATH
|
||||
RUN swift --version
|
||||
|
||||
# Locale(s) for cpp unit tests
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
@ -260,15 +280,11 @@ RUN apt-get install -y --no-install-recommends \
|
||||
locale-gen de_DE.UTF-8 && \
|
||||
update-locale
|
||||
|
||||
# cppcheck-1.82 has a nasty cpp parser bug, so we're using something newer
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Static Code Analysis dependencies` \
|
||||
cppcheck \
|
||||
sloccount && \
|
||||
pip install flake8 && \
|
||||
wget -q "https://launchpad.net/ubuntu/+source/cppcheck/1.83-2/+build/14874703/+files/cppcheck_1.83-2_amd64.deb" && \
|
||||
dpkg -i cppcheck_1.83-2_amd64.deb && \
|
||||
rm cppcheck_1.83-2_amd64.deb
|
||||
pip install flake8
|
||||
|
||||
# NOTE: this does not reduce the image size but adds an additional layer.
|
||||
# # Clean up
|
||||
|
286
build/docker/ubuntu-focal/Dockerfile
Normal file
286
build/docker/ubuntu-focal/Dockerfile
Normal file
@ -0,0 +1,286 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# Apache Thrift Docker build environment for Ubuntu Focal
|
||||
# with some updated packages.
|
||||
#
|
||||
|
||||
FROM buildpack-deps:focal-scm
|
||||
LABEL MAINTAINER="Apache Thrift <dev@thrift.apache.org>"
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
### Add apt repos
|
||||
|
||||
RUN apt-get update -yq && \
|
||||
apt-get dist-upgrade -y && \
|
||||
apt-get install -y --no-install-recommends --fix-missing \
|
||||
apt \
|
||||
apt-transport-https \
|
||||
apt-utils \
|
||||
curl \
|
||||
dirmngr \
|
||||
software-properties-common \
|
||||
wget
|
||||
|
||||
# Dart
|
||||
RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
||||
curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \
|
||||
/etc/apt/sources.list.d/dart_stable.list
|
||||
|
||||
# dotnet (netcore)
|
||||
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \
|
||||
wget -q -O /etc/apt/sources.list.d/microsoft-prod.list https://packages.microsoft.com/config/ubuntu/18.04/prod.list && \
|
||||
chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \
|
||||
chown root:root /etc/apt/sources.list.d/microsoft-prod.list
|
||||
|
||||
# node.js
|
||||
RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \
|
||||
echo "deb https://deb.nodesource.com/node_16.x focal main" | tee /etc/apt/sources.list.d/nodesource.list
|
||||
|
||||
### install general dependencies
|
||||
RUN apt-get update -yq && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
`# General dependencies` \
|
||||
bash-completion \
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
cmake \
|
||||
debhelper \
|
||||
flex \
|
||||
gdb \
|
||||
libasound2 \
|
||||
libatk-bridge2.0-0 \
|
||||
libgtk-3-0 \
|
||||
llvm \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
unzip \
|
||||
valgrind \
|
||||
vim
|
||||
ENV PATH /usr/lib/llvm-6.0/bin:$PATH
|
||||
|
||||
# lib/as3 (ActionScript)
|
||||
RUN mkdir -p /usr/local/adobe/flex/4.6 && \
|
||||
cd /usr/local/adobe/flex/4.6 && \
|
||||
wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \
|
||||
unzip flex_sdk_4.6.zip
|
||||
ENV FLEX_HOME /usr/local/adobe/flex/4.6
|
||||
|
||||
# TODO: "apt-get install" without "apt-get update" in the same "RUN" step can cause cache issues if modified later.
|
||||
# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# C++ dependencies` \
|
||||
libboost-all-dev \
|
||||
libevent-dev \
|
||||
libssl-dev \
|
||||
qt5-default \
|
||||
qtbase5-dev \
|
||||
qtbase5-dev-tools
|
||||
|
||||
ENV SBCL_VERSION 1.5.3
|
||||
RUN \
|
||||
`# Common Lisp (sbcl) dependencies` \
|
||||
curl --version && \
|
||||
curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \
|
||||
tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
|
||||
cd sbcl-${SBCL_VERSION}-x86-64-linux && \
|
||||
./install.sh && \
|
||||
sbcl --version && \
|
||||
cd .. && \
|
||||
rm -rf sbcl*
|
||||
|
||||
ENV D_VERSION 2.087.0
|
||||
ENV DMD_DEB dmd_2.087.0-0_amd64.deb
|
||||
RUN \
|
||||
`# D dependencies` \
|
||||
wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \
|
||||
dpkg --install ${DMD_DEB} && \
|
||||
rm -f ${DMD_DEB} && \
|
||||
mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
|
||||
git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \
|
||||
mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
|
||||
mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \
|
||||
rm -rf deimos-libevent-2.0 && \
|
||||
git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \
|
||||
mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
|
||||
mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \
|
||||
rm -rf deimos-openssl-1.1.0h
|
||||
|
||||
ENV DART_VERSION 2.7.2-1
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Dart dependencies` \
|
||||
dart=$DART_VERSION
|
||||
ENV PATH /usr/lib/dart/bin:$PATH
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# dotnet core dependencies` \
|
||||
dotnet-sdk-7.0 \
|
||||
dotnet-runtime-7.0 \
|
||||
aspnetcore-runtime-7.0 \
|
||||
dotnet-apphost-pack-7.0
|
||||
|
||||
# Erlang dependencies
|
||||
ARG ERLANG_OTP_VERSION=23.3.4.11
|
||||
ARG ERLANG_REBAR_VERSION=3.18.0
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends libncurses5-dev && \
|
||||
curl -ssLo /usr/local/bin/kerl https://raw.githubusercontent.com/kerl/kerl/master/kerl && chmod +x /usr/local/bin/kerl && \
|
||||
kerl build $ERLANG_OTP_VERSION && kerl install $ERLANG_OTP_VERSION /usr/local/lib/otp/ && . /usr/local/lib/otp/activate && \
|
||||
curl -ssLo /usr/local/bin/rebar3 https://github.com/erlang/rebar3/releases/download/${ERLANG_REBAR_VERSION}/rebar3 && chmod +x /usr/local/bin/rebar3 && \
|
||||
rebar3 --version
|
||||
ENV PATH /usr/local/lib/otp/bin:$PATH
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# GlibC dependencies` \
|
||||
libglib2.0-dev
|
||||
|
||||
# golang
|
||||
ENV GOLANG_VERSION 1.20
|
||||
ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
|
||||
ENV GOLANG_DOWNLOAD_SHA256 5a9ebcc65c1cce56e0d2dc616aff4c4cedcfbda8cc6f0288cc08cda3b18dcbf1
|
||||
RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \
|
||||
echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \
|
||||
tar -C /usr/local -xzf golang.tar.gz && \
|
||||
ln -s /usr/local/go/bin/go /usr/local/bin && \
|
||||
rm golang.tar.gz
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Haxe dependencies` \
|
||||
haxe \
|
||||
neko \
|
||||
neko-dev && \
|
||||
haxelib setup --always /usr/share/haxe/lib && \
|
||||
haxelib install --always hxcpp 2>&1 > /dev/null
|
||||
|
||||
ENV GRADLE_VERSION="8.0.2"
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Java dependencies` \
|
||||
ant \
|
||||
ant-optional \
|
||||
maven \
|
||||
openjdk-17-jdk-headless && \
|
||||
`# Gradle` \
|
||||
wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
(echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \
|
||||
unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \
|
||||
ln -s /usr/local/gradle/bin/gradle /usr/local/bin
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Lua dependencies` \
|
||||
lua5.2 \
|
||||
lua5.2-dev
|
||||
# https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212
|
||||
# lua5.3 does not install alternatives!
|
||||
# need to update our luasocket code, lua doesn't have luaL_openlib any more
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Node.js dependencies` \
|
||||
nodejs
|
||||
|
||||
# Test dependencies for running puppeteer
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# JS dependencies` \
|
||||
libxss1 \
|
||||
libxtst6
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# OCaml dependencies` \
|
||||
ocaml \
|
||||
opam && \
|
||||
`# disable sandboxing see https://github.com/ocaml/opam/issues/4327` \
|
||||
opam init --yes --disable-sandboxing && \
|
||||
opam install --yes oasis
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Perl dependencies` \
|
||||
libbit-vector-perl \
|
||||
libclass-accessor-class-perl \
|
||||
libcrypt-ssleay-perl \
|
||||
libio-socket-ssl-perl \
|
||||
libnet-ssleay-perl \
|
||||
libtest-exception-perl
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Php dependencies` \
|
||||
php \
|
||||
php-cli \
|
||||
php-dev \
|
||||
php-json \
|
||||
php-pear \
|
||||
re2c \
|
||||
composer
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Python3 dependencies` \
|
||||
python3-all \
|
||||
python3-all-dbg \
|
||||
python3-all-dev \
|
||||
python3-pip \
|
||||
python3-setuptools \
|
||||
python3-six \
|
||||
python3-tornado \
|
||||
python3-twisted \
|
||||
python3-wheel \
|
||||
python3-zope.interface
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Ruby dependencies` \
|
||||
ruby \
|
||||
ruby-dev \
|
||||
ruby-bundler
|
||||
|
||||
# Rust dependencies
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y
|
||||
ENV PATH /root/.cargo/bin:$PATH
|
||||
|
||||
# Swift on Linux for cross tests
|
||||
RUN apt-get install -yq \
|
||||
libedit-dev \
|
||||
libz3-dev \
|
||||
libpython2-dev \
|
||||
libxml2-dev && \
|
||||
cd / && \
|
||||
wget --quiet https://download.swift.org/swift-5.7-release/ubuntu2004/swift-5.7-RELEASE/swift-5.7-RELEASE-ubuntu20.04.tar.gz && \
|
||||
tar xf swift-5.7-RELEASE-ubuntu20.04.tar.gz && \
|
||||
mv swift-5.7-RELEASE-ubuntu20.04 /usr/share/swift && \
|
||||
rm swift-5.7-RELEASE-ubuntu20.04.tar.gz
|
||||
|
||||
ENV PATH /usr/share/swift/usr/bin:$PATH
|
||||
RUN swift --version
|
||||
|
||||
# Locale(s) for cpp unit tests
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Locale dependencies` \
|
||||
locales && \
|
||||
locale-gen en_US.UTF-8 && \
|
||||
locale-gen de_DE.UTF-8 && \
|
||||
update-locale
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Static Code Analysis dependencies` \
|
||||
cppcheck \
|
||||
sloccount && \
|
||||
pip install flake8
|
||||
|
||||
# NOTE: this does not reduce the image size but adds an additional layer.
|
||||
# # Clean up
|
||||
# RUN rm -rf /var/cache/apt/* && \
|
||||
# rm -rf /var/lib/apt/lists/* && \
|
||||
# rm -rf /tmp/* && \
|
||||
# rm -rf /var/tmp/*
|
||||
|
||||
ENV THRIFT_ROOT /thrift
|
||||
RUN mkdir -p $THRIFT_ROOT/src
|
||||
COPY Dockerfile $THRIFT_ROOT/
|
||||
WORKDIR $THRIFT_ROOT/src
|
286
build/docker/ubuntu-jammy/Dockerfile
Normal file
286
build/docker/ubuntu-jammy/Dockerfile
Normal file
@ -0,0 +1,286 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# Apache Thrift Docker build environment for Ubuntu Jammy
|
||||
# with some updated packages.
|
||||
#
|
||||
|
||||
FROM buildpack-deps:jammy-scm
|
||||
LABEL MAINTAINER="Apache Thrift <dev@thrift.apache.org>"
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
### Add apt repos
|
||||
|
||||
RUN apt-get update -yq && \
|
||||
apt-get dist-upgrade -y && \
|
||||
apt-get install -y --no-install-recommends --fix-missing \
|
||||
apt \
|
||||
apt-transport-https \
|
||||
apt-utils \
|
||||
curl \
|
||||
dirmngr \
|
||||
software-properties-common \
|
||||
wget
|
||||
|
||||
# Dart
|
||||
RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
||||
curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \
|
||||
/etc/apt/sources.list.d/dart_stable.list
|
||||
|
||||
# dotnet (netcore)
|
||||
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \
|
||||
wget -q -O /etc/apt/sources.list.d/microsoft-prod.list https://packages.microsoft.com/config/ubuntu/18.04/prod.list && \
|
||||
chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \
|
||||
chown root:root /etc/apt/sources.list.d/microsoft-prod.list
|
||||
|
||||
# node.js
|
||||
RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \
|
||||
echo "deb https://deb.nodesource.com/node_16.x focal main" | tee /etc/apt/sources.list.d/nodesource.list
|
||||
|
||||
### install general dependencies
|
||||
RUN apt-get update -yq && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
`# General dependencies` \
|
||||
bash-completion \
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
cmake \
|
||||
debhelper \
|
||||
flex \
|
||||
gdb \
|
||||
libasound2 \
|
||||
libatk-bridge2.0-0 \
|
||||
libgtk-3-0 \
|
||||
llvm \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
unzip \
|
||||
valgrind \
|
||||
vim
|
||||
ENV PATH /usr/lib/llvm-6.0/bin:$PATH
|
||||
|
||||
# lib/as3 (ActionScript)
|
||||
RUN mkdir -p /usr/local/adobe/flex/4.6 && \
|
||||
cd /usr/local/adobe/flex/4.6 && \
|
||||
wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \
|
||||
unzip flex_sdk_4.6.zip
|
||||
ENV FLEX_HOME /usr/local/adobe/flex/4.6
|
||||
|
||||
# TODO: "apt-get install" without "apt-get update" in the same "RUN" step can cause cache issues if modified later.
|
||||
# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# C++ dependencies` \
|
||||
libboost-all-dev \
|
||||
libevent-dev \
|
||||
libssl-dev \
|
||||
qt5-default \
|
||||
qtbase5-dev \
|
||||
qtbase5-dev-tools
|
||||
|
||||
ENV SBCL_VERSION 1.5.3
|
||||
RUN \
|
||||
`# Common Lisp (sbcl) dependencies` \
|
||||
curl --version && \
|
||||
curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \
|
||||
tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \
|
||||
cd sbcl-${SBCL_VERSION}-x86-64-linux && \
|
||||
./install.sh && \
|
||||
sbcl --version && \
|
||||
cd .. && \
|
||||
rm -rf sbcl*
|
||||
|
||||
ENV D_VERSION 2.087.0
|
||||
ENV DMD_DEB dmd_2.087.0-0_amd64.deb
|
||||
RUN \
|
||||
`# D dependencies` \
|
||||
wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \
|
||||
dpkg --install ${DMD_DEB} && \
|
||||
rm -f ${DMD_DEB} && \
|
||||
mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \
|
||||
git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \
|
||||
mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
|
||||
mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \
|
||||
rm -rf deimos-libevent-2.0 && \
|
||||
git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \
|
||||
mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \
|
||||
mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \
|
||||
rm -rf deimos-openssl-1.1.0h
|
||||
|
||||
ENV DART_VERSION 2.7.2-1
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Dart dependencies` \
|
||||
dart=$DART_VERSION
|
||||
ENV PATH /usr/lib/dart/bin:$PATH
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# dotnet core dependencies` \
|
||||
dotnet-sdk-7.0 \
|
||||
dotnet-runtime-7.0 \
|
||||
aspnetcore-runtime-7.0 \
|
||||
dotnet-apphost-pack-7.0
|
||||
|
||||
# Erlang dependencies
|
||||
ARG ERLANG_OTP_VERSION=23.3.4.11
|
||||
ARG ERLANG_REBAR_VERSION=3.18.0
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends libncurses5-dev && \
|
||||
curl -ssLo /usr/local/bin/kerl https://raw.githubusercontent.com/kerl/kerl/master/kerl && chmod +x /usr/local/bin/kerl && \
|
||||
kerl build $ERLANG_OTP_VERSION && kerl install $ERLANG_OTP_VERSION /usr/local/lib/otp/ && . /usr/local/lib/otp/activate && \
|
||||
curl -ssLo /usr/local/bin/rebar3 https://github.com/erlang/rebar3/releases/download/${ERLANG_REBAR_VERSION}/rebar3 && chmod +x /usr/local/bin/rebar3 && \
|
||||
rebar3 --version
|
||||
ENV PATH /usr/local/lib/otp/bin:$PATH
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# GlibC dependencies` \
|
||||
libglib2.0-dev
|
||||
|
||||
# golang
|
||||
ENV GOLANG_VERSION 1.20
|
||||
ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
|
||||
ENV GOLANG_DOWNLOAD_SHA256 5a9ebcc65c1cce56e0d2dc616aff4c4cedcfbda8cc6f0288cc08cda3b18dcbf1
|
||||
RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \
|
||||
echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \
|
||||
tar -C /usr/local -xzf golang.tar.gz && \
|
||||
ln -s /usr/local/go/bin/go /usr/local/bin && \
|
||||
rm golang.tar.gz
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Haxe dependencies` \
|
||||
haxe \
|
||||
neko \
|
||||
neko-dev && \
|
||||
haxelib setup --always /usr/share/haxe/lib && \
|
||||
haxelib install --always hxcpp 2>&1 > /dev/null
|
||||
|
||||
ENV GRADLE_VERSION="8.0.2"
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Java dependencies` \
|
||||
ant \
|
||||
ant-optional \
|
||||
maven \
|
||||
openjdk-11-jdk-headless && \
|
||||
`# Gradle` \
|
||||
wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
(echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \
|
||||
unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \
|
||||
mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \
|
||||
ln -s /usr/local/gradle/bin/gradle /usr/local/bin
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Lua dependencies` \
|
||||
lua5.2 \
|
||||
lua5.2-dev
|
||||
# https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212
|
||||
# lua5.3 does not install alternatives!
|
||||
# need to update our luasocket code, lua doesn't have luaL_openlib any more
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Node.js dependencies` \
|
||||
nodejs
|
||||
|
||||
# Test dependencies for running puppeteer
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# JS dependencies` \
|
||||
libxss1 \
|
||||
libxtst6
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# OCaml dependencies` \
|
||||
ocaml \
|
||||
opam && \
|
||||
`# disable sandboxing see https://github.com/ocaml/opam/issues/4327` \
|
||||
opam init --yes --disable-sandboxing && \
|
||||
opam install --yes oasis
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Perl dependencies` \
|
||||
libbit-vector-perl \
|
||||
libclass-accessor-class-perl \
|
||||
libcrypt-ssleay-perl \
|
||||
libio-socket-ssl-perl \
|
||||
libnet-ssleay-perl \
|
||||
libtest-exception-perl
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Php dependencies` \
|
||||
php \
|
||||
php-cli \
|
||||
php-dev \
|
||||
php-json \
|
||||
php-pear \
|
||||
re2c \
|
||||
composer
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Python3 dependencies` \
|
||||
python3-all \
|
||||
python3-all-dbg \
|
||||
python3-all-dev \
|
||||
python3-pip \
|
||||
python3-setuptools \
|
||||
python3-six \
|
||||
python3-tornado \
|
||||
python3-twisted \
|
||||
python3-wheel \
|
||||
python3-zope.interface
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Ruby dependencies` \
|
||||
ruby \
|
||||
ruby-dev \
|
||||
ruby-bundler
|
||||
|
||||
# Rust dependencies
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y
|
||||
ENV PATH /root/.cargo/bin:$PATH
|
||||
|
||||
# Swift on Linux for cross tests
|
||||
RUN apt-get install -yq \
|
||||
libedit-dev \
|
||||
libz3-dev \
|
||||
libpython2-dev \
|
||||
libxml2-dev && \
|
||||
cd / && \
|
||||
wget --quiet https://download.swift.org/swift-5.7-release/ubuntu2204/swift-5.7-RELEASE/swift-5.7-RELEASE-ubuntu22.04.tar.gz && \
|
||||
tar xf swift-5.7-RELEASE-ubuntu22.04.tar.gz && \
|
||||
mv swift-5.7-RELEASE-ubuntu22.04 /usr/share/swift && \
|
||||
rm swift-5.7-RELEASE-ubuntu22.04.tar.gz
|
||||
|
||||
ENV PATH /usr/share/swift/usr/bin:$PATH
|
||||
RUN swift --version
|
||||
|
||||
# Locale(s) for cpp unit tests
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Locale dependencies` \
|
||||
locales && \
|
||||
locale-gen en_US.UTF-8 && \
|
||||
locale-gen de_DE.UTF-8 && \
|
||||
update-locale
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
`# Static Code Analysis dependencies` \
|
||||
cppcheck \
|
||||
sloccount && \
|
||||
pip install flake8
|
||||
|
||||
# NOTE: this does not reduce the image size but adds an additional layer.
|
||||
# # Clean up
|
||||
# RUN rm -rf /var/cache/apt/* && \
|
||||
# rm -rf /var/lib/apt/lists/* && \
|
||||
# rm -rf /tmp/* && \
|
||||
# rm -rf /var/tmp/*
|
||||
|
||||
ENV THRIFT_ROOT /thrift
|
||||
RUN mkdir -p $THRIFT_ROOT/src
|
||||
COPY Dockerfile $THRIFT_ROOT/
|
||||
WORKDIR $THRIFT_ROOT/src
|
@ -1,4 +1,4 @@
|
||||
x#!/usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
|
@ -46,6 +46,8 @@ add_library(parse STATIC ${parse_SOURCES})
|
||||
set(compiler_core
|
||||
src/thrift/common.cc
|
||||
src/thrift/generate/t_generator.cc
|
||||
src/thrift/generate/validator_parser.cc
|
||||
src/thrift/generate/validator_parser.h
|
||||
src/thrift/parse/t_typedef.cc
|
||||
src/thrift/parse/parse.cc
|
||||
src/thrift/version.h
|
||||
@ -71,8 +73,21 @@ macro(THRIFT_ADD_COMPILER name description initial)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# This macro adds an option THRIFT_VALIDATOR_COMPILER_${NAME}
|
||||
# that allows enabling or disabling certain languages' validator
|
||||
macro(THRIFT_ADD_VALIDATOR_COMPILER name description initial)
|
||||
string(TOUPPER "THRIFT_COMPILER_${name}" enabler)
|
||||
set(src "src/thrift/generate/${name}_validator_generator.cc")
|
||||
list(APPEND "src/thrift/generate/${name}_validator_generator.h")
|
||||
option(${enabler} ${description} ${initial})
|
||||
if(${enabler})
|
||||
list(APPEND thrift-compiler_SOURCES ${src})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# The following compiler can be enabled or disabled
|
||||
THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" ON)
|
||||
THRIFT_ADD_COMPILER(cl "Enable compiler for Common LISP" ON)
|
||||
THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" ON)
|
||||
THRIFT_ADD_COMPILER(d "Enable compiler for D" ON)
|
||||
THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" ON)
|
||||
@ -102,6 +117,9 @@ THRIFT_ADD_COMPILER(swift "Enable compiler for Cocoa Swift" ON)
|
||||
THRIFT_ADD_COMPILER(xml "Enable compiler for XML" ON)
|
||||
THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" ON)
|
||||
|
||||
# The following compiler can be enabled or disabled by enabling or disabling certain languages
|
||||
THRIFT_ADD_VALIDATOR_COMPILER(go "Enable validator compiler for Go" ON)
|
||||
|
||||
option(STATIC "Enable static linking of core libraries (libgcc / libstdc++)")
|
||||
|
||||
set(thrift-compiler_LINKER_FLAGS)
|
||||
|
@ -70,6 +70,7 @@ thrift_SOURCES = src/thrift/audit/t_audit.cpp \
|
||||
|
||||
# Specific client generator source
|
||||
thrift_SOURCES += src/thrift/generate/t_c_glib_generator.cc \
|
||||
src/thrift/generate/t_cl_generator.cc \
|
||||
src/thrift/generate/t_cpp_generator.cc \
|
||||
src/thrift/generate/t_d_generator.cc \
|
||||
src/thrift/generate/t_dart_generator.cc \
|
||||
@ -77,6 +78,7 @@ thrift_SOURCES += src/thrift/generate/t_c_glib_generator.cc \
|
||||
src/thrift/generate/t_erl_generator.cc \
|
||||
src/thrift/generate/t_erlang_generator.cc \
|
||||
src/thrift/generate/t_go_generator.cc \
|
||||
src/thrift/generate/t_go_generator.h \
|
||||
src/thrift/generate/t_gv_generator.cc \
|
||||
src/thrift/generate/t_haxe_generator.cc \
|
||||
src/thrift/generate/t_html_generator.cc \
|
||||
@ -98,7 +100,11 @@ thrift_SOURCES += src/thrift/generate/t_c_glib_generator.cc \
|
||||
src/thrift/generate/t_st_generator.cc \
|
||||
src/thrift/generate/t_swift_generator.cc \
|
||||
src/thrift/generate/t_xml_generator.cc \
|
||||
src/thrift/generate/t_xsd_generator.cc
|
||||
src/thrift/generate/t_xsd_generator.cc \
|
||||
src/thrift/generate/validator_parser.cc \
|
||||
src/thrift/generate/validator_parser.h \
|
||||
src/thrift/generate/go_validator_generator.cc \
|
||||
src/thrift/generate/go_validator_generator.h
|
||||
|
||||
thrift_CPPFLAGS = -I$(srcdir)/src
|
||||
thrift_CXXFLAGS = -Wall -Wextra -pedantic -Werror
|
||||
|
@ -54,6 +54,7 @@
|
||||
<ClCompile Include="src\thrift\audit\t_audit.cpp" />
|
||||
<ClCompile Include="src\thrift\common.cc" />
|
||||
<ClCompile Include="src\thrift\generate\t_c_glib_generator.cc" />
|
||||
<ClCompile Include="src\thrift\generate\t_cl_generator.cc" />
|
||||
<ClCompile Include="src\thrift\generate\t_cpp_generator.cc" />
|
||||
<ClCompile Include="src\thrift\generate\t_d_generator.cc" />
|
||||
<ClCompile Include="src\thrift\generate\t_dart_generator.cc" />
|
||||
|
@ -23,6 +23,7 @@
|
||||
t_type* g_type_void;
|
||||
t_type* g_type_string;
|
||||
t_type* g_type_binary;
|
||||
t_type* g_type_uuid;
|
||||
t_type* g_type_bool;
|
||||
t_type* g_type_i8;
|
||||
t_type* g_type_i16;
|
||||
@ -35,6 +36,7 @@ void initGlobals() {
|
||||
g_type_string = new t_base_type("string", t_base_type::TYPE_STRING);
|
||||
g_type_binary = new t_base_type("string", t_base_type::TYPE_STRING);
|
||||
((t_base_type*)g_type_binary)->set_binary(true);
|
||||
g_type_uuid = new t_base_type("string", t_base_type::TYPE_UUID);
|
||||
g_type_bool = new t_base_type("bool", t_base_type::TYPE_BOOL);
|
||||
g_type_i8 = new t_base_type("i8", t_base_type::TYPE_I8);
|
||||
g_type_i16 = new t_base_type("i16", t_base_type::TYPE_I16);
|
||||
@ -46,6 +48,8 @@ void initGlobals() {
|
||||
void clearGlobals() {
|
||||
delete g_type_void;
|
||||
delete g_type_string;
|
||||
delete g_type_binary;
|
||||
delete g_type_uuid;
|
||||
delete g_type_bool;
|
||||
delete g_type_i8;
|
||||
delete g_type_i16;
|
||||
|
@ -29,6 +29,7 @@
|
||||
extern t_type* g_type_void;
|
||||
extern t_type* g_type_string;
|
||||
extern t_type* g_type_binary;
|
||||
extern t_type* g_type_uuid;
|
||||
extern t_type* g_type_bool;
|
||||
extern t_type* g_type_i8;
|
||||
extern t_type* g_type_i16;
|
||||
|
906
compiler/cpp/src/thrift/generate/go_validator_generator.cc
Normal file
906
compiler/cpp/src/thrift/generate/go_validator_generator.cc
Normal file
@ -0,0 +1,906 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is programmatically sanitized for style:
|
||||
* astyle --style=1tbs -f -p -H -j -U go_validator_generator.cc
|
||||
*
|
||||
* The output of astyle should not be taken unquestioningly, but it is a good
|
||||
* guide for ensuring uniformity and readability.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "thrift/generate/go_validator_generator.h"
|
||||
#include "thrift/generate/validator_parser.h"
|
||||
#include "thrift/platform.h"
|
||||
#include "thrift/version.h"
|
||||
#include <algorithm>
|
||||
#include <clocale>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
std::string go_validator_generator::get_field_reference_name(t_field* field) {
|
||||
t_type* type(field->get_type());
|
||||
std::string tgt;
|
||||
t_const_value* def_value;
|
||||
go_generator->get_publicized_name_and_def_value(field, &tgt, &def_value);
|
||||
tgt = "p." + tgt;
|
||||
if (go_generator->is_pointer_field(field)
|
||||
&& (type->is_base_type() || type->is_enum() || type->is_container())) {
|
||||
tgt = "*" + tgt;
|
||||
}
|
||||
return tgt;
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_struct_validator(std::ostream& out, t_struct* tstruct) {
|
||||
std::vector<t_field*> members = tstruct->get_members();
|
||||
validation_parser parser(tstruct);
|
||||
for (auto it = members.begin(); it != members.end(); it++) {
|
||||
t_field* field(*it);
|
||||
const std::vector<validation_rule*>& rules
|
||||
= parser.parse_field(field->get_type(), field->annotations_);
|
||||
if (rules.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
bool opt = field->get_req() == t_field::T_OPTIONAL;
|
||||
t_type* type = field->get_type();
|
||||
std::string tgt = get_field_reference_name(field);
|
||||
std::string field_symbol = tstruct->get_name() + "." + field->get_name();
|
||||
generate_field_validator(out, generator_context{field_symbol, "", tgt, opt, type, rules});
|
||||
}
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
t_type* type = context.type;
|
||||
if (type->is_typedef()) {
|
||||
type = type->get_true_type();
|
||||
}
|
||||
if (type->is_enum()) {
|
||||
if (context.tgt[0] == '*') {
|
||||
out << indent() << "if " << context.tgt.substr(1) << " != nil {" << endl;
|
||||
indent_up();
|
||||
}
|
||||
generate_enum_field_validator(out, context);
|
||||
if (context.tgt[0] == '*') {
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
return;
|
||||
} else if (type->is_base_type()) {
|
||||
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
|
||||
if (context.tgt[0] == '*') {
|
||||
out << indent() << "if " << context.tgt.substr(1) << " != nil {" << endl;
|
||||
indent_up();
|
||||
}
|
||||
switch (tbase) {
|
||||
case t_base_type::TYPE_UUID:
|
||||
case t_base_type::TYPE_VOID:
|
||||
break;
|
||||
case t_base_type::TYPE_I8:
|
||||
case t_base_type::TYPE_I16:
|
||||
case t_base_type::TYPE_I32:
|
||||
case t_base_type::TYPE_I64:
|
||||
generate_integer_field_validator(out, context);
|
||||
break;
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
generate_double_field_validator(out, context);
|
||||
break;
|
||||
case t_base_type::TYPE_STRING:
|
||||
generate_string_field_validator(out, context);
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
generate_bool_field_validator(out, context);
|
||||
break;
|
||||
}
|
||||
if (context.tgt[0] == '*') {
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
return;
|
||||
} else if (type->is_list()) {
|
||||
return generate_list_field_validator(out, context);
|
||||
} else if (type->is_set()) {
|
||||
return generate_set_field_validator(out, context);
|
||||
} else if (type->is_map()) {
|
||||
return generate_map_field_validator(out, context);
|
||||
} else if (type->is_struct() || type->is_xception()) {
|
||||
return generate_struct_field_validator(out, context);
|
||||
}
|
||||
throw "validator error: unsupported type: " + type->get_name();
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_enum_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
for (auto it = context.rules.begin(); it != context.rules.end(); it++) {
|
||||
const std::vector<validation_value*>& values = (*it)->get_values();
|
||||
if (values.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
std::string key = (*it)->get_name();
|
||||
|
||||
if (key == "vt.in") {
|
||||
if (values.size() > 1) {
|
||||
std::string exist = GenID("_exist");
|
||||
out << indent() << "var " << exist << " bool" << endl;
|
||||
|
||||
std::string src = GenID("_src");
|
||||
out << indent() << src << " := []int64{";
|
||||
for (auto it = values.begin(); it != values.end(); it++) {
|
||||
if (it != values.begin()) {
|
||||
out << ", ";
|
||||
}
|
||||
out << "int64(";
|
||||
if ((*it)->is_field_reference()) {
|
||||
out << get_field_reference_name((*it)->get_field_reference());
|
||||
} else {
|
||||
out << (*it)->get_enum()->get_value();
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << "}" << endl;
|
||||
|
||||
out << indent() << "for _, src := range " << src << " {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "if int64(" << context.tgt << ") == src {" << endl;
|
||||
indent_up();
|
||||
out << indent() << exist << " = true" << endl;
|
||||
out << indent() << "break" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
out << indent() << "if " << exist << " == false {" << endl;
|
||||
} else {
|
||||
out << indent() << "if int64(" << context.tgt << ") != int64(";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else {
|
||||
out << values[0]->get_enum()->get_value();
|
||||
}
|
||||
out << ") {" << endl;
|
||||
}
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.in\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol
|
||||
<< " not valid, rule vt.in check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
if (values.size() > 1) {
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
} else if (key == "vt.not_in") {
|
||||
if (values.size() > 1) {
|
||||
std::string src = GenID("_src");
|
||||
out << indent() << src << " := []int64{";
|
||||
for (auto it = values.begin(); it != values.end(); it++) {
|
||||
if (it != values.begin()) {
|
||||
out << ", ";
|
||||
}
|
||||
out << "int64(";
|
||||
if ((*it)->is_field_reference()) {
|
||||
out << get_field_reference_name((*it)->get_field_reference());
|
||||
} else {
|
||||
out << (*it)->get_enum()->get_value();
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << "}" << endl;
|
||||
|
||||
out << indent() << "for _, src := range " << src << " {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "if int64(" << context.tgt << ") == src {" << endl;
|
||||
} else {
|
||||
out << indent() << "if int64(" << context.tgt << ") == ";
|
||||
out << "int64(";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else {
|
||||
out << values[0]->get_enum()->get_value();
|
||||
}
|
||||
out << ") {" << endl;
|
||||
}
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.not_in\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol
|
||||
<< " not valid, rule vt.not_in check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
if (values.size() > 1) {
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
} else if (key == "vt.defined_only") {
|
||||
if (values[0]->get_bool()) {
|
||||
out << indent() << "if (" << context.tgt << ").String() == \"<UNSET>\" ";
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
out << "{" << endl;
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key
|
||||
<< " check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_bool_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
for (auto it = context.rules.begin(); it != context.rules.end(); it++) {
|
||||
const std::vector<validation_value*>& values = (*it)->get_values();
|
||||
if (values.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
std::string key = (*it)->get_name();
|
||||
|
||||
if (key == "vt.const") {
|
||||
out << indent() << "if " << context.tgt << " != ";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else {
|
||||
if (values[0]->get_bool()) {
|
||||
out << "true";
|
||||
} else {
|
||||
out << "false";
|
||||
}
|
||||
}
|
||||
}
|
||||
out << "{" << endl;
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key
|
||||
<< " check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_double_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
for (auto it = context.rules.begin(); it != context.rules.end(); it++) {
|
||||
const std::vector<validation_value*>& values = (*it)->get_values();
|
||||
if (values.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> signs{{"vt.lt", ">="},
|
||||
{"vt.le", ">"},
|
||||
{"vt.gt", "<="},
|
||||
{"vt.ge", "<"}};
|
||||
std::string key = (*it)->get_name();
|
||||
auto key_it = signs.find(key);
|
||||
if (key_it != signs.end()) {
|
||||
out << indent() << "if " << context.tgt << " " << key_it->second << " ";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else {
|
||||
out << values[0]->get_double();
|
||||
}
|
||||
out << "{" << endl;
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key
|
||||
<< " check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
continue;
|
||||
} else if (key == "vt.in") {
|
||||
if (values.size() > 1) {
|
||||
std::string exist = GenID("_exist");
|
||||
out << indent() << "var " << exist << " bool" << endl;
|
||||
|
||||
std::string src = GenID("_src");
|
||||
out << indent() << src << " := []float64{";
|
||||
for (auto it = values.begin(); it != values.end(); it++) {
|
||||
if (it != values.begin()) {
|
||||
out << ", ";
|
||||
}
|
||||
if ((*it)->is_field_reference()) {
|
||||
out << get_field_reference_name((*it)->get_field_reference());
|
||||
} else {
|
||||
out << (*it)->get_double();
|
||||
}
|
||||
}
|
||||
out << "}" << endl;
|
||||
|
||||
out << indent() << "for _, src := range " << src << " {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "if " << context.tgt << " == src {" << endl;
|
||||
indent_up();
|
||||
out << indent() << exist << " = true" << endl;
|
||||
out << indent() << "break" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
out << indent() << "if " << exist << " == false {" << endl;
|
||||
} else {
|
||||
out << indent() << "if " << context.tgt << " != ";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else {
|
||||
out << values[0]->get_double();
|
||||
}
|
||||
out << "{" << endl;
|
||||
}
|
||||
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.in\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol
|
||||
<< " not valid, rule vt.in check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
} else if (key == "vt.not_in") {
|
||||
if (values.size() > 1) {
|
||||
std::string src = GenID("_src");
|
||||
out << indent() << src << " := []float64{";
|
||||
for (auto it = values.begin(); it != values.end(); it++) {
|
||||
if (it != values.begin()) {
|
||||
out << ", ";
|
||||
}
|
||||
if ((*it)->is_field_reference()) {
|
||||
out << get_field_reference_name((*it)->get_field_reference());
|
||||
} else {
|
||||
out << (*it)->get_double();
|
||||
}
|
||||
}
|
||||
out << "}" << endl;
|
||||
|
||||
out << indent() << "for _, src := range " << src << " {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "if " << context.tgt << " == src {" << endl;
|
||||
} else {
|
||||
out << indent() << "if " << context.tgt << " == ";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else {
|
||||
out << values[0]->get_double();
|
||||
}
|
||||
out << "{" << endl;
|
||||
}
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.not_in\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol
|
||||
<< " not valid, rule vt.not_in check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
if (values.size() > 1) {
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_integer_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
auto generate_current_type = [](std::ostream& out, t_type* type) {
|
||||
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
|
||||
switch (tbase) {
|
||||
case t_base_type::TYPE_I8:
|
||||
out << "int8";
|
||||
break;
|
||||
case t_base_type::TYPE_I16:
|
||||
out << "int16";
|
||||
break;
|
||||
case t_base_type::TYPE_I32:
|
||||
out << "int32";
|
||||
break;
|
||||
case t_base_type::TYPE_I64:
|
||||
out << "int64";
|
||||
break;
|
||||
default:
|
||||
throw "validator error: unsupported integer type: " + type->get_name();
|
||||
}
|
||||
};
|
||||
|
||||
for (auto it = context.rules.begin(); it != context.rules.end(); it++) {
|
||||
const std::vector<validation_value*>& values = (*it)->get_values();
|
||||
if (values.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> signs{{"vt.lt", ">="},
|
||||
{"vt.le", ">"},
|
||||
{"vt.gt", "<="},
|
||||
{"vt.ge", "<"}};
|
||||
std::string key = (*it)->get_name();
|
||||
auto key_it = signs.find(key);
|
||||
if (key_it != signs.end()) {
|
||||
out << indent() << "if " << context.tgt << " " << key_it->second << " ";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else if (values[0]->is_validation_function()) {
|
||||
generate_current_type(out, context.type);
|
||||
out << "(";
|
||||
validation_value::validation_function* func = values[0]->get_function();
|
||||
if (func->name == "len") {
|
||||
out << "len(";
|
||||
if (func->arguments[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(func->arguments[0]->get_field_reference());
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << ")";
|
||||
} else {
|
||||
out << values[0]->get_int();
|
||||
}
|
||||
out << "{" << endl;
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key
|
||||
<< " check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
} else if (key == "vt.in") {
|
||||
if (values.size() > 1) {
|
||||
std::string exist = GenID("_exist");
|
||||
out << indent() << "var " << exist << " bool" << endl;
|
||||
|
||||
std::string src = GenID("_src");
|
||||
out << indent() << src << " := []";
|
||||
generate_current_type(out, context.type);
|
||||
out << "{";
|
||||
for (auto it = values.begin(); it != values.end(); it++) {
|
||||
if (it != values.begin()) {
|
||||
out << ", ";
|
||||
}
|
||||
if ((*it)->is_field_reference()) {
|
||||
out << get_field_reference_name((*it)->get_field_reference());
|
||||
} else if ((*it)->is_validation_function()) {
|
||||
generate_current_type(out, context.type);
|
||||
out << "(";
|
||||
validation_value::validation_function* func = (*it)->get_function();
|
||||
if (func->name == "len") {
|
||||
out << "len(";
|
||||
if (func->arguments[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(func->arguments[0]->get_field_reference());
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << ")";
|
||||
} else {
|
||||
out << (*it)->get_int();
|
||||
}
|
||||
}
|
||||
out << "}" << endl;
|
||||
|
||||
out << indent() << "for _, src := range " << src << " {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "if " << context.tgt << " == src {" << endl;
|
||||
indent_up();
|
||||
out << indent() << exist << " = true" << endl;
|
||||
out << indent() << "break" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
out << indent() << "if " << exist << " == false {" << endl;
|
||||
} else {
|
||||
out << indent() << "if " << context.tgt << " != ";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else if (values[0]->is_validation_function()) {
|
||||
generate_current_type(out, context.type);
|
||||
out << "(";
|
||||
validation_value::validation_function* func = values[0]->get_function();
|
||||
if (func->name == "len") {
|
||||
out << "len(";
|
||||
if (func->arguments[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(func->arguments[0]->get_field_reference());
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << ")";
|
||||
} else {
|
||||
out << values[0]->get_int();
|
||||
}
|
||||
out << "{" << endl;
|
||||
}
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.in\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol
|
||||
<< " not valid, rule vt.in check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
} else if (key == "vt.not_in") {
|
||||
if (values.size() > 1) {
|
||||
std::string src = GenID("_src");
|
||||
out << indent() << src << " := []";
|
||||
t_base_type::t_base tbase = ((t_base_type*)context.type)->get_base();
|
||||
switch (tbase) {
|
||||
case t_base_type::TYPE_I8:
|
||||
out << "int8";
|
||||
break;
|
||||
case t_base_type::TYPE_I16:
|
||||
out << "int16";
|
||||
break;
|
||||
case t_base_type::TYPE_I32:
|
||||
out << "int32";
|
||||
break;
|
||||
case t_base_type::TYPE_I64:
|
||||
out << "int64";
|
||||
break;
|
||||
default:
|
||||
throw "validator error: unsupported integer type: " + context.type->get_name();
|
||||
}
|
||||
out << "{";
|
||||
for (auto it = values.begin(); it != values.end(); it++) {
|
||||
if (it != values.begin()) {
|
||||
out << ", ";
|
||||
}
|
||||
if ((*it)->is_field_reference()) {
|
||||
out << get_field_reference_name((*it)->get_field_reference());
|
||||
} else if ((*it)->is_validation_function()) {
|
||||
generate_current_type(out, context.type);
|
||||
out << "(";
|
||||
validation_value::validation_function* func = (*it)->get_function();
|
||||
if (func->name == "len") {
|
||||
out << "len(";
|
||||
if (func->arguments[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(func->arguments[0]->get_field_reference());
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << ")";
|
||||
} else {
|
||||
out << (*it)->get_int();
|
||||
}
|
||||
}
|
||||
out << "}" << endl;
|
||||
|
||||
out << indent() << "for _, src := range " << src << " {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "if " << context.tgt << " == src {" << endl;
|
||||
} else {
|
||||
out << indent() << "if " << context.tgt << " == ";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else if (values[0]->is_validation_function()) {
|
||||
generate_current_type(out, context.type);
|
||||
out << "(";
|
||||
validation_value::validation_function* func = values[0]->get_function();
|
||||
if (func->name == "len") {
|
||||
out << "len(";
|
||||
if (func->arguments[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(func->arguments[0]->get_field_reference());
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << ")";
|
||||
} else {
|
||||
out << values[0]->get_int();
|
||||
}
|
||||
out << "{" << endl;
|
||||
}
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.not_in\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol
|
||||
<< " not valid, rule vt.not_in check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
if (values.size() > 1) {
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_string_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
std::string target = context.tgt;
|
||||
t_type* type = context.type;
|
||||
if (type->is_typedef()) {
|
||||
type = type->get_true_type();
|
||||
}
|
||||
if (type->is_binary()) {
|
||||
target = GenID("_tgt");
|
||||
out << indent() << target << " := "
|
||||
<< "string(" << context.tgt << ")" << endl;
|
||||
}
|
||||
for (auto it = context.rules.begin(); it != context.rules.end(); it++) {
|
||||
const std::vector<validation_value*>& values = (*it)->get_values();
|
||||
if (values.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
std::string key = (*it)->get_name();
|
||||
|
||||
if (key == "vt.const") {
|
||||
out << indent() << "if " << target << " != ";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << "string(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
} else {
|
||||
out << "\"" << values[0]->get_string() << "\"";
|
||||
}
|
||||
} else if (key == "vt.min_size" || key == "vt.max_size") {
|
||||
out << indent() << "if len(" << target << ") ";
|
||||
if (key == "vt.min_size") {
|
||||
out << "<";
|
||||
} else {
|
||||
out << ">";
|
||||
}
|
||||
out << " int(";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
} else if (values[0]->is_validation_function()) {
|
||||
validation_value::validation_function* func = values[0]->get_function();
|
||||
if (func->name == "len") {
|
||||
out << "len(";
|
||||
if (func->arguments[0]->is_field_reference()) {
|
||||
out << "string(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
} else {
|
||||
out << values[0]->get_int();
|
||||
}
|
||||
out << ")";
|
||||
} else if (key == "vt.pattern") {
|
||||
out << indent() << "if ok, _ := regexp.MatchString(" << target << ",";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << "string(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
} else {
|
||||
out << "\"" << values[0]->get_string() << "\"";
|
||||
}
|
||||
out << "); ok ";
|
||||
} else if (key == "vt.prefix") {
|
||||
out << indent() << "if !strings.HasPrefix(" << target << ",";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << "string(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
} else {
|
||||
out << "\"" << values[0]->get_string() << "\"";
|
||||
}
|
||||
out << ")";
|
||||
} else if (key == "vt.suffix") {
|
||||
out << indent() << "if !strings.HasSuffix(" << target << ",";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << "string(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
} else {
|
||||
out << "\"" << values[0]->get_string() << "\"";
|
||||
}
|
||||
out << ")";
|
||||
} else if (key == "vt.contains") {
|
||||
out << indent() << "if !strings.Contains(" << target << ",";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << "string(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
} else {
|
||||
out << "\"" << values[0]->get_string() << "\"";
|
||||
}
|
||||
out << ")";
|
||||
} else if (key == "vt.not_contains") {
|
||||
out << indent() << "if strings.Contains(" << target << ",";
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << "string(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
} else {
|
||||
out << "\"" << values[0]->get_string() << "\"";
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << "{" << endl;
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key
|
||||
<< " check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_set_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
return generate_list_field_validator(out, context);
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_list_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
for (auto it = context.rules.begin(); it != context.rules.end(); it++) {
|
||||
const std::vector<validation_value*>& values = (*it)->get_values();
|
||||
std::string key = (*it)->get_name();
|
||||
if (key == "vt.min_size" || key == "vt.max_size") {
|
||||
out << indent() << "if len(" << context.tgt << ")";
|
||||
if (key == "vt.min_size") {
|
||||
out << " < ";
|
||||
} else {
|
||||
out << " > ";
|
||||
}
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << "int(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
} else {
|
||||
out << values[0]->get_int();
|
||||
}
|
||||
out << "{" << endl;
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key
|
||||
<< " check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
} else if (key == "vt.elem") {
|
||||
out << indent() << "for i := 0; i < len(" << context.tgt << ");i++ {" << endl;
|
||||
indent_up();
|
||||
std::string src = GenID("_elem");
|
||||
out << indent() << src << " := " << context.tgt << "[i]" << endl;
|
||||
t_type* elem_type;
|
||||
if (context.type->is_list()) {
|
||||
elem_type = ((t_list*)context.type)->get_elem_type();
|
||||
} else {
|
||||
elem_type = ((t_set*)context.type)->get_elem_type();
|
||||
}
|
||||
generator_context ctx{context.field_symbol + ".elem",
|
||||
"",
|
||||
src,
|
||||
false,
|
||||
elem_type,
|
||||
std::vector<validation_rule*>{(*it)->get_inner()}};
|
||||
generate_field_validator(out, ctx);
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_map_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
for (auto it = context.rules.begin(); it != context.rules.end(); it++) {
|
||||
const std::vector<validation_value*>& values = (*it)->get_values();
|
||||
std::string key = (*it)->get_name();
|
||||
if (key == "vt.min_size" || key == "vt.max_size") {
|
||||
out << indent() << "if len(" << context.tgt << ")";
|
||||
if (key == "vt.min_size") {
|
||||
out << " < ";
|
||||
} else {
|
||||
out << " > ";
|
||||
}
|
||||
if (values[0]->is_field_reference()) {
|
||||
out << "int(";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << ")";
|
||||
} else {
|
||||
out << values[0]->get_int();
|
||||
}
|
||||
out << "{" << endl;
|
||||
indent_up();
|
||||
out << indent()
|
||||
<< "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \""
|
||||
<< context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key
|
||||
<< " check failed\")" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
} else if (key == "vt.key") {
|
||||
std::string src = GenID("_key");
|
||||
out << indent() << "for " << src << " := range " << context.tgt << " {" << endl;
|
||||
indent_up();
|
||||
generator_context ctx{context.field_symbol + ".key",
|
||||
"",
|
||||
src,
|
||||
false,
|
||||
((t_map*)context.type)->get_key_type(),
|
||||
std::vector<validation_rule*>{(*it)->get_inner()}};
|
||||
generate_field_validator(out, ctx);
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
} else if (key == "vt.value") {
|
||||
std::string src = GenID("_value");
|
||||
out << indent() << "for _, " << src << " := range " << context.tgt << " {" << endl;
|
||||
indent_up();
|
||||
generator_context ctx{context.field_symbol + ".value",
|
||||
"",
|
||||
src,
|
||||
false,
|
||||
((t_map*)context.type)->get_val_type(),
|
||||
std::vector<validation_rule*>{(*it)->get_inner()}};
|
||||
generate_field_validator(out, ctx);
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void go_validator_generator::generate_struct_field_validator(std::ostream& out,
|
||||
const generator_context& context) {
|
||||
bool generate_valid = true;
|
||||
validation_rule* last_valid_rule = nullptr;
|
||||
for (auto it = context.rules.begin(); it != context.rules.end(); it++) {
|
||||
const std::vector<validation_value*>& values = (*it)->get_values();
|
||||
if (values.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
std::string key = (*it)->get_name();
|
||||
|
||||
if (key == "vt.skip") {
|
||||
if (values[0]->is_field_reference() || !values[0]->get_bool()) {
|
||||
generate_valid = true;
|
||||
} else if (values[0]->get_bool()) {
|
||||
generate_valid = false;
|
||||
}
|
||||
last_valid_rule = *it;
|
||||
}
|
||||
}
|
||||
if (generate_valid) {
|
||||
if (last_valid_rule == nullptr) {
|
||||
out << indent() << "if err := " << context.tgt << ".Validate(); err != nil {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "return err" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
} else {
|
||||
const std::vector<validation_value*>& values = last_valid_rule->get_values();
|
||||
if (!values[0]->get_bool()) {
|
||||
out << indent() << "if err := " << context.tgt << ".Validate(); err != nil {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "return err" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
} else if (values[0]->is_field_reference()) {
|
||||
out << indent() << "if !";
|
||||
out << get_field_reference_name(values[0]->get_field_reference());
|
||||
out << "{" << endl;
|
||||
indent_up();
|
||||
out << indent() << "if err := " << context.tgt << ".Validate(); err != nil {" << endl;
|
||||
indent_up();
|
||||
out << indent() << "return err" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
72
compiler/cpp/src/thrift/generate/go_validator_generator.h
Normal file
72
compiler/cpp/src/thrift/generate/go_validator_generator.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef T_GO_VALIDATOR_GENERATOR_H
|
||||
#define T_GO_VALIDATOR_GENERATOR_H
|
||||
|
||||
#include "thrift/generate/t_generator.h"
|
||||
#include "thrift/generate/t_go_generator.h"
|
||||
#include "thrift/generate/validator_parser.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class go_validator_generator {
|
||||
public:
|
||||
go_validator_generator(t_go_generator* gg) : go_generator(gg){};
|
||||
void generate_struct_validator(std::ostream& out, t_struct* tstruct);
|
||||
|
||||
struct generator_context {
|
||||
std::string field_symbol;
|
||||
std::string src;
|
||||
std::string tgt;
|
||||
bool opt;
|
||||
t_type* type;
|
||||
std::vector<validation_rule*> rules;
|
||||
};
|
||||
|
||||
private:
|
||||
void generate_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_enum_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_bool_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_integer_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_double_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_string_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_list_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_set_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_map_field_validator(std::ostream& out, const generator_context& context);
|
||||
void generate_struct_field_validator(std::ostream& out, const generator_context& context);
|
||||
|
||||
void indent_up() { go_generator->indent_up(); }
|
||||
void indent_down() { go_generator->indent_down(); }
|
||||
std::string indent() { return go_generator->indent(); }
|
||||
|
||||
//std::string get_field_name(t_field* field); -- no impl?
|
||||
std::string get_field_reference_name(t_field* field);
|
||||
|
||||
std::string GenID(std::string id) { return id + std::to_string(tmp_[id]++); };
|
||||
|
||||
t_go_generator* go_generator;
|
||||
|
||||
std::map<std::string, int> tmp_;
|
||||
};
|
||||
|
||||
#endif
|
@ -105,6 +105,7 @@ public:
|
||||
/* initialization and destruction */
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/* generation functions */
|
||||
void generate_typedef(t_typedef* ttypedef) override;
|
||||
@ -723,6 +724,8 @@ string t_c_glib_generator::type_to_enum(t_type* type) {
|
||||
return "T_I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "T_DOUBLE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "T_I32";
|
||||
@ -4581,4 +4584,9 @@ string underscores_to_initial_caps(string name) {
|
||||
}
|
||||
|
||||
/* register this generator with the main program */
|
||||
std::string t_c_glib_generator::display_name() const {
|
||||
return "C, using GLib";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(c_glib, "C, using GLib", "")
|
||||
|
564
compiler/cpp/src/thrift/generate/t_cl_generator.cc
Normal file
564
compiler/cpp/src/thrift/generate/t_cl_generator.cc
Normal file
@ -0,0 +1,564 @@
|
||||
/*
|
||||
* Copyright (c) 2008- Patrick Collison <patrick@collison.ie>
|
||||
* Copyright (c) 2006- Facebook
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "thrift/platform.h"
|
||||
#include "t_oop_generator.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
/**
|
||||
* Common Lisp code generator.
|
||||
*
|
||||
* @author Patrick Collison <patrick@collison.ie>
|
||||
*/
|
||||
class t_cl_generator : public t_oop_generator {
|
||||
public:
|
||||
t_cl_generator(
|
||||
t_program* program,
|
||||
const std::map<std::string, std::string>& parsed_options,
|
||||
const std::string& option_string)
|
||||
: t_oop_generator(program)
|
||||
{
|
||||
no_asd = false;
|
||||
system_prefix = "thrift-gen-";
|
||||
|
||||
std::map<std::string, std::string>::const_iterator iter;
|
||||
|
||||
for(iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
|
||||
if(iter->first.compare("no_asd") == 0) {
|
||||
no_asd = true;
|
||||
} else if (iter->first.compare("sys_pref") == 0) {
|
||||
system_prefix = iter->second;
|
||||
} else {
|
||||
throw "unknown option cl:" + iter->first;
|
||||
}
|
||||
}
|
||||
|
||||
out_dir_base_ = "gen-cl";
|
||||
copy_options_ = option_string;
|
||||
}
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_typedef (t_typedef* ttypedef) override;
|
||||
void generate_enum (t_enum* tenum) override;
|
||||
void generate_const (t_const* tconst) override;
|
||||
void generate_struct (t_struct* tstruct) override;
|
||||
void generate_xception (t_struct* txception) override;
|
||||
void generate_service (t_service* tservice) override;
|
||||
void generate_cl_struct (std::ostream& out, t_struct* tstruct, bool is_exception);
|
||||
void generate_cl_struct_internal (std::ostream& out, t_struct* tstruct, bool is_exception);
|
||||
void generate_exception_sig(std::ostream& out, t_function* f);
|
||||
std::string render_const_value(t_type* type, t_const_value* value);
|
||||
|
||||
std::string cl_autogen_comment();
|
||||
void asdf_def(std::ostream &out);
|
||||
void package_def(std::ostream &out);
|
||||
void package_in(std::ostream &out);
|
||||
std::string generated_package();
|
||||
std::string prefix(std::string name);
|
||||
std::string package_of(t_program* program);
|
||||
std::string package();
|
||||
std::string render_includes();
|
||||
|
||||
std::string type_name(t_type* ttype);
|
||||
std::string typespec (t_type *t);
|
||||
std::string function_signature(t_function* tfunction);
|
||||
std::string argument_list(t_struct* tstruct);
|
||||
|
||||
std::string cl_docstring(std::string raw);
|
||||
|
||||
private:
|
||||
|
||||
int temporary_var;
|
||||
/**
|
||||
* Isolate the variable definitions, as they can require structure definitions
|
||||
*/
|
||||
ofstream_with_content_based_conditional_update f_asd_;
|
||||
ofstream_with_content_based_conditional_update f_types_;
|
||||
ofstream_with_content_based_conditional_update f_vars_;
|
||||
|
||||
std::string copy_options_;
|
||||
|
||||
bool no_asd;
|
||||
std::string system_prefix;
|
||||
};
|
||||
|
||||
|
||||
void t_cl_generator::init_generator() {
|
||||
MKDIR(get_out_dir().c_str());
|
||||
string program_dir = get_out_dir() + "/" + program_name_;
|
||||
MKDIR(program_dir.c_str());
|
||||
|
||||
temporary_var = 0;
|
||||
|
||||
string f_types_name = program_dir + "/" + program_name_ + "-types.lisp";
|
||||
string f_vars_name = program_dir + "/" + program_name_ + "-vars.lisp";
|
||||
|
||||
f_types_.open(f_types_name);
|
||||
f_types_ << cl_autogen_comment() << endl;
|
||||
f_vars_.open(f_vars_name);
|
||||
f_vars_ << cl_autogen_comment() << endl;
|
||||
|
||||
package_def(f_types_);
|
||||
package_in(f_types_);
|
||||
package_in(f_vars_);
|
||||
|
||||
if (!no_asd) {
|
||||
string f_asd_name = program_dir + "/" + system_prefix + program_name_ + ".asd";
|
||||
f_asd_.open(f_asd_name);
|
||||
f_asd_ << cl_autogen_comment() << endl;
|
||||
asdf_def(f_asd_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders all the imports necessary for including another Thrift program
|
||||
*/
|
||||
string t_cl_generator::render_includes() {
|
||||
const vector<t_program*>& includes = program_->get_includes();
|
||||
string result = "";
|
||||
result += ":depends-on (:thrift";
|
||||
for (auto include : includes) {
|
||||
result += " :" + system_prefix + underscore(include->get_name());
|
||||
}
|
||||
result += ")\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
string t_cl_generator::package_of(t_program* program) {
|
||||
string prefix = program->get_namespace("cl");
|
||||
return prefix.empty() ? "thrift-generated" : prefix;
|
||||
}
|
||||
|
||||
string t_cl_generator::package() {
|
||||
return package_of(program_);
|
||||
}
|
||||
|
||||
string t_cl_generator::prefix(string symbol) {
|
||||
return "\"" + symbol + "\"";
|
||||
}
|
||||
|
||||
string t_cl_generator::cl_autogen_comment() {
|
||||
return
|
||||
std::string(";;; ") + "Autogenerated by Thrift\n" +
|
||||
";;; DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" +
|
||||
";;; options string: " + copy_options_ + "\n";
|
||||
}
|
||||
|
||||
string t_cl_generator::cl_docstring(string raw) {
|
||||
replace(raw.begin(), raw.end(), '"', '\'');
|
||||
return raw;
|
||||
}
|
||||
|
||||
|
||||
void t_cl_generator::close_generator() {
|
||||
f_asd_.close();
|
||||
f_types_.close();
|
||||
f_vars_.close();
|
||||
}
|
||||
|
||||
string t_cl_generator::generated_package() {
|
||||
return program_->get_namespace("cpp");
|
||||
}
|
||||
|
||||
void t_cl_generator::asdf_def(std::ostream &out) {
|
||||
out << "(asdf:defsystem #:" << system_prefix << program_name_ << endl;
|
||||
indent_up();
|
||||
out << indent() << render_includes()
|
||||
<< indent() << ":serial t" << endl
|
||||
<< indent() << ":components ("
|
||||
<< "(:file \"" << program_name_ << "-types\") "
|
||||
<< "(:file \"" << program_name_ << "-vars\")))" << endl;
|
||||
indent_down();
|
||||
}
|
||||
|
||||
/***
|
||||
* Generate a package definition. Add use references equivalent to the idl file's include statements.
|
||||
*/
|
||||
void t_cl_generator::package_def(std::ostream &out) {
|
||||
const vector<t_program*>& includes = program_->get_includes();
|
||||
|
||||
out << "(thrift:def-package :" << package();
|
||||
if ( includes.size() > 0 ) {
|
||||
out << " :use (";
|
||||
for (auto include : includes) {
|
||||
out << " :" << include->get_name();
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
out << ")" << endl << endl;
|
||||
}
|
||||
|
||||
void t_cl_generator::package_in(std::ostream &out) {
|
||||
out << "(cl:in-package :" << package() << ")" << endl << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a typedef. This is not done in Common Lisp, types are all implicit.
|
||||
*
|
||||
* @param ttypedef The type definition
|
||||
*/
|
||||
void t_cl_generator::generate_typedef(t_typedef* ttypedef) {
|
||||
(void)ttypedef;
|
||||
}
|
||||
|
||||
void t_cl_generator::generate_enum(t_enum* tenum) {
|
||||
f_types_ << "(thrift:def-enum " << prefix(tenum->get_name()) << endl;
|
||||
|
||||
vector<t_enum_value*> constants = tenum->get_constants();
|
||||
vector<t_enum_value*>::iterator c_iter;
|
||||
int value = -1;
|
||||
|
||||
indent_up();
|
||||
f_types_ << indent() << "(";
|
||||
for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
|
||||
value = (*c_iter)->get_value();
|
||||
|
||||
if(c_iter != constants.begin()) f_types_ << endl << indent() << " ";
|
||||
|
||||
f_types_ << "(\"" << (*c_iter)->get_name() << "\" . " << value << ")";
|
||||
}
|
||||
indent_down();
|
||||
f_types_ << "))" << endl << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a constant value
|
||||
*/
|
||||
void t_cl_generator::generate_const(t_const* tconst) {
|
||||
t_type* type = tconst->get_type();
|
||||
string name = tconst->get_name();
|
||||
t_const_value* value = tconst->get_value();
|
||||
|
||||
f_vars_ << "(thrift:def-constant " << prefix(name) << " " << render_const_value(type, value) << ")"
|
||||
<< endl << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the value of a constant with the given type. Note that type checking
|
||||
* is NOT performed in this function as it is always run beforehand using the
|
||||
* validate_types method in main.cc
|
||||
*/
|
||||
string t_cl_generator::render_const_value(t_type* type, t_const_value* value) {
|
||||
type = get_true_type(type);
|
||||
std::ostringstream out;
|
||||
if (type->is_base_type()) {
|
||||
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
|
||||
switch (tbase) {
|
||||
case t_base_type::TYPE_STRING:
|
||||
out << "\"" << value->get_string() << "\"";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
out << (value->get_integer() > 0 ? "t" : "nil");
|
||||
break;
|
||||
case t_base_type::TYPE_I8:
|
||||
case t_base_type::TYPE_I16:
|
||||
case t_base_type::TYPE_I32:
|
||||
case t_base_type::TYPE_I64:
|
||||
out << value->get_integer();
|
||||
break;
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
if (value->get_type() == t_const_value::CV_INTEGER) {
|
||||
out << value->get_integer();
|
||||
} else {
|
||||
out << value->get_double();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
indent(out) << value->get_integer();
|
||||
} else if (type->is_struct() || type->is_xception()) {
|
||||
out << (type->is_struct() ? "(make-instance '" : "(make-exception '") <<
|
||||
lowercase(type->get_name()) << " " << endl;
|
||||
indent_up();
|
||||
|
||||
const vector<t_field*>& fields = ((t_struct*)type)->get_members();
|
||||
vector<t_field*>::const_iterator f_iter;
|
||||
const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
|
||||
map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
|
||||
|
||||
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
|
||||
t_type* field_type = nullptr;
|
||||
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
|
||||
if ((*f_iter)->get_name() == v_iter->first->get_string()) {
|
||||
field_type = (*f_iter)->get_type();
|
||||
}
|
||||
}
|
||||
if (field_type == nullptr) {
|
||||
throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
|
||||
}
|
||||
|
||||
out << indent() << ":" << v_iter->first->get_string() << " " <<
|
||||
render_const_value(field_type, v_iter->second) << endl;
|
||||
}
|
||||
out << indent() << ")";
|
||||
|
||||
indent_down();
|
||||
} else if (type->is_map()) {
|
||||
// emit an hash form with both keys and values to be evaluated
|
||||
t_type* ktype = ((t_map*)type)->get_key_type();
|
||||
t_type* vtype = ((t_map*)type)->get_val_type();
|
||||
out << "(thrift:map ";
|
||||
indent_up();
|
||||
const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
|
||||
map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
|
||||
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
|
||||
out << endl << indent()
|
||||
<< "(cl:cons " << render_const_value(ktype, v_iter->first) << " "
|
||||
<< render_const_value(vtype, v_iter->second) << ")";
|
||||
}
|
||||
indent_down();
|
||||
out << indent() << ")";
|
||||
} else if (type->is_list() || type->is_set()) {
|
||||
t_type* etype;
|
||||
if (type->is_list()) {
|
||||
etype = ((t_list*)type)->get_elem_type();
|
||||
} else {
|
||||
etype = ((t_set*)type)->get_elem_type();
|
||||
}
|
||||
if (type->is_set()) {
|
||||
out << "(thrift:set" << endl;
|
||||
} else {
|
||||
out << "(thrift:list" << endl;
|
||||
}
|
||||
indent_up();
|
||||
indent_up();
|
||||
const vector<t_const_value*>& val = value->get_list();
|
||||
vector<t_const_value*>::const_iterator v_iter;
|
||||
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
|
||||
out << indent() << render_const_value(etype, *v_iter) << endl;
|
||||
}
|
||||
out << indent() << ")";
|
||||
indent_down();
|
||||
indent_down();
|
||||
} else {
|
||||
throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
void t_cl_generator::generate_struct(t_struct* tstruct) {
|
||||
generate_cl_struct(f_types_, tstruct, false);
|
||||
}
|
||||
|
||||
void t_cl_generator::generate_xception(t_struct* txception) {
|
||||
generate_cl_struct(f_types_, txception, true);
|
||||
}
|
||||
|
||||
void t_cl_generator::generate_cl_struct_internal(std::ostream& out, t_struct* tstruct, bool is_exception) {
|
||||
(void)is_exception;
|
||||
const vector<t_field*>& members = tstruct->get_members();
|
||||
vector<t_field*>::const_iterator m_iter;
|
||||
|
||||
out << "(";
|
||||
|
||||
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
|
||||
t_const_value* value = (*m_iter)->get_value();
|
||||
t_type* type = (*m_iter)->get_type();
|
||||
|
||||
if (m_iter != members.begin()) {
|
||||
out << endl << indent() << " ";
|
||||
}
|
||||
out << "(" << prefix((*m_iter)->get_name()) << " " <<
|
||||
( (nullptr != value) ? render_const_value(type, value) : "nil" ) <<
|
||||
" :id " << (*m_iter)->get_key();
|
||||
if ( type->is_base_type() && "string" == typespec(type) )
|
||||
if ( ((t_base_type*)type)->is_binary() )
|
||||
out << " :type binary";
|
||||
else
|
||||
out << " :type string";
|
||||
else
|
||||
out << " :type " << typespec(type);
|
||||
if ( (*m_iter)->get_req() == t_field::T_OPTIONAL ) {
|
||||
out << " :optional t";
|
||||
}
|
||||
if ( (*m_iter)->has_doc()) {
|
||||
out << " :documentation \"" << cl_docstring((*m_iter)->get_doc()) << "\"";
|
||||
}
|
||||
out <<")";
|
||||
}
|
||||
|
||||
out << ")";
|
||||
}
|
||||
|
||||
void t_cl_generator::generate_cl_struct(std::ostream& out, t_struct* tstruct, bool is_exception = false) {
|
||||
std::string name = type_name(tstruct);
|
||||
out << (is_exception ? "(thrift:def-exception " : "(thrift:def-struct ") <<
|
||||
prefix(name) << endl;
|
||||
indent_up();
|
||||
if ( tstruct->has_doc() ) {
|
||||
out << indent() ;
|
||||
out << "\"" << cl_docstring(tstruct->get_doc()) << "\"" << endl;
|
||||
}
|
||||
out << indent() ;
|
||||
generate_cl_struct_internal(out, tstruct, is_exception);
|
||||
indent_down();
|
||||
out << ")" << endl << endl;
|
||||
}
|
||||
|
||||
void t_cl_generator::generate_exception_sig(std::ostream& out, t_function* f) {
|
||||
generate_cl_struct_internal(out, f->get_xceptions(), true);
|
||||
}
|
||||
|
||||
void t_cl_generator::generate_service(t_service* tservice) {
|
||||
string extends_client;
|
||||
vector<t_function*> functions = tservice->get_functions();
|
||||
vector<t_function*>::iterator f_iter;
|
||||
|
||||
if (tservice->get_extends() != nullptr) {
|
||||
extends_client = type_name(tservice->get_extends());
|
||||
}
|
||||
|
||||
extends_client = extends_client.empty() ? "nil" : prefix(extends_client);
|
||||
|
||||
f_types_ << "(thrift:def-service " << prefix(service_name_) << " "
|
||||
<< extends_client;
|
||||
|
||||
indent_up();
|
||||
|
||||
if ( tservice->has_doc()) {
|
||||
f_types_ << endl << indent()
|
||||
<< "(:documentation \"" << cl_docstring(tservice->get_doc()) << "\")";
|
||||
}
|
||||
|
||||
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
|
||||
t_function* function = *f_iter;
|
||||
string fname = function->get_name();
|
||||
string signature = function_signature(function);
|
||||
t_struct* exceptions = function->get_xceptions();
|
||||
const vector<t_field*>& xmembers = exceptions->get_members();
|
||||
|
||||
f_types_ << endl << indent() << "(:method " << prefix(fname);
|
||||
f_types_ << " (" << signature << " " << typespec((*f_iter)->get_returntype()) << ")";
|
||||
if (xmembers.size() > 0) {
|
||||
f_types_ << endl << indent() << " :exceptions " ;
|
||||
generate_exception_sig(f_types_, function);
|
||||
}
|
||||
if ( (*f_iter)->is_oneway() ) {
|
||||
f_types_ << endl << indent() << " :oneway t";
|
||||
}
|
||||
if ( (*f_iter)->has_doc() ) {
|
||||
f_types_ << endl << indent() << " :documentation \""
|
||||
<< cl_docstring((*f_iter)->get_doc()) << "\"";
|
||||
}
|
||||
f_types_ << ")";
|
||||
}
|
||||
|
||||
f_types_ << ")" << endl << endl;
|
||||
|
||||
indent_down();
|
||||
}
|
||||
|
||||
string t_cl_generator::typespec(t_type *t) {
|
||||
t = get_true_type(t);
|
||||
|
||||
if (t -> is_binary()){
|
||||
return "binary";
|
||||
} else if (t->is_base_type()) {
|
||||
return type_name(t);
|
||||
} else if (t->is_map()) {
|
||||
t_map *m = (t_map*) t;
|
||||
return "(thrift:map " + typespec(m->get_key_type()) + " " +
|
||||
typespec(m->get_val_type()) + ")";
|
||||
} else if (t->is_struct() || t->is_xception()) {
|
||||
return "(struct " + prefix(type_name(t)) + ")";
|
||||
} else if (t->is_list()) {
|
||||
return "(thrift:list " + typespec(((t_list*) t)->get_elem_type()) + ")";
|
||||
} else if (t->is_set()) {
|
||||
return "(thrift:set " + typespec(((t_set*) t)->get_elem_type()) + ")";
|
||||
} else if (t->is_enum()) {
|
||||
return "(enum \"" + ((t_enum*) t)->get_name() + "\")";
|
||||
} else {
|
||||
throw "Sorry, I don't know how to generate this: " + type_name(t);
|
||||
}
|
||||
}
|
||||
|
||||
string t_cl_generator::function_signature(t_function* tfunction) {
|
||||
return argument_list(tfunction->get_arglist());
|
||||
}
|
||||
|
||||
string t_cl_generator::argument_list(t_struct* tstruct) {
|
||||
stringstream res;
|
||||
res << "(";
|
||||
|
||||
const vector<t_field*>& fields = tstruct->get_members();
|
||||
vector<t_field*>::const_iterator f_iter;
|
||||
bool first = true;
|
||||
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
res << " ";
|
||||
}
|
||||
res << "(" + prefix((*f_iter)->get_name()) << " " <<
|
||||
typespec((*f_iter)->get_type()) << " " <<
|
||||
(*f_iter)->get_key() << ")";
|
||||
|
||||
|
||||
}
|
||||
res << ")";
|
||||
return res.str();
|
||||
}
|
||||
|
||||
string t_cl_generator::type_name(t_type* ttype) {
|
||||
string prefix = "";
|
||||
t_program* program = ttype->get_program();
|
||||
|
||||
if (program != nullptr && program != program_)
|
||||
prefix = package_of(program) == package() ? "" : package_of(program) + ":";
|
||||
|
||||
string name = ttype->get_name();
|
||||
|
||||
if (ttype->is_struct() || ttype->is_xception())
|
||||
name = lowercase(ttype->get_name());
|
||||
|
||||
return prefix + name;
|
||||
}
|
||||
|
||||
std::string t_cl_generator::display_name() const {
|
||||
return "Common Lisp";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
cl,
|
||||
"Common Lisp",
|
||||
" no_asd: Do not define ASDF systems for each generated Thrift program.\n"
|
||||
" sys_pref= The prefix to give ASDF system names. Default: thrift-gen-\n")
|
@ -104,6 +104,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_consts(std::vector<t_const*> consts) override;
|
||||
|
||||
@ -4398,9 +4399,9 @@ string t_cpp_generator::namespace_close(string ns) {
|
||||
string t_cpp_generator::type_name(t_type* ttype, bool in_typedef, bool arg) {
|
||||
if (ttype->is_base_type()) {
|
||||
string bname = base_type_name(((t_base_type*)ttype)->get_base());
|
||||
std::map<string, string>::iterator it = ttype->annotations_.find("cpp.type");
|
||||
if (it != ttype->annotations_.end()) {
|
||||
bname = it->second;
|
||||
std::map<string, std::vector<string>>::iterator it = ttype->annotations_.find("cpp.type");
|
||||
if (it != ttype->annotations_.end() && !it->second.empty()) {
|
||||
bname = it->second.back();
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
@ -4660,6 +4661,8 @@ string t_cpp_generator::type_to_enum(t_type* type) {
|
||||
return "::apache::thrift::protocol::T_I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "::apache::thrift::protocol::T_DOUBLE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "::apache::thrift::protocol::T_I32";
|
||||
@ -4749,6 +4752,11 @@ string t_cpp_generator::get_legal_program_name(std::string program_name)
|
||||
return program_name;
|
||||
}
|
||||
|
||||
std::string t_cpp_generator::display_name() const {
|
||||
return "C++";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
cpp,
|
||||
"C++",
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
|
||||
out_dir_base_ = "gen-d";
|
||||
}
|
||||
std::string display_name() const override;
|
||||
|
||||
protected:
|
||||
|
||||
@ -371,6 +372,7 @@ private:
|
||||
/**
|
||||
* Writes a server skeleton for the passed service to out.
|
||||
*/
|
||||
|
||||
void print_server_skeleton(ostream& out, t_service* tservice) {
|
||||
string svc_name = suffix_if_reserved(tservice->get_name());
|
||||
|
||||
@ -432,6 +434,7 @@ private:
|
||||
/**
|
||||
* Writes the definition of a struct or an exception type to out.
|
||||
*/
|
||||
|
||||
void print_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) {
|
||||
const vector<t_field*>& members = tstruct->get_members();
|
||||
|
||||
@ -495,6 +498,7 @@ private:
|
||||
* Prints the D function signature (including return type) for the given
|
||||
* method.
|
||||
*/
|
||||
|
||||
void print_function_signature(ostream& out, t_function* fn) {
|
||||
out << render_type_name(fn->get_returntype()) << " " << suffix_if_reserved(fn->get_name()) << "(";
|
||||
|
||||
@ -722,6 +726,7 @@ private:
|
||||
* Writes the default list of imports (which are written to every generated
|
||||
* module) to f.
|
||||
*/
|
||||
|
||||
void print_default_imports(ostream& out) {
|
||||
indent(out) << "import thrift.base;" << endl << "import thrift.codegen.base;" << endl
|
||||
<< "import thrift.util.hashset;" << endl << endl;
|
||||
@ -771,4 +776,9 @@ vector<string> t_d_generator::d_reserved_words = {
|
||||
"ushort", "version", "void", "wchar", "while", "with"
|
||||
};
|
||||
|
||||
std::string t_d_generator::display_name() const {
|
||||
return "D";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(d, "D", "")
|
||||
|
@ -123,6 +123,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void export_class_to_library(string file_name, string class_name);
|
||||
|
||||
@ -2216,6 +2217,8 @@ string t_dart_generator::declare_field(t_field* tfield, bool init) {
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
result += " = 0.0";
|
||||
break;
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
|
||||
} else if (ttype->is_enum()) {
|
||||
@ -2297,6 +2300,8 @@ string t_dart_generator::type_to_enum(t_type* type) {
|
||||
return "TType.I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "TType.DOUBLE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "TType.I32";
|
||||
@ -2351,6 +2356,8 @@ std::string t_dart_generator::init_value(t_field* field) {
|
||||
case t_base_type::TYPE_STRING:
|
||||
result = "";
|
||||
break;
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -2502,6 +2509,11 @@ std::string t_dart_generator::get_ttype_class_name(t_type* ttype) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string t_dart_generator::display_name() const {
|
||||
return "Dart";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
dart,
|
||||
"Dart",
|
||||
|
@ -45,6 +45,7 @@
|
||||
#endif
|
||||
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::ofstream;
|
||||
using std::ostream;
|
||||
using std::ostringstream;
|
||||
@ -70,14 +71,18 @@ public:
|
||||
ansistr_binary_ = false;
|
||||
register_types_ = false;
|
||||
constprefix_ = false;
|
||||
old_names_ = false;
|
||||
events_ = false;
|
||||
xmldoc_ = false;
|
||||
async_ = false;
|
||||
com_types_ = false;
|
||||
for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
|
||||
if( iter->first.compare("ansistr_binary") == 0) {
|
||||
ansistr_binary_ = true;
|
||||
} else if( iter->first.compare("register_types") == 0) {
|
||||
register_types_ = true;
|
||||
} else if( iter->first.compare("old_names") == 0) {
|
||||
old_names_ = true;
|
||||
} else if( iter->first.compare("constprefix") == 0) {
|
||||
constprefix_ = true;
|
||||
} else if( iter->first.compare("events") == 0) {
|
||||
@ -86,11 +91,17 @@ public:
|
||||
xmldoc_ = true;
|
||||
} else if( iter->first.compare("async") == 0) {
|
||||
async_ = true;
|
||||
} else if( iter->first.compare("com_types") == 0) {
|
||||
com_types_ = true;
|
||||
} else {
|
||||
throw "unknown option delphi:" + iter->first;
|
||||
}
|
||||
}
|
||||
|
||||
if(com_types_ && ansistr_binary_) {
|
||||
throw "com_types and ansistr_binary are mutually exclusive";
|
||||
}
|
||||
|
||||
out_dir_base_ = "gen-delphi";
|
||||
escape_.clear();
|
||||
escape_['\''] = "''";
|
||||
@ -98,6 +109,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_consts(std::vector<t_const*> consts) override;
|
||||
|
||||
@ -345,8 +357,8 @@ public:
|
||||
std::string argument_list(t_struct* tstruct);
|
||||
std::string constructor_argument_list(t_struct* tstruct, std::string current_indent);
|
||||
std::string type_to_enum(t_type* ttype);
|
||||
std::string prop_name(t_field* tfield, bool is_xception = false);
|
||||
std::string prop_name(std::string name, bool is_xception = false);
|
||||
std::string prop_name(t_field* tfield, bool is_xception = false, std::string prefix = "");
|
||||
std::string prop_name(std::string name, bool is_xception = false, std::string prefix = "");
|
||||
std::string constructor_param_name(string name);
|
||||
|
||||
void write_enum(std::string line);
|
||||
@ -394,18 +406,59 @@ private:
|
||||
bool has_enum;
|
||||
bool has_const;
|
||||
std::string namespace_dir_;
|
||||
std::map<std::string, int> delphi_keywords;
|
||||
std::map<std::string, int> delphi_reserved_method;
|
||||
std::map<std::string, int> delphi_reserved_method_exception;
|
||||
std::map<std::string, int> types_known;
|
||||
std::set<std::string> types_known;
|
||||
std::list<t_typedef*> typedefs_pending;
|
||||
std::vector<std::string> uses_list;
|
||||
void create_keywords();
|
||||
bool find_keyword(std::map<std::string, int>& keyword_map, std::string name);
|
||||
std::string empty_value(t_type* type);
|
||||
|
||||
const std::string DELPHI_KEYWORDS[81] = {
|
||||
// keywords
|
||||
"and", "array", "as", "asm", "at", "automated", "begin", "case", "class", "const", "constructor",
|
||||
"destructor", "dispinterface", "div", "do", "downto", "else", "end", "except", "exports", "file",
|
||||
"finalization", "finally", "for", "function", "goto", "if", "implementation", "in", "inherited",
|
||||
"initialization", "inline", "interface", "is", "label", "library", "mod", "nil", "not", "object",
|
||||
"of", "on", "or", "out", "packed", "private", "procedure", "program", "property", "protected",
|
||||
"public", "published", "raise", "record", "repeat", "resourcestring", "set", "shl", "shr", "string",
|
||||
"then", "threadvar", "to", "try", "type", "unit", "until", "uses", "var", "while", "with", "xor",
|
||||
// predefined types (lowercase!)
|
||||
"ansistring", "boolean", "double", "int64", "integer", "shortint", "smallint", "string", "unicodestring"
|
||||
};
|
||||
|
||||
// reserved variables and types (lowercase!)
|
||||
const std::string DELPHI_RESERVED_NAMES[8] = {
|
||||
"result", "system", "sysutils", "tbytes", "tclass", "thrift", "tinterfacedobject", "tobject"
|
||||
};
|
||||
|
||||
// reserved method names (lowercase!)
|
||||
const std::string DELPHI_RESERVED_METHOD[31] = {
|
||||
"afterconstruction", "beforedestruction", "classinfo", "classname", "classnameis", "classparent",
|
||||
"classtype", "cleanupinstance", "create", "defaulthandler", "destroy", "dispatch", "equals",
|
||||
"fieldaddress", "free", "freeinstance", "gethashcode", "getinterface", "getinterfaceentry",
|
||||
"getinterfacetable", "inheritsfrom", "initinstance", "instancesize", "methodaddress", "methodname",
|
||||
"newinstance", "read", "safecallexception", "tostring", "unitname", "write"
|
||||
};
|
||||
|
||||
// reserved exception class method names (lowercase!)
|
||||
const std::string DELPHI_RESERVED_METHOD_EXCEPTION[23] = {
|
||||
"setinnerexception", "setstackinfo", "getstacktrace", "raisingexception", "createfmt", "createres",
|
||||
"createresfmt", "createhelp", "createfmthelp", "createreshelp", "createresfmthelp", "getbaseexception",
|
||||
"baseexception", "helpcontext", "innerexception", "message", "stacktrace", "stackinfo",
|
||||
"getexceptionstackinfoproc", "getstackinfostringproc", "cleanupstackinfoproc", "raiseouterexception",
|
||||
"throwouterexception"
|
||||
};
|
||||
|
||||
// TODO: put all into one map, value=flags tells what it is
|
||||
std::set<std::string> delphi_keywords = std::set<string>(DELPHI_KEYWORDS, DELPHI_KEYWORDS + sizeof(DELPHI_KEYWORDS) / sizeof(DELPHI_KEYWORDS[0]));
|
||||
std::set<std::string> delphi_reserved_names = std::set<string>(DELPHI_RESERVED_NAMES, DELPHI_RESERVED_NAMES + sizeof(DELPHI_RESERVED_NAMES) / sizeof(DELPHI_RESERVED_NAMES[0]));
|
||||
std::set<std::string> delphi_reserved_method = std::set<string>(DELPHI_RESERVED_METHOD, DELPHI_RESERVED_METHOD + sizeof(DELPHI_RESERVED_METHOD) / sizeof(DELPHI_RESERVED_METHOD[0]));
|
||||
std::set<std::string> delphi_reserved_method_exception = std::set<string>(DELPHI_RESERVED_METHOD_EXCEPTION, DELPHI_RESERVED_METHOD_EXCEPTION + sizeof(DELPHI_RESERVED_METHOD_EXCEPTION) / sizeof(DELPHI_RESERVED_METHOD_EXCEPTION[0]));
|
||||
|
||||
bool find_keyword(std::set<std::string>& keywords, std::string name);
|
||||
std::string normalize_name(std::string name,
|
||||
bool b_method = false,
|
||||
bool b_exception_method = false);
|
||||
std::string empty_value(t_type* type);
|
||||
bool b_exception_method = false,
|
||||
bool b_force_underscore = false);
|
||||
|
||||
bool is_fully_defined_type(t_type* ttype);
|
||||
void add_defined_type(t_type* ttype);
|
||||
void init_known_types_list();
|
||||
@ -414,9 +467,11 @@ private:
|
||||
bool ansistr_binary_;
|
||||
bool register_types_;
|
||||
bool constprefix_;
|
||||
bool old_names_;
|
||||
bool events_;
|
||||
bool xmldoc_;
|
||||
bool async_;
|
||||
bool com_types_;
|
||||
void indent_up_impl() { ++indent_impl_; };
|
||||
void indent_down_impl() { --indent_impl_; };
|
||||
std::string indent_impl() {
|
||||
@ -537,7 +592,7 @@ void t_delphi_generator::generate_delphi_doc(ostream& out, t_function* tfunction
|
||||
}
|
||||
}
|
||||
|
||||
bool t_delphi_generator::find_keyword(std::map<std::string, int>& keyword_map, std::string name) {
|
||||
bool t_delphi_generator::find_keyword(std::set<std::string>& keywords, std::string name) {
|
||||
std::string::size_type len = name.length();
|
||||
|
||||
if (len <= 0) {
|
||||
@ -549,182 +604,45 @@ bool t_delphi_generator::find_keyword(std::map<std::string, int>& keyword_map, s
|
||||
if (nlast >= 1) {
|
||||
if (nlast == (len - 1)) {
|
||||
string new_name(name, 0, nlast);
|
||||
return find_keyword(keyword_map, new_name);
|
||||
return find_keyword(keywords, new_name);
|
||||
}
|
||||
}
|
||||
return (keyword_map[name] == 1);
|
||||
|
||||
return (keywords.find(name) != keywords.end());
|
||||
}
|
||||
|
||||
std::string t_delphi_generator::normalize_name(std::string name,
|
||||
bool b_method,
|
||||
bool b_exception_method) {
|
||||
bool b_exception_method,
|
||||
bool b_force_underscore) {
|
||||
string tmp(name);
|
||||
std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower));
|
||||
|
||||
bool b_found = false;
|
||||
bool b_reserved = false;
|
||||
bool b_keyword = false;
|
||||
|
||||
if (find_keyword(delphi_keywords, tmp)) {
|
||||
b_found = true;
|
||||
b_keyword = true;
|
||||
} else if (find_keyword(delphi_reserved_names, tmp)) {
|
||||
b_reserved = true;
|
||||
} else if (b_method && find_keyword(delphi_reserved_method, tmp)) {
|
||||
b_found = true;
|
||||
b_reserved = true;
|
||||
} else if (b_exception_method && find_keyword(delphi_reserved_method_exception, tmp)) {
|
||||
b_found = true;
|
||||
b_reserved = true;
|
||||
}
|
||||
|
||||
if (b_found) {
|
||||
return name + "_";
|
||||
} else {
|
||||
// neither reserved nor keyword?
|
||||
if (!(b_reserved || b_keyword)) {
|
||||
return name;
|
||||
}
|
||||
|
||||
// apply the rule: old style '_' postfix or more modern '&' prefix?
|
||||
// underscore always on non-keywords or when explicitly asked via arg
|
||||
if( (!b_keyword) || old_names_ || b_force_underscore) {
|
||||
return name + "_";
|
||||
} else {
|
||||
return "&" + name;
|
||||
}
|
||||
|
||||
void t_delphi_generator::create_keywords() {
|
||||
delphi_keywords["and"] = 1;
|
||||
delphi_keywords["end"] = 1;
|
||||
delphi_keywords["interface"] = 1;
|
||||
delphi_keywords["raise"] = 1;
|
||||
delphi_keywords["uses"] = 1;
|
||||
delphi_keywords["array"] = 1;
|
||||
delphi_keywords["except"] = 1;
|
||||
delphi_keywords["is"] = 1;
|
||||
delphi_keywords["record"] = 1;
|
||||
delphi_keywords["var"] = 1;
|
||||
delphi_keywords["as"] = 1;
|
||||
delphi_keywords["exports"] = 1;
|
||||
delphi_keywords["label"] = 1;
|
||||
delphi_keywords["repeat"] = 1;
|
||||
delphi_keywords["while"] = 1;
|
||||
delphi_keywords["asm"] = 1;
|
||||
delphi_keywords["file"] = 1;
|
||||
delphi_keywords["library"] = 1;
|
||||
delphi_keywords["resourcestring"] = 1;
|
||||
delphi_keywords["with"] = 1;
|
||||
delphi_keywords["begin"] = 1;
|
||||
delphi_keywords["finalization"] = 1;
|
||||
delphi_keywords["mod"] = 1;
|
||||
delphi_keywords["set"] = 1;
|
||||
delphi_keywords["xor"] = 1;
|
||||
delphi_keywords["case"] = 1;
|
||||
delphi_keywords["finally"] = 1;
|
||||
delphi_keywords["nil"] = 1;
|
||||
delphi_keywords["shl"] = 1;
|
||||
delphi_keywords["class"] = 1;
|
||||
delphi_keywords["for"] = 1;
|
||||
delphi_keywords["not"] = 1;
|
||||
delphi_keywords["shr"] = 1;
|
||||
delphi_keywords["const"] = 1;
|
||||
delphi_keywords["function"] = 1;
|
||||
delphi_keywords["object"] = 1;
|
||||
delphi_keywords["string"] = 1;
|
||||
delphi_keywords["constructor"] = 1;
|
||||
delphi_keywords["goto"] = 1;
|
||||
delphi_keywords["of"] = 1;
|
||||
delphi_keywords["then"] = 1;
|
||||
delphi_keywords["destructor"] = 1;
|
||||
delphi_keywords["if"] = 1;
|
||||
delphi_keywords["or"] = 1;
|
||||
delphi_keywords["threadvar"] = 1;
|
||||
delphi_keywords["dispinterface"] = 1;
|
||||
delphi_keywords["implementation"] = 1;
|
||||
delphi_keywords["out"] = 1;
|
||||
delphi_keywords["to"] = 1;
|
||||
delphi_keywords["div"] = 1;
|
||||
delphi_keywords["in"] = 1;
|
||||
delphi_keywords["packed"] = 1;
|
||||
delphi_keywords["try"] = 1;
|
||||
delphi_keywords["do"] = 1;
|
||||
delphi_keywords["inherited"] = 1;
|
||||
delphi_keywords["procedure"] = 1;
|
||||
delphi_keywords["type"] = 1;
|
||||
delphi_keywords["downto"] = 1;
|
||||
delphi_keywords["initialization"] = 1;
|
||||
delphi_keywords["program"] = 1;
|
||||
delphi_keywords["unit"] = 1;
|
||||
delphi_keywords["else"] = 1;
|
||||
delphi_keywords["inline"] = 1;
|
||||
delphi_keywords["property"] = 1;
|
||||
delphi_keywords["until"] = 1;
|
||||
delphi_keywords["private"] = 1;
|
||||
delphi_keywords["protected"] = 1;
|
||||
delphi_keywords["public"] = 1;
|
||||
delphi_keywords["published"] = 1;
|
||||
delphi_keywords["automated"] = 1;
|
||||
delphi_keywords["at"] = 1;
|
||||
delphi_keywords["on"] = 1;
|
||||
|
||||
// reserved/predefined variables and types (lowercase!)
|
||||
delphi_keywords["result"] = 1;
|
||||
delphi_keywords["system"] = 1;
|
||||
delphi_keywords["sysutils"] = 1;
|
||||
delphi_keywords["thrift"] = 1;
|
||||
delphi_keywords["tbytes"] = 1;
|
||||
delphi_keywords["tobject"] = 1;
|
||||
delphi_keywords["tclass"] = 1;
|
||||
delphi_keywords["tinterfacedobject"] = 1;
|
||||
delphi_keywords["ansistring"] = 1;
|
||||
delphi_keywords["string"] = 1;
|
||||
delphi_keywords["boolean"] = 1;
|
||||
delphi_keywords["shortint"] = 1;
|
||||
delphi_keywords["smallint"] = 1;
|
||||
delphi_keywords["integer"] = 1;
|
||||
delphi_keywords["int64"] = 1;
|
||||
delphi_keywords["double"] = 1;
|
||||
|
||||
delphi_reserved_method["create"] = 1;
|
||||
delphi_reserved_method["free"] = 1;
|
||||
delphi_reserved_method["initinstance"] = 1;
|
||||
delphi_reserved_method["cleanupinstance"] = 1;
|
||||
delphi_reserved_method["classtype"] = 1;
|
||||
delphi_reserved_method["classname"] = 1;
|
||||
delphi_reserved_method["classnameis"] = 1;
|
||||
delphi_reserved_method["classparent"] = 1;
|
||||
delphi_reserved_method["classinfo"] = 1;
|
||||
delphi_reserved_method["instancesize"] = 1;
|
||||
delphi_reserved_method["inheritsfrom"] = 1;
|
||||
delphi_reserved_method["methodaddress"] = 1;
|
||||
delphi_reserved_method["methodname"] = 1;
|
||||
delphi_reserved_method["fieldaddress"] = 1;
|
||||
delphi_reserved_method["getinterface"] = 1;
|
||||
delphi_reserved_method["getinterfaceentry"] = 1;
|
||||
delphi_reserved_method["getinterfacetable"] = 1;
|
||||
delphi_reserved_method["unitname"] = 1;
|
||||
delphi_reserved_method["equals"] = 1;
|
||||
delphi_reserved_method["gethashcode"] = 1;
|
||||
delphi_reserved_method["tostring"] = 1;
|
||||
delphi_reserved_method["safecallexception"] = 1;
|
||||
delphi_reserved_method["afterconstruction"] = 1;
|
||||
delphi_reserved_method["beforedestruction"] = 1;
|
||||
delphi_reserved_method["dispatch"] = 1;
|
||||
delphi_reserved_method["defaulthandler"] = 1;
|
||||
delphi_reserved_method["newinstance"] = 1;
|
||||
delphi_reserved_method["freeinstance"] = 1;
|
||||
delphi_reserved_method["destroy"] = 1;
|
||||
delphi_reserved_method["read"] = 1;
|
||||
delphi_reserved_method["write"] = 1;
|
||||
|
||||
delphi_reserved_method_exception["setinnerexception"] = 1;
|
||||
delphi_reserved_method_exception["setstackinfo"] = 1;
|
||||
delphi_reserved_method_exception["getstacktrace"] = 1;
|
||||
delphi_reserved_method_exception["raisingexception"] = 1;
|
||||
delphi_reserved_method_exception["createfmt"] = 1;
|
||||
delphi_reserved_method_exception["createres"] = 1;
|
||||
delphi_reserved_method_exception["createresfmt"] = 1;
|
||||
delphi_reserved_method_exception["createhelp"] = 1;
|
||||
delphi_reserved_method_exception["createfmthelp"] = 1;
|
||||
delphi_reserved_method_exception["createreshelp"] = 1;
|
||||
delphi_reserved_method_exception["createresfmthelp"] = 1;
|
||||
delphi_reserved_method_exception["getbaseexception"] = 1;
|
||||
delphi_reserved_method_exception["baseexception"] = 1;
|
||||
delphi_reserved_method_exception["helpcontext"] = 1;
|
||||
delphi_reserved_method_exception["innerexception"] = 1;
|
||||
delphi_reserved_method_exception["message"] = 1;
|
||||
delphi_reserved_method_exception["stacktrace"] = 1;
|
||||
delphi_reserved_method_exception["stackinfo"] = 1;
|
||||
delphi_reserved_method_exception["getexceptionstackinfoproc"] = 1;
|
||||
delphi_reserved_method_exception["getstackinfostringproc"] = 1;
|
||||
delphi_reserved_method_exception["cleanupstackinfoproc"] = 1;
|
||||
delphi_reserved_method_exception["raiseouterexception"] = 1;
|
||||
delphi_reserved_method_exception["throwouterexception"] = 1;
|
||||
}
|
||||
|
||||
void t_delphi_generator::add_delphi_uses_list(string unitname) {
|
||||
@ -747,7 +665,6 @@ void t_delphi_generator::init_generator() {
|
||||
has_forward = false;
|
||||
has_enum = false;
|
||||
has_const = false;
|
||||
create_keywords();
|
||||
|
||||
add_delphi_uses_list("Classes");
|
||||
add_delphi_uses_list("SysUtils");
|
||||
@ -773,7 +690,7 @@ void t_delphi_generator::init_generator() {
|
||||
unitname = include->get_name();
|
||||
nsname = include->get_namespace("delphi");
|
||||
if ("" != nsname) {
|
||||
unitname = normalize_name(nsname);
|
||||
unitname = normalize_name(nsname,false,false,true/*force underscore*/);
|
||||
}
|
||||
add_delphi_uses_list(unitname);
|
||||
}
|
||||
@ -793,7 +710,7 @@ void t_delphi_generator::close_generator() {
|
||||
}
|
||||
}
|
||||
|
||||
unitname = normalize_name(unitname);
|
||||
unitname = normalize_name(unitname,false,false,true/*force underscore*/);
|
||||
|
||||
std::string f_name = get_out_dir() + "/" + unitname + ".pas";
|
||||
ofstream_with_content_based_conditional_update f_all;
|
||||
@ -804,6 +721,9 @@ void t_delphi_generator::close_generator() {
|
||||
generate_delphi_doc(f_all, program_);
|
||||
f_all << "unit " << unitname << ";" << endl << endl;
|
||||
f_all << "{$WARN SYMBOL_DEPRECATED OFF}" << endl << endl;
|
||||
if(com_types_) {
|
||||
f_all << "{$MINENUMSIZE 4}" << endl << endl;
|
||||
}
|
||||
f_all << "interface" << endl << endl;
|
||||
f_all << "uses" << endl;
|
||||
|
||||
@ -831,18 +751,14 @@ void t_delphi_generator::close_generator() {
|
||||
|
||||
f_all << "const" << endl;
|
||||
indent_up();
|
||||
indent(f_all) << "c" << tmp_unit
|
||||
<< "_Option_AnsiStr_Binary = " << (ansistr_binary_ ? "True" : "False") << ";"
|
||||
<< endl;
|
||||
indent(f_all) << "c" << tmp_unit
|
||||
<< "_Option_Register_Types = " << (register_types_ ? "True" : "False") << ";"
|
||||
<< endl;
|
||||
indent(f_all) << "c" << tmp_unit
|
||||
<< "_Option_ConstPrefix = " << (constprefix_ ? "True" : "False") << ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_Events = " << (events_ ? "True" : "False")
|
||||
<< ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_XmlDoc = " << (xmldoc_ ? "True" : "False")
|
||||
<< ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_AnsiStr_Binary = " << (ansistr_binary_ ? "True" : "False") << ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_Register_Types = " << (register_types_ ? "True" : "False") << ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_ConstPrefix = " << (constprefix_ ? "True" : "False") << ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_Events = " << (events_ ? "True" : "False") << ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_XmlDoc = " << (xmldoc_ ? "True" : "False") << ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_Async = " << (async_ ? "True" : "False") << ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_COM_types = " << (com_types_ ? "True" : "False") << ";" << endl;
|
||||
indent(f_all) << "c" << tmp_unit << "_Option_Old_Names = " << (old_names_ ? "True" : "False") << ";" << endl;
|
||||
indent_down();
|
||||
|
||||
f_all << endl;
|
||||
@ -920,7 +836,7 @@ void t_delphi_generator::delphi_type_usings(ostream& out) {
|
||||
void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) {
|
||||
// Forward declare struct def
|
||||
has_forward = true;
|
||||
pverbose("forward declaration of %s\n", type_name(tstruct).c_str());
|
||||
pdebug("forward declaration of %s\n", type_name(tstruct).c_str());
|
||||
|
||||
string what = tstruct->is_xception() ? "class" : "interface";
|
||||
|
||||
@ -968,11 +884,11 @@ bool t_delphi_generator::is_fully_defined_type(t_type* ttype) {
|
||||
}
|
||||
|
||||
if (ttype->is_typedef()) {
|
||||
return (1 == types_known[type_name(ttype)]);
|
||||
return (types_known.find(type_name(ttype)) != types_known.end());
|
||||
}
|
||||
|
||||
if (ttype->is_base_type()) {
|
||||
return (1 == types_known[base_type_name((t_base_type*)ttype)]);
|
||||
return (types_known.find(base_type_name((t_base_type*)ttype)) != types_known.end());
|
||||
} else if (ttype->is_enum()) {
|
||||
return true; // enums are written first, before all other types
|
||||
} else if (ttype->is_map()) {
|
||||
@ -987,12 +903,12 @@ bool t_delphi_generator::is_fully_defined_type(t_type* ttype) {
|
||||
return is_fully_defined_type(tlist->get_elem_type());
|
||||
}
|
||||
|
||||
return (1 == types_known[type_name(ttype)]);
|
||||
return (types_known.find(type_name(ttype)) != types_known.end());
|
||||
}
|
||||
|
||||
void t_delphi_generator::add_defined_type(t_type* ttype) {
|
||||
// mark as known type
|
||||
types_known[type_name(ttype)] = 1;
|
||||
types_known.insert(type_name(ttype));
|
||||
|
||||
// check all pending typedefs
|
||||
std::list<t_typedef*>::iterator iter;
|
||||
@ -1016,14 +932,15 @@ void t_delphi_generator::add_defined_type(t_type* ttype) {
|
||||
|
||||
void t_delphi_generator::init_known_types_list() {
|
||||
// known base types
|
||||
types_known[type_name(g_type_string)] = 1;
|
||||
types_known[type_name(g_type_binary)] = 1;
|
||||
types_known[type_name(g_type_bool)] = 1;
|
||||
types_known[type_name(g_type_i8)] = 1;
|
||||
types_known[type_name(g_type_i16)] = 1;
|
||||
types_known[type_name(g_type_i32)] = 1;
|
||||
types_known[type_name(g_type_i64)] = 1;
|
||||
types_known[type_name(g_type_double)] = 1;
|
||||
types_known.insert( type_name(g_type_string));
|
||||
types_known.insert( type_name(g_type_binary));
|
||||
types_known.insert( type_name(g_type_uuid));
|
||||
types_known.insert( type_name(g_type_bool));
|
||||
types_known.insert( type_name(g_type_i8));
|
||||
types_known.insert( type_name(g_type_i16));
|
||||
types_known.insert( type_name(g_type_i32));
|
||||
types_known.insert( type_name(g_type_i64));
|
||||
types_known.insert( type_name(g_type_double));
|
||||
}
|
||||
|
||||
void t_delphi_generator::generate_enum(t_enum* tenum) {
|
||||
@ -1156,7 +1073,7 @@ void t_delphi_generator::generate_consts(std::vector<t_const*> consts) {
|
||||
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
|
||||
initialize_field(vars,
|
||||
code,
|
||||
"F" + prop_name((*c_iter)->get_name()),
|
||||
prop_name((*c_iter)->get_name(), false, "F"),
|
||||
(*c_iter)->get_type(),
|
||||
(*c_iter)->get_value());
|
||||
}
|
||||
@ -1200,7 +1117,7 @@ void t_delphi_generator::generate_consts(std::vector<t_const*> consts) {
|
||||
if (const_needs_var((*c_iter)->get_type())) {
|
||||
initialize_field(vars,
|
||||
code,
|
||||
constants_class + ".F" + prop_name((*c_iter)->get_name()),
|
||||
constants_class + "." + prop_name((*c_iter)->get_name(), false, "F"),
|
||||
(*c_iter)->get_type(),
|
||||
(*c_iter)->get_value());
|
||||
}
|
||||
@ -1392,6 +1309,9 @@ string t_delphi_generator::render_const_value(ostream& vars,
|
||||
case t_base_type::TYPE_STRING:
|
||||
render << "'" << get_escaped_string(value) << "'";
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
render << "['{" << value->get_uuid() << "}']";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
render << ((value->get_integer() > 0) ? "True" : "False");
|
||||
break;
|
||||
@ -1493,11 +1413,11 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
|
||||
if ((*m_iter)->get_value() != nullptr) {
|
||||
initialize_field(vars,
|
||||
code,
|
||||
"F" + prop_name((*m_iter)->get_name(), is_exception),
|
||||
prop_name((*m_iter)->get_name(), is_exception, ""),
|
||||
t,
|
||||
(*m_iter)->get_value());
|
||||
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
|
||||
indent_impl(code) << "F__isset_" << prop_name((*m_iter), is_exception) << " := True;"
|
||||
indent_impl(code) << prop_name((*m_iter), is_exception, "F__isset_") << " := True;"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
@ -1777,7 +1697,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
|
||||
out << endl;
|
||||
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
|
||||
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
|
||||
isset_name = "__isset_" + prop_name(*m_iter, is_exception);
|
||||
isset_name = prop_name(*m_iter, is_exception, "__isset_");
|
||||
indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
|
||||
<< endl;
|
||||
}
|
||||
@ -1826,7 +1746,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
|
||||
indent(out) << endl;
|
||||
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
|
||||
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
|
||||
isset_name = "F__isset_" + prop_name(*m_iter, is_exception);
|
||||
isset_name = prop_name(*m_iter, is_exception, "F__isset_");
|
||||
indent(out) << isset_name << ": System.Boolean;" << endl;
|
||||
}
|
||||
}
|
||||
@ -1849,7 +1769,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
|
||||
out << endl;
|
||||
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
|
||||
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
|
||||
isset_name = "__isset_" + prop_name(*m_iter, is_exception);
|
||||
isset_name = prop_name(*m_iter, is_exception, "__isset_");
|
||||
indent(out) << "function Get" << isset_name << ": System.Boolean;" << endl;
|
||||
indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << endl;
|
||||
}
|
||||
@ -1914,7 +1834,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
|
||||
indent(out) << "// isset" << endl;
|
||||
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
|
||||
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
|
||||
isset_name = "__isset_" + prop_name(*m_iter, is_exception);
|
||||
isset_name = prop_name(*m_iter, is_exception, "__isset_");
|
||||
indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
|
||||
<< endl;
|
||||
}
|
||||
@ -1986,7 +1906,7 @@ void t_delphi_generator::generate_guid(std::ostream& out) {
|
||||
#ifdef _WIN32 // TODO: add support for non-windows platforms if needed
|
||||
GUID guid;
|
||||
if (SUCCEEDED(CoCreateGuid(&guid))) {
|
||||
OLECHAR guid_chars[40];
|
||||
OLECHAR guid_chars[40]{};
|
||||
if (StringFromGUID2(guid, &guid_chars[0], sizeof(guid_chars) / sizeof(guid_chars[0])) > 0) {
|
||||
std::wstring guid_wstr(guid_chars);
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
|
||||
@ -2272,7 +2192,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) {
|
||||
|
||||
vector<t_field*>::const_iterator x_iter;
|
||||
for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
|
||||
indent_impl(s_service_impl) << "if (" << retvar << ".__isset_" << prop_name(*x_iter)
|
||||
indent_impl(s_service_impl) << "if (" << retvar << "." << prop_name(*x_iter, false, "__isset_")
|
||||
<< ") then begin" << endl;
|
||||
indent_up_impl();
|
||||
indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter)
|
||||
@ -2697,12 +2617,15 @@ void t_delphi_generator::generate_deserialize_field(ostream& out,
|
||||
if (ansistr_binary_) {
|
||||
out << "ReadAnsiString();";
|
||||
} else {
|
||||
out << "ReadBinary();";
|
||||
out << (com_types_ ? "ReadBinaryCOM();" : "ReadBinary();");
|
||||
}
|
||||
} else {
|
||||
out << "ReadString();";
|
||||
}
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "ReadUuid();";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
out << "ReadBool();";
|
||||
break;
|
||||
@ -2904,6 +2827,9 @@ void t_delphi_generator::generate_serialize_field(ostream& out,
|
||||
}
|
||||
out << name << ");";
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "WriteUuid(" << name << ");";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
out << "WriteBool(" << name << ");";
|
||||
break;
|
||||
@ -3061,26 +2987,26 @@ void t_delphi_generator::generate_delphi_property(ostream& out,
|
||||
bool is_xception = ftype->is_xception();
|
||||
generate_delphi_doc(out, tfield);
|
||||
indent(out) << "property " << prop_name(tfield, struct_is_xception) << ": "
|
||||
<< type_name(ftype, false, true, is_xception, true) << " read "
|
||||
<< fieldPrefix + prop_name(tfield, struct_is_xception) << " write Set"
|
||||
<< prop_name(tfield, struct_is_xception) << ";" << endl;
|
||||
<< type_name(ftype, false, true, is_xception, true)
|
||||
<< " read " << prop_name(tfield, struct_is_xception, fieldPrefix)
|
||||
<< " write " << prop_name(tfield, struct_is_xception, "Set")
|
||||
<< ";" << endl;
|
||||
}
|
||||
|
||||
std::string t_delphi_generator::prop_name(t_field* tfield, bool is_xception) {
|
||||
return prop_name(tfield->get_name(), is_xception);
|
||||
std::string t_delphi_generator::prop_name(t_field* tfield, bool is_xception, std::string prefix) {
|
||||
return prop_name(tfield->get_name(), is_xception, prefix);
|
||||
}
|
||||
|
||||
std::string t_delphi_generator::prop_name(string name, bool is_xception) {
|
||||
std::string t_delphi_generator::prop_name(string name, bool is_xception, std::string prefix) {
|
||||
string ret = name;
|
||||
ret[0] = toupper(ret[0]);
|
||||
return normalize_name(ret, true, is_xception);
|
||||
return normalize_name(prefix + ret, true, is_xception);
|
||||
}
|
||||
|
||||
std::string t_delphi_generator::constructor_param_name(string name) {
|
||||
string ret = name;
|
||||
ret[0] = toupper(ret[0]);
|
||||
ret = "A" + ret;
|
||||
return normalize_name(ret, false, false);
|
||||
return normalize_name("a" + ret, false, false);
|
||||
}
|
||||
|
||||
string t_delphi_generator::normalize_clsnm(string clsnm, string prefix, bool b_no_check_keyword) {
|
||||
@ -3138,9 +3064,9 @@ string t_delphi_generator::type_name(t_type* ttype,
|
||||
} else if (ttype->is_set()) {
|
||||
t_set* tset = (t_set*)ttype;
|
||||
if (b_cls) {
|
||||
typ_nm = "THashSetImpl";
|
||||
typ_nm = "TThriftHashSetImpl";
|
||||
} else {
|
||||
typ_nm = "IHashSet";
|
||||
typ_nm = "IThriftHashSet";
|
||||
}
|
||||
return typ_nm + "<" + type_name(tset->get_elem_type()) + ">";
|
||||
} else if (ttype->is_list()) {
|
||||
@ -3189,6 +3115,7 @@ string t_delphi_generator::input_arg_prefix(t_type* ttype) {
|
||||
|
||||
// these should be const'ed for optimal performamce
|
||||
case t_base_type::TYPE_STRING: // refcounted pointer
|
||||
case t_base_type::TYPE_UUID: // refcounted pointer
|
||||
case t_base_type::TYPE_I64: // larger than 32 bit
|
||||
case t_base_type::TYPE_DOUBLE: // larger than 32 bit
|
||||
return "const ";
|
||||
@ -3236,11 +3163,13 @@ string t_delphi_generator::base_type_name(t_base_type* tbase) {
|
||||
if (ansistr_binary_) {
|
||||
return "System.AnsiString";
|
||||
} else {
|
||||
return "SysUtils.TBytes";
|
||||
return com_types_ ? "IThriftBytes" : "SysUtils.TBytes";
|
||||
}
|
||||
} else {
|
||||
return "System.string";
|
||||
return com_types_ ? "System.WideString" : "System.string";
|
||||
}
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "System.TGuid";
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return "System.Boolean";
|
||||
case t_base_type::TYPE_I8:
|
||||
@ -3268,7 +3197,7 @@ string t_delphi_generator::declare_field(t_field* tfield,
|
||||
t_type* ftype = tfield->get_type();
|
||||
bool is_xception = ftype->is_xception();
|
||||
|
||||
string result = prefix + prop_name(tfield, is_xception_class) + ": "
|
||||
string result = prop_name(tfield, is_xception_class, prefix) + ": "
|
||||
+ type_name(ftype, false, true, is_xception, true) + ";";
|
||||
return result;
|
||||
}
|
||||
@ -3310,11 +3239,11 @@ string t_delphi_generator::function_signature(t_function* tfunction,
|
||||
// deprecated method? only at intf decl!
|
||||
if( full_cls == "") {
|
||||
auto iter = tfunction->annotations_.find("deprecated");
|
||||
if( tfunction->annotations_.end() != iter) {
|
||||
if( tfunction->annotations_.end() != iter && !iter->second.empty()) {
|
||||
signature += " deprecated";
|
||||
// empty annotation values end up with "1" somewhere, ignore these as well
|
||||
if ((iter->second.length() > 0) && (iter->second != "1")) {
|
||||
signature += " " + make_pascal_string_literal(iter->second);
|
||||
if ((iter->second.back().length() > 0) && (iter->second.back() != "1")) {
|
||||
signature += " " + make_pascal_string_literal(iter->second.back());
|
||||
}
|
||||
signature += ";";
|
||||
}
|
||||
@ -3407,6 +3336,8 @@ string t_delphi_generator::type_to_enum(t_type* type) {
|
||||
throw "NO T_VOID CONSTRUCT";
|
||||
case t_base_type::TYPE_STRING:
|
||||
return "TType.String_";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "TType.Uuid";
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return "TType.Bool_";
|
||||
case t_base_type::TYPE_I8:
|
||||
@ -3455,6 +3386,8 @@ string t_delphi_generator::empty_value(t_type* type) {
|
||||
} else {
|
||||
return "''";
|
||||
}
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "System.TGuid.Empty";
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return "False";
|
||||
case t_base_type::TYPE_I8:
|
||||
@ -3486,7 +3419,7 @@ void t_delphi_generator::generate_delphi_property_writer_definition(ostream& out
|
||||
t_type* ftype = tfield->get_type();
|
||||
bool is_xception = ftype->is_xception();
|
||||
|
||||
indent(out) << "procedure Set" << prop_name(tfield, is_xception_class)
|
||||
indent(out) << "procedure " << prop_name(tfield, is_xception_class, "Set")
|
||||
<< "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");"
|
||||
<< endl;
|
||||
}
|
||||
@ -3497,15 +3430,15 @@ void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out
|
||||
t_type* ftype = tfield->get_type();
|
||||
bool is_xception = ftype->is_xception();
|
||||
|
||||
indent(out) << "function Get" << prop_name(tfield, is_xception_class) << ": "
|
||||
indent(out) << "function " << prop_name(tfield, is_xception_class, "Get") << ": "
|
||||
<< type_name(ftype, false, true, is_xception, true) << ";" << endl;
|
||||
}
|
||||
|
||||
void t_delphi_generator::generate_delphi_isset_reader_writer_definition(ostream& out,
|
||||
t_field* tfield,
|
||||
bool is_xception) {
|
||||
indent(out) << "function Get__isset_" << prop_name(tfield, is_xception) << ": System.Boolean;" << endl;
|
||||
indent(out) << "procedure Set__isset_" << prop_name(tfield, is_xception) << "( const value : System.Boolean);" << endl;
|
||||
indent(out) << "function " << prop_name(tfield, is_xception,"Get__isset_") << ": System.Boolean;" << endl;
|
||||
indent(out) << "procedure " << prop_name(tfield, is_xception, "Set__isset_") << "( const value : System.Boolean);" << endl;
|
||||
}
|
||||
|
||||
void t_delphi_generator::generate_delphi_clear_union_value(ostream& out,
|
||||
@ -3528,11 +3461,11 @@ void t_delphi_generator::generate_delphi_clear_union_value(ostream& out,
|
||||
t_type* ftype = tfield->get_type();
|
||||
bool is_xception = ftype->is_xception();
|
||||
|
||||
indent_impl(out) << "if F__isset_" << prop_name(tfield, is_xception_class) << " then begin"
|
||||
indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin"
|
||||
<< endl;
|
||||
indent_up_impl();
|
||||
indent_impl(out) << "F__isset_" << prop_name(tfield, is_xception_class) << " := False;" << endl;
|
||||
indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := "
|
||||
indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := False;" << endl;
|
||||
indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := "
|
||||
<< "Default( " << type_name(ftype, false, true, is_xception, true) << ");"
|
||||
<< endl;
|
||||
indent_down_impl();
|
||||
@ -3555,7 +3488,7 @@ void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out,
|
||||
bool is_xception = ftype->is_xception();
|
||||
|
||||
indent_impl(out) << "procedure " << cls_prefix << name << "."
|
||||
<< "Set" << prop_name(tfield, is_xception_class)
|
||||
<< prop_name(tfield, is_xception_class,"Set")
|
||||
<< "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");"
|
||||
<< endl;
|
||||
indent_impl(out) << "begin" << endl;
|
||||
@ -3564,9 +3497,9 @@ void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out,
|
||||
indent_impl(out) << "ClearUnionValues;" << endl;
|
||||
}
|
||||
if (tfield->get_req() != t_field::T_REQUIRED) {
|
||||
indent_impl(out) << "F__isset_" << prop_name(tfield, is_xception_class) << " := True;" << endl;
|
||||
indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := True;" << endl;
|
||||
}
|
||||
indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := Value;" << endl;
|
||||
indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := Value;" << endl;
|
||||
|
||||
if (is_xception_class && (!is_xception_factory)) {
|
||||
indent_impl(out) << xception_factory_name << "." << prop_name(tfield, is_xception_class)
|
||||
@ -3590,11 +3523,11 @@ void t_delphi_generator::generate_delphi_property_reader_impl(ostream& out,
|
||||
bool is_xception = ftype->is_xception();
|
||||
|
||||
indent_impl(out) << "function " << cls_prefix << name << "."
|
||||
<< "Get" << prop_name(tfield, is_xception_class) << ": "
|
||||
<< prop_name(tfield, is_xception_class,"Get") << ": "
|
||||
<< type_name(ftype, false, true, is_xception, true) << ";" << endl;
|
||||
indent_impl(out) << "begin" << endl;
|
||||
indent_up_impl();
|
||||
indent_impl(out) << "Result := " << fieldPrefix << prop_name(tfield, is_xception_class) << ";"
|
||||
indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class,fieldPrefix) << ";"
|
||||
<< endl;
|
||||
indent_down_impl();
|
||||
indent_impl(out) << "end;" << endl << endl;
|
||||
@ -3609,7 +3542,7 @@ void t_delphi_generator::generate_delphi_isset_reader_writer_impl(ostream& out,
|
||||
bool is_xception) {
|
||||
(void)type;
|
||||
|
||||
string isset_name = "__isset_" + prop_name(tfield, is_xception);
|
||||
string isset_name = prop_name(tfield, is_xception, "__isset_");
|
||||
|
||||
indent_impl(out) << "function " << cls_prefix << name << "."
|
||||
<< "Get" << isset_name << ": System.Boolean;" << endl;
|
||||
@ -3655,7 +3588,7 @@ void t_delphi_generator::generate_delphi_create_exception_impl(ostream& out,
|
||||
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
|
||||
propname = prop_name(*f_iter, is_exception);
|
||||
if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
|
||||
indent_impl(out) << "if __isset_" << propname << " then begin" << endl;
|
||||
indent_impl(out) << "if " << prop_name(*f_iter, is_exception,"__isset_") << " then begin" << endl;
|
||||
indent_up_impl();
|
||||
}
|
||||
indent_impl(out) << "Result." << propname << " := " << propname << ";" << endl;
|
||||
@ -3692,9 +3625,9 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
|
||||
// local bools for required fields
|
||||
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
|
||||
if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
|
||||
indent_impl(local_vars) << "_req_isset_" << prop_name(*f_iter, is_exception) << " : System.Boolean;"
|
||||
indent_impl(local_vars) << prop_name(*f_iter, is_exception,"_req_isset_") << " : System.Boolean;"
|
||||
<< endl;
|
||||
indent_impl(code_block) << "_req_isset_" << prop_name(*f_iter, is_exception) << " := FALSE;"
|
||||
indent_impl(code_block) << prop_name(*f_iter, is_exception,"_req_isset_") << " := FALSE;"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
@ -3736,7 +3669,7 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
|
||||
|
||||
// required field?
|
||||
if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
|
||||
indent_impl(code_block) << "_req_isset_" << prop_name(*f_iter, is_exception) << " := TRUE;"
|
||||
indent_impl(code_block) << prop_name(*f_iter, is_exception,"_req_isset_") << " := TRUE;"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@ -3786,7 +3719,7 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
|
||||
code_block << endl;
|
||||
first = false;
|
||||
}
|
||||
indent_impl(code_block) << "if not _req_isset_" << prop_name(*f_iter, is_exception) << endl;
|
||||
indent_impl(code_block) << "if not " << prop_name(*f_iter, is_exception,"_req_isset_") << endl;
|
||||
indent_impl(code_block)
|
||||
<< "then raise TProtocolExceptionInvalidData.Create("
|
||||
<< "'required field " << prop_name(*f_iter, is_exception) << " not set');"
|
||||
@ -3841,7 +3774,7 @@ void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out,
|
||||
if (fields.size() > 0) {
|
||||
indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << endl;
|
||||
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
|
||||
indent_impl(code_block) << "if (__isset_" << prop_name(*f_iter, is_exception) << ") then"
|
||||
indent_impl(code_block) << "if (" << prop_name(*f_iter, is_exception,"__isset_") << ") then"
|
||||
<< endl;
|
||||
indent_impl(code_block) << "begin" << endl;
|
||||
indent_up_impl();
|
||||
@ -3909,6 +3842,7 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out,
|
||||
|
||||
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
|
||||
string fieldname = prop_name((*f_iter), is_exception);
|
||||
string isset_name = prop_name((*f_iter), is_exception, "__isset_");
|
||||
bool null_allowed = type_can_be_null((*f_iter)->get_type());
|
||||
bool is_required = ((*f_iter)->get_req() == t_field::T_REQUIRED);
|
||||
bool has_isset = (!is_required);
|
||||
@ -3922,13 +3856,13 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out,
|
||||
if (null_allowed) {
|
||||
indent_impl(code_block) << "if (Self." << fieldname << " <> nil)";
|
||||
if (has_isset) {
|
||||
code_block << " and __isset_" << fieldname;
|
||||
code_block << " and " << isset_name;
|
||||
}
|
||||
code_block << " then begin" << endl;
|
||||
indent_up_impl();
|
||||
} else {
|
||||
if (has_isset) {
|
||||
indent_impl(code_block) << "if (__isset_" << fieldname << ") then begin" << endl;
|
||||
indent_impl(code_block) << "if (" << isset_name << ") then begin" << endl;
|
||||
indent_up_impl();
|
||||
}
|
||||
}
|
||||
@ -4021,13 +3955,13 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
|
||||
if (null_allowed) {
|
||||
indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " <> nil)";
|
||||
if (is_optional) {
|
||||
out << " and __isset_" << prop_name(*f_iter, is_exception);
|
||||
out << " and " << prop_name(*f_iter, is_exception,"__isset_");
|
||||
}
|
||||
out << " then begin" << endl;
|
||||
indent_up_impl();
|
||||
} else {
|
||||
if (is_optional) {
|
||||
indent_impl(out) << "if (__isset_" << prop_name(*f_iter, is_exception) << ") then begin"
|
||||
indent_impl(out) << "if (" << prop_name(*f_iter, is_exception, "__isset_") << ") then begin"
|
||||
<< endl;
|
||||
indent_up_impl();
|
||||
}
|
||||
@ -4059,6 +3993,9 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
|
||||
<< type_name(ttype, false, true, false, false)
|
||||
<< ">.ToString( System.Ord( Self."
|
||||
<< prop_name((*f_iter), is_exception) << ")));" << endl;
|
||||
} else if (ttype->is_uuid()) {
|
||||
indent_impl(out) << tmp_sb << ".Append( GUIDToString(Self." << prop_name((*f_iter), is_exception) << "));"
|
||||
<< endl;
|
||||
} else {
|
||||
indent_impl(out) << tmp_sb << ".Append( Self." << prop_name((*f_iter), is_exception) << ");"
|
||||
<< endl;
|
||||
@ -4105,13 +4042,20 @@ bool t_delphi_generator::is_void(t_type* type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string t_delphi_generator::display_name() const {
|
||||
return "Delphi";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
delphi,
|
||||
"delphi",
|
||||
"Delphi",
|
||||
" ansistr_binary: Use AnsiString for binary datatype (default is TBytes).\n"
|
||||
" register_types: Enable TypeRegistry, allows for creation of struct, union\n"
|
||||
" and container instances by interface or TypeInfo()\n"
|
||||
" constprefix: Name TConstants classes after IDL to reduce ambiguities\n"
|
||||
" events: Enable and use processing events in the generated code.\n"
|
||||
" xmldoc: Enable XMLDoc comments for Help Insight etc.\n"
|
||||
" async: Generate IAsync interface to use Parallel Programming Library (XE7+ only).\n")
|
||||
" async: Generate IAsync interface to use Parallel Programming Library (XE7+ only).\n"
|
||||
" com_types: Use COM-compatible data types (e.g. WideString).\n"
|
||||
" old_names: Compatibility: generate \"reserved\" identifiers with '_' postfix instead of '&' prefix.\n")
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -1168,6 +1169,8 @@ string t_erl_generator::type_to_enum(t_type* type) {
|
||||
return "?tType_I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "?tType_DOUBLE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "?tType_I32";
|
||||
@ -1211,6 +1214,8 @@ std::string t_erl_generator::render_type_term(t_type* type,
|
||||
return "i64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "double";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "i32";
|
||||
@ -1276,6 +1281,11 @@ std::string t_erl_generator::type_module(t_type* ttype) {
|
||||
return make_safe_for_module_name(ttype->get_program()->get_name()) + "_types";
|
||||
}
|
||||
|
||||
std::string t_erl_generator::display_name() const {
|
||||
return "Erl";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
erl,
|
||||
"Erlang",
|
||||
|
@ -154,6 +154,7 @@ public:
|
||||
*/
|
||||
void init_generator();
|
||||
void close_generator();
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -1366,6 +1367,8 @@ string t_erlang_generator::type_to_enum(t_type* type) {
|
||||
return "?tType_I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "?tType_DOUBLE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "?tType_I32";
|
||||
@ -1409,6 +1412,8 @@ std::string t_erlang_generator::render_type_term(t_type* type,
|
||||
return "i64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "double";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "{enum, {" + type_module(type) + ", " + type_name(type) + "}}";
|
||||
@ -1554,6 +1559,10 @@ string t_erlang_generator::erl_autogen_comment() {
|
||||
);
|
||||
}
|
||||
|
||||
std::string t_erlang_generator::display_name() const {
|
||||
return "Erlang";
|
||||
}
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
erlang,
|
||||
"Erlang",
|
||||
|
@ -76,20 +76,11 @@ void t_generator::generate_program() {
|
||||
close_generator();
|
||||
}
|
||||
|
||||
std::set<std::string> t_generator::lang_keywords() const {
|
||||
std::string keywords[] = { "BEGIN", "END", "__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__",
|
||||
"__LINE__", "__METHOD__", "__NAMESPACE__", "abstract", "alias", "and", "args", "as",
|
||||
"assert", "begin", "break", "case", "catch", "class", "clone", "continue", "declare",
|
||||
"def", "default", "del", "delete", "do", "dynamic", "elif", "else", "elseif", "elsif",
|
||||
"end", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "ensure",
|
||||
"except", "exec", "finally", "float", "for", "foreach", "from", "function", "global",
|
||||
"goto", "if", "implements", "import", "in", "inline", "instanceof", "interface", "is",
|
||||
"lambda", "module", "native", "new", "next", "nil", "not", "or", "package", "pass",
|
||||
"public", "print", "private", "protected", "raise", "redo", "rescue", "retry", "register",
|
||||
"return", "self", "sizeof", "static", "super", "switch", "synchronized", "then", "this",
|
||||
"throw", "transient", "try", "undef", "unless", "unsigned", "until", "use", "var",
|
||||
"virtual", "volatile", "when", "while", "with", "xor", "yield" };
|
||||
return std::set<std::string>(keywords, keywords + sizeof(keywords)/sizeof(keywords[0]) );
|
||||
std::set<std::string> t_generator::lang_keywords_for_validation() const {
|
||||
// Nothing by default. It makes no sense to restrict the whole world to use non-PHP keywords only.
|
||||
// Override on a per-generator(!) basis if you cannot live without it, e.g. that particular language has no
|
||||
// mechanism or way to deal with it properly, so we absolutely need to fail on it as the last possible resort.
|
||||
return {};
|
||||
}
|
||||
|
||||
void t_generator::validate_input() const {
|
||||
@ -143,7 +134,8 @@ void t_generator::validate(t_field const* f) const {
|
||||
|
||||
void t_generator::validate_id(const string& id) const {
|
||||
if (keywords_.find(id) != keywords_.end()) {
|
||||
failure("Cannot use reserved language keyword: \"%s\"", id.c_str());
|
||||
// What the message really means is "we did not get it done yet"
|
||||
failure("Cannot use reserved language keyword \"%s\" with target language %s", id.c_str(), display_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
class t_generator {
|
||||
public:
|
||||
t_generator(t_program* program) {
|
||||
update_keywords();
|
||||
update_keywords_for_validation();
|
||||
|
||||
tmp_ = 0;
|
||||
indent_ = 0;
|
||||
@ -100,18 +100,24 @@ public:
|
||||
|
||||
/**
|
||||
* Check if all identifiers are valid for the target language
|
||||
* See update_keywords()
|
||||
* See update_keywords_for_validation()
|
||||
*/
|
||||
virtual void validate_input() const;
|
||||
|
||||
/**
|
||||
* Must override. Should be equivalent to the "long name" parameter at THRIFT_REGISTER_GENERATOR.
|
||||
* TODO: essentially duplicates, so we should find a way to get rid of one
|
||||
*/
|
||||
virtual std::string display_name() const = 0;
|
||||
protected:
|
||||
virtual std::set<std::string> lang_keywords() const;
|
||||
virtual std::set<std::string> lang_keywords_for_validation() const;
|
||||
|
||||
/**
|
||||
* Call this from constructor if you implement lang_keywords()
|
||||
* Call this from constructor if you implement lang_keywords_for_validation()
|
||||
*/
|
||||
void update_keywords() {
|
||||
keywords_ = lang_keywords();
|
||||
|
||||
void update_keywords_for_validation() {
|
||||
keywords_ = lang_keywords_for_validation();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "thrift/platform.h"
|
||||
#include "thrift/version.h"
|
||||
#include "thrift/generate/t_generator.h"
|
||||
#include "thrift/generate/t_go_generator.h"
|
||||
#include "thrift/generate/go_validator_generator.h"
|
||||
|
||||
using std::map;
|
||||
using std::ostream;
|
||||
@ -49,8 +51,6 @@ using std::string;
|
||||
using std::stringstream;
|
||||
using std::vector;
|
||||
|
||||
static const string endl = "\n"; // avoid ostream << std::endl flushes
|
||||
|
||||
/**
|
||||
* A helper for automatically formatting the emitted Go code from the Thrift
|
||||
* IDL per the Go style guide.
|
||||
@ -62,277 +62,6 @@ static const string endl = "\n"; // avoid ostream << std::endl flushes
|
||||
*/
|
||||
bool format_go_output(const string& file_path);
|
||||
|
||||
const string DEFAULT_THRIFT_IMPORT = "github.com/apache/thrift/lib/go/thrift";
|
||||
static std::string package_flag;
|
||||
|
||||
/**
|
||||
* Go code generator.
|
||||
*/
|
||||
class t_go_generator : public t_generator {
|
||||
public:
|
||||
t_go_generator(t_program* program,
|
||||
const std::map<std::string, std::string>& parsed_options,
|
||||
const std::string& option_string)
|
||||
: t_generator(program) {
|
||||
(void)option_string;
|
||||
std::map<std::string, std::string>::const_iterator iter;
|
||||
|
||||
|
||||
gen_thrift_import_ = DEFAULT_THRIFT_IMPORT;
|
||||
gen_package_prefix_ = "";
|
||||
package_flag = "";
|
||||
read_write_private_ = false;
|
||||
ignore_initialisms_ = false;
|
||||
skip_remote_ = false;
|
||||
for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
|
||||
if( iter->first.compare("package_prefix") == 0) {
|
||||
gen_package_prefix_ = (iter->second);
|
||||
} else if( iter->first.compare("thrift_import") == 0) {
|
||||
gen_thrift_import_ = (iter->second);
|
||||
} else if( iter->first.compare("package") == 0) {
|
||||
package_flag = (iter->second);
|
||||
} else if( iter->first.compare("read_write_private") == 0) {
|
||||
read_write_private_ = true;
|
||||
} else if( iter->first.compare("ignore_initialisms") == 0) {
|
||||
ignore_initialisms_ = true;
|
||||
} else if( iter->first.compare("skip_remote") == 0) {
|
||||
skip_remote_ = true;
|
||||
} else {
|
||||
throw "unknown option go:" + iter->first;
|
||||
}
|
||||
}
|
||||
|
||||
out_dir_base_ = "gen-go";
|
||||
}
|
||||
|
||||
/**
|
||||
* Init and close methods
|
||||
*/
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
*/
|
||||
|
||||
void generate_typedef(t_typedef* ttypedef) override;
|
||||
void generate_enum(t_enum* tenum) override;
|
||||
void generate_const(t_const* tconst) override;
|
||||
void generate_struct(t_struct* tstruct) override;
|
||||
void generate_xception(t_struct* txception) override;
|
||||
void generate_service(t_service* tservice) override;
|
||||
|
||||
std::string render_const_value(t_type* type, t_const_value* value, const string& name, bool opt = false);
|
||||
|
||||
/**
|
||||
* Struct generation code
|
||||
*/
|
||||
|
||||
void generate_go_struct(t_struct* tstruct, bool is_exception);
|
||||
void generate_go_struct_definition(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
bool is_xception = false,
|
||||
bool is_result = false,
|
||||
bool is_args = false);
|
||||
void generate_go_struct_initializer(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
bool is_args_or_result = false);
|
||||
void generate_isset_helpers(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
const string& tstruct_name,
|
||||
bool is_result = false);
|
||||
void generate_countsetfields_helper(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
const string& tstruct_name,
|
||||
bool is_result = false);
|
||||
void generate_go_struct_reader(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
const string& tstruct_name,
|
||||
bool is_result = false);
|
||||
void generate_go_struct_writer(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
const string& tstruct_name,
|
||||
bool is_result = false,
|
||||
bool uses_countsetfields = false);
|
||||
void generate_go_struct_equals(std::ostream& out, t_struct* tstruct, const string& tstruct_name);
|
||||
void generate_go_function_helpers(t_function* tfunction);
|
||||
void get_publicized_name_and_def_value(t_field* tfield,
|
||||
string* OUT_pub_name,
|
||||
t_const_value** OUT_def_value) const;
|
||||
|
||||
/**
|
||||
* Service-level generation functions
|
||||
*/
|
||||
|
||||
void generate_service_helpers(t_service* tservice);
|
||||
void generate_service_interface(t_service* tservice);
|
||||
void generate_service_client(t_service* tservice);
|
||||
void generate_service_remote(t_service* tservice);
|
||||
void generate_service_server(t_service* tservice);
|
||||
void generate_process_function(t_service* tservice, t_function* tfunction);
|
||||
|
||||
/**
|
||||
* Serialization constructs
|
||||
*/
|
||||
|
||||
void generate_deserialize_field(std::ostream& out,
|
||||
t_field* tfield,
|
||||
bool declare,
|
||||
std::string prefix = "",
|
||||
bool inclass = false,
|
||||
bool coerceData = false,
|
||||
bool inkey = false,
|
||||
bool in_container = false);
|
||||
|
||||
void generate_deserialize_struct(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
bool is_pointer_field,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_deserialize_container(std::ostream& out,
|
||||
t_type* ttype,
|
||||
bool pointer_field,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_deserialize_set_element(std::ostream& out,
|
||||
t_set* tset,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_deserialize_map_element(std::ostream& out,
|
||||
t_map* tmap,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_deserialize_list_element(std::ostream& out,
|
||||
t_list* tlist,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_serialize_field(std::ostream& out,
|
||||
t_field* tfield,
|
||||
std::string prefix = "",
|
||||
bool inkey = false);
|
||||
|
||||
void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
|
||||
|
||||
void generate_serialize_container(std::ostream& out,
|
||||
t_type* ttype,
|
||||
bool pointer_field,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_serialize_map_element(std::ostream& out,
|
||||
t_map* tmap,
|
||||
std::string kiter,
|
||||
std::string viter);
|
||||
|
||||
void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
|
||||
|
||||
void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
|
||||
|
||||
void generate_go_equals(std::ostream& out, t_type* ttype, string tgt, string src);
|
||||
|
||||
void generate_go_equals_struct(std::ostream& out, t_type* ttype, string tgt, string src);
|
||||
|
||||
void generate_go_equals_container(std::ostream& out, t_type* ttype, string tgt, string src);
|
||||
|
||||
void generate_go_docstring(std::ostream& out, t_struct* tstruct);
|
||||
|
||||
void generate_go_docstring(std::ostream& out, t_function* tfunction);
|
||||
|
||||
void generate_go_docstring(std::ostream& out,
|
||||
t_doc* tdoc,
|
||||
t_struct* tstruct,
|
||||
const char* subheader);
|
||||
|
||||
void generate_go_docstring(std::ostream& out, t_doc* tdoc);
|
||||
|
||||
void parse_go_tags(map<string,string>* tags, const string in);
|
||||
|
||||
/**
|
||||
* Helper rendering functions
|
||||
*/
|
||||
|
||||
std::string go_autogen_comment();
|
||||
std::string go_package();
|
||||
std::string go_imports_begin(bool consts);
|
||||
std::string go_imports_end();
|
||||
std::string render_includes(bool consts);
|
||||
std::string render_included_programs(string& unused_protection);
|
||||
std::string render_program_import(const t_program* program, string& unused_protection);
|
||||
std::string render_system_packages(std::vector<string> &system_packages);
|
||||
std::string render_import_protection();
|
||||
std::string render_fastbinary_includes();
|
||||
std::string declare_argument(t_field* tfield);
|
||||
std::string render_field_initial_value(t_field* tfield, const string& name, bool optional_field);
|
||||
std::string type_name(t_type* ttype);
|
||||
std::string module_name(t_type* ttype);
|
||||
std::string function_signature(t_function* tfunction, std::string prefix = "");
|
||||
std::string function_signature_if(t_function* tfunction,
|
||||
std::string prefix = "",
|
||||
bool addError = false);
|
||||
std::string argument_list(t_struct* tstruct);
|
||||
std::string type_to_enum(t_type* ttype);
|
||||
std::string type_to_go_type(t_type* ttype);
|
||||
std::string type_to_go_type_with_opt(t_type* ttype,
|
||||
bool optional_field);
|
||||
std::string type_to_go_key_type(t_type* ttype);
|
||||
std::string type_to_spec_args(t_type* ttype);
|
||||
|
||||
static std::string get_real_go_module(const t_program* program) {
|
||||
|
||||
if (!package_flag.empty()) {
|
||||
return package_flag;
|
||||
}
|
||||
std::string real_module = program->get_namespace("go");
|
||||
if (!real_module.empty()) {
|
||||
return real_module;
|
||||
}
|
||||
|
||||
return lowercase(program->get_name());
|
||||
}
|
||||
|
||||
private:
|
||||
std::string gen_package_prefix_;
|
||||
std::string gen_thrift_import_;
|
||||
bool read_write_private_;
|
||||
bool ignore_initialisms_;
|
||||
bool skip_remote_;
|
||||
|
||||
/**
|
||||
* File streams
|
||||
*/
|
||||
|
||||
ofstream_with_content_based_conditional_update f_types_;
|
||||
std::string f_types_name_;
|
||||
ofstream_with_content_based_conditional_update f_consts_;
|
||||
std::string f_consts_name_;
|
||||
std::stringstream f_const_values_;
|
||||
|
||||
std::string package_name_;
|
||||
std::string package_dir_;
|
||||
std::unordered_map<std::string, std::string> package_identifiers_;
|
||||
std::set<std::string> package_identifiers_set_;
|
||||
std::string read_method_name_;
|
||||
std::string write_method_name_;
|
||||
std::string equals_method_name_;
|
||||
|
||||
std::set<std::string> commonInitialisms;
|
||||
|
||||
std::string camelcase(const std::string& value) const;
|
||||
void fix_common_initialism(std::string& value, int i) const;
|
||||
std::string publicize(const std::string& value, bool is_args_or_result = false) const;
|
||||
std::string publicize(const std::string& value, bool is_args_or_result, const std::string& service_name) const;
|
||||
std::string privatize(const std::string& value) const;
|
||||
std::string new_prefix(const std::string& value) const;
|
||||
static std::string variable_name_to_go_name(const std::string& value);
|
||||
static bool is_pointer_field(t_field* tfield, bool in_container = false);
|
||||
static bool omit_initialization(t_field* tfield);
|
||||
};
|
||||
|
||||
// returns true if field initialization can be omitted since it has corresponding go type zero value
|
||||
// or default value is not set
|
||||
bool t_go_generator::omit_initialization(t_field* tfield) {
|
||||
@ -368,6 +97,13 @@ bool t_go_generator::omit_initialization(t_field* tfield) {
|
||||
} else {
|
||||
return value->get_double() == 0.;
|
||||
}
|
||||
|
||||
case t_base_type::TYPE_UUID:
|
||||
// it's hard to detect all zero uuid here, so just always inline it.
|
||||
return false;
|
||||
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -419,7 +155,11 @@ bool t_go_generator::is_pointer_field(t_field* tfield, bool in_container_value)
|
||||
case t_base_type::TYPE_I32:
|
||||
case t_base_type::TYPE_I64:
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
case t_base_type::TYPE_UUID:
|
||||
return !has_default;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return !has_default;
|
||||
@ -969,6 +709,10 @@ string t_go_generator::go_imports_begin(bool consts) {
|
||||
system_packages.push_back("time");
|
||||
// For the thrift import, always do rename import to make sure it's called thrift.
|
||||
system_packages.push_back("thrift \"" + gen_thrift_import_ + "\"");
|
||||
|
||||
// validator import
|
||||
system_packages.push_back("strings");
|
||||
system_packages.push_back("regexp");
|
||||
return "import (\n" + render_system_packages(system_packages);
|
||||
}
|
||||
|
||||
@ -979,7 +723,7 @@ string t_go_generator::go_imports_begin(bool consts) {
|
||||
* This will have to do in lieu of more intelligent import statement construction
|
||||
*/
|
||||
string t_go_generator::go_imports_end() {
|
||||
return string(
|
||||
string import_end = string(
|
||||
")\n\n"
|
||||
"// (needed to ensure safety because of naive import list construction.)\n"
|
||||
"var _ = thrift.ZERO\n"
|
||||
@ -987,7 +731,11 @@ string t_go_generator::go_imports_end() {
|
||||
"var _ = errors.New\n"
|
||||
"var _ = context.Background\n"
|
||||
"var _ = time.Now\n"
|
||||
"var _ = bytes.Equal\n\n");
|
||||
"var _ = bytes.Equal\n"
|
||||
"// (needed by validator.)\n"
|
||||
"var _ = strings.Contains\n"
|
||||
"var _ = regexp.MatchString\n\n");
|
||||
return import_end;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1126,7 +874,7 @@ void t_go_generator::generate_const(t_const* tconst) {
|
||||
t_type* type = tconst->get_type();
|
||||
string name = publicize(tconst->get_name());
|
||||
t_const_value* value = tconst->get_value();
|
||||
if (type->is_base_type() || type->is_enum()) {
|
||||
if (type->is_enum() || (type->is_base_type() && ((t_base_type*)type)->get_base() != t_base_type::TYPE_UUID)) {
|
||||
indent(f_consts_) << "const " << name << " = " << render_const_value(type, value, name) << endl;
|
||||
} else {
|
||||
f_const_values_ << indent() << name << " = " << render_const_value(type, value, name) << endl
|
||||
@ -1143,8 +891,10 @@ void t_go_generator::generate_const(t_const* tconst) {
|
||||
*/
|
||||
string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name, bool opt) {
|
||||
string typedef_opt_ptr;
|
||||
string typedef_opt;
|
||||
if (type->is_typedef()) {
|
||||
typedef_opt_ptr = type_name(type) + "Ptr";
|
||||
typedef_opt = publicize(type_name(type));
|
||||
typedef_opt_ptr = typedef_opt + "Ptr";
|
||||
}
|
||||
type = get_true_type(type);
|
||||
std::ostringstream out;
|
||||
@ -1225,6 +975,19 @@ string t_go_generator::render_const_value(t_type* type, t_const_value* value, co
|
||||
out << '"' + get_escaped_string(value) + '"';
|
||||
break;
|
||||
|
||||
case t_base_type::TYPE_UUID:
|
||||
if (typedef_opt_ptr != "") {
|
||||
out << typedef_opt_ptr << "(" << typedef_opt;
|
||||
} else {
|
||||
out << "thrift.TuuidPtr";
|
||||
}
|
||||
out << "(";
|
||||
out << "thrift.Must(thrift.ParseTuuid(\"" + get_escaped_string(value) + "\"))";
|
||||
if (typedef_opt_ptr != "") {
|
||||
out << ")";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
|
||||
}
|
||||
@ -1266,6 +1029,17 @@ string t_go_generator::render_const_value(t_type* type, t_const_value* value, co
|
||||
|
||||
break;
|
||||
|
||||
case t_base_type::TYPE_UUID:
|
||||
if (typedef_opt != "") {
|
||||
out << typedef_opt << "(";
|
||||
}
|
||||
out << "thrift.Must(thrift.ParseTuuid(\"" + get_escaped_string(value) + "\"))";
|
||||
if (typedef_opt != "") {
|
||||
out << ")";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
|
||||
}
|
||||
@ -1380,6 +1154,14 @@ void t_go_generator::generate_xception(t_struct* txception) {
|
||||
*/
|
||||
void t_go_generator::generate_go_struct(t_struct* tstruct, bool is_exception) {
|
||||
generate_go_struct_definition(f_types_, tstruct, is_exception);
|
||||
// generate Validate function
|
||||
std::string tstruct_name(publicize(tstruct->get_name(), false));
|
||||
f_types_ << "func (p *" << tstruct_name << ") Validate() error {" << endl;
|
||||
indent_up();
|
||||
go_validator_generator(this).generate_struct_validator(f_types_, tstruct);
|
||||
f_types_ << indent() << "return nil" << endl;
|
||||
indent_down();
|
||||
f_types_ << "}" << endl;
|
||||
}
|
||||
|
||||
void t_go_generator::get_publicized_name_and_def_value(t_field* tfield,
|
||||
@ -1494,9 +1276,9 @@ void t_go_generator::generate_go_struct_definition(ostream& out,
|
||||
|
||||
// Check for user defined tags and them if there are any. User defined tags
|
||||
// can override the above db and json tags.
|
||||
std::map<string, string>::iterator it = (*m_iter)->annotations_.find("go.tag");
|
||||
std::map<string, std::vector<string>>::iterator it = (*m_iter)->annotations_.find("go.tag");
|
||||
if (it != (*m_iter)->annotations_.end()) {
|
||||
parse_go_tags(&tags, it->second);
|
||||
parse_go_tags(&tags, it->second.back());
|
||||
}
|
||||
|
||||
string gotag;
|
||||
@ -2676,6 +2458,15 @@ void t_go_generator::generate_service_remote(t_service* tservice) {
|
||||
f_remote << indent() << "}" << endl;
|
||||
break;
|
||||
|
||||
case t_base_type::TYPE_UUID:
|
||||
f_remote << indent() << "argvalue" << i << ", " << err
|
||||
<< " := (thrift.ParseTuuid(flag.Arg(" << flagArg << ")))" << endl;
|
||||
f_remote << indent() << "if " << err << " != nil {" << endl;
|
||||
f_remote << indent() << " Usage()" << endl;
|
||||
f_remote << indent() << " return" << endl;
|
||||
f_remote << indent() << "}" << endl;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw("Invalid base type in generate_service_remote");
|
||||
}
|
||||
@ -2790,6 +2581,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) {
|
||||
case t_base_type::TYPE_I32:
|
||||
case t_base_type::TYPE_I64:
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
case t_base_type::TYPE_UUID:
|
||||
f_remote << "value" << i;
|
||||
break;
|
||||
|
||||
@ -3005,13 +2797,13 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function*
|
||||
f_types_ << indent() << "if thrift.ServerConnectivityCheckInterval > 0 {" << endl;
|
||||
|
||||
indent_up();
|
||||
f_types_ << indent() << "var cancel context.CancelFunc" << endl;
|
||||
f_types_ << indent() << "ctx, cancel = context.WithCancel(ctx)" << endl;
|
||||
f_types_ << indent() << "defer cancel()" << endl;
|
||||
f_types_ << indent() << "var cancel context.CancelCauseFunc" << endl;
|
||||
f_types_ << indent() << "ctx, cancel = context.WithCancelCause(ctx)" << endl;
|
||||
f_types_ << indent() << "defer cancel(nil)" << endl;
|
||||
f_types_ << indent() << "var tickerCtx context.Context" << endl;
|
||||
f_types_ << indent() << "tickerCtx, tickerCancel = context.WithCancel(context.Background())" << endl;
|
||||
f_types_ << indent() << "defer tickerCancel()" << endl;
|
||||
f_types_ << indent() << "go func(ctx context.Context, cancel context.CancelFunc) {" << endl;
|
||||
f_types_ << indent() << "go func(ctx context.Context, cancel context.CancelCauseFunc) {" << endl;
|
||||
|
||||
indent_up();
|
||||
f_types_ << indent() << "ticker := time.NewTicker(thrift.ServerConnectivityCheckInterval)" << endl;
|
||||
@ -3029,7 +2821,7 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function*
|
||||
indent_up();
|
||||
f_types_ << indent() << "if !iprot.Transport().IsOpen() {" << endl;
|
||||
indent_up();
|
||||
f_types_ << indent() << "cancel()" << endl;
|
||||
f_types_ << indent() << "cancel(thrift.ErrAbandonRequest)" << endl;
|
||||
f_types_ << indent() << "return" << endl;
|
||||
indent_down();
|
||||
f_types_ << indent() << "}" << endl;
|
||||
@ -3109,6 +2901,15 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function*
|
||||
f_types_ << indent() << "return false, thrift.WrapTException(err2)" << endl;
|
||||
indent_down();
|
||||
f_types_ << indent() << "}" << endl;
|
||||
f_types_ << indent() << "if errors.Is(err2, context.Canceled) {" << endl;
|
||||
indent_up();
|
||||
f_types_ << indent() << "if err := context.Cause(ctx); errors.Is(err, thrift.ErrAbandonRequest) {" << endl;
|
||||
indent_up();
|
||||
f_types_ << indent() << "return false, thrift.WrapTException(err)" << endl;
|
||||
indent_down();
|
||||
f_types_ << indent() << "}" << endl;
|
||||
indent_down();
|
||||
f_types_ << indent() << "}" << endl;
|
||||
|
||||
string exc(tmp("_exc"));
|
||||
f_types_ << indent() << exc << " := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "
|
||||
@ -3303,6 +3104,10 @@ void t_go_generator::generate_deserialize_field(ostream& out,
|
||||
out << "ReadDouble(ctx)";
|
||||
break;
|
||||
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "ReadUUID(ctx)";
|
||||
break;
|
||||
|
||||
default:
|
||||
throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase);
|
||||
}
|
||||
@ -3552,6 +3357,10 @@ void t_go_generator::generate_serialize_field(ostream& out,
|
||||
out << "WriteDouble(ctx, float64(" << name << "))";
|
||||
break;
|
||||
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "WriteUUID(ctx, thrift.Tuuid(" << name << "))";
|
||||
break;
|
||||
|
||||
default:
|
||||
throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase);
|
||||
}
|
||||
@ -3751,6 +3560,7 @@ void t_go_generator::generate_go_equals(ostream& out, t_type* ori_type, string t
|
||||
case t_base_type::TYPE_I32:
|
||||
case t_base_type::TYPE_I64:
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << tgt << " != " << src;
|
||||
break;
|
||||
|
||||
@ -4057,6 +3867,12 @@ string t_go_generator::type_to_enum(t_type* type) {
|
||||
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "thrift.DOUBLE";
|
||||
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "thrift.UUID";
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "thrift.I32";
|
||||
@ -4144,6 +3960,12 @@ string t_go_generator::type_to_go_type_with_opt(t_type* type,
|
||||
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return maybe_pointer + "float64";
|
||||
|
||||
case t_base_type::TYPE_UUID:
|
||||
return maybe_pointer + "thrift.Tuuid";
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return maybe_pointer + publicize(type_name(type));
|
||||
@ -4257,6 +4079,11 @@ bool format_go_output(const string& file_path) {
|
||||
*/
|
||||
}
|
||||
|
||||
std::string t_go_generator::display_name() const {
|
||||
return "Go";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(go, "Go",
|
||||
" package_prefix= Package prefix for generated files.\n" \
|
||||
" thrift_import= Override thrift package import path (default:" + DEFAULT_THRIFT_IMPORT + ")\n" \
|
||||
|
330
compiler/cpp/src/thrift/generate/t_go_generator.h
Normal file
330
compiler/cpp/src/thrift/generate/t_go_generator.h
Normal file
@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef T_GO_GENERATOR_H
|
||||
#define T_GO_GENERATOR_H
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "thrift/generate/t_generator.h"
|
||||
#include "thrift/platform.h"
|
||||
#include "thrift/version.h"
|
||||
#include <algorithm>
|
||||
#include <clocale>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
using std::map;
|
||||
using std::ostream;
|
||||
using std::ostringstream;
|
||||
using std::string;
|
||||
using std::stringstream;
|
||||
using std::vector;
|
||||
|
||||
static const string endl = "\n"; // avoid ostream << std::endl flushes
|
||||
|
||||
const string DEFAULT_THRIFT_IMPORT = "github.com/apache/thrift/lib/go/thrift";
|
||||
static std::string package_flag;
|
||||
|
||||
/**
|
||||
* Go code generator.
|
||||
*/
|
||||
class t_go_generator : public t_generator {
|
||||
public:
|
||||
t_go_generator(t_program* program,
|
||||
const std::map<std::string, std::string>& parsed_options,
|
||||
const std::string& option_string)
|
||||
: t_generator(program) {
|
||||
(void)option_string;
|
||||
std::map<std::string, std::string>::const_iterator iter;
|
||||
|
||||
gen_thrift_import_ = DEFAULT_THRIFT_IMPORT;
|
||||
gen_package_prefix_ = "";
|
||||
package_flag = "";
|
||||
read_write_private_ = false;
|
||||
ignore_initialisms_ = false;
|
||||
skip_remote_ = false;
|
||||
for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
|
||||
if (iter->first.compare("package_prefix") == 0) {
|
||||
gen_package_prefix_ = (iter->second);
|
||||
} else if (iter->first.compare("thrift_import") == 0) {
|
||||
gen_thrift_import_ = (iter->second);
|
||||
} else if (iter->first.compare("package") == 0) {
|
||||
package_flag = (iter->second);
|
||||
} else if (iter->first.compare("read_write_private") == 0) {
|
||||
read_write_private_ = true;
|
||||
} else if (iter->first.compare("ignore_initialisms") == 0) {
|
||||
ignore_initialisms_ = true;
|
||||
} else if( iter->first.compare("skip_remote") == 0) {
|
||||
skip_remote_ = true;
|
||||
} else {
|
||||
throw "unknown option go:" + iter->first;
|
||||
}
|
||||
}
|
||||
|
||||
out_dir_base_ = "gen-go";
|
||||
}
|
||||
|
||||
/**
|
||||
* Init and close methods
|
||||
*/
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
*/
|
||||
|
||||
void generate_typedef(t_typedef* ttypedef) override;
|
||||
void generate_enum(t_enum* tenum) override;
|
||||
void generate_const(t_const* tconst) override;
|
||||
void generate_struct(t_struct* tstruct) override;
|
||||
void generate_xception(t_struct* txception) override;
|
||||
void generate_service(t_service* tservice) override;
|
||||
|
||||
std::string render_const_value(t_type* type,
|
||||
t_const_value* value,
|
||||
const string& name,
|
||||
bool opt = false);
|
||||
|
||||
/**
|
||||
* Struct generation code
|
||||
*/
|
||||
|
||||
void generate_go_struct(t_struct* tstruct, bool is_exception);
|
||||
void generate_go_struct_definition(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
bool is_xception = false,
|
||||
bool is_result = false,
|
||||
bool is_args = false);
|
||||
void generate_go_struct_initializer(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
bool is_args_or_result = false);
|
||||
void generate_isset_helpers(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
const string& tstruct_name,
|
||||
bool is_result = false);
|
||||
void generate_countsetfields_helper(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
const string& tstruct_name,
|
||||
bool is_result = false);
|
||||
void generate_go_struct_reader(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
const string& tstruct_name,
|
||||
bool is_result = false);
|
||||
void generate_go_struct_writer(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
const string& tstruct_name,
|
||||
bool is_result = false,
|
||||
bool uses_countsetfields = false);
|
||||
void generate_go_struct_equals(std::ostream& out, t_struct* tstruct, const string& tstruct_name);
|
||||
void generate_go_function_helpers(t_function* tfunction);
|
||||
void get_publicized_name_and_def_value(t_field* tfield,
|
||||
string* OUT_pub_name,
|
||||
t_const_value** OUT_def_value) const;
|
||||
|
||||
/**
|
||||
* Service-level generation functions
|
||||
*/
|
||||
|
||||
void generate_service_helpers(t_service* tservice);
|
||||
void generate_service_interface(t_service* tservice);
|
||||
void generate_service_client(t_service* tservice);
|
||||
void generate_service_remote(t_service* tservice);
|
||||
void generate_service_server(t_service* tservice);
|
||||
void generate_process_function(t_service* tservice, t_function* tfunction);
|
||||
|
||||
/**
|
||||
* Serialization constructs
|
||||
*/
|
||||
|
||||
void generate_deserialize_field(std::ostream& out,
|
||||
t_field* tfield,
|
||||
bool declare,
|
||||
std::string prefix = "",
|
||||
bool inclass = false,
|
||||
bool coerceData = false,
|
||||
bool inkey = false,
|
||||
bool in_container = false);
|
||||
|
||||
void generate_deserialize_struct(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
bool is_pointer_field,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_deserialize_container(std::ostream& out,
|
||||
t_type* ttype,
|
||||
bool pointer_field,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_deserialize_set_element(std::ostream& out,
|
||||
t_set* tset,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_deserialize_map_element(std::ostream& out,
|
||||
t_map* tmap,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_deserialize_list_element(std::ostream& out,
|
||||
t_list* tlist,
|
||||
bool declare,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_serialize_field(std::ostream& out,
|
||||
t_field* tfield,
|
||||
std::string prefix = "",
|
||||
bool inkey = false);
|
||||
|
||||
void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
|
||||
|
||||
void generate_serialize_container(std::ostream& out,
|
||||
t_type* ttype,
|
||||
bool pointer_field,
|
||||
std::string prefix = "");
|
||||
|
||||
void generate_serialize_map_element(std::ostream& out,
|
||||
t_map* tmap,
|
||||
std::string kiter,
|
||||
std::string viter);
|
||||
|
||||
void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
|
||||
|
||||
void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
|
||||
|
||||
void generate_go_equals(std::ostream& out, t_type* ttype, string tgt, string src);
|
||||
|
||||
void generate_go_equals_struct(std::ostream& out, t_type* ttype, string tgt, string src);
|
||||
|
||||
void generate_go_equals_container(std::ostream& out, t_type* ttype, string tgt, string src);
|
||||
|
||||
void generate_go_docstring(std::ostream& out, t_struct* tstruct);
|
||||
|
||||
void generate_go_docstring(std::ostream& out, t_function* tfunction);
|
||||
|
||||
void generate_go_docstring(std::ostream& out,
|
||||
t_doc* tdoc,
|
||||
t_struct* tstruct,
|
||||
const char* subheader);
|
||||
|
||||
void generate_go_docstring(std::ostream& out, t_doc* tdoc);
|
||||
|
||||
void parse_go_tags(map<string, string>* tags, const string in);
|
||||
|
||||
/**
|
||||
* Helper rendering functions
|
||||
*/
|
||||
|
||||
std::string go_autogen_comment();
|
||||
std::string go_package();
|
||||
std::string go_imports_begin(bool consts);
|
||||
std::string go_imports_end();
|
||||
std::string render_includes(bool consts);
|
||||
std::string render_included_programs(string& unused_protection);
|
||||
std::string render_program_import(const t_program* program, string& unused_protection);
|
||||
std::string render_system_packages(std::vector<string>& system_packages);
|
||||
std::string render_import_protection();
|
||||
std::string render_fastbinary_includes();
|
||||
std::string declare_argument(t_field* tfield);
|
||||
std::string render_field_initial_value(t_field* tfield, const string& name, bool optional_field);
|
||||
std::string type_name(t_type* ttype);
|
||||
std::string module_name(t_type* ttype);
|
||||
std::string function_signature(t_function* tfunction, std::string prefix = "");
|
||||
std::string function_signature_if(t_function* tfunction,
|
||||
std::string prefix = "",
|
||||
bool addError = false);
|
||||
std::string argument_list(t_struct* tstruct);
|
||||
std::string type_to_enum(t_type* ttype);
|
||||
std::string type_to_go_type(t_type* ttype);
|
||||
std::string type_to_go_type_with_opt(t_type* ttype, bool optional_field);
|
||||
std::string type_to_go_key_type(t_type* ttype);
|
||||
std::string type_to_spec_args(t_type* ttype);
|
||||
|
||||
void indent_up() { t_generator::indent_up(); }
|
||||
void indent_down() { t_generator::indent_down(); }
|
||||
std::string indent() { return t_generator::indent(); }
|
||||
std::ostream& indent(std::ostream& os) { return t_generator::indent(os); }
|
||||
|
||||
static std::string get_real_go_module(const t_program* program) {
|
||||
|
||||
if (!package_flag.empty()) {
|
||||
return package_flag;
|
||||
}
|
||||
std::string real_module = program->get_namespace("go");
|
||||
if (!real_module.empty()) {
|
||||
return real_module;
|
||||
}
|
||||
|
||||
return lowercase(program->get_name());
|
||||
}
|
||||
|
||||
static bool is_pointer_field(t_field* tfield, bool in_container = false);
|
||||
|
||||
private:
|
||||
std::string gen_package_prefix_;
|
||||
std::string gen_thrift_import_;
|
||||
bool read_write_private_;
|
||||
bool ignore_initialisms_;
|
||||
bool skip_remote_;
|
||||
|
||||
/**
|
||||
* File streams
|
||||
*/
|
||||
|
||||
ofstream_with_content_based_conditional_update f_types_;
|
||||
std::string f_types_name_;
|
||||
ofstream_with_content_based_conditional_update f_consts_;
|
||||
std::string f_consts_name_;
|
||||
std::stringstream f_const_values_;
|
||||
|
||||
std::string package_name_;
|
||||
std::string package_dir_;
|
||||
std::unordered_map<std::string, std::string> package_identifiers_;
|
||||
std::set<std::string> package_identifiers_set_;
|
||||
std::string read_method_name_;
|
||||
std::string write_method_name_;
|
||||
std::string equals_method_name_;
|
||||
|
||||
std::set<std::string> commonInitialisms;
|
||||
|
||||
std::string camelcase(const std::string& value) const;
|
||||
void fix_common_initialism(std::string& value, int i) const;
|
||||
std::string publicize(const std::string& value, bool is_args_or_result = false) const;
|
||||
std::string publicize(const std::string& value,
|
||||
bool is_args_or_result,
|
||||
const std::string& service_name) const;
|
||||
std::string privatize(const std::string& value) const;
|
||||
std::string new_prefix(const std::string& value) const;
|
||||
static std::string variable_name_to_go_name(const std::string& value);
|
||||
static bool omit_initialization(t_field* tfield);
|
||||
};
|
||||
|
||||
#endif
|
@ -67,12 +67,15 @@ public:
|
||||
/**
|
||||
* Init and end of generator
|
||||
*/
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
*/
|
||||
|
||||
void generate_typedef(t_typedef* ttypedef) override;
|
||||
void generate_enum(t_enum* tenum) override;
|
||||
void generate_const(t_const* tconst) override;
|
||||
@ -83,6 +86,7 @@ protected:
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
void print_type(t_type* ttype, string struct_field_ref);
|
||||
void print_const_value(t_type* type, t_const_value* tvalue);
|
||||
|
||||
@ -339,6 +343,11 @@ void t_gv_generator::generate_service(t_service* tservice) {
|
||||
f_out_ << " }" << endl;
|
||||
}
|
||||
|
||||
std::string t_gv_generator::display_name() const {
|
||||
return "Graphviz";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
gv,
|
||||
"Graphviz",
|
||||
|
@ -75,6 +75,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_consts(std::vector<t_const*> consts) override;
|
||||
|
||||
@ -200,6 +201,7 @@ public:
|
||||
std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false);
|
||||
std::string base_type_name(t_base_type* tbase, bool in_container = false);
|
||||
std::string declare_field(t_field* tfield, bool init = false);
|
||||
std::string render_default_value_for_type(t_type* type, bool allow_null);
|
||||
std::string function_signature_combined(t_function* tfunction);
|
||||
std::string function_signature_normal(t_function* tfunction);
|
||||
std::string argument_list(t_struct* tstruct);
|
||||
@ -208,6 +210,8 @@ public:
|
||||
string generate_service_method_onsuccess(t_function* tfunction, bool as_type, bool omit_name);
|
||||
void generate_service_method_signature_combined(t_function* tfunction, bool is_interface);
|
||||
void generate_service_method_signature_normal(t_function* tfunction, bool is_interface);
|
||||
void generate_deprecation_attribute(ostream& out, t_function* func, bool as_comment);
|
||||
string make_haxe_string_literal( string const& value);
|
||||
|
||||
bool type_can_be_null(t_type* ttype) {
|
||||
ttype = get_true_type(ttype);
|
||||
@ -544,6 +548,9 @@ void t_haxe_generator::render_const_value(std::ostream& out,
|
||||
case t_base_type::TYPE_STRING:
|
||||
out << '"' << get_escaped_string(value) << '"';
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << '"' << get_escaped_string(value) << '"';
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
out << ((value->get_integer() > 0) ? "true" : "false");
|
||||
break;
|
||||
@ -1443,6 +1450,9 @@ std::string t_haxe_generator::get_haxe_type_string(t_type* type) {
|
||||
case t_base_type::TYPE_STRING:
|
||||
return "TType.STRING";
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "TType.UUID";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return "TType.BOOL";
|
||||
break;
|
||||
@ -1657,6 +1667,7 @@ void t_haxe_generator::generate_service_method_signature(t_function* tfunction,
|
||||
void t_haxe_generator::generate_service_method_signature_normal(t_function* tfunction,
|
||||
bool is_interface) {
|
||||
if (is_interface) {
|
||||
generate_deprecation_attribute(f_service_, tfunction, true);
|
||||
indent(f_service_) << function_signature_normal(tfunction) << ";" << endl << endl;
|
||||
} else {
|
||||
indent(f_service_) << "public " << function_signature_normal(tfunction) << " {" << endl;
|
||||
@ -1677,12 +1688,60 @@ void t_haxe_generator::generate_service_method_signature_combined(t_function* tf
|
||||
}
|
||||
|
||||
if (is_interface) {
|
||||
generate_deprecation_attribute(f_service_, tfunction, false);
|
||||
indent(f_service_) << function_signature_combined(tfunction) << ";" << endl << endl;
|
||||
} else {
|
||||
indent(f_service_) << "public " << function_signature_combined(tfunction) << " {" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
string t_haxe_generator::make_haxe_string_literal( string const& value)
|
||||
{
|
||||
if (value.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream result;
|
||||
result << "\"";
|
||||
for (signed char const c: value) {
|
||||
if( (c >= 0) && (c < 32)) { // convert ctrl chars, but leave UTF-8 alone
|
||||
int width = std::min( (int)sizeof(c), 6);
|
||||
result << "\\u{" << std::hex << std::setw(width) << std::setfill('0') << (int)c << '}';
|
||||
} else if ((c == '\\') || (c == '"')) {
|
||||
result << "\\" << c;
|
||||
} else {
|
||||
result << c; // anything else "as is"
|
||||
}
|
||||
}
|
||||
result << "\"";
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void t_haxe_generator::generate_deprecation_attribute(ostream& out, t_function* func, bool as_comment)
|
||||
{
|
||||
auto iter = func->annotations_.find("deprecated");
|
||||
if( func->annotations_.end() != iter) {
|
||||
if( as_comment) {
|
||||
out << indent() << "// DEPRECATED";
|
||||
} else {
|
||||
out << indent() << "@:deprecated";
|
||||
}
|
||||
|
||||
// empty annotation values end up with "1" somewhere, ignore these as well
|
||||
if ((iter->second.back().length() > 0) && (iter->second.back() != "1")) {
|
||||
string text = make_haxe_string_literal(iter->second.back());
|
||||
if( as_comment) {
|
||||
out << ": " << text;
|
||||
} else {
|
||||
out << "(" << text << ")";
|
||||
}
|
||||
}
|
||||
|
||||
out << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a service interface definition.
|
||||
*
|
||||
@ -1820,8 +1879,9 @@ void t_haxe_generator::generate_service_client(t_service* tservice) {
|
||||
|
||||
string retval = tmp("retval");
|
||||
if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) {
|
||||
f_service_ << indent() << "var " << retval << " : " << type_name((*f_iter)->get_returntype()) << ";"
|
||||
<< endl;
|
||||
f_service_ << indent() << "var " << retval << " : " << type_name((*f_iter)->get_returntype())
|
||||
<< " = " << render_default_value_for_type((*f_iter)->get_returntype(),true)
|
||||
<< ";" << endl;
|
||||
}
|
||||
|
||||
if ((*f_iter)->is_oneway()) {
|
||||
@ -2222,6 +2282,9 @@ void t_haxe_generator::generate_deserialize_field(ostream& out, t_field* tfield,
|
||||
out << "readString();";
|
||||
}
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "readUuid();";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
out << "readBool();";
|
||||
break;
|
||||
@ -2406,6 +2469,9 @@ void t_haxe_generator::generate_serialize_field(ostream& out, t_field* tfield, s
|
||||
out << "writeString(" << name << ");";
|
||||
}
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "writeUuid(" << name << ");";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
out << "writeBool(" << name << ");";
|
||||
break;
|
||||
@ -2457,7 +2523,6 @@ void t_haxe_generator::generate_serialize_struct(ostream& out, t_struct* tstruct
|
||||
* @param prefix String prefix for fields
|
||||
*/
|
||||
void t_haxe_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
|
||||
scope_up(out);
|
||||
|
||||
if (ttype->is_map()) {
|
||||
string iter = tmp("_key");
|
||||
@ -2508,7 +2573,6 @@ void t_haxe_generator::generate_serialize_container(ostream& out, t_type* ttype,
|
||||
indent(out) << "oprot.writeListEnd();" << endl;
|
||||
}
|
||||
|
||||
scope_down(out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2573,6 +2637,8 @@ string t_haxe_generator::type_name(t_type* ttype, bool in_container, bool in_ini
|
||||
return "StringMap< " + type_name(tval) + ">";
|
||||
}
|
||||
break; // default to ObjectMap<>
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "StringMap< " + type_name(tval) + ">"; // uuids are stored as strings
|
||||
case t_base_type::TYPE_I8:
|
||||
case t_base_type::TYPE_I16:
|
||||
case t_base_type::TYPE_I32:
|
||||
@ -2599,6 +2665,8 @@ string t_haxe_generator::type_name(t_type* ttype, bool in_container, bool in_ini
|
||||
return "StringSet";
|
||||
}
|
||||
break; // default to ObjectSet
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "StringSet"; // uuids are stored as strings
|
||||
case t_base_type::TYPE_I8:
|
||||
case t_base_type::TYPE_I16:
|
||||
case t_base_type::TYPE_I32:
|
||||
@ -2651,6 +2719,8 @@ string t_haxe_generator::base_type_name(t_base_type* type, bool in_container) {
|
||||
} else {
|
||||
return "String";
|
||||
}
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "String";
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return "Bool";
|
||||
case t_base_type::TYPE_I8:
|
||||
@ -2672,44 +2742,50 @@ string t_haxe_generator::base_type_name(t_base_type* type, bool in_container) {
|
||||
* @param ttype The type
|
||||
*/
|
||||
string t_haxe_generator::declare_field(t_field* tfield, bool init) {
|
||||
// TODO(mcslee): do we ever need to initialize the field?
|
||||
string result = "var " + tfield->get_name() + " : " + type_name(tfield->get_type());
|
||||
if (init) {
|
||||
t_type* ttype = get_true_type(tfield->get_type());
|
||||
if (ttype->is_base_type() && tfield->get_value() != nullptr) {
|
||||
result += " = " + render_const_value_str( ttype, tfield->get_value());
|
||||
} else if (ttype->is_base_type()) {
|
||||
} else {
|
||||
result += " = " + render_default_value_for_type( ttype, false);
|
||||
}
|
||||
}
|
||||
return result + ";";
|
||||
}
|
||||
|
||||
string t_haxe_generator::render_default_value_for_type( t_type* type, bool allow_null) {
|
||||
t_type* ttype = get_true_type(type);
|
||||
|
||||
if (ttype->is_base_type()) {
|
||||
t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
|
||||
switch (tbase) {
|
||||
case t_base_type::TYPE_VOID:
|
||||
throw "NO T_VOID CONSTRUCT";
|
||||
case t_base_type::TYPE_STRING:
|
||||
result += " = null";
|
||||
break;
|
||||
return "null";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "uuid.Uuid.NIL";
|
||||
case t_base_type::TYPE_BOOL:
|
||||
result += " = false";
|
||||
break;
|
||||
return "false";
|
||||
case t_base_type::TYPE_I8:
|
||||
case t_base_type::TYPE_I16:
|
||||
case t_base_type::TYPE_I32:
|
||||
case t_base_type::TYPE_I64:
|
||||
result += " = 0";
|
||||
break;
|
||||
return "0";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
result += " = (double)0";
|
||||
break;
|
||||
return "0.0";
|
||||
default:
|
||||
throw "unhandled type";
|
||||
}
|
||||
|
||||
} else if (ttype->is_enum()) {
|
||||
result += " = 0";
|
||||
return "0";
|
||||
} else if (ttype->is_container()) {
|
||||
result += " = new " + type_name(ttype, false, true) + "()";
|
||||
return allow_null ? "null" : "new " + type_name(ttype, false, true) + "()";
|
||||
} else {
|
||||
result += " = new " + type_name(ttype, false, true) + "()";
|
||||
return allow_null ? "null" : "new " + type_name(ttype, false, true) + "()";
|
||||
}
|
||||
}
|
||||
return result + ";";
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a function signature of the form 'type name(args)'
|
||||
@ -2793,6 +2869,8 @@ string t_haxe_generator::type_to_enum(t_type* type) {
|
||||
throw "NO T_VOID CONSTRUCT";
|
||||
case t_base_type::TYPE_STRING:
|
||||
return "TType.STRING";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "TType.UUID";
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return "TType.BOOL";
|
||||
case t_base_type::TYPE_I8:
|
||||
@ -2805,6 +2883,8 @@ string t_haxe_generator::type_to_enum(t_type* type) {
|
||||
return "TType.I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "TType.DOUBLE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "TType.I32";
|
||||
@ -2994,6 +3074,11 @@ std::string t_haxe_generator::get_enum_class_name(t_type* type) {
|
||||
return package + type->get_name();
|
||||
}
|
||||
|
||||
std::string t_haxe_generator::display_name() const {
|
||||
return "Haxe";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
haxe,
|
||||
"Haxe",
|
||||
|
@ -81,6 +81,7 @@ public:
|
||||
|
||||
init_allowed__markup();
|
||||
}
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_program() override;
|
||||
void generate_program_toc();
|
||||
@ -1076,6 +1077,11 @@ void t_html_generator::generate_service(t_service* tservice) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string t_html_generator::display_name() const {
|
||||
return "HTML";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
html,
|
||||
"HTML",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -67,6 +67,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_consts(std::vector<t_const*> consts) override;
|
||||
|
||||
@ -2869,6 +2870,8 @@ string t_javame_generator::declare_field(t_field* tfield, bool init) {
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
result += " = (double)0";
|
||||
break;
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
|
||||
} else if (ttype->is_enum()) {
|
||||
@ -2951,6 +2954,8 @@ string t_javame_generator::type_to_enum(t_type* type) {
|
||||
return "TType.I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "TType.DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "TType.I32";
|
||||
@ -3291,4 +3296,9 @@ void t_javame_generator::generate_java_struct_clear(std::ostream& out, t_struct*
|
||||
indent(out) << "}" << endl << endl;
|
||||
}
|
||||
|
||||
std::string t_javame_generator::display_name() const {
|
||||
return "Java ME";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(javame, "Java ME", "")
|
||||
|
@ -134,6 +134,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -154,6 +155,7 @@ public:
|
||||
/**
|
||||
* Structs!
|
||||
*/
|
||||
|
||||
void generate_js_struct(t_struct* tstruct, bool is_exception);
|
||||
void generate_js_struct_definition(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
@ -166,6 +168,7 @@ public:
|
||||
/**
|
||||
* Service-level generation functions
|
||||
*/
|
||||
|
||||
void generate_service_helpers(t_service* tservice);
|
||||
void generate_service_interface(t_service* tservice);
|
||||
void generate_service_rest(t_service* tservice);
|
||||
@ -232,6 +235,7 @@ public:
|
||||
/**
|
||||
* Helper parser functions
|
||||
*/
|
||||
|
||||
void parse_imports(t_program* program, const std::string& imports_string);
|
||||
void parse_thrift_package_output_directory(const std::string& thrift_package_output_directory);
|
||||
|
||||
@ -1489,7 +1493,7 @@ void t_js_generator::generate_process_function(t_service* tservice, t_function*
|
||||
indent_up();
|
||||
|
||||
if (gen_es6_) {
|
||||
indent(f_service_) << "Promise.resolve(this._handler." << tfunction->get_name() << ".bind(this._handler)(" << endl;
|
||||
indent(f_service_) << "new Promise((resolve) => resolve(this._handler." << tfunction->get_name() << ".bind(this._handler)(" << endl;
|
||||
} else {
|
||||
string maybeComma = (fields.size() > 0 ? "," : "");
|
||||
indent(f_service_) << "Q.fcall(this._handler." << tfunction->get_name() << ".bind(this._handler)"
|
||||
@ -1504,7 +1508,7 @@ void t_js_generator::generate_process_function(t_service* tservice, t_function*
|
||||
indent_down();
|
||||
|
||||
if (gen_es6_) {
|
||||
indent(f_service_) << ")).then(result => {" << endl;
|
||||
indent(f_service_) << "))).then(result => {" << endl;
|
||||
} else {
|
||||
indent(f_service_) << ").then(function(result) {" << endl;
|
||||
}
|
||||
@ -2703,6 +2707,8 @@ string t_js_generator::type_to_enum(t_type* type) {
|
||||
return "Thrift.Type.I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "Thrift.Type.DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "Thrift.Type.I32";
|
||||
@ -2751,6 +2757,9 @@ string t_js_generator::ts_get_type(t_type* type) {
|
||||
break;
|
||||
case t_base_type::TYPE_VOID:
|
||||
ts_type = "void";
|
||||
break;
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum() || type->is_struct() || type->is_xception()) {
|
||||
std::string type_name;
|
||||
@ -2998,6 +3007,11 @@ std::string t_js_generator::next_identifier_name(const std::vector<t_field*>& fi
|
||||
return current_name;
|
||||
}
|
||||
|
||||
std::string t_js_generator::display_name() const {
|
||||
return "Javascript";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(js,
|
||||
"Javascript",
|
||||
" jquery: Generate jQuery compatible code.\n"
|
||||
|
@ -73,9 +73,9 @@ public:
|
||||
/**
|
||||
* Init and close methods
|
||||
*/
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_typedef(t_typedef* ttypedef) override;
|
||||
void generate_enum(t_enum* tenum) override;
|
||||
@ -245,7 +245,7 @@ void t_json_generator::end_array() {
|
||||
|
||||
void t_json_generator::write_type_spec_object(const char* name, t_type* ttype) {
|
||||
ttype = ttype->get_true_type();
|
||||
if (ttype->is_struct() || ttype->is_xception() || ttype->is_container()) {
|
||||
if (ttype->is_struct() || ttype->is_xception() || ttype->is_container() || ttype->is_enum()) {
|
||||
write_key_and(name);
|
||||
start_object(NO_INDENT);
|
||||
write_key_and("typeId");
|
||||
@ -268,12 +268,14 @@ void t_json_generator::write_type_spec(t_type* ttype) {
|
||||
write_key_and("annotations");
|
||||
start_object();
|
||||
for (auto & annotation : ttype->annotations_) {
|
||||
write_key_and_string(annotation.first, annotation.second);
|
||||
for (auto& annotation_value : annotation.second) {
|
||||
write_key_and_string(annotation.first, annotation_value);
|
||||
}
|
||||
}
|
||||
end_object();
|
||||
}
|
||||
|
||||
if (ttype->is_struct() || ttype->is_xception()) {
|
||||
if (ttype->is_struct() || ttype->is_xception() || ttype->is_enum()) {
|
||||
write_key_and_string("class", get_qualified_name(ttype));
|
||||
} else if (ttype->is_map()) {
|
||||
t_type* ktype = ((t_map*)ttype)->get_key_type();
|
||||
@ -459,7 +461,9 @@ void t_json_generator::generate_typedef(t_typedef* ttypedef) {
|
||||
write_key_and("annotations");
|
||||
start_object();
|
||||
for (auto & annotation : ttypedef->annotations_) {
|
||||
write_key_and_string(annotation.first, annotation.second);
|
||||
for (auto& annotation_value : annotation.second) {
|
||||
write_key_and_string(annotation.first, annotation_value);
|
||||
}
|
||||
}
|
||||
end_object();
|
||||
}
|
||||
@ -566,7 +570,9 @@ void t_json_generator::generate_enum(t_enum* tenum) {
|
||||
write_key_and("annotations");
|
||||
start_object();
|
||||
for (auto & annotation : tenum->annotations_) {
|
||||
write_key_and_string(annotation.first, annotation.second);
|
||||
for (auto& annotation_value : annotation.second) {
|
||||
write_key_and_string(annotation.first, annotation_value);
|
||||
}
|
||||
}
|
||||
end_object();
|
||||
}
|
||||
@ -605,7 +611,9 @@ void t_json_generator::generate_struct(t_struct* tstruct) {
|
||||
write_key_and("annotations");
|
||||
start_object();
|
||||
for (auto & annotation : tstruct->annotations_) {
|
||||
write_key_and_string(annotation.first, annotation.second);
|
||||
for (auto& annotation_value : annotation.second) {
|
||||
write_key_and_string(annotation.first, annotation_value);
|
||||
}
|
||||
}
|
||||
end_object();
|
||||
}
|
||||
@ -645,7 +653,9 @@ void t_json_generator::generate_service(t_service* tservice) {
|
||||
write_key_and("annotations");
|
||||
start_object();
|
||||
for (auto & annotation : tservice->annotations_) {
|
||||
write_key_and_string(annotation.first, annotation.second);
|
||||
for (auto& annotation_value : annotation.second) {
|
||||
write_key_and_string(annotation.first, annotation_value);
|
||||
}
|
||||
}
|
||||
end_object();
|
||||
}
|
||||
@ -682,7 +692,9 @@ void t_json_generator::generate_function(t_function* tfunc) {
|
||||
write_key_and("annotations");
|
||||
start_object();
|
||||
for (auto & annotation : tfunc->annotations_) {
|
||||
write_key_and_string(annotation.first, annotation.second);
|
||||
for (auto& annotation_value : annotation.second) {
|
||||
write_key_and_string(annotation.first, annotation_value);
|
||||
}
|
||||
}
|
||||
end_object();
|
||||
}
|
||||
@ -728,7 +740,9 @@ void t_json_generator::generate_field(t_field* field) {
|
||||
write_key_and("annotations");
|
||||
start_object();
|
||||
for (auto & annotation : field->annotations_) {
|
||||
write_key_and_string(annotation.first, annotation.second);
|
||||
for (auto& annotation_value : annotation.second) {
|
||||
write_key_and_string(annotation.first, annotation_value);
|
||||
}
|
||||
}
|
||||
end_object();
|
||||
}
|
||||
@ -766,7 +780,7 @@ string t_json_generator::get_type_name(t_type* ttype) {
|
||||
return "map";
|
||||
}
|
||||
if (ttype->is_enum()) {
|
||||
return "i32";
|
||||
return "enum";
|
||||
}
|
||||
if (ttype->is_struct()) {
|
||||
return ((t_struct*)ttype)->is_union() ? "union" : "struct";
|
||||
@ -789,6 +803,11 @@ string t_json_generator::get_qualified_name(t_type* ttype) {
|
||||
return ttype->get_program()->get_name() + "." + ttype->get_name();
|
||||
}
|
||||
|
||||
std::string t_json_generator::display_name() const {
|
||||
return "JSON";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(json,
|
||||
"JSON",
|
||||
" merge: Generate output with included files merged\n")
|
||||
|
@ -75,8 +75,10 @@ public:
|
||||
/**
|
||||
* Init and close methods
|
||||
*/
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_consts(std::vector<t_const*> consts) override;
|
||||
|
||||
@ -348,6 +350,8 @@ string t_kotlin_generator::base_type_name(t_base_type* type) {
|
||||
return "kotlin.Int";
|
||||
case t_base_type::TYPE_I64:
|
||||
return "kotlin.Long";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "java.util.UUID";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "kotlin.Double";
|
||||
default:
|
||||
@ -583,7 +587,7 @@ void t_kotlin_generator::generate_metadata_for_field_annotations(std::ostream& o
|
||||
out << "mapOf(" << endl;
|
||||
indent_up();
|
||||
for (auto& annotation : field->annotations_) {
|
||||
indent(out) << "\"" + annotation.first + "\" to \"" + annotation.second + "\"," << endl;
|
||||
indent(out) << "\"" + annotation.first + "\" to \"" + annotation.second.back() + "\"," << endl;
|
||||
}
|
||||
indent_down();
|
||||
indent(out) << ")";
|
||||
@ -1218,6 +1222,8 @@ string t_kotlin_generator::base_type_write_expression(t_base_type* tbase, string
|
||||
return "writeI32(" + it + ")";
|
||||
case t_base_type::TYPE_I64:
|
||||
return "writeI64(" + it + ")";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "writeUuid(" + it + ")";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "writeDouble(" + it + ")";
|
||||
default:
|
||||
@ -1246,6 +1252,8 @@ string t_kotlin_generator::base_type_read_expression(t_base_type* tbase) {
|
||||
return "readI32()";
|
||||
case t_base_type::TYPE_I64:
|
||||
return "readI64()";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "readUuid()";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "readDouble()";
|
||||
default:
|
||||
@ -1908,8 +1916,12 @@ string t_kotlin_generator::type_to_enum(t_type* type) {
|
||||
return "org.apache.thrift.protocol.TType.I32";
|
||||
case t_base_type::TYPE_I64:
|
||||
return "org.apache.thrift.protocol.TType.I64";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "org.apache.thrift.protocol.TType.UUID";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "org.apache.thrift.protocol.TType.DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "org.apache.thrift.protocol.TType.I32";
|
||||
@ -2013,4 +2025,9 @@ void t_kotlin_generator::generate_kdoc_comment(ostream& out, t_doc* tdoc) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string t_kotlin_generator::display_name() const {
|
||||
return "Kotlin";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(kotlin, "Kotlin", "")
|
||||
|
@ -56,12 +56,15 @@ public:
|
||||
/**
|
||||
* Init and close methods
|
||||
*/
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
*/
|
||||
|
||||
void generate_typedef(t_typedef* ttypedef) override;
|
||||
void generate_enum(t_enum* tenum) override;
|
||||
void generate_const(t_const* tconst) override;
|
||||
@ -80,6 +83,7 @@ private:
|
||||
/**
|
||||
* Struct-level generation functions
|
||||
*/
|
||||
|
||||
void generate_lua_struct_definition(std::ostream& out,
|
||||
t_struct* tstruct,
|
||||
bool is_xception = false);
|
||||
@ -89,6 +93,7 @@ private:
|
||||
/**
|
||||
* Service-level generation functions
|
||||
*/
|
||||
|
||||
void generate_service_client(std::ostream& out, t_service* tservice);
|
||||
void generate_service_interface(std::ostream& out, t_service* tservice);
|
||||
void generate_service_processor(std::ostream& out, t_service* tservice);
|
||||
@ -99,6 +104,7 @@ private:
|
||||
/**
|
||||
* Deserialization (Read)
|
||||
*/
|
||||
|
||||
void generate_deserialize_field(std::ostream& out,
|
||||
t_field* tfield,
|
||||
bool local,
|
||||
@ -125,6 +131,7 @@ private:
|
||||
/**
|
||||
* Serialization (Write)
|
||||
*/
|
||||
|
||||
void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
|
||||
|
||||
void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
|
||||
@ -1146,6 +1153,8 @@ string t_lua_generator::type_to_enum(t_type* type) {
|
||||
return "TType.I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "TType.DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "TType.I32";
|
||||
@ -1162,6 +1171,11 @@ string t_lua_generator::type_to_enum(t_type* type) {
|
||||
throw "INVALID TYPE IN type_to_enum: " + type->get_name();
|
||||
}
|
||||
|
||||
std::string t_lua_generator::display_name() const {
|
||||
return "Lua";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
lua,
|
||||
"Lua",
|
||||
|
@ -84,6 +84,8 @@ public:
|
||||
init_allowed__markup();
|
||||
}
|
||||
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_program() override;
|
||||
void generate_program_toc();
|
||||
void generate_program_toc_row(t_program* tprog);
|
||||
@ -1103,6 +1105,11 @@ void t_markdown_generator::generate_service(t_service* tservice) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string t_markdown_generator::display_name() const {
|
||||
return "Markdown";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
markdown,
|
||||
"Markdown",
|
||||
|
@ -123,11 +123,6 @@ bool t_netstd_generator::is_serialize_enabled() const { return serialize_; }
|
||||
|
||||
bool t_netstd_generator::is_union_enabled() const { return union_; }
|
||||
|
||||
map<string, int> t_netstd_generator::get_keywords_list() const
|
||||
{
|
||||
return netstd_keywords;
|
||||
}
|
||||
|
||||
void t_netstd_generator::init_generator()
|
||||
{
|
||||
MKDIR(get_out_dir().c_str());
|
||||
@ -151,7 +146,6 @@ void t_netstd_generator::init_generator()
|
||||
}
|
||||
|
||||
namespace_dir_ = subdir;
|
||||
init_keywords();
|
||||
|
||||
while (!member_mapping_scopes.empty())
|
||||
{
|
||||
@ -185,120 +179,16 @@ string t_netstd_generator::normalize_name(string name, bool is_arg_name)
|
||||
return "@" + name;
|
||||
}
|
||||
|
||||
// prevent CS8981 "The type name only contains lower-cased ascii characters"
|
||||
if( name.find_first_not_of("abcdefghijklmnopqrstuvwxyz") == std::string::npos)
|
||||
{
|
||||
return "@" + name;
|
||||
}
|
||||
|
||||
// no changes necessary
|
||||
return name;
|
||||
}
|
||||
|
||||
void t_netstd_generator::init_keywords()
|
||||
{
|
||||
netstd_keywords.clear();
|
||||
|
||||
// C# keywords
|
||||
netstd_keywords["abstract"] = 1;
|
||||
netstd_keywords["as"] = 1;
|
||||
netstd_keywords["base"] = 1;
|
||||
netstd_keywords["bool"] = 1;
|
||||
netstd_keywords["break"] = 1;
|
||||
netstd_keywords["byte"] = 1;
|
||||
netstd_keywords["case"] = 1;
|
||||
netstd_keywords["catch"] = 1;
|
||||
netstd_keywords["char"] = 1;
|
||||
netstd_keywords["checked"] = 1;
|
||||
netstd_keywords["class"] = 1;
|
||||
netstd_keywords["const"] = 1;
|
||||
netstd_keywords["continue"] = 1;
|
||||
netstd_keywords["decimal"] = 1;
|
||||
netstd_keywords["default"] = 1;
|
||||
netstd_keywords["delegate"] = 1;
|
||||
netstd_keywords["do"] = 1;
|
||||
netstd_keywords["double"] = 1;
|
||||
netstd_keywords["else"] = 1;
|
||||
netstd_keywords["enum"] = 1;
|
||||
netstd_keywords["event"] = 1;
|
||||
netstd_keywords["explicit"] = 1;
|
||||
netstd_keywords["extern"] = 1;
|
||||
netstd_keywords["false"] = 1;
|
||||
netstd_keywords["finally"] = 1;
|
||||
netstd_keywords["fixed"] = 1;
|
||||
netstd_keywords["float"] = 1;
|
||||
netstd_keywords["for"] = 1;
|
||||
netstd_keywords["foreach"] = 1;
|
||||
netstd_keywords["goto"] = 1;
|
||||
netstd_keywords["if"] = 1;
|
||||
netstd_keywords["implicit"] = 1;
|
||||
netstd_keywords["in"] = 1;
|
||||
netstd_keywords["int"] = 1;
|
||||
netstd_keywords["interface"] = 1;
|
||||
netstd_keywords["internal"] = 1;
|
||||
netstd_keywords["is"] = 1;
|
||||
netstd_keywords["lock"] = 1;
|
||||
netstd_keywords["long"] = 1;
|
||||
netstd_keywords["namespace"] = 1;
|
||||
netstd_keywords["new"] = 1;
|
||||
netstd_keywords["null"] = 1;
|
||||
netstd_keywords["object"] = 1;
|
||||
netstd_keywords["operator"] = 1;
|
||||
netstd_keywords["out"] = 1;
|
||||
netstd_keywords["override"] = 1;
|
||||
netstd_keywords["params"] = 1;
|
||||
netstd_keywords["private"] = 1;
|
||||
netstd_keywords["protected"] = 1;
|
||||
netstd_keywords["public"] = 1;
|
||||
netstd_keywords["readonly"] = 1;
|
||||
netstd_keywords["ref"] = 1;
|
||||
netstd_keywords["return"] = 1;
|
||||
netstd_keywords["sbyte"] = 1;
|
||||
netstd_keywords["sealed"] = 1;
|
||||
netstd_keywords["short"] = 1;
|
||||
netstd_keywords["sizeof"] = 1;
|
||||
netstd_keywords["stackalloc"] = 1;
|
||||
netstd_keywords["static"] = 1;
|
||||
netstd_keywords["string"] = 1;
|
||||
netstd_keywords["struct"] = 1;
|
||||
netstd_keywords["switch"] = 1;
|
||||
netstd_keywords["this"] = 1;
|
||||
netstd_keywords["throw"] = 1;
|
||||
netstd_keywords["true"] = 1;
|
||||
netstd_keywords["try"] = 1;
|
||||
netstd_keywords["typeof"] = 1;
|
||||
netstd_keywords["uint"] = 1;
|
||||
netstd_keywords["ulong"] = 1;
|
||||
netstd_keywords["unchecked"] = 1;
|
||||
netstd_keywords["unsafe"] = 1;
|
||||
netstd_keywords["ushort"] = 1;
|
||||
netstd_keywords["using"] = 1;
|
||||
netstd_keywords["virtual"] = 1;
|
||||
netstd_keywords["void"] = 1;
|
||||
netstd_keywords["volatile"] = 1;
|
||||
netstd_keywords["while"] = 1;
|
||||
|
||||
// C# contextual keywords
|
||||
netstd_keywords["add"] = 1;
|
||||
netstd_keywords["alias"] = 1;
|
||||
netstd_keywords["ascending"] = 1;
|
||||
netstd_keywords["async"] = 1;
|
||||
netstd_keywords["await"] = 1;
|
||||
netstd_keywords["descending"] = 1;
|
||||
netstd_keywords["dynamic"] = 1;
|
||||
netstd_keywords["from"] = 1;
|
||||
netstd_keywords["get"] = 1;
|
||||
netstd_keywords["global"] = 1;
|
||||
netstd_keywords["group"] = 1;
|
||||
netstd_keywords["into"] = 1;
|
||||
netstd_keywords["join"] = 1;
|
||||
netstd_keywords["let"] = 1;
|
||||
netstd_keywords["orderby"] = 1;
|
||||
netstd_keywords["partial"] = 1;
|
||||
netstd_keywords["remove"] = 1;
|
||||
netstd_keywords["select"] = 1;
|
||||
netstd_keywords["set"] = 1;
|
||||
netstd_keywords["value"] = 1;
|
||||
netstd_keywords["var"] = 1;
|
||||
netstd_keywords["where"] = 1;
|
||||
netstd_keywords["yield"] = 1;
|
||||
|
||||
netstd_keywords["when"] = 1;
|
||||
}
|
||||
|
||||
void t_netstd_generator::reset_indent() {
|
||||
while( indent_count() > 0) {
|
||||
@ -427,7 +317,7 @@ void t_netstd_generator::generate_enum(ostream& out, t_enum* tenum)
|
||||
{
|
||||
generate_netstd_doc(out, *c_iter);
|
||||
int value = (*c_iter)->get_value();
|
||||
out << indent() << (*c_iter)->get_name() << " = " << value << "," << endl;
|
||||
out << indent() << normalize_name((*c_iter)->get_name()) << " = " << value << "," << endl;
|
||||
}
|
||||
|
||||
scope_down(out);
|
||||
@ -472,7 +362,7 @@ void t_netstd_generator::generate_consts(ostream& out, vector<t_const*> consts)
|
||||
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter)
|
||||
{
|
||||
generate_netstd_doc(out, *c_iter);
|
||||
if (print_const_value(out, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value(), false))
|
||||
if (print_const_value(out, normalize_name((*c_iter)->get_name()), (*c_iter)->get_type(), (*c_iter)->get_value(), false))
|
||||
{
|
||||
need_static_constructor = true;
|
||||
}
|
||||
@ -590,7 +480,7 @@ bool t_netstd_generator::print_const_value(ostream& out, string name, t_type* ty
|
||||
if (type->is_base_type())
|
||||
{
|
||||
string v2 = render_const_value(out, name, type, value);
|
||||
out << normalize_name(name) << " = " << v2 << ";" << endl;
|
||||
out << name << " = " << v2 << ";" << endl;
|
||||
need_static_construction = false;
|
||||
}
|
||||
else if (type->is_enum())
|
||||
@ -636,6 +526,9 @@ string t_netstd_generator::render_const_value(ostream& out, string name, t_type*
|
||||
render << '"' << get_escaped_string(value) << '"';
|
||||
}
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
render << "new System.Guid(\"" << get_escaped_string(value) << "\")";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
render << ((value->get_integer() > 0) ? "true" : "false");
|
||||
break;
|
||||
@ -665,7 +558,7 @@ string t_netstd_generator::render_const_value(ostream& out, string name, t_type*
|
||||
}
|
||||
else
|
||||
{
|
||||
string t = tmp("tmp");
|
||||
string t = normalize_name(tmp("tmp"));
|
||||
print_const_value(out, t, type, value, true, true, true);
|
||||
render << t;
|
||||
}
|
||||
@ -1053,7 +946,7 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc
|
||||
{
|
||||
if (field_is_required((*m_iter)))
|
||||
{
|
||||
print_const_value(out, "this." + prop_name(*m_iter), t, (*m_iter)->get_value(), true, true);
|
||||
print_const_value(out, "this." + normalize_name(prop_name(*m_iter)), t, (*m_iter)->get_value(), true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1569,14 +1462,14 @@ void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct
|
||||
// Let's define the class first
|
||||
start_netstd_namespace(out);
|
||||
|
||||
out << indent() << "public abstract partial class " << tunion->get_name() << " : TUnionBase" << endl;
|
||||
out << indent() << "public abstract partial class " << normalize_name(tunion->get_name()) << " : TUnionBase" << endl;
|
||||
out << indent() << "{" << endl;
|
||||
indent_up();
|
||||
|
||||
out << indent() << "public abstract global::System.Threading.Tasks.Task WriteAsync(TProtocol tProtocol, CancellationToken " << CANCELLATION_TOKEN_NAME << ");" << endl
|
||||
<< indent() << "public readonly int Isset;" << endl
|
||||
<< indent() << "public abstract object" << nullable_suffix() <<" Data { get; }" << endl
|
||||
<< indent() << "protected " << tunion->get_name() << "(int isset)" << endl
|
||||
<< indent() << "protected " << normalize_name(tunion->get_name()) << "(int isset)" << endl
|
||||
<< indent() << "{" << endl;
|
||||
indent_up();
|
||||
out << indent() << "Isset = isset;" << endl;
|
||||
@ -1782,13 +1675,13 @@ void t_netstd_generator::generate_netstd_union_class(ostream& out, t_struct* tun
|
||||
<< endl;
|
||||
|
||||
|
||||
out << indent() << "public class " << tfield->get_name() << " : " << tunion->get_name() << endl;
|
||||
out << indent() << "public class " << normalize_name(tfield->get_name()) << " : " << normalize_name(tunion->get_name()) << endl;
|
||||
out << indent() << "{" << endl;
|
||||
indent_up();
|
||||
|
||||
out << indent() << "private readonly " << type_name(tfield->get_type()) << " _data;" << endl
|
||||
<< indent() << "public override object" << nullable_suffix() <<" Data { get { return _data; } }" << endl
|
||||
<< indent() << "public " << tfield->get_name() << "(" << type_name(tfield->get_type()) << " data) : base("<< tfield->get_key() <<")" << endl
|
||||
<< indent() << "public " << normalize_name(tfield->get_name()) << "(" << type_name(tfield->get_type()) << " data) : base("<< tfield->get_key() <<")" << endl
|
||||
<< indent() << "{" << endl;
|
||||
indent_up();
|
||||
out << indent() << "this._data = data;" << endl;
|
||||
@ -1796,13 +1689,13 @@ void t_netstd_generator::generate_netstd_union_class(ostream& out, t_struct* tun
|
||||
out << indent() << "}" << endl;
|
||||
|
||||
if( ! suppress_deepcopy) {
|
||||
out << indent() << "public new " << tfield->get_name() << " " << DEEP_COPY_METHOD_NAME << "()" << endl;
|
||||
out << indent() << "public new " << normalize_name(tfield->get_name()) << " " << DEEP_COPY_METHOD_NAME << "()" << endl;
|
||||
out << indent() << "{" << endl;
|
||||
indent_up();
|
||||
bool needs_typecast = false;
|
||||
string suffix("");
|
||||
string copy_op = get_deep_copy_method_call(tfield->get_type(), true, needs_typecast, suffix);
|
||||
out << indent() << "return new " << tfield->get_name() << "(_data" << copy_op << ");" << endl;
|
||||
out << indent() << "return new " << normalize_name(tfield->get_name()) << "(_data" << copy_op << ");" << endl;
|
||||
indent_down();
|
||||
out << indent() << "}" << endl << endl;
|
||||
}
|
||||
@ -2056,8 +1949,8 @@ void t_netstd_generator::generate_deprecation_attribute(ostream& out, t_function
|
||||
if( func->annotations_.end() != iter) {
|
||||
out << indent() << "[Obsolete";
|
||||
// empty annotation values end up with "1" somewhere, ignore these as well
|
||||
if ((iter->second.length() > 0) && (iter->second != "1")) {
|
||||
out << "(" << make_csharp_string_literal(iter->second) << ")";
|
||||
if ((iter->second.back().length() > 0) && (iter->second.back() != "1")) {
|
||||
out << "(" << make_csharp_string_literal(iter->second.back()) << ")";
|
||||
}
|
||||
out << "]" << endl;
|
||||
}
|
||||
@ -2703,6 +2596,9 @@ void t_netstd_generator::generate_deserialize_field(ostream& out, t_field* tfiel
|
||||
out << "ReadStringAsync(" << CANCELLATION_TOKEN_NAME << ");";
|
||||
}
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "ReadUuidAsync(" << CANCELLATION_TOKEN_NAME << ");";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
out << "ReadBoolAsync(" << CANCELLATION_TOKEN_NAME << ");";
|
||||
break;
|
||||
@ -2906,6 +2802,9 @@ void t_netstd_generator::generate_serialize_field(ostream& out, t_field* tfield,
|
||||
}
|
||||
out << name << ", " << CANCELLATION_TOKEN_NAME << ");";
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "WriteUuidAsync(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
out << "WriteBoolAsync(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");";
|
||||
break;
|
||||
@ -3492,6 +3391,8 @@ string t_netstd_generator::base_type_name(t_base_type* tbase)
|
||||
} else {
|
||||
return "string";
|
||||
}
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "global::System.Guid";
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return "bool";
|
||||
case t_base_type::TYPE_I8:
|
||||
@ -3614,6 +3515,9 @@ string t_netstd_generator::initialize_field(t_field* tfield)
|
||||
return " = null";
|
||||
}
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
return " = System.Guid.Empty";
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return " = false";
|
||||
break;
|
||||
@ -3725,6 +3629,8 @@ string t_netstd_generator::type_to_enum(t_type* type)
|
||||
throw "NO T_VOID CONSTRUCT";
|
||||
case t_base_type::TYPE_STRING:
|
||||
return "TType.String";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "TType.Uuid";
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return "TType.Bool";
|
||||
case t_base_type::TYPE_I8:
|
||||
@ -3858,6 +3764,11 @@ string t_netstd_generator::get_enum_class_name(t_type* type)
|
||||
return "global::" + package + type->get_name();
|
||||
}
|
||||
|
||||
std::string t_netstd_generator::display_name() const {
|
||||
return "C#";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
netstd,
|
||||
"C#",
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "thrift/generate/t_oop_generator.h"
|
||||
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::ostream;
|
||||
using std::ostringstream;
|
||||
using std::string;
|
||||
@ -66,11 +67,11 @@ public:
|
||||
bool is_hashcode_enabled() const;
|
||||
bool is_serialize_enabled() const;
|
||||
bool is_union_enabled() const;
|
||||
map<string, int> get_keywords_list() const;
|
||||
|
||||
// overrides
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
void generate_consts(vector<t_const*> consts) override;
|
||||
void generate_consts(ostream& out, vector<t_const*> consts);
|
||||
void generate_typedef(t_typedef* ttypedef) override;
|
||||
@ -179,13 +180,26 @@ private:
|
||||
bool use_net6_features;
|
||||
bool add_async_postfix;
|
||||
|
||||
const std::string CSHARP_KEYWORDS[101] = {
|
||||
// C# keywords
|
||||
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue",
|
||||
"decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally",
|
||||
"fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
|
||||
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected",
|
||||
"public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string",
|
||||
"struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort",
|
||||
"using", "virtual", "void", "volatile", "while",
|
||||
// C# contextual keywords
|
||||
"add", "alias", "ascending", "async", "await", "descending", "dynamic", "from", "get", "global", "group", "into",
|
||||
"join", "let", "orderby", "partial", "remove", "select", "set", "value", "var", "when", "where", "yield"
|
||||
};
|
||||
|
||||
string wcf_namespace_;
|
||||
map<string, int> netstd_keywords;
|
||||
std::set<string> netstd_keywords = std::set<string>(CSHARP_KEYWORDS, CSHARP_KEYWORDS + sizeof(CSHARP_KEYWORDS) / sizeof(CSHARP_KEYWORDS[0]));
|
||||
vector<member_mapping_scope> member_mapping_scopes;
|
||||
map<string, t_type*> collected_extension_types;
|
||||
map<string, t_type*> checked_extension_types;
|
||||
|
||||
void init_keywords();
|
||||
string normalize_name(string name, bool is_arg_name = false);
|
||||
string make_valid_csharp_identifier(string const& fromName);
|
||||
string make_csharp_string_literal( string const& value);
|
||||
|
@ -61,16 +61,15 @@ public:
|
||||
out_dir_base_ = "gen-ocaml";
|
||||
}
|
||||
|
||||
/**
|
||||
* Init and close methods
|
||||
*/
|
||||
~t_ocaml_generator() override;
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
*/
|
||||
|
||||
void generate_program() override;
|
||||
void generate_typedef(t_typedef* ttypedef) override;
|
||||
void generate_enum(t_enum* tenum) override;
|
||||
@ -147,16 +146,20 @@ public:
|
||||
* Helper rendering functions
|
||||
*/
|
||||
|
||||
std::string ocaml_autogen_comment();
|
||||
/** Need to disable codegen comment for unit tests to be version-agnostic */
|
||||
virtual std::string ocaml_autogen_comment();
|
||||
|
||||
std::string ocaml_imports();
|
||||
std::string type_name(t_type* ttype);
|
||||
std::string exception_ctor(t_type* ttype);
|
||||
std::string function_signature(t_function* tfunction, std::string prefix = "");
|
||||
std::string function_type(t_function* tfunc, bool method = false, bool options = false);
|
||||
std::string argument_list(t_struct* tstruct);
|
||||
std::string type_to_enum(t_type* ttype);
|
||||
std::string render_ocaml_type(t_type* type);
|
||||
|
||||
private:
|
||||
// Need access to output file streams for testing.
|
||||
protected:
|
||||
/**
|
||||
* File streams
|
||||
*/
|
||||
@ -216,9 +219,6 @@ void t_ocaml_generator::generate_program() {
|
||||
// Generate constants
|
||||
vector<t_const*> consts = program_->get_consts();
|
||||
generate_consts(consts);
|
||||
|
||||
// Close the generator
|
||||
close_generator();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -262,12 +262,12 @@ string t_ocaml_generator::ocaml_imports() {
|
||||
return "open Thrift";
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the type files
|
||||
*/
|
||||
void t_ocaml_generator::close_generator() {
|
||||
// Close types file
|
||||
t_ocaml_generator::~t_ocaml_generator() {
|
||||
f_consts_.close();
|
||||
f_types_.close();
|
||||
f_types_i_.close();
|
||||
f_service_.close();
|
||||
f_service_i_.close();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -914,10 +914,6 @@ void t_ocaml_generator::generate_service(t_service* tservice) {
|
||||
generate_service_interface(tservice);
|
||||
generate_service_client(tservice);
|
||||
generate_service_server(tservice);
|
||||
|
||||
// Close service file
|
||||
f_service_.close();
|
||||
f_service_i_.close();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1108,7 +1104,7 @@ void t_ocaml_generator::generate_service_client(t_service* tservice) {
|
||||
for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
|
||||
f_service_ << indent() << "(match result#get_" << (*x_iter)->get_name()
|
||||
<< " with None -> () | Some _v ->" << endl;
|
||||
indent(f_service_) << " raise (" << capitalize(type_name((*x_iter)->get_type()))
|
||||
indent(f_service_) << " raise (" << capitalize(exception_ctor((*x_iter)->get_type()))
|
||||
<< " _v));" << endl;
|
||||
}
|
||||
|
||||
@ -1270,7 +1266,7 @@ void t_ocaml_generator::generate_process_function(t_service* tservice, t_functio
|
||||
indent(f_service_) << "with" << endl;
|
||||
indent_up();
|
||||
for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
|
||||
f_service_ << indent() << "| " << capitalize(type_name((*x_iter)->get_type())) << " "
|
||||
f_service_ << indent() << "| " << capitalize(exception_ctor((*x_iter)->get_type())) << " "
|
||||
<< (*x_iter)->get_name() << " -> " << endl;
|
||||
indent_up();
|
||||
indent_up();
|
||||
@ -1673,6 +1669,18 @@ string t_ocaml_generator::type_name(t_type* ttype) {
|
||||
return prefix + name;
|
||||
}
|
||||
|
||||
string t_ocaml_generator::exception_ctor(t_type* ttype) {
|
||||
string prefix = "";
|
||||
t_program* program = ttype->get_program();
|
||||
if (program != nullptr && program != program_) {
|
||||
if (!ttype->is_service()) {
|
||||
prefix = capitalize(program->get_name()) + "_types.";
|
||||
}
|
||||
}
|
||||
|
||||
return prefix + capitalize(ttype->get_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the parse type to a Protocol.t_type enum
|
||||
*/
|
||||
@ -1698,6 +1706,8 @@ string t_ocaml_generator::type_to_enum(t_type* type) {
|
||||
return "Protocol.T_I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "Protocol.T_DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "Protocol.T_I32";
|
||||
@ -1739,6 +1749,8 @@ string t_ocaml_generator::render_ocaml_type(t_type* type) {
|
||||
return "Int64.t";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "float";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return capitalize(((t_enum*)type)->get_name()) + ".t";
|
||||
@ -1759,4 +1771,9 @@ string t_ocaml_generator::render_ocaml_type(t_type* type) {
|
||||
throw "INVALID TYPE IN type_to_enum: " + type->get_name();
|
||||
}
|
||||
|
||||
std::string t_ocaml_generator::display_name() const {
|
||||
return "OCaml";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(ocaml, "OCaml", "")
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void generate_java_doc(std::ostream& out, t_field* field) {
|
||||
if (field->get_type()->is_enum()) {
|
||||
if (get_true_type(field->get_type())->is_enum()) {
|
||||
std::string combined_message = field->get_doc() + "\n@see "
|
||||
+ get_enum_class_name(field->get_type());
|
||||
generate_java_docstring_comment(out, combined_message);
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -1666,6 +1667,8 @@ string t_perl_generator::type_to_enum(t_type* type) {
|
||||
return "Thrift::TType::I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "Thrift::TType::DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "Thrift::TType::I32";
|
||||
@ -1682,4 +1685,9 @@ string t_perl_generator::type_to_enum(t_type* type) {
|
||||
throw "INVALID TYPE IN type_to_enum: " + type->get_name();
|
||||
}
|
||||
|
||||
std::string t_perl_generator::display_name() const {
|
||||
return "Perl";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(perl, "Perl", "")
|
||||
|
@ -99,6 +99,7 @@ public:
|
||||
throw "oop and inlined are mutually exclusive.";
|
||||
}
|
||||
|
||||
update_keywords_for_validation();
|
||||
out_dir_base_ = (binary_inline_ ? "gen-phpi" : "gen-php");
|
||||
escape_['$'] = "\\$";
|
||||
}
|
||||
@ -115,6 +116,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -128,6 +130,7 @@ public:
|
||||
void generate_service(t_service* tservice) override;
|
||||
|
||||
std::string render_const_value(t_type* type, t_const_value* value);
|
||||
std::set<std::string> lang_keywords_for_validation() const override;
|
||||
|
||||
/**
|
||||
* Structs!
|
||||
@ -418,6 +421,22 @@ private:
|
||||
bool getters_setters_;
|
||||
};
|
||||
|
||||
std::set<std::string> t_php_generator::lang_keywords_for_validation() const {
|
||||
std::string keywords[] = { "BEGIN", "END", "__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__",
|
||||
"__LINE__", "__METHOD__", "__NAMESPACE__", "abstract", "alias", "and", "args", "as",
|
||||
"assert", "begin", "break", "case", "catch", "class", "clone", "continue", "declare",
|
||||
"def", "default", "del", "delete", "do", "dynamic", "elif", "else", "elseif", "elsif",
|
||||
"end", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "ensure",
|
||||
"except", "exec", "finally", "float", "for", "foreach", "from", "function", "global",
|
||||
"goto", "if", "implements", "import", "in", "inline", "instanceof", "interface", "is",
|
||||
"lambda", "module", "native", "new", "next", "nil", "not", "or", "package", "pass",
|
||||
"public", "print", "private", "protected", "raise", "redo", "rescue", "retry", "register",
|
||||
"return", "self", "sizeof", "static", "super", "switch", "synchronized", "then", "this",
|
||||
"throw", "transient", "try", "undef", "unless", "unsigned", "until", "use", "var",
|
||||
"virtual", "volatile", "when", "while", "with", "xor", "yield" };
|
||||
return std::set<std::string>(keywords, keywords + sizeof(keywords)/sizeof(keywords[0]) );
|
||||
}
|
||||
|
||||
bool t_php_generator::is_valid_namespace(const std::string& sub_namespace) {
|
||||
return sub_namespace == "path";
|
||||
}
|
||||
@ -2798,6 +2817,8 @@ string t_php_generator::type_to_enum(t_type* type) {
|
||||
return "TType::I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "TType::DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "TType::I32";
|
||||
@ -2839,6 +2860,8 @@ string t_php_generator::type_to_phpdoc(t_type* type) {
|
||||
return "int";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "double";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "int";
|
||||
@ -2867,6 +2890,11 @@ string t_php_generator::type_to_phpdoc(t_type* type) {
|
||||
throw "INVALID TYPE IN type_to_enum: " + type->get_name();
|
||||
}
|
||||
|
||||
std::string t_php_generator::display_name() const {
|
||||
return "PHP";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
php,
|
||||
"PHP",
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
const std::map<std::string, std::string>& parsed_options,
|
||||
const std::string& option_string)
|
||||
: t_generator (program) {
|
||||
update_keywords();
|
||||
update_keywords_for_validation();
|
||||
|
||||
std::map<std::string, std::string>::const_iterator iter;
|
||||
|
||||
@ -157,6 +157,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -280,12 +281,12 @@ public:
|
||||
}
|
||||
|
||||
static bool is_immutable(t_type* ttype) {
|
||||
std::map<std::string, std::string>::iterator it = ttype->annotations_.find("python.immutable");
|
||||
std::map<std::string, std::vector<std::string>>::iterator it = ttype->annotations_.find("python.immutable");
|
||||
|
||||
if (it == ttype->annotations_.end()) {
|
||||
// Exceptions are immutable by default.
|
||||
return ttype->is_xception();
|
||||
} else if (it->second == "false") {
|
||||
} else if (!it->second.empty() && it->second.back() == "false") {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
@ -357,7 +358,7 @@ private:
|
||||
std::string module_;
|
||||
|
||||
protected:
|
||||
std::set<std::string> lang_keywords() const override {
|
||||
std::set<std::string> lang_keywords_for_validation() const override {
|
||||
std::string keywords[] = { "False", "None", "True", "and", "as", "assert", "break", "class",
|
||||
"continue", "def", "del", "elif", "else", "except", "exec", "finally", "for", "from",
|
||||
"global", "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass", "print",
|
||||
@ -606,7 +607,7 @@ string t_py_generator::render_const_value(t_type* type, t_const_value* value) {
|
||||
int64_t int_val = value->get_integer();
|
||||
if (gen_enum_) {
|
||||
t_enum_value* enum_val = ((t_enum*)type)->get_constant_by_value(int_val);
|
||||
out << type->get_name() << "." << enum_val->get_name();
|
||||
out << type_name(type) << "." << enum_val->get_name();
|
||||
} else {
|
||||
out << int_val;
|
||||
}
|
||||
@ -870,7 +871,12 @@ void t_py_generator::generate_py_struct_definition(ostream& out,
|
||||
}
|
||||
|
||||
if (is_immutable(tstruct)) {
|
||||
if (gen_newstyle_ || gen_dynamic_) {
|
||||
if (gen_enum_ && type->is_enum()) {
|
||||
indent(out) << "super(" << tstruct->get_name() << ", self).__setattr__('"
|
||||
<< (*m_iter)->get_name() << "', " << (*m_iter)->get_name()
|
||||
<< " if hasattr(" << (*m_iter)->get_name() << ", 'value') else "
|
||||
<< type_name(type) << ".__members__.get(" << (*m_iter)->get_name() << "))" << endl;
|
||||
} else if (gen_newstyle_ || gen_dynamic_) {
|
||||
indent(out) << "super(" << tstruct->get_name() << ", self).__setattr__('"
|
||||
<< (*m_iter)->get_name() << "', " << (*m_iter)->get_name() << ")" << endl;
|
||||
} else {
|
||||
@ -887,12 +893,42 @@ void t_py_generator::generate_py_struct_definition(ostream& out,
|
||||
|
||||
if (is_immutable(tstruct)) {
|
||||
out << endl;
|
||||
out << indent() << "def __setattr__(self, *args):" << endl
|
||||
<< indent() << indent_str() << "raise TypeError(\"can't modify immutable instance\")" << endl
|
||||
<< endl;
|
||||
out << indent() << "def __delattr__(self, *args):" << endl
|
||||
<< indent() << indent_str() << "raise TypeError(\"can't modify immutable instance\")" << endl
|
||||
<< endl;
|
||||
out << indent() << "def __setattr__(self, *args):" << endl;
|
||||
indent_up();
|
||||
|
||||
// Not user-provided fields should be editable so that the Python Standard Library can edit
|
||||
// internal fields of std library base classes. For example, in Python 3.11 ContextManager
|
||||
// edits the `__traceback__` field on Exceptions. Allowing this to work with `__slots__` is
|
||||
// trivial because we know which fields are user-provided, without slots we need to build a
|
||||
// way to know which fields are user-provided.
|
||||
if (gen_slots_ && !gen_dynamic_) {
|
||||
out << indent() << "if args[0] not in self.__slots__:" << endl;
|
||||
indent_up();
|
||||
out << indent() << "super().__setattr__(*args)" << endl
|
||||
<< indent() << "return" << endl;
|
||||
indent_down();
|
||||
}
|
||||
out << indent() << "raise TypeError(\"can't modify immutable instance\")" << endl;
|
||||
indent_down();
|
||||
out << endl;
|
||||
out << indent() << "def __delattr__(self, *args):" << endl;
|
||||
indent_up();
|
||||
|
||||
// Not user-provided fields should be editable so that the Python Standard Library can edit
|
||||
// internal fields of std library base classes. For example, in Python 3.11 ContextManager
|
||||
// edits the `__traceback__` field on Exceptions. Allowing this to work with `__slots__` is
|
||||
// trivial because we know which fields are user-provided, without slots we need to build a
|
||||
// way to know which fields are user-provided.
|
||||
if (gen_slots_ && !gen_dynamic_) {
|
||||
out << indent() << "if args[0] not in self.__slots__:" << endl;
|
||||
indent_up();
|
||||
out << indent() << "super().__delattr__(*args)" << endl
|
||||
<< indent() << "return" << endl;
|
||||
indent_down();
|
||||
}
|
||||
out << indent() << "raise TypeError(\"can't modify immutable instance\")" << endl;
|
||||
indent_down();
|
||||
out << endl;
|
||||
|
||||
// Hash all of the members in order, and also hash in the class
|
||||
// to avoid collisions for stuff like single-field structures.
|
||||
@ -904,6 +940,32 @@ void t_py_generator::generate_py_struct_definition(ostream& out,
|
||||
}
|
||||
|
||||
out << "))" << endl;
|
||||
} else if (gen_enum_) {
|
||||
bool has_enum = false;
|
||||
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
|
||||
t_type* type = (*m_iter)->get_type();
|
||||
if (type->is_enum()) {
|
||||
has_enum = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_enum) {
|
||||
out << endl;
|
||||
indent(out) << "def __setattr__(self, name, value):" << endl;
|
||||
indent_up();
|
||||
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
|
||||
t_type* type = (*m_iter)->get_type();
|
||||
if (type->is_enum()) {
|
||||
out << indent() << "if name == \"" << (*m_iter)->get_name() << "\":" << endl
|
||||
<< indent() << indent_str() << "super().__setattr__(name, value if hasattr(value, 'value') else "
|
||||
<< type_name(type) << ".__members__.get(value))" << endl
|
||||
<< indent() << indent_str() << "return" << endl;
|
||||
}
|
||||
}
|
||||
indent(out) << "super().__setattr__(name, value)" << endl << endl;
|
||||
indent_down();
|
||||
}
|
||||
}
|
||||
|
||||
if (!gen_dynamic_) {
|
||||
@ -2286,7 +2348,7 @@ void t_py_generator::generate_deserialize_field(ostream& out,
|
||||
out << endl;
|
||||
} else if (type->is_enum()) {
|
||||
if (gen_enum_) {
|
||||
indent(out) << name << " = " << type_name(type) << "(iprot.readI32()).name";
|
||||
indent(out) << name << " = " << type_name(type) << "(iprot.readI32())";
|
||||
} else {
|
||||
indent(out) << name << " = iprot.readI32()";
|
||||
}
|
||||
@ -2476,7 +2538,7 @@ void t_py_generator::generate_serialize_field(ostream& out, t_field* tfield, str
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
if (gen_enum_){
|
||||
out << "writeI32(" << type_name(type) << "[" << name << "].value)";
|
||||
out << "writeI32(" << name << ".value)";
|
||||
} else {
|
||||
out << "writeI32(" << name << ")";
|
||||
}
|
||||
@ -2767,6 +2829,8 @@ string t_py_generator::type_to_enum(t_type* type) {
|
||||
return "TType.I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "TType.DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "TType.I32";
|
||||
@ -2819,6 +2883,11 @@ string t_py_generator::type_to_spec_args(t_type* ttype) {
|
||||
throw "INVALID TYPE IN type_to_spec_args: " + ttype->get_name();
|
||||
}
|
||||
|
||||
std::string t_py_generator::display_name() const {
|
||||
return "Python";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
py,
|
||||
"Python",
|
||||
|
@ -104,6 +104,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -943,7 +944,12 @@ void t_rb_generator::generate_service_client(t_service* tservice) {
|
||||
f_service_.indent() << "def " << function_signature(&recv_function) << endl;
|
||||
f_service_.indent_up();
|
||||
|
||||
// TODO(mcslee): Validate message reply here, seq ids etc.
|
||||
f_service_.indent() << "fname, mtype, rseqid = receive_message_begin()" << endl;
|
||||
f_service_.indent() << "handle_exception(mtype)" << endl;
|
||||
|
||||
f_service_.indent() << "if reply_seqid(rseqid)==false" << endl;
|
||||
f_service_.indent() << " raise \"seqid reply faild\"" << endl;
|
||||
f_service_.indent() << "end" << endl;
|
||||
|
||||
f_service_.indent() << "result = receive_message(" << resultname << ")" << endl;
|
||||
|
||||
@ -1171,6 +1177,8 @@ string t_rb_generator::type_to_enum(t_type* type) {
|
||||
return "::Thrift::Types::I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "::Thrift::Types::DOUBLE";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "::Thrift::Types::I32";
|
||||
@ -1281,6 +1289,11 @@ void t_rb_generator::generate_rb_union_validator(t_rb_ofstream& out, t_struct* t
|
||||
out.indent() << "end" << endl << endl;
|
||||
}
|
||||
|
||||
std::string t_rb_generator::display_name() const {
|
||||
return "Ruby";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
rb,
|
||||
"Ruby",
|
||||
|
@ -76,6 +76,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -127,7 +128,7 @@ private:
|
||||
void render_const_value_holder(const string& name, t_type* ttype, t_const_value* tvalue);
|
||||
|
||||
// Write the actual const value - the right side of a const definition.
|
||||
void render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned = true);
|
||||
void render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned = true, bool is_inline = true);
|
||||
|
||||
// Write a const struct (returned from `const_value` method).
|
||||
void render_const_struct(t_type* ttype, t_const_value* tvalue);
|
||||
@ -141,14 +142,6 @@ private:
|
||||
// Write a const map (returned from `const_value` method).
|
||||
void render_const_map(t_type* ttype, t_const_value* tvalue);
|
||||
|
||||
// Write the code to insert constant values into a rust vec or set. The
|
||||
// `insert_function` is the rust function that we'll use to insert the elements.
|
||||
void render_container_const_value(
|
||||
const string& insert_function,
|
||||
t_type* ttype,
|
||||
t_const_value* tvalue
|
||||
);
|
||||
|
||||
// Write the rust representation of a thrift struct to the generated file. Set `struct_type` to `T_ARGS`
|
||||
// if rendering the struct used to pack arguments for a service call. When `struct_type` is `T_ARGS` the
|
||||
// struct and its members have module visibility, and all fields are required. When `struct_type` is
|
||||
@ -195,10 +188,6 @@ private:
|
||||
// user-defined exception to be properly handled as Rust errors.
|
||||
void render_exception_struct_error_trait_impls(const string& struct_name, t_struct* tstruct);
|
||||
|
||||
// Write the implementations for the `Default`. This trait allows you to specify only the fields you want
|
||||
// and use `..Default::default()` to fill in the rest.
|
||||
void render_struct_default_trait_impl(const string& struct_name, t_struct* tstruct);
|
||||
|
||||
// Write the function that serializes a struct to its wire representation. If `struct_type` is `T_ARGS`
|
||||
// then all fields are considered "required", if not, the default optionality is used.
|
||||
void render_struct_sync_write(t_struct *tstruct, t_rs_generator::e_struct_type struct_type);
|
||||
@ -541,18 +530,21 @@ void t_rs_generator::init_generator() {
|
||||
void t_rs_generator::render_attributes_and_includes() {
|
||||
// turn off some compiler/clippy warnings
|
||||
|
||||
// code may not be used
|
||||
f_gen_ << "#![allow(dead_code)]" << endl;
|
||||
// code always includes BTreeMap/BTreeSet/OrderedFloat
|
||||
f_gen_ << "#![allow(unused_imports)]" << endl;
|
||||
// code might not include imports from crates
|
||||
f_gen_ << "#![allow(unused_extern_crates)]" << endl;
|
||||
// constructors take *all* struct parameters, which can trigger the "too many arguments" warning
|
||||
// some auto-gen'd types can be deeply nested. clippy recommends factoring them out which is hard to autogen
|
||||
// some methods may start with "is_"
|
||||
// FIXME: re-enable the 'vec_box' lint see: [THRIFT-5364](https://issues.apache.org/jira/browse/THRIFT-5364)
|
||||
// This can happen because we automatically generate a Vec<Box<Type>> when the type is a typedef
|
||||
// and it's a forward typedef. This (typedef + forward typedef) can happen in two situations:
|
||||
// 1. When the type is recursive
|
||||
// 2. When you define types out of order
|
||||
f_gen_ << "#![allow(clippy::too_many_arguments, clippy::type_complexity, clippy::vec_box)]" << endl;
|
||||
f_gen_ << "#![allow(clippy::too_many_arguments, clippy::type_complexity, clippy::vec_box, clippy::wrong_self_convention)]" << endl;
|
||||
// prevent rustfmt from running against this file
|
||||
// lines are too long, code is (thankfully!) not visual-indented, etc.
|
||||
// can't use #[rustfmt::skip] see: https://github.com/rust-lang/rust/issues/54726
|
||||
@ -684,7 +676,7 @@ void t_rs_generator::render_const_value_holder(const string& name, t_type* ttype
|
||||
|
||||
f_gen_ << indent() << "pub fn const_value() -> " << to_rust_type(ttype) << " {" << endl;
|
||||
indent_up();
|
||||
render_const_value(ttype, tvalue);
|
||||
render_const_value(ttype, tvalue, true, false);
|
||||
indent_down();
|
||||
f_gen_ << indent() << "}" << endl;
|
||||
|
||||
@ -693,7 +685,11 @@ void t_rs_generator::render_const_value_holder(const string& name, t_type* ttype
|
||||
f_gen_ << endl;
|
||||
}
|
||||
|
||||
void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned) {
|
||||
void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned, bool is_inline) {
|
||||
if (!is_inline) {
|
||||
f_gen_ << indent();
|
||||
}
|
||||
|
||||
if (ttype->is_base_type()) {
|
||||
t_base_type* tbase_type = (t_base_type*)ttype;
|
||||
switch (tbase_type->get_base()) {
|
||||
@ -727,9 +723,9 @@ void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bo
|
||||
throw "cannot generate const value for " + t_base_type::t_base_name(tbase_type->get_base());
|
||||
}
|
||||
} else if (ttype->is_typedef()) {
|
||||
render_const_value(get_true_type(ttype), tvalue);
|
||||
render_const_value(get_true_type(ttype), tvalue, is_owned, true);
|
||||
} else if (ttype->is_enum()) {
|
||||
f_gen_ << indent() << "{" << endl;
|
||||
f_gen_ << "{" << endl;
|
||||
indent_up();
|
||||
f_gen_
|
||||
<< indent()
|
||||
@ -739,13 +735,11 @@ void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bo
|
||||
<< ").expect(\"expecting valid const value\")"
|
||||
<< endl;
|
||||
indent_down();
|
||||
f_gen_ << indent() << "}" << endl;
|
||||
f_gen_ << indent() << "}";
|
||||
} else if (ttype->is_struct() || ttype->is_xception()) {
|
||||
render_const_struct(ttype, tvalue);
|
||||
} else if (ttype->is_container()) {
|
||||
f_gen_ << indent() << "{" << endl;
|
||||
indent_up();
|
||||
|
||||
// all of them use vec! or from(), extra block is no longer needed
|
||||
if (ttype->is_list()) {
|
||||
render_const_list(ttype, tvalue);
|
||||
} else if (ttype->is_set()) {
|
||||
@ -755,111 +749,87 @@ void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bo
|
||||
} else {
|
||||
throw "cannot generate const container value for " + ttype->get_name();
|
||||
}
|
||||
|
||||
indent_down();
|
||||
f_gen_ << indent() << "}" << endl;
|
||||
} else {
|
||||
throw "cannot generate const value for " + ttype->get_name();
|
||||
}
|
||||
|
||||
if (!is_inline) {
|
||||
f_gen_ << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void t_rs_generator::render_const_struct(t_type* ttype, t_const_value*) {
|
||||
if (((t_struct*)ttype)->is_union()) {
|
||||
f_gen_ << indent() << "{" << endl;
|
||||
f_gen_ << "{" << endl;
|
||||
indent_up();
|
||||
f_gen_ << indent() << "unimplemented!()" << endl;
|
||||
indent_down();
|
||||
f_gen_ << indent() << "}" << endl;
|
||||
f_gen_ << indent() << "}";
|
||||
} else {
|
||||
f_gen_ << indent() << "{" << endl;
|
||||
f_gen_ << "{" << endl;
|
||||
indent_up();
|
||||
f_gen_ << indent() << "unimplemented!()" << endl;
|
||||
indent_down();
|
||||
f_gen_ << indent() << "}" << endl;
|
||||
f_gen_ << indent() << "}";
|
||||
}
|
||||
}
|
||||
|
||||
void t_rs_generator::render_const_list(t_type* ttype, t_const_value* tvalue) {
|
||||
t_type* elem_type = ((t_list*)ttype)->get_elem_type();
|
||||
f_gen_ << indent() << "let mut l: Vec<" << to_rust_type(elem_type) << "> = Vec::new();" << endl;
|
||||
f_gen_ << "vec![" << endl;
|
||||
indent_up();
|
||||
const vector<t_const_value*>& elems = tvalue->get_list();
|
||||
vector<t_const_value*>::const_iterator elem_iter;
|
||||
for(elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) {
|
||||
f_gen_ << indent();
|
||||
t_const_value* elem_value = (*elem_iter);
|
||||
render_container_const_value("l.push", elem_type, elem_value);
|
||||
render_const_value(elem_type, elem_value);
|
||||
f_gen_ << "," << endl;
|
||||
}
|
||||
f_gen_ << indent() << "l" << endl;
|
||||
indent_down();
|
||||
f_gen_ << indent() << "]";
|
||||
}
|
||||
|
||||
void t_rs_generator::render_const_set(t_type* ttype, t_const_value* tvalue) {
|
||||
t_type* elem_type = ((t_set*)ttype)->get_elem_type();
|
||||
f_gen_ << indent() << "let mut s: BTreeSet<" << to_rust_type(elem_type) << "> = BTreeSet::new();" << endl;
|
||||
f_gen_ << "BTreeSet::from([" << endl;
|
||||
indent_up();
|
||||
const vector<t_const_value*>& elems = tvalue->get_list();
|
||||
vector<t_const_value*>::const_iterator elem_iter;
|
||||
for(elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) {
|
||||
f_gen_ << indent();
|
||||
t_const_value* elem_value = (*elem_iter);
|
||||
render_container_const_value("s.insert", elem_type, elem_value);
|
||||
render_const_value(elem_type, elem_value);
|
||||
f_gen_ << "," << endl;
|
||||
}
|
||||
f_gen_ << indent() << "s" << endl;
|
||||
indent_down();
|
||||
f_gen_ << indent() << "])";
|
||||
}
|
||||
|
||||
void t_rs_generator::render_const_map(t_type* ttype, t_const_value* tvalue) {
|
||||
t_type* key_type = ((t_map*)ttype)->get_key_type();
|
||||
t_type* val_type = ((t_map*)ttype)->get_val_type();
|
||||
f_gen_
|
||||
<< indent()
|
||||
<< "let mut m: BTreeMap<"
|
||||
<< to_rust_type(key_type) << ", " << to_rust_type(val_type)
|
||||
<< "> = BTreeMap::new();"
|
||||
<< endl;
|
||||
f_gen_ << "BTreeMap::from([" << endl;
|
||||
indent_up();
|
||||
const map<t_const_value*, t_const_value*, t_const_value::value_compare>& elems = tvalue->get_map();
|
||||
map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator elem_iter;
|
||||
for (elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) {
|
||||
t_const_value* key_value = elem_iter->first;
|
||||
t_const_value* val_value = elem_iter->second;
|
||||
if (get_true_type(key_type)->is_base_type()) {
|
||||
f_gen_ << indent() << "let k = ";
|
||||
render_const_value(key_type, key_value);
|
||||
f_gen_ << ";" << endl;
|
||||
} else {
|
||||
f_gen_ << indent() << "let k = {" << endl;
|
||||
indent_up();
|
||||
render_const_value(key_type, key_value);
|
||||
indent_down();
|
||||
f_gen_ << indent() << "};" << endl;
|
||||
}
|
||||
if (get_true_type(val_type)->is_base_type()) {
|
||||
f_gen_ << indent() << "let v = ";
|
||||
render_const_value(val_type, val_value);
|
||||
f_gen_ << ";" << endl;
|
||||
} else {
|
||||
f_gen_ << indent() << "let v = {" << endl;
|
||||
indent_up();
|
||||
render_const_value(val_type, val_value);
|
||||
indent_down();
|
||||
f_gen_ << indent() << "};" << endl;
|
||||
}
|
||||
f_gen_ << indent() << "m.insert(k, v);" << endl;
|
||||
}
|
||||
f_gen_ << indent() << "m" << endl;
|
||||
}
|
||||
|
||||
void t_rs_generator::render_container_const_value(
|
||||
const string& insert_function,
|
||||
t_type* ttype,
|
||||
t_const_value* tvalue
|
||||
) {
|
||||
if (get_true_type(ttype)->is_base_type()) {
|
||||
f_gen_ << indent() << insert_function << "(";
|
||||
render_const_value(ttype, tvalue);
|
||||
f_gen_ << ");" << endl;
|
||||
} else {
|
||||
f_gen_ << indent() << insert_function << "(" << endl;
|
||||
f_gen_ << indent() << "(" << endl;
|
||||
indent_up();
|
||||
render_const_value(ttype, tvalue);
|
||||
f_gen_ << indent();
|
||||
render_const_value(key_type, key_value);
|
||||
f_gen_ << "," << endl;
|
||||
f_gen_ << indent();
|
||||
render_const_value(val_type, val_value);
|
||||
f_gen_ << "," << endl;
|
||||
indent_down();
|
||||
f_gen_ << indent() << ");" << endl;
|
||||
f_gen_ << indent() << ")," << endl;
|
||||
}
|
||||
indent_down();
|
||||
f_gen_ << indent() << "])";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1057,9 +1027,6 @@ void t_rs_generator::render_struct(
|
||||
render_type_comment(struct_name);
|
||||
render_struct_definition(struct_name, tstruct, struct_type);
|
||||
render_struct_impl(struct_name, tstruct, struct_type);
|
||||
if (struct_type == t_rs_generator::T_REGULAR || struct_type == t_rs_generator::T_EXCEPTION) {
|
||||
render_struct_default_trait_impl(struct_name, tstruct);
|
||||
}
|
||||
if (struct_type == t_rs_generator::T_EXCEPTION) {
|
||||
render_exception_struct_error_trait_impls(struct_name, tstruct);
|
||||
}
|
||||
@ -1071,15 +1038,27 @@ void t_rs_generator::render_struct_definition(
|
||||
t_rs_generator::e_struct_type struct_type
|
||||
) {
|
||||
render_rustdoc((t_doc*) tstruct);
|
||||
f_gen_ << "#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]" << endl;
|
||||
|
||||
const vector<t_field*> members = tstruct->get_sorted_members();
|
||||
vector<t_field*>::const_iterator members_iter;
|
||||
bool need_default = struct_type == t_rs_generator::T_REGULAR || struct_type == t_rs_generator::T_EXCEPTION;
|
||||
for (members_iter = members.begin(); need_default && members_iter != members.end(); ++members_iter) {
|
||||
t_field* member = *members_iter;
|
||||
if (!is_optional(member->get_req())) {
|
||||
need_default = false;
|
||||
}
|
||||
}
|
||||
f_gen_
|
||||
<< "#[derive(Clone, Debug"
|
||||
<< (need_default ? ", Default" : "")
|
||||
<< ", Eq, Hash, Ord, PartialEq, PartialOrd)]"
|
||||
<< endl;
|
||||
f_gen_ << visibility_qualifier(struct_type) << "struct " << struct_name << " {" << endl;
|
||||
|
||||
// render the members
|
||||
vector<t_field*> members = tstruct->get_sorted_members();
|
||||
if (!members.empty()) {
|
||||
indent_up();
|
||||
|
||||
vector<t_field*>::iterator members_iter;
|
||||
for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) {
|
||||
t_field* member = (*members_iter);
|
||||
t_field::e_req member_req = actual_field_req(member, struct_type);
|
||||
@ -1137,49 +1116,6 @@ void t_rs_generator::render_exception_struct_error_trait_impls(const string& str
|
||||
f_gen_ << endl;
|
||||
}
|
||||
|
||||
void t_rs_generator::render_struct_default_trait_impl(const string& struct_name, t_struct* tstruct) {
|
||||
bool has_required_field = false;
|
||||
|
||||
const vector<t_field*>& members = tstruct->get_sorted_members();
|
||||
vector<t_field*>::const_iterator members_iter;
|
||||
for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) {
|
||||
t_field* member = *members_iter;
|
||||
if (!is_optional(member->get_req())) {
|
||||
has_required_field = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_required_field) {
|
||||
return;
|
||||
}
|
||||
|
||||
f_gen_ << "impl Default for " << struct_name << " {" << endl;
|
||||
indent_up();
|
||||
f_gen_ << indent() << "fn default() -> Self {" << endl;
|
||||
indent_up();
|
||||
|
||||
if (members.empty()) {
|
||||
f_gen_ << indent() << struct_name << "{}" << endl;
|
||||
} else {
|
||||
f_gen_ << indent() << struct_name << "{" << endl;
|
||||
indent_up();
|
||||
for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) {
|
||||
t_field *member = (*members_iter);
|
||||
string member_name(rust_field_name(member));
|
||||
f_gen_ << indent() << member_name << ": " << opt_in_req_out_value(member->get_type()) << "," << endl;
|
||||
}
|
||||
indent_down();
|
||||
f_gen_ << indent() << "}" << endl;
|
||||
}
|
||||
|
||||
indent_down();
|
||||
f_gen_ << indent() << "}" << endl;
|
||||
indent_down();
|
||||
f_gen_ << "}" << endl;
|
||||
f_gen_ << endl;
|
||||
}
|
||||
|
||||
void t_rs_generator::render_struct_impl(
|
||||
const string& struct_name,
|
||||
t_struct* tstruct,
|
||||
@ -1616,6 +1552,8 @@ void t_rs_generator::render_type_sync_write(const string &type_var, bool type_va
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
f_gen_ << indent() << "o_prot.write_double(" + type_var + ".into())?;" << endl;
|
||||
return;
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (ttype->is_typedef()) {
|
||||
t_typedef* ttypedef = (t_typedef*) ttype;
|
||||
@ -1777,6 +1715,10 @@ void t_rs_generator::render_struct_sync_read(
|
||||
f_gen_ << indent() << "}" << endl;
|
||||
|
||||
// now read all the fields found
|
||||
// avoid clippy::match_single_binding
|
||||
if (members.empty()) {
|
||||
f_gen_ << indent() << "i_prot.skip(field_ident.field_type)?;" << endl;
|
||||
} else {
|
||||
f_gen_ << indent() << "let field_id = field_id(&field_ident)?;" << endl;
|
||||
f_gen_ << indent() << "match field_id {" << endl; // start match
|
||||
indent_up();
|
||||
@ -1800,6 +1742,8 @@ void t_rs_generator::render_struct_sync_read(
|
||||
|
||||
indent_down();
|
||||
f_gen_ << indent() << "};" << endl; // finish match
|
||||
}
|
||||
|
||||
f_gen_ << indent() << "i_prot.read_field_end()?;" << endl;
|
||||
indent_down();
|
||||
f_gen_ << indent() << "}" << endl; // finish loop
|
||||
@ -1985,6 +1929,8 @@ void t_rs_generator::render_type_sync_read(const string &type_var, t_type *ttype
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
f_gen_ << indent() << "let " << type_var << " = OrderedFloat::from(i_prot.read_double()?);" << endl;
|
||||
return;
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (ttype->is_typedef()) {
|
||||
// FIXME: not a fan of separate `is_boxed` parameter
|
||||
@ -3084,6 +3030,8 @@ string t_rs_generator::to_rust_type(t_type* ttype) {
|
||||
return "i64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "OrderedFloat<f64>";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (ttype->is_typedef()) {
|
||||
t_typedef* ttypedef = (t_typedef*)ttype;
|
||||
@ -3144,6 +3092,8 @@ string t_rs_generator::to_rust_field_type_enum(t_type* ttype) {
|
||||
return "TType::I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "TType::Double";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (ttype->is_enum()) {
|
||||
return "TType::I32";
|
||||
@ -3182,6 +3132,8 @@ string t_rs_generator::opt_in_req_out_value(t_type* ttype) {
|
||||
return "Some(0)";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "Some(OrderedFloat::from(0.0))";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
|
||||
} else if (ttype->is_enum() || ttype->is_struct() || ttype->is_xception()) {
|
||||
@ -3415,6 +3367,11 @@ void t_rs_generator::string_replace(string& target, const string& search_string,
|
||||
}
|
||||
}
|
||||
|
||||
std::string t_rs_generator::display_name() const {
|
||||
return "Rust";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
rs,
|
||||
"Rust",
|
||||
|
@ -73,6 +73,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -1037,6 +1038,8 @@ string t_st_generator::type_to_enum(t_type* type) {
|
||||
return "TType i64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "TType double";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return "TType i32";
|
||||
@ -1053,4 +1056,9 @@ string t_st_generator::type_to_enum(t_type* type) {
|
||||
throw "INVALID TYPE IN type_to_enum: " + type->get_name();
|
||||
}
|
||||
|
||||
std::string t_st_generator::display_name() const {
|
||||
return "Smalltalk";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(st, "Smalltalk", "")
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
const map<string, string>& parsed_options,
|
||||
const string& option_string)
|
||||
: t_oop_generator(program) {
|
||||
update_keywords();
|
||||
update_keywords_for_validation();
|
||||
|
||||
(void)option_string;
|
||||
map<string, string>::const_iterator iter;
|
||||
@ -98,6 +98,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_consts(vector<t_const*> consts) override;
|
||||
|
||||
@ -291,7 +292,7 @@ private:
|
||||
bool promise_kit_;
|
||||
|
||||
protected:
|
||||
std::set<std::string> lang_keywords() const override {
|
||||
std::set<std::string> lang_keywords_for_validation() const override {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
@ -1067,6 +1068,7 @@ void t_swift_generator::generate_swift_union_reader(ostream& out, t_struct* tstr
|
||||
switch (tbase) {
|
||||
case t_base_type::TYPE_STRING:
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
case t_base_type::TYPE_UUID:
|
||||
padding = " ";
|
||||
break;
|
||||
|
||||
@ -1172,6 +1174,7 @@ void t_swift_generator::generate_swift_struct_reader(ostream& out,
|
||||
switch (tbase) {
|
||||
case t_base_type::TYPE_STRING:
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
case t_base_type::TYPE_UUID:
|
||||
padding = " ";
|
||||
break;
|
||||
|
||||
@ -2591,6 +2594,8 @@ string t_swift_generator::base_type_name(t_base_type* type) {
|
||||
return "Int64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return "Double";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return "UUID";
|
||||
default:
|
||||
throw "compiler error: no Swift name for base type " + t_base_type::t_base_name(tbase);
|
||||
}
|
||||
@ -2629,6 +2634,9 @@ void t_swift_generator::render_const_value(ostream& out,
|
||||
}
|
||||
out << ")";
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
out << "UUID(uuidString: \"" << get_escaped_string(value) << "\")";
|
||||
break;
|
||||
default:
|
||||
throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
|
||||
}
|
||||
@ -3136,6 +3144,10 @@ string t_swift_generator::type_to_enum(t_type* type, bool qualified) {
|
||||
return result + "i64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return result + "double";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return result + "uuid";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return result + "i32";
|
||||
@ -3168,6 +3180,10 @@ string t_swift_generator::type_to_enum(t_type* type, bool qualified) {
|
||||
return result + "I64";
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return result + "DOUBLE";
|
||||
case t_base_type::TYPE_UUID:
|
||||
return result + "UUID";
|
||||
default:
|
||||
throw "compiler error: unhandled type";
|
||||
}
|
||||
} else if (type->is_enum()) {
|
||||
return result + "I32";
|
||||
@ -3186,6 +3202,11 @@ string t_swift_generator::type_to_enum(t_type* type, bool qualified) {
|
||||
}
|
||||
|
||||
|
||||
std::string t_swift_generator::display_name() const {
|
||||
return "Swift 3.0";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
swift,
|
||||
"Swift 3.0",
|
||||
|
@ -83,6 +83,8 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
void generate_program() override;
|
||||
|
||||
void iterate_program(t_program* program);
|
||||
@ -94,7 +96,7 @@ public:
|
||||
void generate_service(t_service* tservice) override;
|
||||
void generate_struct(t_struct* tstruct) override;
|
||||
|
||||
void generate_annotations(std::map<std::string, std::string> annotations);
|
||||
void generate_annotations(std::map<std::string, std::vector<std::string>> annotations);
|
||||
|
||||
private:
|
||||
bool should_merge_includes_;
|
||||
@ -165,17 +167,23 @@ void t_xml_generator::init_generator() {
|
||||
string t_xml_generator::target_namespace(t_program* program) {
|
||||
std::map<std::string, std::string> map;
|
||||
std::map<std::string, std::string>::iterator iter;
|
||||
map = program->get_namespace_annotations("xml");
|
||||
if ((iter = map.find("targetNamespace")) != map.end()) {
|
||||
return iter->second;
|
||||
std::map<std::string, std::vector<std::string>> annotations;
|
||||
std::map<std::string, std::vector<std::string>>::iterator annotations_iter;
|
||||
annotations = program->get_namespace_annotations("xml");
|
||||
if ((annotations_iter = annotations.find("targetNamespace")) != annotations.end()) {
|
||||
if (!annotations_iter->second.empty()) {
|
||||
return annotations_iter->second.back();
|
||||
}
|
||||
}
|
||||
map = program->get_namespaces();
|
||||
if ((iter = map.find("xml")) != map.end()) {
|
||||
return default_ns_prefix + iter->second;
|
||||
}
|
||||
map = program->get_namespace_annotations("*");
|
||||
if ((iter = map.find("xml.targetNamespace")) != map.end()) {
|
||||
return iter->second;
|
||||
annotations = program->get_namespace_annotations("*");
|
||||
if ((annotations_iter = annotations.find("xml.targetNamespace")) != annotations.end()) {
|
||||
if (!annotations_iter->second.empty()) {
|
||||
return annotations_iter->second.back();
|
||||
}
|
||||
}
|
||||
map = program->get_namespaces();
|
||||
if ((iter = map.find("*")) != map.end()) {
|
||||
@ -432,15 +440,17 @@ void t_xml_generator::write_doc(t_doc* tdoc) {
|
||||
}
|
||||
|
||||
void t_xml_generator::generate_annotations(
|
||||
std::map<std::string, std::string> annotations) {
|
||||
std::map<std::string, std::string>::iterator iter;
|
||||
std::map<std::string, std::vector<std::string>> annotations) {
|
||||
std::map<std::string, std::vector<std::string>>::iterator iter;
|
||||
for (iter = annotations.begin(); iter != annotations.end(); ++iter) {
|
||||
for (auto& annotations_value : iter->second) {
|
||||
write_element_start("annotation");
|
||||
write_attribute("key", iter->first);
|
||||
write_attribute("value", iter->second);
|
||||
write_attribute("value", annotations_value);
|
||||
write_element_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void t_xml_generator::generate_constant(t_const* con) {
|
||||
write_element_start("const");
|
||||
@ -684,6 +694,11 @@ string t_xml_generator::get_type_name(t_type* ttype) {
|
||||
return "(unknown)";
|
||||
}
|
||||
|
||||
std::string t_xml_generator::display_name() const {
|
||||
return "XML";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(
|
||||
xml,
|
||||
"XML",
|
||||
|
@ -67,6 +67,7 @@ public:
|
||||
|
||||
void init_generator() override;
|
||||
void close_generator() override;
|
||||
std::string display_name() const override;
|
||||
|
||||
/**
|
||||
* Program-level generation functions
|
||||
@ -262,10 +263,10 @@ void t_xsd_generator::generate_service(t_service* tservice) {
|
||||
f_xsd_.open(f_xsd_name.c_str());
|
||||
|
||||
string ns = program_->get_namespace("xsd");
|
||||
const std::map<std::string, std::string> annot = program_->get_namespace_annotations("xsd");
|
||||
const std::map<std::string, std::string>::const_iterator uri = annot.find("uri");
|
||||
if (uri != annot.end()) {
|
||||
ns = uri->second;
|
||||
const std::map<std::string, std::vector<std::string>> annot = program_->get_namespace_annotations("xsd");
|
||||
const std::map<std::string, std::vector<std::string>>::const_iterator uri = annot.find("uri");
|
||||
if (uri != annot.end() && !uri->second.empty()) {
|
||||
ns = uri->second.back();
|
||||
}
|
||||
if (ns.size() > 0) {
|
||||
ns = " targetNamespace=\"" + ns + "\" xmlns=\"" + ns + "\" "
|
||||
@ -360,4 +361,9 @@ string t_xsd_generator::base_type_name(t_base_type::t_base tbase) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string t_xsd_generator::display_name() const {
|
||||
return "XSD";
|
||||
}
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(xsd, "XSD", "")
|
||||
|
551
compiler/cpp/src/thrift/generate/validator_parser.cc
Normal file
551
compiler/cpp/src/thrift/generate/validator_parser.cc
Normal file
@ -0,0 +1,551 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is programmatically sanitized for style:
|
||||
* astyle --style=1tbs -f -p -H -j -U t_validator_parser.cc
|
||||
*
|
||||
* The output of astyle should not be taken unquestioningly, but it is a good
|
||||
* guide for ensuring uniformity and readability.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "thrift/generate/t_generator.h"
|
||||
#include "thrift/generate/validator_parser.h"
|
||||
#include "thrift/platform.h"
|
||||
#include "thrift/version.h"
|
||||
#include <algorithm>
|
||||
#include <clocale>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
const char* list_delimiter = "[], ";
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
std::vector<validation_rule*> empty_rules;
|
||||
if (type->is_typedef()) {
|
||||
type = type->get_true_type();
|
||||
}
|
||||
if (type->is_enum()) {
|
||||
return parse_enum_field(type, annotations);
|
||||
} else if (type->is_base_type()) {
|
||||
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
|
||||
switch (tbase) {
|
||||
case t_base_type::TYPE_UUID:
|
||||
case t_base_type::TYPE_VOID:
|
||||
return empty_rules;
|
||||
case t_base_type::TYPE_I8:
|
||||
case t_base_type::TYPE_I16:
|
||||
case t_base_type::TYPE_I32:
|
||||
case t_base_type::TYPE_I64:
|
||||
return parse_integer_field(type, annotations);
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
return parse_double_field(type, annotations);
|
||||
case t_base_type::TYPE_STRING:
|
||||
return parse_string_field(type, annotations);
|
||||
case t_base_type::TYPE_BOOL:
|
||||
return parse_bool_field(type, annotations);
|
||||
}
|
||||
} else if (type->is_list()) {
|
||||
return parse_list_field(type, annotations);
|
||||
} else if (type->is_set()) {
|
||||
return parse_set_field(type, annotations);
|
||||
} else if (type->is_map()) {
|
||||
return parse_map_field(type, annotations);
|
||||
} else if (type->is_struct()) {
|
||||
if (((t_struct*)type)->is_union()) {
|
||||
return parse_union_field(type, annotations);
|
||||
}
|
||||
return parse_struct_field(type, annotations);
|
||||
} else if (type->is_xception()) {
|
||||
return parse_xception_field(type, annotations);
|
||||
}
|
||||
throw "validator error: unsupported type: " + type->get_name();
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_bool_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
(void)type;
|
||||
std::vector<validation_rule*> rules;
|
||||
add_bool_rule(rules, "vt.const", annotations);
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_enum_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
std::vector<validation_rule*> rules;
|
||||
add_bool_rule(rules, "vt.defined_only", annotations);
|
||||
add_enum_list_rule(rules, (t_enum*)type, "vt.in", annotations);
|
||||
add_enum_list_rule(rules, (t_enum*)type, "vt.not_in", annotations);
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_double_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
(void)type;
|
||||
std::vector<validation_rule*> rules;
|
||||
add_double_rule(rules, "vt.lt", annotations);
|
||||
add_double_rule(rules, "vt.le", annotations);
|
||||
add_double_rule(rules, "vt.gt", annotations);
|
||||
add_double_rule(rules, "vt.ge", annotations);
|
||||
add_double_list_rule(rules, "vt.in", annotations);
|
||||
add_double_list_rule(rules, "vt.not_in", annotations);
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_integer_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
(void)type;
|
||||
std::vector<validation_rule*> rules;
|
||||
add_integer_rule(rules, "vt.lt", annotations);
|
||||
add_integer_rule(rules, "vt.le", annotations);
|
||||
add_integer_rule(rules, "vt.gt", annotations);
|
||||
add_integer_rule(rules, "vt.ge", annotations);
|
||||
add_integer_list_rule(rules, "vt.in", annotations);
|
||||
add_integer_list_rule(rules, "vt.not_in", annotations);
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_string_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
(void)type;
|
||||
std::vector<validation_rule*> rules;
|
||||
add_string_rule(rules, "vt.const", annotations);
|
||||
add_integer_rule(rules, "vt.min_size", annotations);
|
||||
add_integer_rule(rules, "vt.max_size", annotations);
|
||||
add_string_rule(rules, "vt.pattern", annotations);
|
||||
add_string_rule(rules, "vt.prefix", annotations);
|
||||
add_string_rule(rules, "vt.suffix", annotations);
|
||||
add_string_rule(rules, "vt.contains", annotations);
|
||||
add_string_rule(rules, "vt.not_contains", annotations);
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_set_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
(void)type;
|
||||
return parse_list_field(type, annotations);
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_list_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
(void)type;
|
||||
std::vector<validation_rule*> rules;
|
||||
add_integer_rule(rules, "vt.min_size", annotations);
|
||||
add_integer_rule(rules, "vt.max_size", annotations);
|
||||
std::string elem_prefix("vt.elem");
|
||||
std::map<std::string, std::vector<std::string>> elem_annotations;
|
||||
for (auto it = annotations.begin(); it != annotations.end(); it++) {
|
||||
if (it->first.compare(0, elem_prefix.size(), elem_prefix) == 0) {
|
||||
std::string elem_key = "vt" + it->first.substr(elem_prefix.size());
|
||||
elem_annotations[elem_key] = it->second;
|
||||
}
|
||||
}
|
||||
std::vector<validation_rule*> elem_rules;
|
||||
if (type->is_list()) {
|
||||
elem_rules = parse_field(((t_list*)type)->get_elem_type(), elem_annotations);
|
||||
} else if (type->is_set()) {
|
||||
elem_rules = parse_field(((t_set*)type)->get_elem_type(), elem_annotations);
|
||||
}
|
||||
for (auto it = elem_rules.begin(); it != elem_rules.end(); it++) {
|
||||
validation_rule* rule = new validation_rule(elem_prefix, *it);
|
||||
rules.push_back(rule);
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_map_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
std::vector<validation_rule*> rules;
|
||||
add_integer_rule(rules, "vt.min_size", annotations);
|
||||
add_integer_rule(rules, "vt.max_size", annotations);
|
||||
std::string key_prefix("vt.key");
|
||||
std::map<std::string, std::vector<std::string>> key_annotations;
|
||||
for (auto it = annotations.begin(); it != annotations.end(); it++) {
|
||||
if (it->first.compare(0, key_prefix.size(), key_prefix) == 0) {
|
||||
std::string key_key = "vt" + it->first.substr(key_prefix.size());
|
||||
key_annotations[key_key] = it->second;
|
||||
}
|
||||
}
|
||||
std::vector<validation_rule*> key_rules;
|
||||
key_rules = parse_field(((t_map*)type)->get_key_type(), key_annotations);
|
||||
for (auto it = key_rules.begin(); it != key_rules.end(); it++) {
|
||||
validation_rule* rule = new validation_rule(key_prefix, *it);
|
||||
rules.push_back(rule);
|
||||
}
|
||||
|
||||
std::string value_prefix("vt.value");
|
||||
std::map<std::string, std::vector<std::string>> value_annotations;
|
||||
for (auto it = annotations.begin(); it != annotations.end(); it++) {
|
||||
if (it->first.compare(0, value_prefix.size(), value_prefix) == 0) {
|
||||
std::string value_key = "vt" + it->first.substr(value_prefix.size());
|
||||
value_annotations[value_key] = it->second;
|
||||
}
|
||||
}
|
||||
std::vector<validation_rule*> value_rules;
|
||||
value_rules = parse_field(((t_map*)type)->get_val_type(), value_annotations);
|
||||
for (auto it = value_rules.begin(); it != value_rules.end(); it++) {
|
||||
validation_rule* rule = new validation_rule(value_prefix, *it);
|
||||
rules.push_back(rule);
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_struct_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
(void)type;
|
||||
std::vector<validation_rule*> rules;
|
||||
add_bool_rule(rules, "vt.skip", annotations);
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_xception_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
return parse_struct_field(type, annotations);
|
||||
}
|
||||
|
||||
std::vector<validation_rule*> validation_parser::parse_union_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
return parse_struct_field(type, annotations);
|
||||
}
|
||||
|
||||
bool validation_parser::is_reference_field(std::string value) {
|
||||
if (value[0] != '$') {
|
||||
return false;
|
||||
}
|
||||
value.erase(value.begin());
|
||||
t_field* field = this->reference->get_field_by_name(value);
|
||||
return field != nullptr;
|
||||
}
|
||||
|
||||
bool validation_parser::is_validation_function(std::string value) {
|
||||
if (value[0] != '@') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void validation_parser::add_bool_rule(
|
||||
std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
auto it = annotations.find(key);
|
||||
if (it != annotations.end() && !it->second.empty()) {
|
||||
for (auto& annotation_value : it->second) {
|
||||
validation_rule* rule = new validation_rule(key);
|
||||
validation_value* value;
|
||||
if (is_reference_field(annotation_value)) {
|
||||
t_field* field = get_referenced_field(annotation_value);
|
||||
value = new validation_value(field);
|
||||
} else {
|
||||
bool constant;
|
||||
std::istringstream(it->second.back()) >> std::boolalpha >> constant;
|
||||
value = new validation_value(constant);
|
||||
}
|
||||
rule->append_value(value);
|
||||
rules.push_back(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validation_parser::add_double_rule(
|
||||
std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
auto it = annotations.find(key);
|
||||
if (it != annotations.end() && !it->second.empty()) {
|
||||
for (auto& annotation_value : it->second) {
|
||||
if (annotation_value.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
validation_rule* rule = new validation_rule(key);
|
||||
validation_value* value;
|
||||
if (is_validation_function(annotation_value)) {
|
||||
validation_value::validation_function* function = get_validation_function(annotation_value);
|
||||
value = new validation_value(function);
|
||||
} else if (is_reference_field(annotation_value)) {
|
||||
t_field* field = get_referenced_field(annotation_value);
|
||||
value = new validation_value(field);
|
||||
} else {
|
||||
double constant = std::stod(annotation_value);
|
||||
value = new validation_value(constant);
|
||||
}
|
||||
rule->append_value(value);
|
||||
rules.push_back(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validation_parser::add_enum_list_rule(
|
||||
std::vector<validation_rule*>& rules,
|
||||
t_enum* enum_,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
auto it = annotations.find(key);
|
||||
if (it != annotations.end() && !it->second.empty()) {
|
||||
for (auto& annotation_value : it->second) {
|
||||
if (annotation_value.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
validation_rule* rule = new validation_rule(key);
|
||||
if (annotation_value[0] == '[') {
|
||||
validation_value* value;
|
||||
char* str = strdup(annotation_value.c_str());
|
||||
char* pch = strtok(str, list_delimiter);
|
||||
std::string val;
|
||||
while (pch != NULL) {
|
||||
std::string temp(pch);
|
||||
if (is_validation_function(temp)) {
|
||||
validation_value::validation_function* function = get_validation_function(temp);
|
||||
value = new validation_value(function);
|
||||
} else if (is_reference_field(temp)) {
|
||||
t_field* field = get_referenced_field(temp);
|
||||
value = new validation_value(field);
|
||||
} else if (std::stringstream(temp) >> val) {
|
||||
std::string::size_type dot = val.rfind('.');
|
||||
if (dot != std::string::npos) {
|
||||
val = val.substr(dot + 1);
|
||||
}
|
||||
t_enum_value* enum_val = enum_->get_constant_by_name(val);
|
||||
value = new validation_value(enum_val);
|
||||
} else {
|
||||
delete rule;
|
||||
throw "validator error: validation double list parse failed: " + temp;
|
||||
}
|
||||
rule->append_value(value);
|
||||
pch = strtok(NULL, list_delimiter);
|
||||
}
|
||||
} else {
|
||||
validation_value* value;
|
||||
std::string val = annotation_value;
|
||||
std::string::size_type dot = val.rfind('.');
|
||||
if (dot != std::string::npos) {
|
||||
val = val.substr(dot + 1);
|
||||
}
|
||||
t_enum_value* enum_val = enum_->get_constant_by_name(val);
|
||||
value = new validation_value(enum_val);
|
||||
rule->append_value(value);
|
||||
}
|
||||
rules.push_back(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validation_parser::add_double_list_rule(
|
||||
std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
std::map<std::string, std::vector<std::string>> double_rules;
|
||||
auto it = annotations.find(key);
|
||||
if (it != annotations.end() && !it->second.empty()) {
|
||||
for (auto& annotation_value : it->second) {
|
||||
if (annotation_value.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
if (annotation_value[0] == '[') {
|
||||
validation_rule* rule = new validation_rule(key);
|
||||
validation_value* value;
|
||||
char* str = strdup(annotation_value.c_str());
|
||||
char* pch = strtok(str, list_delimiter);
|
||||
double val;
|
||||
while (pch != NULL) {
|
||||
std::string temp(pch);
|
||||
if (is_validation_function(temp)) {
|
||||
validation_value::validation_function* function = get_validation_function(temp);
|
||||
value = new validation_value(function);
|
||||
} else if (is_reference_field(temp)) {
|
||||
t_field* field = get_referenced_field(temp);
|
||||
value = new validation_value(field);
|
||||
} else if (std::stringstream(temp) >> val) {
|
||||
value = new validation_value(val);
|
||||
} else {
|
||||
delete rule;
|
||||
throw "validator error: validation double list parse failed: " + temp;
|
||||
}
|
||||
rule->append_value(value);
|
||||
pch = strtok(NULL, list_delimiter);
|
||||
}
|
||||
rules.push_back(rule);
|
||||
} else {
|
||||
double_rules[key].push_back(annotation_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (double_rules[key].size() > 0) {
|
||||
add_double_rule(rules, key, double_rules);
|
||||
}
|
||||
}
|
||||
|
||||
void validation_parser::add_integer_rule(
|
||||
std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
auto it = annotations.find(key);
|
||||
if (it != annotations.end() && !it->second.empty()) {
|
||||
for (auto& annotation_value : it->second) {
|
||||
if (annotation_value.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
validation_rule* rule = new validation_rule(key);
|
||||
validation_value* value;
|
||||
if (is_reference_field(annotation_value)) {
|
||||
t_field* field = get_referenced_field(annotation_value);
|
||||
value = new validation_value(field);
|
||||
} else if (is_validation_function(annotation_value)) {
|
||||
validation_value::validation_function* function = get_validation_function(annotation_value);
|
||||
value = new validation_value(function);
|
||||
} else {
|
||||
int64_t constant = std::stoll(annotation_value);
|
||||
value = new validation_value(constant);
|
||||
}
|
||||
rule->append_value(value);
|
||||
rules.push_back(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validation_parser::add_integer_list_rule(
|
||||
std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
std::map<std::string, std::vector<std::string>> integer_rules;
|
||||
auto it = annotations.find(key);
|
||||
if (it != annotations.end() && !it->second.empty()) {
|
||||
for (auto& annotation_value : it->second) {
|
||||
if (annotation_value.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
if (annotation_value[0] == '[') {
|
||||
validation_rule* rule = new validation_rule(key);
|
||||
validation_value* value;
|
||||
char* str = strdup(annotation_value.c_str());
|
||||
char* pch = strtok(str, list_delimiter);
|
||||
int64_t val;
|
||||
while (pch != NULL) {
|
||||
std::string temp(pch);
|
||||
if (is_validation_function(temp)) {
|
||||
validation_value::validation_function* function = get_validation_function(temp);
|
||||
value = new validation_value(function);
|
||||
} else if (is_reference_field(temp)) {
|
||||
t_field* field = get_referenced_field(temp);
|
||||
value = new validation_value(field);
|
||||
} else if (std::stringstream(temp) >> val) {
|
||||
value = new validation_value(val);
|
||||
} else {
|
||||
delete rule;
|
||||
throw "validator error: validation integer list parse failed: " + temp;
|
||||
}
|
||||
rule->append_value(value);
|
||||
pch = strtok(NULL, list_delimiter);
|
||||
}
|
||||
rules.push_back(rule);
|
||||
} else {
|
||||
integer_rules[key].push_back(annotation_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (integer_rules[key].size() > 0) {
|
||||
add_integer_rule(rules, key, integer_rules);
|
||||
}
|
||||
}
|
||||
|
||||
void validation_parser::add_string_rule(
|
||||
std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations) {
|
||||
auto it = annotations.find(key);
|
||||
if (it != annotations.end() && !it->second.empty()) {
|
||||
for (auto& annotation_value : it->second) {
|
||||
validation_rule* rule = new validation_rule(key);
|
||||
validation_value* value;
|
||||
if (is_reference_field(annotation_value)) {
|
||||
t_field* field = get_referenced_field(annotation_value);
|
||||
value = new validation_value(field);
|
||||
} else {
|
||||
value = new validation_value(annotation_value);
|
||||
}
|
||||
rule->append_value(value);
|
||||
rules.push_back(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t_field* validation_parser::get_referenced_field(std::string annotation_value) {
|
||||
annotation_value.erase(annotation_value.begin());
|
||||
return reference->get_field_by_name(annotation_value);
|
||||
}
|
||||
|
||||
validation_value::validation_function* validation_parser::get_validation_function(
|
||||
std::string annotation_value) {
|
||||
std::string value = annotation_value;
|
||||
value.erase(value.begin());
|
||||
validation_value::validation_function* function = new validation_value::validation_function;
|
||||
|
||||
size_t name_end = value.find_first_of('(');
|
||||
if (name_end >= value.size()) {
|
||||
delete function;
|
||||
throw "validator error: validation function parse failed: " + annotation_value;
|
||||
}
|
||||
function->name = value.substr(0, name_end);
|
||||
value.erase(0, name_end + 1); // name(
|
||||
|
||||
if (function->name == "len") {
|
||||
size_t argument_end = value.find_first_of(')');
|
||||
if (argument_end >= value.size()) {
|
||||
delete function;
|
||||
throw "validator error: validation function parse failed: " + annotation_value;
|
||||
}
|
||||
std::string argument = value.substr(0, argument_end);
|
||||
if (argument.size() > 0 && argument[0] == '$') {
|
||||
t_field* field = get_referenced_field(argument);
|
||||
validation_value* value = new validation_value(field);
|
||||
function->arguments.push_back(value);
|
||||
} else {
|
||||
delete function;
|
||||
throw "validator error: validation function parse failed, unrecognized argument: "
|
||||
+ annotation_value;
|
||||
}
|
||||
} else {
|
||||
delete function;
|
||||
throw "validator error: validation function parse failed, function not supported: "
|
||||
+ annotation_value;
|
||||
}
|
||||
return function;
|
||||
}
|
208
compiler/cpp/src/thrift/generate/validator_parser.h
Normal file
208
compiler/cpp/src/thrift/generate/validator_parser.h
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef T_VALIDATOR_GENERATOR_H
|
||||
#define T_VALIDATOR_GENERATOR_H
|
||||
|
||||
#include "thrift/generate/t_generator.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class validation_value {
|
||||
public:
|
||||
struct validation_function {
|
||||
public:
|
||||
std::string name;
|
||||
std::vector<validation_value*> arguments;
|
||||
};
|
||||
|
||||
enum validation_value_type {
|
||||
VV_INTEGER,
|
||||
VV_DOUBLE,
|
||||
VV_BOOL,
|
||||
VV_ENUM,
|
||||
VV_STRING,
|
||||
VV_FUNCTION,
|
||||
VV_FIELD_REFERENCE,
|
||||
VV_UNKNOWN
|
||||
};
|
||||
|
||||
validation_value() : val_type(VV_UNKNOWN) {}
|
||||
validation_value(const int64_t val) : int_val(val), val_type(VV_INTEGER) {}
|
||||
validation_value(const double val) : double_val(val), val_type(VV_DOUBLE) {}
|
||||
validation_value(const bool val) : bool_val(val), val_type(VV_BOOL) {}
|
||||
validation_value(t_enum_value* val) : enum_val(val), val_type(VV_ENUM) {}
|
||||
validation_value(const std::string val) : string_val(val), val_type(VV_STRING) {}
|
||||
validation_value(validation_function* val) : function_val(val), val_type(VV_FUNCTION) {}
|
||||
validation_value(t_field* val) : field_reference_val(val), val_type(VV_FIELD_REFERENCE) {}
|
||||
|
||||
void set_int(const int64_t val) {
|
||||
int_val = val;
|
||||
val_type = VV_INTEGER;
|
||||
}
|
||||
int64_t get_int() const { return int_val; };
|
||||
|
||||
void set_double(const double val) {
|
||||
double_val = val;
|
||||
val_type = VV_DOUBLE;
|
||||
}
|
||||
double get_double() { return double_val; };
|
||||
|
||||
void set_bool(const bool val) {
|
||||
bool_val = val;
|
||||
val_type = VV_BOOL;
|
||||
}
|
||||
bool get_bool() const { return bool_val; };
|
||||
|
||||
void set_enum(t_enum_value* val) {
|
||||
enum_val = val;
|
||||
val_type = VV_ENUM;
|
||||
}
|
||||
t_enum_value* get_enum() const { return enum_val; };
|
||||
|
||||
void set_string(const std::string val) {
|
||||
string_val = val;
|
||||
val_type = VV_STRING;
|
||||
}
|
||||
std::string get_string() const { return string_val; };
|
||||
|
||||
void set_function(validation_function* val) {
|
||||
function_val = val;
|
||||
val_type = VV_FUNCTION;
|
||||
}
|
||||
|
||||
validation_function* get_function() { return function_val; };
|
||||
|
||||
void set_field_reference(t_field* val) {
|
||||
field_reference_val = val;
|
||||
val_type = VV_FIELD_REFERENCE;
|
||||
}
|
||||
t_field* get_field_reference() const { return field_reference_val; };
|
||||
|
||||
bool is_field_reference() const { return val_type == VV_FIELD_REFERENCE; };
|
||||
|
||||
bool is_validation_function() const { return val_type == VV_FUNCTION; };
|
||||
|
||||
validation_value_type get_type() const { return val_type; };
|
||||
|
||||
private:
|
||||
int64_t int_val = 0;
|
||||
double double_val = 0.0;
|
||||
bool bool_val = false;
|
||||
t_enum_value* enum_val = nullptr;
|
||||
std::string string_val;
|
||||
validation_function* function_val = nullptr;
|
||||
t_field* field_reference_val = nullptr;
|
||||
|
||||
validation_value_type val_type;
|
||||
};
|
||||
|
||||
class validation_rule {
|
||||
public:
|
||||
validation_rule(){};
|
||||
validation_rule(std::string name) : name(name){};
|
||||
validation_rule(std::string name, validation_rule* inner) : name(name), inner(inner){};
|
||||
|
||||
std::string get_name() { return name; };
|
||||
void append_value(validation_value* value) { values.push_back(value); }
|
||||
const std::vector<validation_value*>& get_values() { return values; };
|
||||
validation_rule* get_inner() { return inner; };
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
std::vector<validation_value*> values;
|
||||
validation_rule* inner = nullptr;
|
||||
};
|
||||
|
||||
class validation_parser {
|
||||
public:
|
||||
validation_parser() {}
|
||||
validation_parser(t_struct* reference) : reference(reference) {}
|
||||
std::vector<validation_rule*> parse_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
void set_reference(t_struct* reference) { this->reference = reference; };
|
||||
|
||||
private:
|
||||
std::vector<validation_rule*> parse_bool_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_enum_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_double_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_integer_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_string_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_set_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_list_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_map_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_struct_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_xception_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
std::vector<validation_rule*> parse_union_field(
|
||||
t_type* type,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
bool is_reference_field(std::string value);
|
||||
bool is_validation_function(std::string value);
|
||||
void add_bool_rule(std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
void add_double_rule(std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
void add_double_list_rule(std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
void add_integer_rule(std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
void add_integer_list_rule(std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
void add_string_rule(std::vector<validation_rule*>& rules,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
void add_enum_list_rule(std::vector<validation_rule*>& rules,
|
||||
t_enum* enum_,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<std::string>>& annotations);
|
||||
t_field* get_referenced_field(std::string annotation_value);
|
||||
validation_value::validation_function* get_validation_function(std::string annotation_value);
|
||||
t_struct* reference = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
@ -738,6 +738,12 @@ void validate_const_rec(std::string name, t_type* type, t_const_value* value) {
|
||||
throw "type error: const \"" + name + "\" was declared as string";
|
||||
}
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
if (value->get_type() != t_const_value::CV_STRING) {
|
||||
throw "type error: const \"" + name + "\" was declared as uuid";
|
||||
}
|
||||
value->set_uuid(value->get_uuid()); // validates constant
|
||||
break;
|
||||
case t_base_type::TYPE_BOOL:
|
||||
if (value->get_type() != t_const_value::CV_INTEGER) {
|
||||
throw "type error: const \"" + name + "\" was declared as bool";
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
enum t_base {
|
||||
TYPE_VOID,
|
||||
TYPE_STRING,
|
||||
TYPE_UUID,
|
||||
TYPE_BOOL,
|
||||
TYPE_I8,
|
||||
TYPE_I16,
|
||||
@ -55,6 +56,8 @@ public:
|
||||
|
||||
bool is_bool() const override { return base_ == TYPE_BOOL; }
|
||||
|
||||
bool is_uuid() const override { return base_ == TYPE_UUID; }
|
||||
|
||||
void set_binary(bool val) { binary_ = val; }
|
||||
|
||||
bool is_binary() const override { return binary_ && (base_ == TYPE_STRING); }
|
||||
@ -69,6 +72,9 @@ public:
|
||||
case TYPE_STRING:
|
||||
return "string";
|
||||
break;
|
||||
case TYPE_UUID:
|
||||
return "uuid";
|
||||
break;
|
||||
case TYPE_BOOL:
|
||||
return "bool";
|
||||
break;
|
||||
|
@ -85,6 +85,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void set_uuid(std::string val) {
|
||||
validate_uuid(val);
|
||||
valType_ = CV_STRING;
|
||||
stringVal_ = val;
|
||||
}
|
||||
|
||||
std::string get_uuid() const {
|
||||
std::string tmp = stringVal_;
|
||||
validate_uuid(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void set_double(double val) {
|
||||
valType_ = CV_DOUBLE;
|
||||
doubleVal_ = val;
|
||||
@ -199,6 +211,39 @@ private:
|
||||
t_enum* enum_;
|
||||
|
||||
t_const_value_type valType_;
|
||||
|
||||
void validate_uuid(std::string & uuid) const {
|
||||
const std::string HEXCHARS = std::string("0123456789ABCDEFabcdef");
|
||||
|
||||
// we also allow for usual "Windows GUID" format "{01234567-9012-4567-9012-456789012345}"
|
||||
if ((uuid.length() == 38) && ('{' == uuid[0]) && ('}' == uuid[37])) {
|
||||
uuid = uuid.substr(1, 36);
|
||||
}
|
||||
|
||||
// canonical format "01234567-9012-4567-9012-456789012345" expected
|
||||
bool valid = (uuid.length() == 36);
|
||||
for (size_t i = 0; valid && (i < uuid.length()); ++i) {
|
||||
switch(i) {
|
||||
case 8:
|
||||
case 13:
|
||||
case 18:
|
||||
case 23:
|
||||
if(uuid[i] != '-') {
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(HEXCHARS.find(uuid[i]) == std::string::npos) {
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( ! valid) {
|
||||
throw "invalid uuid " + uuid;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,9 +20,9 @@
|
||||
#ifndef T_ENUM_VALUE_H
|
||||
#define T_ENUM_VALUE_H
|
||||
|
||||
#include "thrift/parse/t_doc.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "thrift/parse/t_doc.h"
|
||||
|
||||
/**
|
||||
* A constant. These are used inside of enum definitions. Constants are just
|
||||
@ -40,7 +40,7 @@ public:
|
||||
|
||||
int get_value() const { return value_; }
|
||||
|
||||
std::map<std::string, std::string> annotations_;
|
||||
std::map<std::string, std::vector<std::string>> annotations_;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
|
@ -21,8 +21,8 @@
|
||||
#define T_FIELD_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "thrift/parse/t_doc.h"
|
||||
#include "thrift/parse/t_type.h"
|
||||
@ -106,7 +106,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
std::map<std::string, std::string> annotations_;
|
||||
std::map<std::string, std::vector<std::string>> annotations_;
|
||||
|
||||
bool get_reference() const { return reference_; }
|
||||
|
||||
|
@ -20,10 +20,10 @@
|
||||
#ifndef T_FUNCTION_H
|
||||
#define T_FUNCTION_H
|
||||
|
||||
#include <string>
|
||||
#include "thrift/parse/t_type.h"
|
||||
#include "thrift/parse/t_struct.h"
|
||||
#include "thrift/parse/t_doc.h"
|
||||
#include "thrift/parse/t_struct.h"
|
||||
#include "thrift/parse/t_type.h"
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Representation of a function. Key parts are return type, function name,
|
||||
@ -40,6 +40,7 @@ public:
|
||||
xceptions_(new t_struct(nullptr)),
|
||||
own_xceptions_(true),
|
||||
oneway_(oneway) {
|
||||
xceptions_->set_method_xcepts(true);
|
||||
if (oneway_ && (!returntype_->is_void())) {
|
||||
pwarning(1, "Oneway methods should return void.\n");
|
||||
}
|
||||
@ -56,6 +57,7 @@ public:
|
||||
xceptions_(xceptions),
|
||||
own_xceptions_(false),
|
||||
oneway_(oneway) {
|
||||
xceptions_->set_method_xcepts(true);
|
||||
if (oneway_ && !xceptions_->get_members().empty()) {
|
||||
throw std::string("Oneway methods can't throw exceptions.");
|
||||
}
|
||||
@ -79,7 +81,7 @@ public:
|
||||
|
||||
bool is_oneway() const { return oneway_; }
|
||||
|
||||
std::map<std::string, std::string> annotations_;
|
||||
std::map<std::string, std::vector<std::string>> annotations_;
|
||||
|
||||
private:
|
||||
t_type* returntype_;
|
||||
|
@ -331,20 +331,20 @@ public:
|
||||
return namespaces_;
|
||||
}
|
||||
|
||||
void set_namespace_annotations(std::string language, std::map<std::string, std::string> annotations) {
|
||||
void set_namespace_annotations(std::string language, std::map<std::string, std::vector<std::string>> annotations) {
|
||||
namespace_annotations_[language] = annotations;
|
||||
}
|
||||
|
||||
const std::map<std::string, std::string>& get_namespace_annotations(const std::string& language) const {
|
||||
const std::map<std::string, std::vector<std::string>>& get_namespace_annotations(const std::string& language) const {
|
||||
auto it = namespace_annotations_.find(language);
|
||||
if (namespace_annotations_.end() != it) {
|
||||
return it->second;
|
||||
}
|
||||
static const std::map<std::string, std::string> emptyMap;
|
||||
static const std::map<std::string, std::vector<std::string>> emptyMap;
|
||||
return emptyMap;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>& get_namespace_annotations(const std::string& language) {
|
||||
std::map<std::string, std::vector<std::string>>& get_namespace_annotations(const std::string& language) {
|
||||
return namespace_annotations_[language];
|
||||
}
|
||||
|
||||
@ -400,7 +400,7 @@ private:
|
||||
std::map<std::string, std::string> namespaces_;
|
||||
|
||||
// Annotations for dynamic namespaces
|
||||
std::map<std::string, std::map<std::string, std::string> > namespace_annotations_;
|
||||
std::map<std::string, std::map<std::string, std::vector<std::string>>> namespace_annotations_;
|
||||
|
||||
// C++ extra includes
|
||||
std::vector<std::string> cpp_includes_;
|
||||
|
@ -166,6 +166,9 @@ public:
|
||||
case t_base_type::TYPE_STRING:
|
||||
const_val->set_string(constant->get_value()->get_string());
|
||||
break;
|
||||
case t_base_type::TYPE_UUID:
|
||||
const_val->set_uuid(constant->get_value()->get_uuid());
|
||||
break;
|
||||
case t_base_type::TYPE_DOUBLE:
|
||||
const_val->set_double(constant->get_value()->get_double());
|
||||
break;
|
||||
|
@ -44,64 +44,40 @@ public:
|
||||
: t_type(program),
|
||||
is_xception_(false),
|
||||
is_union_(false),
|
||||
members_validated(false),
|
||||
members_with_value(0),
|
||||
is_method_xcepts_(false),
|
||||
union_validated_(false),
|
||||
xcepts_validated_(false),
|
||||
members_with_value_(0),
|
||||
xsd_all_(false) {}
|
||||
|
||||
t_struct(t_program* program, const std::string& name)
|
||||
: t_type(program, name),
|
||||
is_xception_(false),
|
||||
is_union_(false),
|
||||
members_validated(false),
|
||||
members_with_value(0),
|
||||
is_method_xcepts_(false),
|
||||
union_validated_(false),
|
||||
xcepts_validated_(false),
|
||||
members_with_value_(0),
|
||||
xsd_all_(false) {}
|
||||
|
||||
void set_name(const std::string& name) override {
|
||||
name_ = name;
|
||||
validate_union_members();
|
||||
union_validated_= false;
|
||||
validate_members();
|
||||
}
|
||||
|
||||
void set_xception(bool is_xception) { is_xception_ = is_xception; }
|
||||
|
||||
void validate_union_member(t_field* field) {
|
||||
if (is_union_ && (!name_.empty())) {
|
||||
|
||||
// 1) unions can't have required fields
|
||||
// 2) union members are implicitly optional, otherwise bugs like THRIFT-3650 wait to happen
|
||||
if (field->get_req() != t_field::T_OPTIONAL) {
|
||||
// no warning on default requiredness, but do warn on anything else that is explicitly asked for
|
||||
if(field->get_req() != t_field::T_OPT_IN_REQ_OUT) {
|
||||
pwarning(1,
|
||||
"Union %s field %s: union members must be optional, ignoring specified requiredness.\n",
|
||||
name_.c_str(),
|
||||
field->get_name().c_str());
|
||||
}
|
||||
field->set_req(t_field::T_OPTIONAL);
|
||||
}
|
||||
|
||||
// unions may have up to one member defaulted, but not more
|
||||
if (field->get_value() != nullptr) {
|
||||
if (1 < ++members_with_value) {
|
||||
throw "Error: Field " + field->get_name() + " provides another default value for union "
|
||||
+ name_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validate_union_members() {
|
||||
if (is_union_ && (!name_.empty()) && (!members_validated)) {
|
||||
members_type::const_iterator m_iter;
|
||||
for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
|
||||
validate_union_member(*m_iter);
|
||||
}
|
||||
members_validated = true;
|
||||
}
|
||||
void set_method_xcepts(bool is_method_xcepts) {
|
||||
is_method_xcepts_ = is_method_xcepts;
|
||||
xcepts_validated_ = false;
|
||||
validate_members();
|
||||
}
|
||||
|
||||
void set_union(bool is_union) {
|
||||
is_union_ = is_union;
|
||||
validate_union_members();
|
||||
union_validated_= false;
|
||||
validate_members();
|
||||
}
|
||||
|
||||
void set_xsd_all(bool xsd_all) { xsd_all_ = xsd_all; }
|
||||
@ -123,7 +99,11 @@ public:
|
||||
}
|
||||
members_.push_back(elem);
|
||||
members_in_id_order_.insert(bounds.second, elem);
|
||||
validate_union_member(elem);
|
||||
if (needs_validation()) {
|
||||
validate_members();
|
||||
} else {
|
||||
validate_member_field(elem);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -154,12 +134,80 @@ public:
|
||||
private:
|
||||
members_type members_;
|
||||
members_type members_in_id_order_;
|
||||
bool is_xception_;
|
||||
bool is_union_;
|
||||
bool members_validated;
|
||||
int members_with_value;
|
||||
bool is_xception_; // struct is an IDL exception
|
||||
bool is_union_; // struct is an IDL union
|
||||
bool is_method_xcepts_; // struct holds the exceptions declared at a service method
|
||||
bool union_validated_;
|
||||
bool xcepts_validated_;
|
||||
int members_with_value_;
|
||||
|
||||
bool xsd_all_;
|
||||
|
||||
void validate_member_field(t_field* field) {
|
||||
validate_union_member(field);
|
||||
validate_method_exception_field(field);
|
||||
}
|
||||
|
||||
void validate_union_member(t_field* field) {
|
||||
if (is_union_ && (!name_.empty())) {
|
||||
union_validated_ = true;
|
||||
|
||||
// 1) unions can't have required fields
|
||||
// 2) union members are implicitly optional, otherwise bugs like THRIFT-3650 wait to happen
|
||||
if (field->get_req() != t_field::T_OPTIONAL) {
|
||||
// no warning on default requiredness, but do warn on anything else that is explicitly asked for
|
||||
if(field->get_req() != t_field::T_OPT_IN_REQ_OUT) {
|
||||
pwarning(1,
|
||||
"Union %s field %s: union members must be optional, ignoring specified requiredness.\n",
|
||||
name_.c_str(),
|
||||
field->get_name().c_str());
|
||||
}
|
||||
field->set_req(t_field::T_OPTIONAL);
|
||||
}
|
||||
|
||||
// unions may have up to one member defaulted, but not more
|
||||
if (field->get_value() != nullptr) {
|
||||
if (1 < ++members_with_value_) {
|
||||
throw "Error: Field " + field->get_name() + " provides another default value for union "
|
||||
+ name_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validate_method_exception_field(t_field* field) {
|
||||
if (is_method_xcepts_) {
|
||||
xcepts_validated_ = true;
|
||||
|
||||
// THRIFT-5669: "required" makes no sense at "throws" clauses
|
||||
if (field->get_req() == t_field::T_REQUIRED) {
|
||||
field->set_req(t_field::T_OPT_IN_REQ_OUT);
|
||||
pwarning(1,
|
||||
"Exception field %s: \"required\" is illegal here, ignoring.\n",
|
||||
field->get_name().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool needs_validation() {
|
||||
if (is_method_xcepts_) {
|
||||
return !xcepts_validated_;
|
||||
}
|
||||
if (is_union_) {
|
||||
return !union_validated_;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void validate_members() {
|
||||
if (needs_validation()) {
|
||||
members_type::const_iterator m_iter;
|
||||
for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
|
||||
validate_member_field(*m_iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,11 +20,11 @@
|
||||
#ifndef T_TYPE_H
|
||||
#define T_TYPE_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
#include <stdint.h>
|
||||
#include "thrift/parse/t_doc.h"
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
class t_program;
|
||||
|
||||
@ -47,6 +47,7 @@ public:
|
||||
virtual bool is_void() const { return false; }
|
||||
virtual bool is_base_type() const { return false; }
|
||||
virtual bool is_string() const { return false; }
|
||||
virtual bool is_uuid() const { return false; }
|
||||
virtual bool is_binary() const { return false; }
|
||||
virtual bool is_bool() const { return false; }
|
||||
virtual bool is_typedef() const { return false; }
|
||||
@ -82,7 +83,7 @@ public:
|
||||
return rv;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> annotations_;
|
||||
std::map<std::string, std::vector<std::string>> annotations_;
|
||||
|
||||
protected:
|
||||
t_type() : program_(nullptr) { ; }
|
||||
|
@ -76,17 +76,17 @@
|
||||
#include "thrift/thrifty.hh"
|
||||
#endif
|
||||
|
||||
void integer_overflow(char* text) {
|
||||
void integer_overflow(const char* text) {
|
||||
yyerror("This integer is too big: \"%s\"\n", text);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void unexpected_token(char* text) {
|
||||
void unexpected_token(const char* text) {
|
||||
yyerror("Unexpected token in input: \"%s\"\n", text);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void error_no_longer_supported(char* text, char* replace_with) {
|
||||
void error_no_longer_supported(const char* text, const char* replace_with) {
|
||||
yyerror("\"%s\" is no longer supported, use \"%s\" instead. Line %d\n", text, replace_with, yylineno);
|
||||
exit(1);
|
||||
}
|
||||
@ -209,29 +209,16 @@ literal_begin (['\"])
|
||||
"true" { yylval.iconst=1; return tok_int_constant; }
|
||||
|
||||
"namespace" { return tok_namespace; }
|
||||
"cpp_namespace" { error_unsupported_namespace_decl("cpp"); /* do nothing */ }
|
||||
"cpp_include" { return tok_cpp_include; }
|
||||
"cpp_type" { return tok_cpp_type; }
|
||||
"java_package" { error_unsupported_namespace_decl("java_package", "java"); /* do nothing */ }
|
||||
"delphi_namespace" { error_unsupported_namespace_decl("delphi"); /* do nothing */ }
|
||||
"php_namespace" { error_unsupported_namespace_decl("php"); /* do nothing */ }
|
||||
"py_module" { error_unsupported_namespace_decl("py_module", "py"); /* do nothing */ }
|
||||
"perl_package" { error_unsupported_namespace_decl("perl_package", "perl"); /* do nothing */ }
|
||||
"ruby_namespace" { error_unsupported_namespace_decl("ruby"); /* do nothing */ }
|
||||
"smalltalk_category" { error_unsupported_namespace_decl("smalltalk_category", "st"); /* do nothing */ }
|
||||
"smalltalk_prefix" { error_unsupported_namespace_decl("smalltalk_prefix", "st"); /* do nothing */ }
|
||||
"xsd_all" { return tok_xsd_all; }
|
||||
"xsd_optional" { return tok_xsd_optional; }
|
||||
"xsd_nillable" { return tok_xsd_nillable; }
|
||||
"xsd_namespace" { error_unsupported_namespace_decl("xsd"); /* do nothing */ }
|
||||
"xsd_attrs" { return tok_xsd_attrs; }
|
||||
"include" { return tok_include; }
|
||||
"void" { return tok_void; }
|
||||
"bool" { return tok_bool; }
|
||||
"byte" {
|
||||
emit_byte_type_warning();
|
||||
return tok_i8;
|
||||
}
|
||||
"byte" { emit_byte_type_warning(); return tok_byte; }
|
||||
"i8" { return tok_i8; }
|
||||
"i16" { return tok_i16; }
|
||||
"i32" { return tok_i32; }
|
||||
@ -239,12 +226,7 @@ literal_begin (['\"])
|
||||
"double" { return tok_double; }
|
||||
"string" { return tok_string; }
|
||||
"binary" { return tok_binary; }
|
||||
"slist" {
|
||||
error_no_longer_supported("slist","string");
|
||||
}
|
||||
"senum" {
|
||||
error_no_longer_supported("senum","string");
|
||||
}
|
||||
"uuid" { return tok_uuid; }
|
||||
"map" { return tok_map; }
|
||||
"list" { return tok_list; }
|
||||
"set" { return tok_set; }
|
||||
@ -262,7 +244,7 @@ literal_begin (['\"])
|
||||
"optional" { return tok_optional; }
|
||||
"async" {
|
||||
pwarning(0, "\"async\" is deprecated. It is called \"oneway\" now.\n");
|
||||
return tok_oneway;
|
||||
return tok_async;
|
||||
}
|
||||
"&" { return tok_reference; }
|
||||
|
||||
|
@ -97,6 +97,7 @@ const int struct_is_union = 1;
|
||||
t_function* tfunction;
|
||||
t_field* tfield;
|
||||
char* dtext;
|
||||
char* keyword;
|
||||
t_field::e_req ereq;
|
||||
t_annotation* tannot;
|
||||
t_field_id tfieldid;
|
||||
@ -118,55 +119,58 @@ const int struct_is_union = 1;
|
||||
/**
|
||||
* Header keywords
|
||||
*/
|
||||
%token tok_include
|
||||
%token tok_namespace
|
||||
%token tok_cpp_include
|
||||
%token tok_cpp_type
|
||||
%token tok_xsd_all
|
||||
%token tok_xsd_optional
|
||||
%token tok_xsd_nillable
|
||||
%token tok_xsd_attrs
|
||||
%token<keyword> tok_include
|
||||
%token<keyword> tok_namespace
|
||||
%token<keyword> tok_cpp_include
|
||||
%token<keyword> tok_cpp_type
|
||||
%token<keyword> tok_xsd_all
|
||||
%token<keyword> tok_xsd_optional
|
||||
%token<keyword> tok_xsd_nillable
|
||||
%token<keyword> tok_xsd_attrs
|
||||
|
||||
/**
|
||||
* Base datatype keywords
|
||||
*/
|
||||
%token tok_void
|
||||
%token tok_bool
|
||||
%token tok_string
|
||||
%token tok_binary
|
||||
%token tok_i8
|
||||
%token tok_i16
|
||||
%token tok_i32
|
||||
%token tok_i64
|
||||
%token tok_double
|
||||
%token<keyword> tok_void
|
||||
%token<keyword> tok_bool
|
||||
%token<keyword> tok_string
|
||||
%token<keyword> tok_binary
|
||||
%token<keyword> tok_uuid
|
||||
%token<keyword> tok_byte
|
||||
%token<keyword> tok_i8
|
||||
%token<keyword> tok_i16
|
||||
%token<keyword> tok_i32
|
||||
%token<keyword> tok_i64
|
||||
%token<keyword> tok_double
|
||||
|
||||
/**
|
||||
* Complex type keywords
|
||||
*/
|
||||
%token tok_map
|
||||
%token tok_list
|
||||
%token tok_set
|
||||
%token<keyword> tok_map
|
||||
%token<keyword> tok_list
|
||||
%token<keyword> tok_set
|
||||
|
||||
/**
|
||||
* Function modifiers
|
||||
*/
|
||||
%token tok_oneway
|
||||
%token<keyword> tok_oneway
|
||||
%token<keyword> tok_async
|
||||
|
||||
/**
|
||||
* Thrift language keywords
|
||||
*/
|
||||
%token tok_typedef
|
||||
%token tok_struct
|
||||
%token tok_xception
|
||||
%token tok_throws
|
||||
%token tok_extends
|
||||
%token tok_service
|
||||
%token tok_enum
|
||||
%token tok_const
|
||||
%token tok_required
|
||||
%token tok_optional
|
||||
%token tok_union
|
||||
%token tok_reference
|
||||
%token<keyword> tok_typedef
|
||||
%token<keyword> tok_struct
|
||||
%token<keyword> tok_xception
|
||||
%token<keyword> tok_throws
|
||||
%token<keyword> tok_extends
|
||||
%token<keyword> tok_service
|
||||
%token<keyword> tok_enum
|
||||
%token<keyword> tok_const
|
||||
%token<keyword> tok_required
|
||||
%token<keyword> tok_optional
|
||||
%token<keyword> tok_union
|
||||
%token<keyword> tok_reference
|
||||
|
||||
/**
|
||||
* Grammar nodes
|
||||
@ -192,6 +196,7 @@ const int struct_is_union = 1;
|
||||
|
||||
%type<tfield> Field
|
||||
%type<tfieldid> FieldIdentifier
|
||||
%type<id> FieldName
|
||||
%type<ereq> FieldRequiredness
|
||||
%type<ttype> FieldType
|
||||
%type<tconstv> FieldValue
|
||||
@ -770,6 +775,10 @@ Oneway:
|
||||
{
|
||||
$$ = true;
|
||||
}
|
||||
| tok_async // deprecated
|
||||
{
|
||||
$$ = true;
|
||||
}
|
||||
|
|
||||
{
|
||||
$$ = false;
|
||||
@ -808,9 +817,9 @@ FieldList:
|
||||
}
|
||||
|
||||
Field:
|
||||
CaptureDocText FieldIdentifier FieldRequiredness FieldType FieldReference tok_identifier FieldValue XsdOptional XsdNillable XsdAttributes TypeAnnotations CommaOrSemicolonOptional
|
||||
CaptureDocText FieldIdentifier FieldRequiredness FieldType FieldReference FieldName FieldValue XsdOptional XsdNillable XsdAttributes TypeAnnotations CommaOrSemicolonOptional
|
||||
{
|
||||
pdebug("tok_int_constant : Field -> FieldType tok_identifier");
|
||||
pdebug("tok_int_constant : Field -> FieldType FieldName");
|
||||
if ($2.auto_assigned) {
|
||||
pwarning(1, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $6);
|
||||
if (g_strict >= 192) {
|
||||
@ -841,6 +850,171 @@ Field:
|
||||
}
|
||||
}
|
||||
|
||||
FieldName: // identifiers and everything that could be one if it would not be identified as a different token already and excluding the "xsd*" keywords to follow a FieldName
|
||||
tok_identifier
|
||||
{
|
||||
pdebug("FieldName -> tok_identifier");
|
||||
$$ = $1;
|
||||
}
|
||||
| tok_namespace
|
||||
{
|
||||
pdebug("FieldName -> tok_namespace");
|
||||
$$ = strdup("namespace");
|
||||
}
|
||||
| tok_cpp_include
|
||||
{
|
||||
pdebug("FieldName -> tok_cpp_include");
|
||||
$$ = strdup("cpp_include");
|
||||
}
|
||||
/* see THRIFT-5627 "More consistent syntax for cpp_type" -> activate when this issue is resolved
|
||||
| tok_cpp_type
|
||||
{
|
||||
pdebug("FieldName -> tok_cpp_type");
|
||||
$$ = $strdup("cpp_type");
|
||||
}
|
||||
*/
|
||||
| tok_include
|
||||
{
|
||||
pdebug("FieldName -> tok_include");
|
||||
$$ = strdup("include");
|
||||
}
|
||||
| tok_void
|
||||
{
|
||||
pdebug("FieldName -> tok_void");
|
||||
$$ = strdup("void");
|
||||
}
|
||||
| tok_bool
|
||||
{
|
||||
pdebug("FieldName -> tok_bool");
|
||||
$$ = strdup("bool");
|
||||
}
|
||||
| tok_byte
|
||||
{
|
||||
pdebug("FieldName -> tok_byte");
|
||||
$$ = strdup("byte");
|
||||
}
|
||||
| tok_i8
|
||||
{
|
||||
pdebug("FieldName -> tok_i8");
|
||||
$$ = strdup("i8");
|
||||
}
|
||||
| tok_i16
|
||||
{
|
||||
pdebug("FieldName -> tok_i16");
|
||||
$$ = strdup("i16");
|
||||
}
|
||||
| tok_i32
|
||||
{
|
||||
pdebug("FieldName -> tok_i32");
|
||||
$$ = strdup("i32");
|
||||
}
|
||||
| tok_i64
|
||||
{
|
||||
pdebug("FieldName -> tok_i64");
|
||||
$$ = strdup("i64");
|
||||
}
|
||||
| tok_double
|
||||
{
|
||||
pdebug("FieldName -> tok_double");
|
||||
$$ = strdup("double");
|
||||
}
|
||||
| tok_string
|
||||
{
|
||||
pdebug("FieldName -> tok_string");
|
||||
$$ = strdup("string");
|
||||
}
|
||||
| tok_binary
|
||||
{
|
||||
pdebug("FieldName -> tok_binary");
|
||||
$$ = strdup("binary");
|
||||
}
|
||||
| tok_uuid
|
||||
{
|
||||
pdebug("FieldName -> tok_uuid");
|
||||
$$ = strdup("uuid");
|
||||
}
|
||||
| tok_map
|
||||
{
|
||||
pdebug("FieldName -> tok_map");
|
||||
$$ = strdup("map");
|
||||
}
|
||||
| tok_list
|
||||
{
|
||||
pdebug("FieldName -> tok_list");
|
||||
$$ = strdup("list");
|
||||
}
|
||||
| tok_set
|
||||
{
|
||||
pdebug("FieldName -> tok_set");
|
||||
$$ = strdup("set");
|
||||
}
|
||||
| tok_oneway
|
||||
{
|
||||
pdebug("FieldName -> tok_oneway");
|
||||
$$ = strdup("oneway");
|
||||
}
|
||||
| tok_async
|
||||
{
|
||||
pdebug("FieldName -> tok_async");
|
||||
$$ = strdup("async");
|
||||
}
|
||||
| tok_typedef
|
||||
{
|
||||
pdebug("FieldName -> tok_typedef");
|
||||
$$ = strdup("typedef");
|
||||
}
|
||||
| tok_struct
|
||||
{
|
||||
pdebug("FieldName -> tok_struct");
|
||||
$$ = strdup("struct");
|
||||
}
|
||||
| tok_union
|
||||
{
|
||||
pdebug("FieldName -> tok_union");
|
||||
$$ = strdup("union");
|
||||
}
|
||||
| tok_xception
|
||||
{
|
||||
pdebug("FieldName -> tok_xception");
|
||||
$$ = strdup("exception");
|
||||
}
|
||||
| tok_extends
|
||||
{
|
||||
pdebug("FieldName -> tok_extends");
|
||||
$$ = strdup("extends");
|
||||
}
|
||||
| tok_throws
|
||||
{
|
||||
pdebug("FieldName -> tok_throws");
|
||||
$$ = strdup("throws");
|
||||
}
|
||||
| tok_service
|
||||
{
|
||||
pdebug("FieldName -> tok_service");
|
||||
$$ = strdup("service");
|
||||
}
|
||||
| tok_enum
|
||||
{
|
||||
pdebug("FieldName -> tok_enum");
|
||||
$$ = strdup("enum");
|
||||
}
|
||||
| tok_const
|
||||
{
|
||||
pdebug("FieldName -> tok_const");
|
||||
$$ = strdup("const");
|
||||
}
|
||||
| tok_required
|
||||
{
|
||||
pdebug("FieldName -> tok_required");
|
||||
$$ = strdup("required");
|
||||
}
|
||||
| tok_optional
|
||||
{
|
||||
pdebug("FieldName -> tok_optional");
|
||||
$$ = strdup("optional");
|
||||
}
|
||||
|
||||
|
||||
FieldIdentifier:
|
||||
tok_int_constant ':'
|
||||
{
|
||||
@ -1002,11 +1176,21 @@ SimpleBaseType:
|
||||
pdebug("BaseType -> tok_binary");
|
||||
$$ = g_type_binary;
|
||||
}
|
||||
| tok_uuid
|
||||
{
|
||||
pdebug("BaseType -> tok_uuid");
|
||||
$$ = g_type_uuid;
|
||||
}
|
||||
| tok_bool
|
||||
{
|
||||
pdebug("BaseType -> tok_bool");
|
||||
$$ = g_type_bool;
|
||||
}
|
||||
| tok_byte
|
||||
{
|
||||
pdebug("BaseType -> tok_byte");
|
||||
$$ = g_type_i8; // byte is signed in Thrift, just an alias for i8
|
||||
}
|
||||
| tok_i8
|
||||
{
|
||||
pdebug("BaseType -> tok_i8");
|
||||
@ -1081,13 +1265,20 @@ SetType:
|
||||
}
|
||||
|
||||
ListType:
|
||||
tok_list '<' FieldType '>' CppType
|
||||
tok_list CppType '<' FieldType '>' CppType // the second CppType is for compatibility reasons = deprecated
|
||||
{
|
||||
pdebug("ListType -> tok_list<FieldType>");
|
||||
check_for_list_of_bytes($3);
|
||||
$$ = new t_list($3);
|
||||
if ($5 != nullptr) {
|
||||
((t_container*)$$)->set_cpp_name(std::string($5));
|
||||
check_for_list_of_bytes($4);
|
||||
$$ = new t_list($4);
|
||||
if ($2 != nullptr) {
|
||||
((t_container*)$$)->set_cpp_name(std::string($2));
|
||||
}
|
||||
if ($6 != nullptr) {
|
||||
((t_container*)$$)->set_cpp_name(std::string($6));
|
||||
pwarning(1, "The syntax 'list<type> cpp_type \"c++ type\"' is deprecated. Use 'list cpp_type \"c++ type\" <type>' instead.\n");
|
||||
}
|
||||
if (($2 != nullptr) && ($6 != nullptr)) {
|
||||
pwarning(1, "Two cpp_types clauses at list<%>\n", $2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1117,7 +1308,7 @@ TypeAnnotationList:
|
||||
{
|
||||
pdebug("TypeAnnotationList -> TypeAnnotationList , TypeAnnotation");
|
||||
$$ = $1;
|
||||
$$->annotations_[$2->key] = $2->val;
|
||||
$$->annotations_[$2->key].push_back($2->val);
|
||||
delete $2;
|
||||
}
|
||||
|
|
||||
|
@ -24,6 +24,6 @@
|
||||
#pragma once
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define THRIFT_VERSION "0.17.0"
|
||||
#define THRIFT_VERSION "0.19.0"
|
||||
|
||||
#endif // _THRIFT_VERSION_H_
|
||||
|
@ -18,8 +18,8 @@
|
||||
#
|
||||
|
||||
file(GLOB KEYWORD_SAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/keyword-samples/*.thrift")
|
||||
set(KEYWORD_LANGS ${thrift_compiler_LANGS})
|
||||
LIST(REMOVE_ITEM KEYWORD_LANGS swift) # in Swift you can escape reserved words
|
||||
set(KEYWORD_LANGS php) # the whole ticket THRIFT-4655 is only about PHP so leave other languages alone
|
||||
LIST(REMOVE_ITEM KEYWORD_LANGS swift) # in Swift you can escape reserved words (and in other languages as well)
|
||||
foreach(LANG ${KEYWORD_LANGS})
|
||||
foreach(SAMPLE ${KEYWORD_SAMPLES})
|
||||
get_filename_component(FILENAME ${SAMPLE} NAME_WE)
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* /*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const string foo = "bar"
|
||||
|
||||
struct a_struct {
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
include "Included.thrift"
|
||||
|
||||
const string s = "string"
|
||||
|
@ -1 +1,20 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
const string foo = "bar"
|
||||
|
@ -1 +1,23 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
namespace * keyword_test_007
|
||||
|
||||
const bool return = 0
|
||||
|
@ -1,2 +1,24 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
namespace * keyword_test_008
|
||||
|
||||
enum return {
|
||||
}
|
||||
|
@ -1,3 +1,25 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
namespace * keyword_test_009
|
||||
|
||||
enum enum_name {
|
||||
return
|
||||
}
|
||||
|
@ -1 +1,22 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_010
|
||||
|
||||
exception return {}
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_011
|
||||
|
||||
exception exception_name {
|
||||
1: required i8 return
|
||||
}
|
||||
|
@ -1 +1,22 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_012
|
||||
|
||||
service return {}
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_013
|
||||
|
||||
service service_name {
|
||||
bool function_name(1: i32 return)
|
||||
}
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_014
|
||||
|
||||
service service_name {
|
||||
void return()
|
||||
}
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_001
|
||||
|
||||
exception exception_name {}
|
||||
|
||||
service service_name {
|
||||
|
@ -1 +1,22 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_002
|
||||
|
||||
struct return {}
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_003
|
||||
|
||||
struct struct_name {
|
||||
1: required bool return = 1
|
||||
}
|
||||
|
@ -1 +1,22 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
namespace * keyword_test_004
|
||||
|
||||
typedef bool return
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user