├── testdata ├── auth │ ├── empty_pkg.proto │ ├── queue.proto │ └── InvalidName.proto ├── import_used │ ├── types.proto │ ├── options.proto │ ├── enums.proto │ ├── field.proto │ ├── for_one_of.proto │ ├── thrd_party │ │ ├── types.proto │ │ ├── for_option.proto │ │ ├── options.proto │ │ ├── enums.proto │ │ ├── for_extends.proto │ │ └── messages.proto │ ├── messages.proto │ └── not_used.proto ├── no_lint │ ├── no_lint_easyp_comment.proto │ └── no_lint_buf_comment.proto ├── breaking_check │ ├── broken │ │ ├── messages.proto │ │ └── services.proto │ ├── original │ │ ├── messages.proto │ │ └── services.proto │ └── not_broken │ │ └── messages.proto ├── invalid_pkg │ └── queue.proto ├── invalid_options │ └── queue.proto └── api │ └── session │ └── v1 │ └── events.proto ├── internal ├── core │ ├── check_lint_ignore.go │ ├── models │ │ ├── revision.go │ │ ├── lock_file_info.go │ │ ├── errors.go │ │ ├── module_config.go │ │ └── cache_download_paths.go │ ├── fs.go │ ├── module_path.go │ ├── vendor.go │ ├── path_helpers │ │ └── is_target_path.go │ └── update.go ├── adapters │ ├── plugin │ │ ├── wasm │ │ │ ├── memory.wat │ │ │ ├── memory.wasm │ │ │ └── protoc_gen_universal.wasm │ │ ├── interface.go │ │ └── wasm_embed.go │ ├── go_git │ │ └── go_git.go │ ├── storage │ │ ├── sanitize.go │ │ ├── get_install_dir_test.go │ │ ├── get_install_dir.go │ │ ├── cache_download.go │ │ ├── write_installed_module_info.go │ │ ├── create_cache_repository_dir.go │ │ ├── get_installed_module_hash.go │ │ ├── get_cache_download_paths_test.go │ │ ├── get_cache_download_paths.go │ │ ├── storage.go │ │ └── read_installed_module_info.go │ ├── lock_file │ │ ├── is_empty.go │ │ ├── deps_iter.go │ │ ├── read.go │ │ ├── write.go │ │ └── lock_file.go │ ├── module_config │ │ └── module_config.go │ ├── repository │ │ ├── git │ │ │ ├── fetch.go │ │ │ ├── archive.go │ │ │ ├── read_file.go │ │ │ └── get_files.go │ │ └── repository.go │ └── console │ │ ├── error.go │ │ └── new.go ├── config │ ├── default.go │ └── breaking_check.go ├── api │ ├── interface.go │ └── enum.go ├── fs │ ├── fs │ │ ├── adapter.go │ │ └── dir_walker.go │ └── go_git │ │ ├── adapter.go │ │ └── dir_walker.go └── rules │ ├── comment_message.go │ ├── comment_service.go │ ├── comment_rpc.go │ ├── package_defined.go │ ├── comment_one_of.go │ ├── comment_field_message.go │ ├── rpc_no_client_streaming.go │ ├── rpc_no_server_streaming.go │ ├── service_suffix.go │ ├── rpc_pascal_case.go │ ├── service_pascal_case.go │ ├── package_lower_snake_case.go │ ├── message_pascal_case.go │ ├── import_no_public.go │ ├── import_no_weak.go │ ├── oneof_lower_snake_case.go │ ├── package_no_import_cycle.go │ ├── message_field_lower_snake_case.go │ └── comment_enum.go ├── docs ├── dist │ ├── docs │ │ ├── guide │ │ │ ├── ci-cd │ │ │ │ ├── gitlab.md │ │ │ │ └── github-actions.md │ │ │ ├── migration │ │ │ │ ├── protoc.md │ │ │ │ ├── buf-cli.md │ │ │ │ ├── protolock.md │ │ │ │ └── prototool.md │ │ │ └── cli │ │ │ │ ├── linter │ │ │ │ └── rules │ │ │ │ │ ├── file-lower-snake-case.md │ │ │ │ │ ├── comment-enum.md │ │ │ │ │ ├── enum-value-prefix.md │ │ │ │ │ ├── package-version-suffix.md │ │ │ │ │ ├── import-no-weak.md │ │ │ │ │ ├── import-no-public.md │ │ │ │ │ ├── package-lower-snake-case.md │ │ │ │ │ ├── package-defined.md │ │ │ │ │ ├── rpc-no-client-streaming.md │ │ │ │ │ ├── rpc-no-server-streaming.md │ │ │ │ │ ├── enum-zero-value-suffix.md │ │ │ │ │ ├── import-used.md │ │ │ │ │ ├── message-pascal-case.md │ │ │ │ │ ├── enum-pascal-case.md │ │ │ │ │ ├── comment-enum-value.md │ │ │ │ │ ├── field-lower-snake-case.md │ │ │ │ │ ├── enum-first-value-zero.md │ │ │ │ │ ├── rpc-pascal-case.md │ │ │ │ │ ├── comment-service.md │ │ │ │ │ ├── service-suffix.md │ │ │ │ │ ├── comment-field.md │ │ │ │ │ ├── rpc-request-standard-name.md │ │ │ │ │ ├── service-pascal-case.md │ │ │ │ │ ├── rpc-response-standard-name.md │ │ │ │ │ ├── comment-oneof.md │ │ │ │ │ ├── enum-value-upper-snake-case.md │ │ │ │ │ ├── comment-message.md │ │ │ │ │ ├── enum-no-allow-alias.md │ │ │ │ │ ├── oneof-lower-snake-case.md │ │ │ │ │ ├── directory-same-package.md │ │ │ │ │ ├── package-directory-match.md │ │ │ │ │ ├── package-same-directory.md │ │ │ │ │ ├── comment-rpc.md │ │ │ │ │ ├── rpc-request-response-unique.md │ │ │ │ │ ├── package-same-ruby-package.md │ │ │ │ │ ├── package-same-swift-prefix.md │ │ │ │ │ ├── package-same-csharp-namespace.md │ │ │ │ │ ├── package-same-php-namespace.md │ │ │ │ │ ├── package-same-go-package.md │ │ │ │ │ ├── package-same-java-package.md │ │ │ │ │ └── package-same-java-multiple-files.md │ │ │ │ └── auto-completion │ │ │ │ └── auto-completion.md │ │ └── ru-guide │ │ │ ├── migration │ │ │ ├── buf-cli.md │ │ │ └── protolock.md │ │ │ └── cli │ │ │ └── linter │ │ │ └── rules │ │ │ ├── package-version-suffix.md │ │ │ ├── comment-enum.md │ │ │ ├── enum-value-prefix.md │ │ │ ├── package-defined.md │ │ │ ├── import-no-public.md │ │ │ ├── enum-zero-value-suffix.md │ │ │ ├── import-used.md │ │ │ ├── enum-first-value-zero.md │ │ │ ├── enum-pascal-case.md │ │ │ ├── file-lower-snake-case.md │ │ │ ├── comment-enum-value.md │ │ │ ├── comment-service.md │ │ │ ├── rpc-no-server-streaming.md │ │ │ ├── message-pascal-case.md │ │ │ ├── rpc-no-client-streaming.md │ │ │ ├── field-lower-snake-case.md │ │ │ ├── service-suffix.md │ │ │ ├── rpc-pascal-case.md │ │ │ ├── comment-field.md │ │ │ ├── rpc-request-standard-name.md │ │ │ ├── rpc-response-standard-name.md │ │ │ ├── service-pascal-case.md │ │ │ ├── comment-message.md │ │ │ ├── comment-oneof.md │ │ │ ├── enum-value-upper-snake-case.md │ │ │ ├── package-lower-snake-case.md │ │ │ ├── enum-no-allow-alias.md │ │ │ ├── oneof-lower-snake-case.md │ │ │ ├── package-same-directory.md │ │ │ ├── directory-same-package.md │ │ │ ├── package-directory-match.md │ │ │ ├── comment-rpc.md │ │ │ ├── import-no-weak.md │ │ │ ├── rpc-request-response-unique.md │ │ │ ├── package-same-ruby-package.md │ │ │ ├── package-same-swift-prefix.md │ │ │ ├── package-same-php-namespace.md │ │ │ ├── package-same-csharp-namespace.md │ │ │ ├── package-same-go-package.md │ │ │ ├── package-same-java-package.md │ │ │ └── package-same-java-multiple-files.md │ ├── favicon.icns │ ├── favicon.ico │ ├── icon-192.png │ ├── icon-512.png │ ├── favicon-16.png │ ├── favicon-32.png │ ├── favicon-512.png │ ├── apple-touch-icon.png │ ├── assets │ │ ├── clone-uEwA9FQU.js │ │ ├── channel-92COyuQS.js │ │ ├── init-Gi6I4Gst.js │ │ ├── chunk-QZHKN3VN-DPxP3j_u.js │ │ ├── chunk-4BX2VUAB-DQFJwyRw.js │ │ ├── chunk-55IACEB6-k1CzMQx-.js │ │ ├── stateDiagram-v2-4FDKWEC3-BaoOWtKj.js │ │ ├── classDiagram-2ON5EDUG-B2e87Lie.js │ │ ├── classDiagram-v2-WZHVMYZB-B2e87Lie.js │ │ ├── chunk-FMBD7UC4-mpZRA3cF.js │ │ ├── prism-json-xwnKirkR.js │ │ ├── chunk-QN33PNHL-Ee1tIsWT.js │ │ ├── infoDiagram-ER5ION4S-Ba3AJNAB.js │ │ ├── prism-go-CyY0RbE6.js │ │ └── prism-protobuf-DiQ_z8B5.js │ ├── favicon-16.svg │ └── favicon.svg ├── public │ ├── docs │ │ ├── guide │ │ │ ├── ci-cd │ │ │ │ ├── gitlab.md │ │ │ │ └── github-actions.md │ │ │ ├── migration │ │ │ │ ├── buf-cli.md │ │ │ │ ├── protoc.md │ │ │ │ ├── protolock.md │ │ │ │ └── prototool.md │ │ │ └── cli │ │ │ │ ├── linter │ │ │ │ └── rules │ │ │ │ │ ├── file-lower-snake-case.md │ │ │ │ │ ├── comment-enum.md │ │ │ │ │ ├── enum-value-prefix.md │ │ │ │ │ ├── package-version-suffix.md │ │ │ │ │ ├── import-no-weak.md │ │ │ │ │ ├── import-no-public.md │ │ │ │ │ ├── package-lower-snake-case.md │ │ │ │ │ ├── package-defined.md │ │ │ │ │ ├── rpc-no-client-streaming.md │ │ │ │ │ ├── rpc-no-server-streaming.md │ │ │ │ │ ├── enum-zero-value-suffix.md │ │ │ │ │ ├── import-used.md │ │ │ │ │ ├── message-pascal-case.md │ │ │ │ │ ├── enum-pascal-case.md │ │ │ │ │ ├── comment-enum-value.md │ │ │ │ │ ├── field-lower-snake-case.md │ │ │ │ │ ├── enum-first-value-zero.md │ │ │ │ │ ├── comment-service.md │ │ │ │ │ ├── rpc-pascal-case.md │ │ │ │ │ ├── service-suffix.md │ │ │ │ │ ├── rpc-request-standard-name.md │ │ │ │ │ ├── service-pascal-case.md │ │ │ │ │ ├── comment-field.md │ │ │ │ │ ├── rpc-response-standard-name.md │ │ │ │ │ ├── comment-oneof.md │ │ │ │ │ ├── enum-value-upper-snake-case.md │ │ │ │ │ ├── comment-message.md │ │ │ │ │ ├── enum-no-allow-alias.md │ │ │ │ │ ├── oneof-lower-snake-case.md │ │ │ │ │ ├── directory-same-package.md │ │ │ │ │ ├── package-directory-match.md │ │ │ │ │ ├── package-same-directory.md │ │ │ │ │ ├── comment-rpc.md │ │ │ │ │ ├── rpc-request-response-unique.md │ │ │ │ │ ├── package-same-ruby-package.md │ │ │ │ │ ├── package-same-swift-prefix.md │ │ │ │ │ ├── package-same-csharp-namespace.md │ │ │ │ │ ├── package-same-php-namespace.md │ │ │ │ │ ├── package-same-go-package.md │ │ │ │ │ ├── package-same-java-multiple-files.md │ │ │ │ │ └── package-same-java-package.md │ │ │ │ └── auto-completion │ │ │ │ └── auto-completion.md │ │ └── ru-guide │ │ │ ├── migration │ │ │ ├── buf-cli.md │ │ │ └── protolock.md │ │ │ └── cli │ │ │ └── linter │ │ │ └── rules │ │ │ ├── package-version-suffix.md │ │ │ ├── comment-enum.md │ │ │ ├── enum-value-prefix.md │ │ │ ├── package-defined.md │ │ │ ├── import-no-public.md │ │ │ ├── enum-zero-value-suffix.md │ │ │ ├── import-used.md │ │ │ ├── enum-pascal-case.md │ │ │ ├── file-lower-snake-case.md │ │ │ ├── comment-enum-value.md │ │ │ ├── enum-first-value-zero.md │ │ │ ├── comment-service.md │ │ │ ├── message-pascal-case.md │ │ │ ├── rpc-no-client-streaming.md │ │ │ ├── rpc-no-server-streaming.md │ │ │ ├── field-lower-snake-case.md │ │ │ ├── service-suffix.md │ │ │ ├── comment-field.md │ │ │ ├── rpc-pascal-case.md │ │ │ ├── rpc-request-standard-name.md │ │ │ ├── rpc-response-standard-name.md │ │ │ ├── service-pascal-case.md │ │ │ ├── comment-message.md │ │ │ ├── comment-oneof.md │ │ │ ├── package-lower-snake-case.md │ │ │ ├── enum-value-upper-snake-case.md │ │ │ ├── enum-no-allow-alias.md │ │ │ ├── oneof-lower-snake-case.md │ │ │ ├── package-same-directory.md │ │ │ ├── directory-same-package.md │ │ │ ├── package-directory-match.md │ │ │ ├── comment-rpc.md │ │ │ ├── import-no-weak.md │ │ │ ├── rpc-request-response-unique.md │ │ │ ├── package-same-ruby-package.md │ │ │ ├── package-same-swift-prefix.md │ │ │ ├── package-same-php-namespace.md │ │ │ ├── package-same-csharp-namespace.md │ │ │ ├── package-same-go-package.md │ │ │ ├── package-same-java-package.md │ │ │ └── package-same-java-multiple-files.md │ ├── favicon.ico │ ├── favicon.icns │ ├── icon-192.png │ ├── icon-512.png │ ├── favicon-16.png │ ├── favicon-32.png │ ├── favicon-512.png │ ├── apple-touch-icon.png │ ├── favicon-16.svg │ └── favicon.svg ├── postcss.config.js ├── src │ ├── types │ │ └── sidebar.ts │ ├── main.tsx │ ├── pages │ │ └── HomePage.tsx │ ├── contexts │ │ └── TocContext.tsx │ └── utils │ │ └── extractHeadings.ts ├── test-pagination.ts ├── vite.config.ts └── tsconfig.json ├── .golangci.yml ├── .rules-mcp └── rules.db ├── .mockery.yaml ├── wellknownimports └── embed.go ├── .gitignore ├── Dockerfile └── .github └── workflows ├── tests.yml └── relator.yml /testdata/auth/empty_pkg.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; -------------------------------------------------------------------------------- /internal/core/check_lint_ignore.go: -------------------------------------------------------------------------------- 1 | package core 2 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/ci-cd/gitlab.md: -------------------------------------------------------------------------------- 1 | # Gitlab 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/dist/docs/guide/migration/protoc.md: -------------------------------------------------------------------------------- 1 | # Protoc 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/migration/buf-cli.md: -------------------------------------------------------------------------------- 1 | # Buf CLI 2 | 3 | ## В работе -------------------------------------------------------------------------------- /docs/public/docs/guide/ci-cd/gitlab.md: -------------------------------------------------------------------------------- 1 | # Gitlab 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/migration/buf-cli.md: -------------------------------------------------------------------------------- 1 | # Buf CLI 2 | 3 | ## В работе -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | linters: 3 | enable: 4 | - staticcheck 5 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/migration/buf-cli.md: -------------------------------------------------------------------------------- 1 | # Buf CLI 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/dist/docs/guide/migration/protolock.md: -------------------------------------------------------------------------------- 1 | # Protolock 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/dist/docs/guide/migration/prototool.md: -------------------------------------------------------------------------------- 1 | # Prototool 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/public/docs/guide/migration/buf-cli.md: -------------------------------------------------------------------------------- 1 | # Buf CLI 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/public/docs/guide/migration/protoc.md: -------------------------------------------------------------------------------- 1 | # Protoc 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/public/docs/guide/migration/protolock.md: -------------------------------------------------------------------------------- 1 | # Protolock 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/public/docs/guide/migration/prototool.md: -------------------------------------------------------------------------------- 1 | # Prototool 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /internal/adapters/plugin/wasm/memory.wat: -------------------------------------------------------------------------------- 1 | (module (memory (export "memory") 13 65536)) -------------------------------------------------------------------------------- /.rules-mcp/rules.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/.rules-mcp/rules.db -------------------------------------------------------------------------------- /docs/dist/docs/guide/ci-cd/github-actions.md: -------------------------------------------------------------------------------- 1 | # Github Actions 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/migration/protolock.md: -------------------------------------------------------------------------------- 1 | # Protolock 2 | 3 | ## В процессе разработки -------------------------------------------------------------------------------- /docs/public/docs/guide/ci-cd/github-actions.md: -------------------------------------------------------------------------------- 1 | # Github Actions 2 | 3 | ## Work in progress -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/migration/protolock.md: -------------------------------------------------------------------------------- 1 | # Protolock 2 | 3 | ## В процессе разработки -------------------------------------------------------------------------------- /docs/dist/favicon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/dist/favicon.icns -------------------------------------------------------------------------------- /docs/dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/dist/favicon.ico -------------------------------------------------------------------------------- /docs/dist/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/dist/icon-192.png -------------------------------------------------------------------------------- /docs/dist/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/dist/icon-512.png -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/public/favicon.ico -------------------------------------------------------------------------------- /docs/dist/favicon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/dist/favicon-16.png -------------------------------------------------------------------------------- /docs/dist/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/dist/favicon-32.png -------------------------------------------------------------------------------- /docs/dist/favicon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/dist/favicon-512.png -------------------------------------------------------------------------------- /docs/public/favicon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/public/favicon.icns -------------------------------------------------------------------------------- /docs/public/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/public/icon-192.png -------------------------------------------------------------------------------- /docs/public/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/public/icon-512.png -------------------------------------------------------------------------------- /docs/public/favicon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/public/favicon-16.png -------------------------------------------------------------------------------- /docs/public/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/public/favicon-32.png -------------------------------------------------------------------------------- /docs/public/favicon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/public/favicon-512.png -------------------------------------------------------------------------------- /docs/dist/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/dist/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/docs/public/apple-touch-icon.png -------------------------------------------------------------------------------- /testdata/import_used/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used; 4 | 5 | message MessageAsType {} 6 | -------------------------------------------------------------------------------- /.mockery.yaml: -------------------------------------------------------------------------------- 1 | with-expecter: true 2 | quiet: false 3 | keeptree: false 4 | inpackage: false 5 | disable-version-string: true 6 | -------------------------------------------------------------------------------- /testdata/import_used/options.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used; 4 | 5 | message Option { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /docs/dist/assets/clone-uEwA9FQU.js: -------------------------------------------------------------------------------- 1 | import{b as r}from"./_baseUniq-UvPYksec.js";var e=4;function a(o){return r(o,e)}export{a as c}; 2 | -------------------------------------------------------------------------------- /docs/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /internal/adapters/go_git/go_git.go: -------------------------------------------------------------------------------- 1 | package go_git 2 | 3 | type GoGit struct{} 4 | 5 | func New() *GoGit { 6 | return &GoGit{} 7 | } 8 | -------------------------------------------------------------------------------- /internal/adapters/plugin/wasm/memory.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/internal/adapters/plugin/wasm/memory.wasm -------------------------------------------------------------------------------- /internal/config/default.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | // Default configurations. 4 | const ( 5 | DefaultFileName = "easyp.yaml" 6 | ) 7 | -------------------------------------------------------------------------------- /testdata/import_used/enums.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used; 4 | 5 | enum SomeEnum { 6 | SOME_ENUM_VALUE = 0; 7 | } -------------------------------------------------------------------------------- /wellknownimports/embed.go: -------------------------------------------------------------------------------- 1 | package wellknownimports 2 | 3 | import ( 4 | "embed" 5 | ) 6 | 7 | //go:embed * 8 | var Content embed.FS 9 | -------------------------------------------------------------------------------- /testdata/import_used/field.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used; 4 | 5 | message SomeField { 6 | string field = 1; 7 | } -------------------------------------------------------------------------------- /testdata/import_used/for_one_of.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used; 4 | 5 | message ForOneOf { 6 | string field = 1; 7 | } -------------------------------------------------------------------------------- /testdata/import_used/thrd_party/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used.thrd_party; 4 | 5 | message MessageAsType {} 6 | -------------------------------------------------------------------------------- /docs/dist/assets/channel-92COyuQS.js: -------------------------------------------------------------------------------- 1 | import{ap as o,aq as n}from"./index-BtiIqbpV.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c}; 2 | -------------------------------------------------------------------------------- /testdata/import_used/thrd_party/for_option.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used.thrd_party; 4 | 5 | message ForExtend { 6 | } 7 | -------------------------------------------------------------------------------- /testdata/import_used/thrd_party/options.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used.thrd_party; 4 | 5 | message Option { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | certs 3 | .env 4 | bin 5 | easyp 6 | coverage.out 7 | easyp.lock 8 | .DS_Store 9 | node_modules 10 | *.tsbuildinfo 11 | -------------------------------------------------------------------------------- /internal/adapters/plugin/wasm/protoc_gen_universal.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyp-tech/easyp/HEAD/internal/adapters/plugin/wasm/protoc_gen_universal.wasm -------------------------------------------------------------------------------- /testdata/import_used/messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used; 4 | 5 | message MessageRequest {} 6 | 7 | message MessageResponse {} 8 | -------------------------------------------------------------------------------- /testdata/import_used/thrd_party/enums.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used.thrd_party; 4 | 5 | enum SomeEnum { 6 | SOME_ENUM_VALUE = 0; 7 | } -------------------------------------------------------------------------------- /testdata/no_lint/no_lint_easyp_comment.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package no_lint; 4 | 5 | // some commenct 6 | // nolint:MESSAGE_PASCAL_CASE 7 | message some_message {} 8 | -------------------------------------------------------------------------------- /docs/dist/assets/init-Gi6I4Gst.js: -------------------------------------------------------------------------------- 1 | function t(e,a){switch(arguments.length){case 0:break;case 1:this.range(e);break;default:this.range(a).domain(e);break}return this}export{t as i}; 2 | -------------------------------------------------------------------------------- /testdata/no_lint/no_lint_buf_comment.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package no_lint; 4 | 5 | // some commenct 6 | // buf:lint:ignore MESSAGE_PASCAL_CASE 7 | message some_message {} 8 | -------------------------------------------------------------------------------- /internal/adapters/storage/sanitize.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import "strings" 4 | 5 | func sanitizePath(source string) string { 6 | return strings.ReplaceAll(source, "/", "-") 7 | } 8 | -------------------------------------------------------------------------------- /internal/adapters/lock_file/is_empty.go: -------------------------------------------------------------------------------- 1 | package lockfile 2 | 3 | // IsEmpty check if lock file doesn't have any deps 4 | func (l *LockFile) IsEmpty() bool { 5 | return len(l.cache) == 0 6 | } 7 | -------------------------------------------------------------------------------- /testdata/import_used/thrd_party/for_extends.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used.thrd_party; 4 | 5 | message MethodOptions { 6 | optional bool deprecated = 33 [default = false]; 7 | } 8 | -------------------------------------------------------------------------------- /testdata/import_used/thrd_party/messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package import_used.thrd_party; 4 | 5 | message MessageRequest { 6 | 7 | } 8 | 9 | message MessageResponse { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /docs/src/types/sidebar.ts: -------------------------------------------------------------------------------- 1 | export interface SidebarItem { 2 | title: string 3 | path?: string 4 | icon?: string 5 | children?: SidebarItem[] 6 | } 7 | 8 | export type SidebarConfig = SidebarItem[] 9 | -------------------------------------------------------------------------------- /docs/dist/assets/chunk-QZHKN3VN-DPxP3j_u.js: -------------------------------------------------------------------------------- 1 | import{_ as s}from"./index-BtiIqbpV.js";var t,e=(t=class{constructor(i){this.init=i,this.records=this.init()}reset(){this.records=this.init()}},s(t,"ImperativeState"),t);export{e as I}; 2 | -------------------------------------------------------------------------------- /testdata/breaking_check/broken/messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package breaking; 4 | 5 | message RPC1Request { 6 | string field_1 = 11; 7 | } 8 | 9 | message RPC1Response { 10 | string field_1 = 1; 11 | } 12 | -------------------------------------------------------------------------------- /testdata/breaking_check/original/messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package breaking; 4 | 5 | message RPC1Request { 6 | string field_1 = 1; 7 | } 8 | 9 | message RPC1Response { 10 | string field_1 = 1; 11 | } 12 | -------------------------------------------------------------------------------- /testdata/import_used/not_used.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "import_used/messages.proto"; 4 | 5 | package import_used; 6 | 7 | message Msg {} 8 | 9 | service TestService { 10 | rpc TestRPC(Msg) returns(Msg) {} 11 | } -------------------------------------------------------------------------------- /docs/dist/assets/chunk-4BX2VUAB-DQFJwyRw.js: -------------------------------------------------------------------------------- 1 | import{_ as i}from"./index-BtiIqbpV.js";function t(c,e){c.accDescr&&e.setAccDescription?.(c.accDescr),c.accTitle&&e.setAccTitle?.(c.accTitle),c.title&&e.setDiagramTitle?.(c.title)}i(t,"populateCommonDb");export{t as p}; 2 | -------------------------------------------------------------------------------- /internal/api/interface.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/urfave/cli/v2" 5 | ) 6 | 7 | // Handler is an interface for a handling command. 8 | type Handler interface { 9 | // Command returns a command. 10 | Command() *cli.Command 11 | } 12 | -------------------------------------------------------------------------------- /testdata/auth/queue.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package Queue; 4 | 5 | import "google/protobuf/empty.proto"; 6 | import "google/rpc/code.proto"; 7 | 8 | option go_package = "github.com/ZergsLaw/back-template/api/session/v1;pb"; 9 | 10 | message Queue {} -------------------------------------------------------------------------------- /docs/dist/assets/chunk-55IACEB6-k1CzMQx-.js: -------------------------------------------------------------------------------- 1 | import{_ as a,d as o}from"./index-BtiIqbpV.js";var d=a((t,e)=>{let n;return e==="sandbox"&&(n=o("#i"+t)),(e==="sandbox"?o(n.nodes()[0].contentDocument.body):o("body")).select(`[id="${t}"]`)},"getDiagramElement");export{d as g}; 2 | -------------------------------------------------------------------------------- /testdata/auth/InvalidName.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package Empty; 4 | 5 | import "google/protobuf/empty.proto"; 6 | import "google/rpc/code.proto"; 7 | 8 | option go_package = "github.com/ZergsLaw/back-template/api/session/v1;pb"; 9 | 10 | message Queue {} -------------------------------------------------------------------------------- /testdata/invalid_pkg/queue.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package Queue; 4 | 5 | import "google/protobuf/empty.proto"; 6 | import "google/rpc/code.proto"; 7 | 8 | option go_package = "github.com/ZergsLaw/back-template/api/session/v1;pb"; 9 | 10 | message Queue {} -------------------------------------------------------------------------------- /internal/adapters/module_config/module_config.go: -------------------------------------------------------------------------------- 1 | package moduleconfig 2 | 3 | type ( 4 | // ModuleConfig implement module config logic such as buf dirs config etc 5 | ModuleConfig struct { 6 | } 7 | ) 8 | 9 | func New() *ModuleConfig { 10 | return &ModuleConfig{} 11 | } 12 | -------------------------------------------------------------------------------- /testdata/breaking_check/not_broken/messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package breaking; 4 | 5 | message RPC1Request { 6 | string field_1 = 1; 7 | string field_2 = 2; 8 | } 9 | 10 | message RPC1Response { 11 | string field_1 = 1; 12 | string field_2 = 2; 13 | } 14 | -------------------------------------------------------------------------------- /internal/core/models/revision.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // Revision collects references to module's commit 4 | // Revision is actual module information from repository 5 | type Revision struct { 6 | CommitHash string // commit's hash 7 | Version string // commit's tag or generated version 8 | } 9 | -------------------------------------------------------------------------------- /internal/config/breaking_check.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | // BreakingCheck is the configuration for `breaking` command 4 | type BreakingCheck struct { 5 | Ignore []string `json:"ignore" yaml:"ignore"` 6 | // git ref to compare with 7 | AgainstGitRef string `json:"against_git_ref" yaml:"against_git_ref"` 8 | } 9 | -------------------------------------------------------------------------------- /internal/adapters/plugin/interface.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/protobuf/types/pluginpb" 7 | ) 8 | 9 | type Executor interface { 10 | Execute(ctx context.Context, plugin Info, request *pluginpb.CodeGeneratorRequest) (*pluginpb.CodeGeneratorResponse, error) 11 | GetName() string 12 | } 13 | -------------------------------------------------------------------------------- /internal/core/models/lock_file_info.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // LockFileInfo contains information about module from lock file 8 | type LockFileInfo struct { 9 | Name string 10 | Version string 11 | Hash ModuleHash 12 | } 13 | 14 | var ( 15 | ErrModuleNotFoundInLockFile = errors.New("module not found in lock file") 16 | ) 17 | -------------------------------------------------------------------------------- /internal/core/models/errors.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | var ( 8 | ErrVersionNotFound = errors.New("version not found") 9 | ErrFileNotFound = errors.New("file not found") 10 | ErrModuleNotInstalled = errors.New("module not installed") 11 | ErrModuleInfoFileNotFound = errors.New("module info file not found") 12 | ) 13 | -------------------------------------------------------------------------------- /docs/dist/assets/stateDiagram-v2-4FDKWEC3-BaoOWtKj.js: -------------------------------------------------------------------------------- 1 | import{s as t,b as r,a,S as s}from"./chunk-DI55MBZ5-J7umTVjb.js";import{_ as i}from"./index-BtiIqbpV.js";import"./chunk-55IACEB6-k1CzMQx-.js";import"./chunk-QN33PNHL-Ee1tIsWT.js";var l={parser:a,get db(){return new s(2)},renderer:r,styles:t,init:i(e=>{e.state||(e.state={}),e.state.arrowMarkerAbsolute=e.arrowMarkerAbsolute},"init")};export{l as diagram}; 2 | -------------------------------------------------------------------------------- /internal/adapters/repository/git/fetch.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/easyp-tech/easyp/internal/core/models" 8 | ) 9 | 10 | func (r *gitRepo) Fetch(ctx context.Context, revision models.Revision) error { 11 | if err := r.fetchCommit(ctx, revision.CommitHash); err != nil { 12 | return fmt.Errorf("r.fetchCommit: %w", err) 13 | } 14 | 15 | return nil 16 | } 17 | -------------------------------------------------------------------------------- /internal/core/models/module_config.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // ModuleConfig contains module config such as dirs from buf.work.yaml 4 | type ModuleConfig struct { 5 | // Directories contains dirs with proto files (buf.work.yaml) 6 | Directories []string 7 | 8 | // Dependencies contains list of required dependencies in repository 9 | // it could be from easyp.yaml or from buf 10 | Dependencies []Module 11 | } 12 | -------------------------------------------------------------------------------- /internal/core/fs.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | type DirWalker interface { 8 | FS 9 | WalkDir(callback func(path string, err error) error) error 10 | } 11 | 12 | // FS an interface for reading from some FS (os disk, git repo etc) 13 | // and for writing to some FS 14 | type FS interface { 15 | Open(name string) (io.ReadCloser, error) 16 | Create(name string) (io.WriteCloser, error) 17 | } 18 | -------------------------------------------------------------------------------- /internal/adapters/storage/get_install_dir_test.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "path" 5 | ) 6 | 7 | func (s *storageSuite) Test_GetInstallDir() { 8 | moduleName := getFakeModule().Name 9 | version := getFakeRevision().Version 10 | 11 | expectedResult := path.Join(s.rootDir, installedDir, moduleName, version) 12 | 13 | res := s.storage.GetInstallDir(moduleName, version) 14 | s.Equal(expectedResult, res) 15 | } 16 | -------------------------------------------------------------------------------- /docs/dist/assets/classDiagram-2ON5EDUG-B2e87Lie.js: -------------------------------------------------------------------------------- 1 | import{s as a,c as s,a as e,C as t}from"./chunk-B4BG7PRW-BM5l_f1F.js";import{_ as i}from"./index-BtiIqbpV.js";import"./chunk-FMBD7UC4-mpZRA3cF.js";import"./chunk-55IACEB6-k1CzMQx-.js";import"./chunk-QN33PNHL-Ee1tIsWT.js";var p={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{p as diagram}; 2 | -------------------------------------------------------------------------------- /docs/dist/assets/classDiagram-v2-WZHVMYZB-B2e87Lie.js: -------------------------------------------------------------------------------- 1 | import{s as a,c as s,a as e,C as t}from"./chunk-B4BG7PRW-BM5l_f1F.js";import{_ as i}from"./index-BtiIqbpV.js";import"./chunk-FMBD7UC4-mpZRA3cF.js";import"./chunk-55IACEB6-k1CzMQx-.js";import"./chunk-QN33PNHL-Ee1tIsWT.js";var p={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{p as diagram}; 2 | -------------------------------------------------------------------------------- /internal/adapters/console/error.go: -------------------------------------------------------------------------------- 1 | package console 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type RunError struct { 8 | Command string 9 | CommandParams []string 10 | Dir string 11 | Err error 12 | Stderr string 13 | } 14 | 15 | func (e RunError) Error() string { 16 | // TODO: extend error output 17 | return fmt.Sprintf("Command: %s; Err: %v; Stderr: %s", e.Command, e.Err, e.Stderr) 18 | } 19 | -------------------------------------------------------------------------------- /docs/test-pagination.ts: -------------------------------------------------------------------------------- 1 | import { getAdjacentPages } from './src/utils/getAdjacentPages.ts' 2 | 3 | const path = 'guide/introduction/what-is' 4 | const result = getAdjacentPages(path) 5 | console.log('Result for', path, ':', JSON.stringify(result, null, 2)) 6 | 7 | const path2 = 'guide/cli/linter/rules/package-same-java-multiple-files' 8 | const result2 = getAdjacentPages(path2) 9 | console.log('Result for', path2, ':', JSON.stringify(result2, null, 2)) 10 | -------------------------------------------------------------------------------- /docs/dist/assets/chunk-FMBD7UC4-mpZRA3cF.js: -------------------------------------------------------------------------------- 1 | import{_ as e}from"./index-BtiIqbpV.js";var l=e(()=>` 2 | /* Font Awesome icon styling - consolidated */ 3 | .label-icon { 4 | display: inline-block; 5 | height: 1em; 6 | overflow: visible; 7 | vertical-align: -0.125em; 8 | } 9 | 10 | .node .label-icon path { 11 | fill: currentColor; 12 | stroke: revert; 13 | stroke-width: revert; 14 | } 15 | `,"getIconStyles");export{l as g}; 16 | -------------------------------------------------------------------------------- /internal/fs/fs/adapter.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "io" 5 | "io/fs" 6 | "os" 7 | "path/filepath" 8 | ) 9 | 10 | type FSAdapter struct { 11 | fs.FS 12 | 13 | rootDir string 14 | } 15 | 16 | func (a *FSAdapter) Open(name string) (io.ReadCloser, error) { 17 | return a.FS.Open(name) 18 | } 19 | 20 | func (a *FSAdapter) Create(name string) (io.WriteCloser, error) { 21 | path := filepath.Join(a.rootDir, name) 22 | return os.Create(path) 23 | } 24 | -------------------------------------------------------------------------------- /docs/dist/assets/prism-json-xwnKirkR.js: -------------------------------------------------------------------------------- 1 | Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}};Prism.languages.webmanifest=Prism.languages.json; 2 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/file-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # FILE_LOWER_SNAKE_CASE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files are in lower_snake_case. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: bar/FooBaz.proto 17 | 18 | syntax = "proto3"; 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | // File: bar/foo_baz.proto // [!code focus] 25 | 26 | syntax = "proto3"; 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/file-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # FILE_LOWER_SNAKE_CASE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files are in lower_snake_case. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: bar/FooBaz.proto 17 | 18 | syntax = "proto3"; 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | // File: bar/foo_baz.proto // [!code focus] 25 | 26 | syntax = "proto3"; 27 | ``` 28 | -------------------------------------------------------------------------------- /internal/adapters/plugin/wasm_embed.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import _ "embed" 4 | 5 | //go:embed wasm/memory.wasm 6 | var wasmMemory []byte 7 | 8 | // Universal WASM module containing all plugins (protobuf and gRPC) 9 | // Base protobuf plugins: cpp, csharp, java, kotlin, objc, php, python, ruby 10 | // gRPC plugins: grpc_cpp, grpc_csharp, grpc_node, grpc_objective_c, grpc_php, grpc_python, grpc_ruby 11 | // 12 | //go:embed wasm/protoc_gen_universal.wasm 13 | var protocGenUniversal []byte 14 | -------------------------------------------------------------------------------- /internal/adapters/storage/get_install_dir.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "path/filepath" 5 | ) 6 | 7 | // getInstallDir returns dir to install package 8 | // rootDir + installedDir + module full remote path + module's version 9 | // eg: ~/.EASYP/mod/github.com/google/googleapis/v1.2.3 10 | func (s *Storage) GetInstallDir(moduleName string, version string) string { 11 | version = sanitizePath(version) 12 | return filepath.Join(s.rootDir, installedDir, moduleName, version) 13 | } 14 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-version-suffix.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_VERSION_SUFFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что суффикс версии пакета имеет формат `_vX`, где `X` — числовая версия. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | package foo.v1; // [!code focus] 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/comment-enum.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ENUM 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that enum has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | enum Foo { 17 | BAR = 0; 18 | BAZ = 1; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | // Foo enum for bar and baz logic // [!code focus] 28 | enum Foo { 29 | BAR = 0; 30 | BAZ = 1; 31 | } 32 | ``` -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/comment-enum.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ENUM 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that enum has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | enum Foo { 17 | BAR = 0; 18 | BAZ = 1; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | // Foo enum for bar and baz logic // [!code focus] 28 | enum Foo { 29 | BAR = 0; 30 | BAZ = 1; 31 | } 32 | ``` -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-version-suffix.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_VERSION_SUFFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что суффикс версии пакета имеет формат `_vX`, где `X` — числовая версия. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | package foo.v1; // [!code focus] 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/src/main.tsx: -------------------------------------------------------------------------------- 1 | // Polyfill Buffer for gray-matter library 2 | import { Buffer } from 'buffer' 3 | ; (globalThis as any).Buffer = Buffer 4 | 5 | 6 | import { StrictMode } from 'react' 7 | import { createRoot } from 'react-dom/client' 8 | import './index.css' 9 | import './lib/markdown/styles.css' 10 | import App from './App.tsx' 11 | import './i18n/config' 12 | 13 | 14 | createRoot(document.getElementById('root')!).render( 15 | 16 | 17 | , 18 | ) 19 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/enum-value-prefix.md: -------------------------------------------------------------------------------- 1 | # ENUM_VALUE_PREFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all enum values are prefixed with the enum name. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | enum Foo { 19 | BAR = 0; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | FOO_BAR = 0; // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-version-suffix.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_VERSION_SUFFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that the package version suffix is `_vX` where `X` is a number of version. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | package foo.v1; // [!code focus] 27 | ``` 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/enum-value-prefix.md: -------------------------------------------------------------------------------- 1 | # ENUM_VALUE_PREFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all enum values are prefixed with the enum name. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | enum Foo { 19 | BAR = 0; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | FOO_BAR = 0; // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-version-suffix.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_VERSION_SUFFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that the package version suffix is `_vX` where `X` is a number of version. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | package foo.v1; // [!code focus] 27 | ``` 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/import-no-weak.md: -------------------------------------------------------------------------------- 1 | # IMPORT_NO_WEAK 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that no weak imports are used in a proto file. 9 | 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto2"; 17 | 18 | package foo; 19 | 20 | import weak "bar.proto"; 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto2"; 27 | 28 | package foo; 29 | 30 | import "bar.proto"; // [!code focus] 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/comment-enum.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ENUM 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что enum имеет комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | enum Foo { 17 | BAR = 0; 18 | BAZ = 1; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | // Foo enum for bar and baz logic // [!code focus] 28 | enum Foo { 29 | BAR = 0; 30 | BAZ = 1; 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/comment-enum.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ENUM 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что enum имеет комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | enum Foo { 17 | BAR = 0; 18 | BAZ = 1; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | // Foo enum for bar and baz logic // [!code focus] 28 | enum Foo { 29 | BAR = 0; 30 | BAZ = 1; 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/dist/assets/chunk-QN33PNHL-Ee1tIsWT.js: -------------------------------------------------------------------------------- 1 | import{_ as a,e as w,l as x}from"./index-BtiIqbpV.js";var d=a((e,t,i,r)=>{e.attr("class",i);const{width:o,height:h,x:n,y:c}=u(e,t);w(e,h,o,r);const s=l(n,c,o,h,t);e.attr("viewBox",s),x.debug(`viewBox configured: ${s} with padding: ${t}`)},"setupViewPortForSVG"),u=a((e,t)=>{const i=e.node()?.getBBox()||{width:0,height:0,x:0,y:0};return{width:i.width+t*2,height:i.height+t*2,x:i.x,y:i.y}},"calculateDimensionsWithPadding"),l=a((e,t,i,r,o)=>`${e-o} ${t-o} ${i} ${r}`,"createViewBox");export{d as s}; 2 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/import-no-weak.md: -------------------------------------------------------------------------------- 1 | # IMPORT_NO_WEAK 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that no weak imports are used in a proto file. 9 | 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto2"; 17 | 18 | package foo; 19 | 20 | import weak "bar.proto"; 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto2"; 27 | 28 | package foo; 29 | 30 | import "bar.proto"; // [!code focus] 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/import-no-public.md: -------------------------------------------------------------------------------- 1 | # IMPORT_NO_PUBLIC 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that no public imports are used in a proto file. 9 | 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | import public "bar.proto"; 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | package foo; 29 | 30 | import "bar.proto"; // [!code focus] 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_LOWER_SNAKE_CASE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that package names are in lower_snake_case. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: bar/foo.proto 17 | syntax = "proto3"; 18 | 19 | package FooBar; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | // File: bar/foo.proto 26 | syntax = "proto3"; 27 | 28 | package foo_bar; // [!code focus] 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/enum-value-prefix.md: -------------------------------------------------------------------------------- 1 | # ENUM_VALUE_PREFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | enum Foo { 19 | BAR = 0; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | FOO_BAR = 0; // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/import-no-public.md: -------------------------------------------------------------------------------- 1 | # IMPORT_NO_PUBLIC 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that no public imports are used in a proto file. 9 | 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | import public "bar.proto"; 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | package foo; 29 | 30 | import "bar.proto"; // [!code focus] 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_LOWER_SNAKE_CASE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that package names are in lower_snake_case. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: bar/foo.proto 17 | syntax = "proto3"; 18 | 19 | package FooBar; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | // File: bar/foo.proto 26 | syntax = "proto3"; 27 | 28 | package foo_bar; // [!code focus] 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/enum-value-prefix.md: -------------------------------------------------------------------------------- 1 | # ENUM_VALUE_PREFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все значения enum имеют префикс, совпадающий с именем enum. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | enum Foo { 19 | BAR = 0; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | FOO_BAR = 0; // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /internal/adapters/storage/cache_download.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/easyp-tech/easyp/internal/core/models" 8 | ) 9 | 10 | // CacheDownload create path to downloaded cache. 11 | // Like $GOPATH/pkg/mod/cache/download 12 | func (s *Storage) CreateCacheDownloadDir(cacheDownloadPaths models.CacheDownloadPaths) error { 13 | if err := os.MkdirAll(cacheDownloadPaths.CacheDownloadDir, dirPerm); err != nil { 14 | return fmt.Errorf("os.MkdirAll: %w", err) 15 | } 16 | 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /internal/core/models/cache_download_paths.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // CacheDownloadPaths collects cache download paths to: 4 | // * archive 5 | // * file with archive hash 6 | // * info about downloaded module 7 | type CacheDownloadPaths struct { 8 | // CacheDownload path to dir with downloaded cache 9 | CacheDownloadDir string 10 | 11 | // ArchiveFile full path to downloaded archive of module 12 | ArchiveFile string 13 | 14 | // ModuleInfoFile full path to file with info about downloaded module 15 | ModuleInfoFile string 16 | } 17 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-defined.md: -------------------------------------------------------------------------------- 1 | 2 | # PACKAGE_DEFINED 3 | 4 | Categories: 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files have a package declaration. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | message Foo { 19 | string bar = 1; 20 | } 21 | 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | package foo; // [!code focus] 30 | 31 | message Foo { 32 | string bar = 1; 33 | } 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-defined.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_DEFINED 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что во всех файлах присутствует директива package. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | message Foo { 18 | string bar = 1; 19 | } 20 | 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | package foo; // [!code focus] 29 | 30 | message Foo { 31 | string bar = 1; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-defined.md: -------------------------------------------------------------------------------- 1 | 2 | # PACKAGE_DEFINED 3 | 4 | Categories: 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files have a package declaration. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | message Foo { 19 | string bar = 1; 20 | } 21 | 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | package foo; // [!code focus] 30 | 31 | message Foo { 32 | string bar = 1; 33 | } 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/rpc-no-client-streaming.md: -------------------------------------------------------------------------------- 1 | # RPC_NO_CLIENT_STREAMING 2 | 3 | Categories: 4 | 5 | - **UNARY_RPC** 6 | 7 | This rule checks that rpc has no client streaming. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (stream BarRequest) returns (BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | service Foo { 27 | rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/rpc-no-server-streaming.md: -------------------------------------------------------------------------------- 1 | # RPC_NO_SERVER_STREAMING 2 | 3 | Categories: 4 | 5 | - **UNARY_RPC** 6 | 7 | This rule checks that rpc has no server streaming. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (stream BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | service Foo { 27 | rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/rpc-no-client-streaming.md: -------------------------------------------------------------------------------- 1 | # RPC_NO_CLIENT_STREAMING 2 | 3 | Categories: 4 | 5 | - **UNARY_RPC** 6 | 7 | This rule checks that rpc has no client streaming. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (stream BarRequest) returns (BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | service Foo { 27 | rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/rpc-no-server-streaming.md: -------------------------------------------------------------------------------- 1 | # RPC_NO_SERVER_STREAMING 2 | 3 | Categories: 4 | 5 | - **UNARY_RPC** 6 | 7 | This rule checks that rpc has no server streaming. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (stream BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | service Foo { 27 | rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-defined.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_DEFINED 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что во всех файлах присутствует директива package. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | message Foo { 18 | string bar = 1; 19 | } 20 | 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | package foo; // [!code focus] 29 | 30 | message Foo { 31 | string bar = 1; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/enum-zero-value-suffix.md: -------------------------------------------------------------------------------- 1 | # ENUM_ZERO_VALUE_SUFFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all enum zero values are suffixed with `_NONE` or your custom suffix. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | enum Foo { 19 | BAR = 0; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | FOO_BAR_NONE = 0; // [!code focus] 30 | } 31 | ``` 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/import-no-public.md: -------------------------------------------------------------------------------- 1 | # IMPORT_NO_PUBLIC 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что в proto-файле не используются `public` импорты (оператор `import public "..."`). 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | import public "bar.proto"; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | package foo; 28 | 29 | import "bar.proto"; // [!code focus] 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/enum-zero-value-suffix.md: -------------------------------------------------------------------------------- 1 | # ENUM_ZERO_VALUE_SUFFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all enum zero values are suffixed with `_NONE` or your custom suffix. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | enum Foo { 19 | BAR = 0; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | FOO_BAR_NONE = 0; // [!code focus] 30 | } 31 | ``` 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/import-no-public.md: -------------------------------------------------------------------------------- 1 | # IMPORT_NO_PUBLIC 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что в proto-файле не используются `public` импорты (оператор `import public "..."`). 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | import public "bar.proto"; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | package foo; 28 | 29 | import "bar.proto"; // [!code focus] 30 | ``` 31 | -------------------------------------------------------------------------------- /internal/fs/go_git/adapter.go: -------------------------------------------------------------------------------- 1 | package go_git 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | 7 | "github.com/go-git/go-git/v5/plumbing/object" 8 | ) 9 | 10 | type GitTreeDiskAdapter struct { 11 | *object.Tree 12 | } 13 | 14 | func (a *GitTreeDiskAdapter) Open(name string) (io.ReadCloser, error) { 15 | gitFile, err := a.File(name) 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | return gitFile.Reader() 21 | } 22 | 23 | func (a *GitTreeDiskAdapter) Create(name string) (io.WriteCloser, error) { 24 | return nil, errors.New("not implemented") 25 | } 26 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/import-used.md: -------------------------------------------------------------------------------- 1 | # IMPORT_USED 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all imports are used in a proto file. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | import "bar.proto"; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | package foo; 28 | 29 | import "bar.proto"; // [!code focus] 30 | 31 | message Foo { 32 | bar.Bar bar = 1; // [!code focus] 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/message-pascal-case.md: -------------------------------------------------------------------------------- 1 | # MESSAGE_PASCAL_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that message names are in PascalCase. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message foo_bar { 20 | string bar_name = 1; 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | package foo; 30 | 31 | message FooBar { // [!code focus] 32 | string bar_name = 1; 33 | } 34 | ``` -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/import-used.md: -------------------------------------------------------------------------------- 1 | # IMPORT_USED 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all imports are used in a proto file. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | import "bar.proto"; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | package foo; 28 | 29 | import "bar.proto"; // [!code focus] 30 | 31 | message Foo { 32 | bar.Bar bar = 1; // [!code focus] 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/message-pascal-case.md: -------------------------------------------------------------------------------- 1 | # MESSAGE_PASCAL_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that message names are in PascalCase. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message foo_bar { 20 | string bar_name = 1; 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | package foo; 30 | 31 | message FooBar { // [!code focus] 32 | string bar_name = 1; 33 | } 34 | ``` -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/enum-pascal-case.md: -------------------------------------------------------------------------------- 1 | # ENUM_PASCAL_CASE 2 | 3 | 4 | Categories: 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that enum names are in PascalCase. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | enum foo_bar { 21 | BAR = 0; 22 | BAZ = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | syntax = "proto3"; 30 | 31 | package foo; 32 | 33 | enum FooBar { // [!code focus] 34 | BAR = 0; 35 | BAZ = 1; 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/enum-zero-value-suffix.md: -------------------------------------------------------------------------------- 1 | # ENUM_ZERO_VALUE_SUFFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все нулевые значения enum имеют суффикс `_NONE` или ваш кастомный (пользовательский) суффикс. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | enum Foo { 19 | BAR = 0; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | FOO_BAR_NONE = 0; // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/import-used.md: -------------------------------------------------------------------------------- 1 | # IMPORT_USED 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все импорты используются в proto-файле. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | import "bar.proto"; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | package foo; 28 | 29 | import "bar.proto"; // [!code focus] 30 | 31 | message Foo { 32 | bar.Bar bar = 1; // [!code focus] 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/enum-pascal-case.md: -------------------------------------------------------------------------------- 1 | # ENUM_PASCAL_CASE 2 | 3 | 4 | Categories: 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that enum names are in PascalCase. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | enum foo_bar { 21 | BAR = 0; 22 | BAZ = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | syntax = "proto3"; 30 | 31 | package foo; 32 | 33 | enum FooBar { // [!code focus] 34 | BAR = 0; 35 | BAZ = 1; 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/enum-zero-value-suffix.md: -------------------------------------------------------------------------------- 1 | # ENUM_ZERO_VALUE_SUFFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все нулевые значения enum имеют суффикс `_NONE` или ваш кастомный (пользовательский) суффикс. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | enum Foo { 19 | BAR = 0; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | FOO_BAR_NONE = 0; // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/import-used.md: -------------------------------------------------------------------------------- 1 | # IMPORT_USED 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все импорты используются в proto-файле. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | import "bar.proto"; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | package foo; 28 | 29 | import "bar.proto"; // [!code focus] 30 | 31 | message Foo { 32 | bar.Bar bar = 1; // [!code focus] 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/comment-enum-value.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ENUM_VALUE 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that enum values have a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | enum Foo { 17 | BAR = 0; 18 | BAZ = 1; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | // BAR value for bar logic // [!code focus] 30 | BAR = 0; 31 | // BAZ value for baz logic // [!code focus] 32 | BAZ = 1; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /internal/adapters/lock_file/deps_iter.go: -------------------------------------------------------------------------------- 1 | package lockfile 2 | 3 | import ( 4 | "iter" 5 | 6 | "github.com/easyp-tech/easyp/internal/core/models" 7 | ) 8 | 9 | func (l *LockFile) DepsIter() iter.Seq[models.LockFileInfo] { 10 | return func(yield func(models.LockFileInfo) bool) { 11 | for moduleName, fileInfo := range l.cache { 12 | lockFileInfo := models.LockFileInfo{ 13 | Name: moduleName, 14 | Version: fileInfo.version, 15 | Hash: models.ModuleHash(fileInfo.hash), 16 | } 17 | if !yield(lockFileInfo) { 18 | return 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM --platform=${BUILDPLATFORM} golang:1.25-alpine AS builder 2 | 3 | ARG TARGETPLATFORM 4 | ARG BUILDPLATFORM 5 | ARG TARGETOS 6 | ARG TARGETARCH 7 | 8 | LABEL stage=gobuilder 9 | 10 | ENV CGO_ENABLED=0 11 | ENV GOOS=${TARGETOS} 12 | ENV GOARCH=${TARGETARCH} 13 | 14 | WORKDIR /build 15 | 16 | COPY go.mod go.sum ./ 17 | RUN go mod download 18 | 19 | COPY . . 20 | 21 | RUN go build -trimpath -o /easyp ./cmd/easyp 22 | 23 | FROM alpine:3.22 24 | 25 | RUN apk add --no-cache ca-certificates tzdata 26 | 27 | COPY --from=builder /easyp /easyp 28 | 29 | ENTRYPOINT ["/easyp"] 30 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/field-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # FIELD_LOWER_SNAKE_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that field names of messages are in lower_snake_case. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message Foo { 20 | string BarName = 1; 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | package foo; 30 | 31 | message Foo { 32 | string bar_name = 1; // [!code focus] 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/enum-first-value-zero.md: -------------------------------------------------------------------------------- 1 | # ENUM_FIRST_VALUE_ZERO 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что первое значение enum равно нулю. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | enum Foo { 21 | BAR = 1; 22 | BAZ = 2; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | syntax = "proto3"; 30 | 31 | package foo; 32 | 33 | enum Foo { 34 | BAR = 0; // [!code focus] 35 | BAZ = 1; 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/enum-pascal-case.md: -------------------------------------------------------------------------------- 1 | # ENUM_PASCAL_CASE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что имена enum написаны в стиле PascalCase. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | enum foo_bar { 20 | BAR = 0; 21 | BAZ = 1; 22 | } 23 | ``` 24 | 25 | ### Good 26 | 27 | ```proto 28 | syntax = "proto3"; 29 | 30 | package foo; 31 | 32 | enum FooBar { // [!code focus] 33 | BAR = 0; 34 | BAZ = 1; 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/file-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # FILE_LOWER_SNAKE_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв). 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: bar/FooBaz.proto 17 | 18 | syntax = "proto3"; 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | // File: bar/foo_baz.proto // [!code focus] 25 | 26 | syntax = "proto3"; 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/comment-enum-value.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ENUM_VALUE 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that enum values have a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | enum Foo { 17 | BAR = 0; 18 | BAZ = 1; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | 26 | syntax = "proto3"; 27 | 28 | enum Foo { 29 | // BAR value for bar logic // [!code focus] 30 | BAR = 0; 31 | // BAZ value for baz logic // [!code focus] 32 | BAZ = 1; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/field-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # FIELD_LOWER_SNAKE_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that field names of messages are in lower_snake_case. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message Foo { 20 | string BarName = 1; 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | package foo; 30 | 31 | message Foo { 32 | string bar_name = 1; // [!code focus] 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/enum-pascal-case.md: -------------------------------------------------------------------------------- 1 | # ENUM_PASCAL_CASE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что имена enum написаны в стиле PascalCase. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | enum foo_bar { 20 | BAR = 0; 21 | BAZ = 1; 22 | } 23 | ``` 24 | 25 | ### Good 26 | 27 | ```proto 28 | syntax = "proto3"; 29 | 30 | package foo; 31 | 32 | enum FooBar { // [!code focus] 33 | BAR = 0; 34 | BAZ = 1; 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/file-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # FILE_LOWER_SNAKE_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все файлы имеют имя в формате lower_snake_case (только строчные буквы, цифры и символ подчеркивания, без пробелов и заглавных букв). 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: bar/FooBaz.proto 17 | 18 | syntax = "proto3"; 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | // File: bar/foo_baz.proto // [!code focus] 25 | 26 | syntax = "proto3"; 27 | ``` 28 | -------------------------------------------------------------------------------- /internal/adapters/repository/git/archive.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/easyp-tech/easyp/internal/core/models" 8 | ) 9 | 10 | func (r *gitRepo) Archive( 11 | ctx context.Context, revision models.Revision, archiveFilePath string, 12 | ) error { 13 | params := []string{ 14 | "archive", "--format=zip", revision.CommitHash, "-o", archiveFilePath, "*.proto", 15 | } 16 | 17 | if _, err := r.console.RunCmd(ctx, r.cacheDir, "git", params...); err != nil { 18 | return fmt.Errorf("utils.RunCmd: %w", err) 19 | } 20 | 21 | return nil 22 | } 23 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/enum-first-value-zero.md: -------------------------------------------------------------------------------- 1 | # ENUM_FIRST_VALUE_ZERO 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that the first value of an enum is zero. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | enum Foo { 22 | BAR = 1; 23 | BAZ = 2; 24 | } 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | syntax = "proto3"; 31 | 32 | package foo; 33 | 34 | enum Foo { 35 | BAR = 0; // [!code focus] 36 | BAZ = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/comment-enum-value.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ENUM_VALUE 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что все значения enum имеют комментарий. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | enum Foo { 17 | BAR = 0; 18 | BAZ = 1; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | enum Foo { 28 | // BAR value for bar logic // [!code focus] 29 | BAR = 0; 30 | // BAZ value for baz logic // [!code focus] 31 | BAZ = 1; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/enum-first-value-zero.md: -------------------------------------------------------------------------------- 1 | # ENUM_FIRST_VALUE_ZERO 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that the first value of an enum is zero. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | enum Foo { 22 | BAR = 1; 23 | BAZ = 2; 24 | } 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | syntax = "proto3"; 31 | 32 | package foo; 33 | 34 | enum Foo { 35 | BAR = 0; // [!code focus] 36 | BAZ = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/comment-enum-value.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ENUM_VALUE 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что все значения enum имеют комментарий. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | enum Foo { 17 | BAR = 0; 18 | BAZ = 1; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | enum Foo { 28 | // BAR value for bar logic // [!code focus] 29 | BAR = 0; 30 | // BAZ value for baz logic // [!code focus] 31 | BAZ = 1; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/enum-first-value-zero.md: -------------------------------------------------------------------------------- 1 | # ENUM_FIRST_VALUE_ZERO 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что первое значение enum равно нулю. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | enum Foo { 21 | BAR = 1; 22 | BAZ = 2; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | syntax = "proto3"; 30 | 31 | package foo; 32 | 33 | enum Foo { 34 | BAR = 0; // [!code focus] 35 | BAZ = 1; 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /internal/api/enum.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type EnumValue struct { 9 | Enum []string 10 | Default string 11 | selected string 12 | } 13 | 14 | func (e *EnumValue) Set(value string) error { 15 | for _, enum := range e.Enum { 16 | if enum == value { 17 | e.selected = value 18 | return nil 19 | } 20 | } 21 | 22 | return fmt.Errorf("allowed values are %s", strings.Join(e.Enum, ", ")) 23 | } 24 | 25 | func (e EnumValue) String() string { 26 | if e.selected == "" { 27 | return e.Default 28 | } 29 | return e.selected 30 | } 31 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/rpc-pascal-case.md: -------------------------------------------------------------------------------- 1 | # RPC_PASCAL_CASE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all RPC names are in PascalCase. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service foo_bar { 19 | rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooBar { 29 | rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/comment-service.md: -------------------------------------------------------------------------------- 1 | # COMMENT_SERVICE 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что сервис имеет комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | // Foo service for bar logic // [!code focus] 27 | service Foo { 28 | // Bar rpc for bar logic 29 | rpc Bar (BarRequest) returns (BarResponse) {} 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/rpc-no-server-streaming.md: -------------------------------------------------------------------------------- 1 | # RPC_NO_SERVER_STREAMING 2 | 3 | Категории: 4 | 5 | - **UNARY_RPC** 6 | 7 | Это правило проверяет, что RPC не использует серверный стриминг (ответ не является `stream ...`). 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (stream BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | service Foo { 27 | rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/comment-service.md: -------------------------------------------------------------------------------- 1 | # COMMENT_SERVICE 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что сервис имеет комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | // Foo service for bar logic // [!code focus] 27 | service Foo { 28 | // Bar rpc for bar logic 29 | rpc Bar (BarRequest) returns (BarResponse) {} 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /internal/adapters/console/new.go: -------------------------------------------------------------------------------- 1 | package console 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "runtime" 7 | ) 8 | 9 | // Console is provide to terminal command in console. 10 | type Console interface { 11 | RunCmd(ctx context.Context, dir string, command string, commandParams ...string) (string, error) 12 | RunCmdWithStdin(ctx context.Context, dir string, stdin io.Reader, command string, commandParams ...string) (string, error) 13 | } 14 | 15 | // New create new console. 16 | func New() Console { 17 | if runtime.GOOS == "windows" { 18 | return powershell{} 19 | } 20 | return bash{} 21 | } 22 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/comment-service.md: -------------------------------------------------------------------------------- 1 | # COMMENT_SERVICE 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that service has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | // Foo service for bar logic // [!code focus] 27 | service Foo { 28 | // Bar rpc for bar logic 29 | rpc Bar (BarRequest) returns (BarResponse) {} 30 | } 31 | ``` 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/service-suffix.md: -------------------------------------------------------------------------------- 1 | # SERVICE_SUFFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all services are suffixed with `Service` or your custom suffix. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc Bar(BarRequest) returns (BarResponse); 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooService { // [!code focus] 29 | rpc Bar(BarRequest) returns (BarResponse); 30 | } 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/message-pascal-case.md: -------------------------------------------------------------------------------- 1 | # MESSAGE_PASCAL_CASE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message foo_bar { 20 | string bar_name = 1; 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | package foo; 30 | 31 | message FooBar { // [!code focus] 32 | string bar_name = 1; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/rpc-no-client-streaming.md: -------------------------------------------------------------------------------- 1 | # RPC_NO_CLIENT_STREAMING 2 | 3 | Категории: 4 | 5 | - **UNARY_RPC** 6 | 7 | Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является `stream ...`). 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (stream BarRequest) returns (BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | service Foo { 27 | rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/comment-service.md: -------------------------------------------------------------------------------- 1 | # COMMENT_SERVICE 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that service has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | // Foo service for bar logic // [!code focus] 27 | service Foo { 28 | // Bar rpc for bar logic 29 | rpc Bar (BarRequest) returns (BarResponse) {} 30 | } 31 | ``` 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/rpc-pascal-case.md: -------------------------------------------------------------------------------- 1 | # RPC_PASCAL_CASE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all RPC names are in PascalCase. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service foo_bar { 19 | rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooBar { 29 | rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/service-suffix.md: -------------------------------------------------------------------------------- 1 | # SERVICE_SUFFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all services are suffixed with `Service` or your custom suffix. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc Bar(BarRequest) returns (BarResponse); 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooService { // [!code focus] 29 | rpc Bar(BarRequest) returns (BarResponse); 30 | } 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/message-pascal-case.md: -------------------------------------------------------------------------------- 1 | # MESSAGE_PASCAL_CASE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что имена сообщений (message) записаны в стиле PascalCase. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message foo_bar { 20 | string bar_name = 1; 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | package foo; 30 | 31 | message FooBar { // [!code focus] 32 | string bar_name = 1; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/rpc-no-client-streaming.md: -------------------------------------------------------------------------------- 1 | # RPC_NO_CLIENT_STREAMING 2 | 3 | Категории: 4 | 5 | - **UNARY_RPC** 6 | 7 | Это правило проверяет, что RPC не использует клиентский стриминг (запрос не является `stream ...`). 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (stream BarRequest) returns (BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | service Foo { 27 | rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/rpc-no-server-streaming.md: -------------------------------------------------------------------------------- 1 | # RPC_NO_SERVER_STREAMING 2 | 3 | Категории: 4 | 5 | - **UNARY_RPC** 6 | 7 | Это правило проверяет, что RPC не использует серверный стриминг (ответ не является `stream ...`). 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (stream BarResponse) {} 18 | } 19 | ``` 20 | 21 | ### Good 22 | 23 | ```proto 24 | syntax = "proto3"; 25 | 26 | service Foo { 27 | rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/comment-field.md: -------------------------------------------------------------------------------- 1 | # COMMENT_FIELD 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that all message fields have a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | string bar = 1; 18 | string baz = 2; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | message Foo { 28 | // bar field for bar logic // [!code focus] 29 | string bar = 1; 30 | // baz field for baz logic // [!code focus] 31 | string baz = 2; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/rpc-request-standard-name.md: -------------------------------------------------------------------------------- 1 | # RPC_REQUEST_STANDARD_NAME 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all RPC request messages are named `MethodRequest`. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | service Foo { 18 | rpc GetFoo (FooRequest) returns (FooResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service Foo { 28 | rpc GetFoo (GetFooRequest) returns (FooResponse) {} // [!code focus] 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/service-pascal-case.md: -------------------------------------------------------------------------------- 1 | # SERVICE_PASCAL_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all service names are in PascalCase. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | service foo_bar { 18 | rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service FooBar { // [!code focus] 28 | rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/field-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # FIELD_LOWER_SNAKE_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | message Foo { 21 | string BarName = 1; 22 | } 23 | ``` 24 | 25 | ### Good 26 | 27 | ```proto 28 | syntax = "proto3"; 29 | 30 | package foo; 31 | 32 | message Foo { 33 | string bar_name = 1; // [!code focus] 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/service-suffix.md: -------------------------------------------------------------------------------- 1 | # SERVICE_SUFFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все сервисы имеют суффикс `Service` или ваш пользовательский суффикс. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc Bar(BarRequest) returns (BarResponse); 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooService { // [!code focus] 29 | rpc Bar(BarRequest) returns (BarResponse); 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/rpc-request-standard-name.md: -------------------------------------------------------------------------------- 1 | # RPC_REQUEST_STANDARD_NAME 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all RPC request messages are named `MethodRequest`. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | service Foo { 18 | rpc GetFoo (FooRequest) returns (FooResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service Foo { 28 | rpc GetFoo (GetFooRequest) returns (FooResponse) {} // [!code focus] 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/service-pascal-case.md: -------------------------------------------------------------------------------- 1 | # SERVICE_PASCAL_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all service names are in PascalCase. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | service foo_bar { 18 | rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service FooBar { // [!code focus] 28 | rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/field-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # FIELD_LOWER_SNAKE_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что имена полей сообщений записаны в стиле lower_snake_case. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | message Foo { 21 | string BarName = 1; 22 | } 23 | ``` 24 | 25 | ### Good 26 | 27 | ```proto 28 | syntax = "proto3"; 29 | 30 | package foo; 31 | 32 | message Foo { 33 | string bar_name = 1; // [!code focus] 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/rpc-pascal-case.md: -------------------------------------------------------------------------------- 1 | # RPC_PASCAL_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все имена RPC написаны в стиле PascalCase. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service foo_bar { 19 | rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooBar { 29 | rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/comment-field.md: -------------------------------------------------------------------------------- 1 | # COMMENT_FIELD 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that all message fields have a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | string bar = 1; 18 | string baz = 2; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | message Foo { 28 | // bar field for bar logic // [!code focus] 29 | string bar = 1; 30 | // baz field for baz logic // [!code focus] 31 | string baz = 2; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/service-suffix.md: -------------------------------------------------------------------------------- 1 | # SERVICE_SUFFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все сервисы имеют суффикс `Service` или ваш пользовательский суффикс. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc Bar(BarRequest) returns (BarResponse); 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooService { // [!code focus] 29 | rpc Bar(BarRequest) returns (BarResponse); 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/rpc-response-standard-name.md: -------------------------------------------------------------------------------- 1 | # RPC_RESPONSE_STANDARD_NAME 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all RPC response messages are named `MethodResponse`. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc GetFoo (GetFooRequest) returns (Foo) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service Foo { 29 | rpc GetFoo (GetFooRequest) returns (GetFooResponse) {} // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/comment-field.md: -------------------------------------------------------------------------------- 1 | # COMMENT_FIELD 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что все поля сообщений имеют комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | string bar = 1; 18 | string baz = 2; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | message Foo { 28 | // bar field for bar logic // [!code focus] 29 | string bar = 1; 30 | // baz field for baz logic // [!code focus] 31 | string baz = 2; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/rpc-response-standard-name.md: -------------------------------------------------------------------------------- 1 | # RPC_RESPONSE_STANDARD_NAME 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all RPC response messages are named `MethodResponse`. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc GetFoo (GetFooRequest) returns (Foo) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service Foo { 29 | rpc GetFoo (GetFooRequest) returns (GetFooResponse) {} // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/comment-field.md: -------------------------------------------------------------------------------- 1 | # COMMENT_FIELD 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что все поля сообщений имеют комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | string bar = 1; 18 | string baz = 2; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | message Foo { 28 | // bar field for bar logic // [!code focus] 29 | string bar = 1; 30 | // baz field for baz logic // [!code focus] 31 | string baz = 2; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/rpc-pascal-case.md: -------------------------------------------------------------------------------- 1 | # RPC_PASCAL_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все имена RPC написаны в стиле PascalCase. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service foo_bar { 19 | rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooBar { 29 | rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/rpc-request-standard-name.md: -------------------------------------------------------------------------------- 1 | # RPC_REQUEST_STANDARD_NAME 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все сообщения запроса RPC названы в формате `MethodRequest`. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | service Foo { 18 | rpc GetFoo (FooRequest) returns (FooResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service Foo { 28 | rpc GetFoo (GetFooRequest) returns (FooResponse) {} // [!code focus] 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/rpc-request-standard-name.md: -------------------------------------------------------------------------------- 1 | # RPC_REQUEST_STANDARD_NAME 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все сообщения запроса RPC названы в формате `MethodRequest`. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | service Foo { 18 | rpc GetFoo (FooRequest) returns (FooResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service Foo { 28 | rpc GetFoo (GetFooRequest) returns (FooResponse) {} // [!code focus] 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/comment-oneof.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ONEOF 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that oneof has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | oneof bar { 18 | string baz = 1; 19 | string qux = 2; 20 | } 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | message Foo { 30 | // bar oneof for baz and qux logic // [!code focus] 31 | oneof bar { 32 | string baz = 1; 33 | string qux = 2; 34 | } 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/rpc-response-standard-name.md: -------------------------------------------------------------------------------- 1 | # RPC_RESPONSE_STANDARD_NAME 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все сообщения ответа RPC названы в формате `MethodResponse`. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc GetFoo (GetFooRequest) returns (Foo) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service Foo { 29 | rpc GetFoo (GetFooRequest) returns (GetFooResponse) {} // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/service-pascal-case.md: -------------------------------------------------------------------------------- 1 | # SERVICE_PASCAL_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все имена сервисов написаны в стиле PascalCase. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service foo_bar { 19 | rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooBar { // [!code focus] 29 | rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/enum-value-upper-snake-case.md: -------------------------------------------------------------------------------- 1 | # ENUM_VALUE_UPPER_SNAKE_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that enum values are in UPPER_SNAKE_CASE. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | enum Foo { 20 | barName = 0; 21 | bazName = 1; 22 | } 23 | ``` 24 | 25 | ### Good 26 | 27 | ```proto 28 | syntax = "proto3"; 29 | 30 | package foo; 31 | 32 | enum Foo { 33 | BAR_NAME = 0; // [!code focus] 34 | BAZ_NAME = 1; // [!code focus] 35 | } 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/comment-oneof.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ONEOF 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that oneof has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | oneof bar { 18 | string baz = 1; 19 | string qux = 2; 20 | } 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | message Foo { 30 | // bar oneof for baz and qux logic // [!code focus] 31 | oneof bar { 32 | string baz = 1; 33 | string qux = 2; 34 | } 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/enum-value-upper-snake-case.md: -------------------------------------------------------------------------------- 1 | # ENUM_VALUE_UPPER_SNAKE_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that enum values are in UPPER_SNAKE_CASE. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | enum Foo { 20 | barName = 0; 21 | bazName = 1; 22 | } 23 | ``` 24 | 25 | ### Good 26 | 27 | ```proto 28 | syntax = "proto3"; 29 | 30 | package foo; 31 | 32 | enum Foo { 33 | BAR_NAME = 0; // [!code focus] 34 | BAZ_NAME = 1; // [!code focus] 35 | } 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/rpc-response-standard-name.md: -------------------------------------------------------------------------------- 1 | # RPC_RESPONSE_STANDARD_NAME 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все сообщения ответа RPC названы в формате `MethodResponse`. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc GetFoo (GetFooRequest) returns (Foo) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service Foo { 29 | rpc GetFoo (GetFooRequest) returns (GetFooResponse) {} // [!code focus] 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/service-pascal-case.md: -------------------------------------------------------------------------------- 1 | # SERVICE_PASCAL_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все имена сервисов написаны в стиле PascalCase. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service foo_bar { 19 | rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | syntax = "proto3"; 27 | 28 | service FooBar { // [!code focus] 29 | rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /testdata/invalid_options/queue.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package same_package; 4 | 5 | import "google/protobuf/empty.proto"; 6 | import "google/rpc/code.proto"; 7 | 8 | option csharp_namespace = "ZergsLaw.BackTemplate.Api.Session.V1"; 9 | option go_package = "github.com/ZergsLaw/back-template/api/session/v1;pb"; 10 | option java_multiple_files = true; 11 | option java_package = "com.zergslaw.backtemplate.api.session.v1"; 12 | option php_namespace = "ZergsLaw\\BackTemplate\\Api\\Session\\V1"; 13 | option ruby_package = "ZergsLaw"; 14 | option swift_prefix = "ZergsLaw.BackTemplate.Api.Session.V1"; 15 | 16 | message Queue {} 17 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/comment-message.md: -------------------------------------------------------------------------------- 1 | # COMMENT_MESSAGE 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that message has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | 15 | syntax = "proto3"; 16 | 17 | message Foo { 18 | string bar = 1; 19 | string baz = 2; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | 27 | syntax = "proto3"; 28 | 29 | // Foo message for bar and baz logic // [!code focus] 30 | message Foo { 31 | // bar field for bar logic 32 | string bar = 1; 33 | // baz field for baz logic 34 | string baz = 2; 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/enum-no-allow-alias.md: -------------------------------------------------------------------------------- 1 | # ENUM_NO_ALLOW_ALIAS 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that the `allow_alias` option is not set to `true` in an enum. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | enum Foo { 21 | option allow_alias = true; // [!code focus] 22 | BAR = 0; 23 | BAZ = 1; 24 | } 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | syntax = "proto3"; 31 | 32 | package foo; 33 | 34 | enum Foo { 35 | BAR = 0; 36 | BAZ = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/comment-message.md: -------------------------------------------------------------------------------- 1 | # COMMENT_MESSAGE 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что message имеет комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | string bar = 1; 18 | string baz = 2; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | // Foo message for bar and baz logic // [!code focus] 28 | message Foo { 29 | // bar field for bar logic 30 | string bar = 1; 31 | // baz field for baz logic 32 | string baz = 2; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/comment-oneof.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ONEOF 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что oneof имеет комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | oneof bar { 18 | string baz = 1; 19 | string qux = 2; 20 | } 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | message Foo { 30 | // bar oneof for baz and qux logic // [!code focus] 31 | oneof bar { 32 | string baz = 1; 33 | string qux = 2; 34 | } 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/comment-message.md: -------------------------------------------------------------------------------- 1 | # COMMENT_MESSAGE 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что message имеет комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | string bar = 1; 18 | string baz = 2; 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | // Foo message for bar and baz logic // [!code focus] 28 | message Foo { 29 | // bar field for bar logic 30 | string bar = 1; 31 | // baz field for baz logic 32 | string baz = 2; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/comment-oneof.md: -------------------------------------------------------------------------------- 1 | # COMMENT_ONEOF 2 | 3 | Категории: 4 | 5 | - **COMMENT** 6 | 7 | Это правило проверяет, что oneof имеет комментарий. 8 | 9 | ## Примеры 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | message Foo { 17 | oneof bar { 18 | string baz = 1; 19 | string qux = 2; 20 | } 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | message Foo { 30 | // bar oneof for baz and qux logic // [!code focus] 31 | oneof bar { 32 | string baz = 1; 33 | string qux = 2; 34 | } 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /testdata/api/session/v1/events.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package api.session.v1; 4 | 5 | import "google/rpc/code.proto"; 6 | 7 | option csharp_namespace = "ZergsLaw.BackTemplate.Api.Session.V1"; 8 | option go_package = "github.com/ZergsLaw/back-template/api/session/v1;pb"; 9 | option java_multiple_files = true; 10 | option java_package = "com.zergslaw.backtemplate.api.session.v1"; 11 | option php_namespace = "ZergsLaw\\BackTemplate\\Api\\Session\\V1"; 12 | option ruby_package = "ZergsLaw"; 13 | option swift_prefix = "ZergsLaw.BackTemplate.Api.Session.V1"; 14 | 15 | // Events, which can be sent by service. 16 | message Event {} 17 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/enum-value-upper-snake-case.md: -------------------------------------------------------------------------------- 1 | # ENUM_VALUE_UPPER_SNAKE_CASE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | enum Foo { 20 | barName = 0; 21 | bazName = 1; 22 | } 23 | ``` 24 | 25 | ### Good 26 | 27 | ```proto 28 | syntax = "proto3"; 29 | 30 | package foo; 31 | 32 | enum Foo { 33 | BAR_NAME = 0; // [!code focus] 34 | BAZ_NAME = 1; // [!code focus] 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_LOWER_SNAKE_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв). 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: bar/foo.proto 17 | syntax = "proto3"; 18 | 19 | package FooBar; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | // File: bar/foo.proto 26 | syntax = "proto3"; 27 | 28 | package foo_bar; // [!code focus] 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/comment-message.md: -------------------------------------------------------------------------------- 1 | # COMMENT_MESSAGE 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that message has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | 15 | syntax = "proto3"; 16 | 17 | message Foo { 18 | string bar = 1; 19 | string baz = 2; 20 | } 21 | ``` 22 | 23 | ### Good 24 | 25 | ```proto 26 | 27 | syntax = "proto3"; 28 | 29 | // Foo message for bar and baz logic // [!code focus] 30 | message Foo { 31 | // bar field for bar logic 32 | string bar = 1; 33 | // baz field for baz logic 34 | string baz = 2; 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/enum-no-allow-alias.md: -------------------------------------------------------------------------------- 1 | # ENUM_NO_ALLOW_ALIAS 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that the `allow_alias` option is not set to `true` in an enum. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | enum Foo { 21 | option allow_alias = true; // [!code focus] 22 | BAR = 0; 23 | BAZ = 1; 24 | } 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | syntax = "proto3"; 31 | 32 | package foo; 33 | 34 | enum Foo { 35 | BAR = 0; 36 | BAZ = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_LOWER_SNAKE_CASE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что имена package записаны в формате lower_snake_case (строчные буквы, при необходимости цифры и символ подчеркивания, без пробелов и заглавных букв). 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: bar/foo.proto 17 | syntax = "proto3"; 18 | 19 | package FooBar; 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | // File: bar/foo.proto 26 | syntax = "proto3"; 27 | 28 | package foo_bar; // [!code focus] 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/enum-value-upper-snake-case.md: -------------------------------------------------------------------------------- 1 | # ENUM_VALUE_UPPER_SNAKE_CASE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что значения enum записаны в стиле UPPER_SNAKE_CASE. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | enum Foo { 20 | barName = 0; 21 | bazName = 1; 22 | } 23 | ``` 24 | 25 | ### Good 26 | 27 | ```proto 28 | syntax = "proto3"; 29 | 30 | package foo; 31 | 32 | enum Foo { 33 | BAR_NAME = 0; // [!code focus] 34 | BAZ_NAME = 1; // [!code focus] 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/enum-no-allow-alias.md: -------------------------------------------------------------------------------- 1 | # ENUM_NO_ALLOW_ALIAS 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что опция `allow_alias` не установлена в значение `true` внутри enum. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | enum Foo { 21 | option allow_alias = true; // [!code focus] 22 | BAR = 0; 23 | BAZ = 1; 24 | } 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | syntax = "proto3"; 31 | 32 | package foo; 33 | 34 | enum Foo { 35 | BAR = 0; 36 | BAZ = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/enum-no-allow-alias.md: -------------------------------------------------------------------------------- 1 | # ENUM_NO_ALLOW_ALIAS 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что опция `allow_alias` не установлена в значение `true` внутри enum. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | package foo; 19 | 20 | enum Foo { 21 | option allow_alias = true; // [!code focus] 22 | BAR = 0; 23 | BAZ = 1; 24 | } 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | syntax = "proto3"; 31 | 32 | package foo; 33 | 34 | enum Foo { 35 | BAR = 0; 36 | BAZ = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/oneof-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # ONEOF_LOWER_SNAKE_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that oneof names are in lower_snake_case. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message Foo { 20 | oneof BarName { 21 | string bar_name = 1; 22 | } 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | syntax = "proto3"; 30 | 31 | package foo; 32 | 33 | message Foo { 34 | oneof bar_name { // [!code focus] 35 | string bar_name = 1; 36 | } 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/oneof-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # ONEOF_LOWER_SNAKE_CASE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that oneof names are in lower_snake_case. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message Foo { 20 | oneof BarName { 21 | string bar_name = 1; 22 | } 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | syntax = "proto3"; 30 | 31 | package foo; 32 | 33 | message Foo { 34 | oneof bar_name { // [!code focus] 35 | string bar_name = 1; 36 | } 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/oneof-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # ONEOF_LOWER_SNAKE_CASE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что имена oneof записаны в стиле lower_snake_case. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message Foo { 20 | oneof BarName { 21 | string bar_name = 1; 22 | } 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | syntax = "proto3"; 30 | 31 | package foo; 32 | 33 | message Foo { 34 | oneof bar_name { // [!code focus] 35 | string bar_name = 1; 36 | } 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/oneof-lower-snake-case.md: -------------------------------------------------------------------------------- 1 | # ONEOF_LOWER_SNAKE_CASE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что имена oneof записаны в стиле lower_snake_case. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | syntax = "proto3"; 16 | 17 | package foo; 18 | 19 | message Foo { 20 | oneof BarName { 21 | string bar_name = 1; 22 | } 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | syntax = "proto3"; 30 | 31 | package foo; 32 | 33 | message Foo { 34 | oneof bar_name { // [!code focus] 35 | string bar_name = 1; 36 | } 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-same-directory.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_DIRECTORY 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы с данным package находятся в одной директории. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: bar/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | // File: bar/foo.proto // [!code focus] 30 | 31 | syntax = "proto3"; 32 | 33 | package bar; // [!code focus] 34 | 35 | message Foo { 36 | string bar = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-same-directory.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_DIRECTORY 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы с данным package находятся в одной директории. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: bar/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | // File: bar/foo.proto // [!code focus] 30 | 31 | syntax = "proto3"; 32 | 33 | package bar; // [!code focus] 34 | 35 | message Foo { 36 | string bar = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/directory-same-package.md: -------------------------------------------------------------------------------- 1 | # DIRECTORY_SAME_PACKAGE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files in a given directory are in the same package. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: dir/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | // File: dir/foo/foo.proto // [!code focus] 30 | 31 | syntax = "proto3"; 32 | 33 | package dir.foo; // [!code focus] 34 | 35 | message Foo { 36 | string bar = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-directory-match.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_DIRECTORY_MATCH 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files are in a directory that matches their package name. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: bar/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | // File: bar/foo.proto // [!code focus] 31 | 32 | syntax = "proto3"; 33 | 34 | package bar; // [!code focus] 35 | 36 | message Foo { 37 | string bar = 1; 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-same-directory.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_DIRECTORY 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files with a given package are in the same directory. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: bar/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | // File: bar/foo.proto // [!code focus] 31 | 32 | syntax = "proto3"; 33 | 34 | package bar; // [!code focus] 35 | 36 | message Foo { 37 | string bar = 1; 38 | } 39 | 40 | ``` 41 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/directory-same-package.md: -------------------------------------------------------------------------------- 1 | # DIRECTORY_SAME_PACKAGE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files in a given directory are in the same package. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: dir/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | // File: dir/foo/foo.proto // [!code focus] 30 | 31 | syntax = "proto3"; 32 | 33 | package dir.foo; // [!code focus] 34 | 35 | message Foo { 36 | string bar = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/assets/infoDiagram-ER5ION4S-Ba3AJNAB.js: -------------------------------------------------------------------------------- 1 | import{_ as e,l as s,H as n,e as i,I as p}from"./index-BtiIqbpV.js";import{p as g}from"./treemap-KMMF4GRG-BdBrUw5q.js";import"./_baseUniq-UvPYksec.js";import"./_basePickBy-Dm_sMLMB.js";import"./clone-uEwA9FQU.js";var v={parse:e(async r=>{const a=await g("info",r);s.debug(a)},"parse")},d={version:p.version+""},m=e(()=>d.version,"getVersion"),c={getVersion:m},l=e((r,a,o)=>{s.debug(`rendering info diagram 2 | `+r);const t=n(a);i(t,100,400,!0),t.append("g").append("text").attr("x",100).attr("y",40).attr("class","version").attr("font-size",32).style("text-anchor","middle").text(`v${o}`)},"draw"),f={draw:l},S={parser:v,db:c,renderer:f};export{S as diagram}; 3 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-directory-match.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_DIRECTORY_MATCH 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files are in a directory that matches their package name. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: bar/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | // File: bar/foo.proto // [!code focus] 31 | 32 | syntax = "proto3"; 33 | 34 | package bar; // [!code focus] 35 | 36 | message Foo { 37 | string bar = 1; 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-same-directory.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_DIRECTORY 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files with a given package are in the same directory. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: bar/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | 25 | ``` 26 | 27 | ### Good 28 | 29 | ```proto 30 | // File: bar/foo.proto // [!code focus] 31 | 32 | syntax = "proto3"; 33 | 34 | package bar; // [!code focus] 35 | 36 | message Foo { 37 | string bar = 1; 38 | } 39 | 40 | ``` 41 | -------------------------------------------------------------------------------- /internal/adapters/storage/write_installed_module_info.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/easyp-tech/easyp/internal/core/models" 9 | ) 10 | 11 | func (s *Storage) WriteInstalledModuleInfo( 12 | cacheDownloadPaths models.CacheDownloadPaths, installedModuleInfo models.InstalledModuleInfo, 13 | ) error { 14 | rawData, err := json.Marshal(&installedModuleInfo) 15 | if err != nil { 16 | return fmt.Errorf("json.Marshal: %w", err) 17 | } 18 | 19 | if err := os.WriteFile(cacheDownloadPaths.ModuleInfoFile, rawData, infoFilePerm); err != nil { 20 | return fmt.Errorf("os.WriteFile: %w", err) 21 | } 22 | 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/directory-same-package.md: -------------------------------------------------------------------------------- 1 | # DIRECTORY_SAME_PACKAGE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: dir/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | // File: dir/foo/foo.proto // [!code focus] 30 | 31 | syntax = "proto3"; 32 | 33 | package dir.foo; // [!code focus] 34 | 35 | message Foo { 36 | string bar = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-directory-match.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_DIRECTORY_MATCH 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: bar/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | // File: bar/foo.proto // [!code focus] 30 | 31 | syntax = "proto3"; 32 | 33 | package bar; // [!code focus] 34 | 35 | message Foo { 36 | string bar = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/comment-rpc.md: -------------------------------------------------------------------------------- 1 | # COMMENT_RPC 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that rpc has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (BarResponse) {} 18 | rpc Baz (BazRequest) returns (BazResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service Foo { 28 | // Bar rpc for bar logic // [!code focus] 29 | rpc Bar (BarRequest) returns (BarResponse) {} 30 | // Baz rpc for baz logic // [!code focus] 31 | rpc Baz (BazRequest) returns (BazResponse) {} 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/comment-rpc.md: -------------------------------------------------------------------------------- 1 | # COMMENT_RPC 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that rpc has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (BarResponse) {} 18 | rpc Baz (BazRequest) returns (BazResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service Foo { 28 | // Bar rpc for bar logic // [!code focus] 29 | rpc Bar (BarRequest) returns (BarResponse) {} 30 | // Baz rpc for baz logic // [!code focus] 31 | rpc Baz (BazRequest) returns (BazResponse) {} 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/directory-same-package.md: -------------------------------------------------------------------------------- 1 | # DIRECTORY_SAME_PACKAGE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы в заданной директории находятся в одном и том же package. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: dir/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | // File: dir/foo/foo.proto // [!code focus] 30 | 31 | syntax = "proto3"; 32 | 33 | package dir.foo; // [!code focus] 34 | 35 | message Foo { 36 | string bar = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-directory-match.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_DIRECTORY_MATCH 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы находятся в директории, имя которой соответствует имени их пакета. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: bar/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package foo; 20 | 21 | message Foo { 22 | string bar = 1; 23 | } 24 | ``` 25 | 26 | ### Good 27 | 28 | ```proto 29 | // File: bar/foo.proto // [!code focus] 30 | 31 | syntax = "proto3"; 32 | 33 | package bar; // [!code focus] 34 | 35 | message Foo { 36 | string bar = 1; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/comment-rpc.md: -------------------------------------------------------------------------------- 1 | # COMMENT_RPC 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that rpc has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (BarResponse) {} 18 | rpc Baz (BazRequest) returns (BazResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service Foo { 28 | // Bar rpc for bar logic // [!code focus] 29 | rpc Bar (BarRequest) returns (BarResponse) {} 30 | // Baz rpc for baz logic // [!code focus] 31 | rpc Baz (BazRequest) returns (BazResponse) {} 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/comment-rpc.md: -------------------------------------------------------------------------------- 1 | # COMMENT_RPC 2 | 3 | Categories: 4 | 5 | - **COMMENT** 6 | 7 | This rule checks that rpc has a comment. 8 | 9 | ## Examples 10 | 11 | ### Bad 12 | 13 | ```proto 14 | syntax = "proto3"; 15 | 16 | service Foo { 17 | rpc Bar (BarRequest) returns (BarResponse) {} 18 | rpc Baz (BazRequest) returns (BazResponse) {} 19 | } 20 | ``` 21 | 22 | ### Good 23 | 24 | ```proto 25 | syntax = "proto3"; 26 | 27 | service Foo { 28 | // Bar rpc for bar logic // [!code focus] 29 | rpc Bar (BarRequest) returns (BarResponse) {} 30 | // Baz rpc for baz logic // [!code focus] 31 | rpc Baz (BazRequest) returns (BazResponse) {} 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /internal/adapters/storage/create_cache_repository_dir.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "crypto/sha256" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | ) 9 | 10 | // CacheDir create and return path to cache dir. 11 | // cache dir contains repository cache for repository with proto files. 12 | // cmd/go/internal/modfetch/codehost/codehost.go: 228 - create workdir 13 | func (s *Storage) CreateCacheRepositoryDir(name string) (string, error) { 14 | cacheDir := filepath.Join(s.rootDir, cacheDir, fmt.Sprintf("%x", sha256.Sum256([]byte(name)))) 15 | 16 | if err := os.MkdirAll(cacheDir, dirPerm); err != nil { 17 | return "", fmt.Errorf("os.MkdirAll: %w", err) 18 | } 19 | 20 | return cacheDir, nil 21 | } 22 | -------------------------------------------------------------------------------- /docs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vite.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | define: { 8 | // Provide Buffer polyfill for gray-matter library 9 | global: 'globalThis', 10 | }, 11 | resolve: { 12 | alias: { 13 | // Use buffer polyfill for browser 14 | buffer: 'buffer', 15 | }, 16 | }, 17 | optimizeDeps: { 18 | esbuildOptions: { 19 | // Node.js global to browser globalThis 20 | define: { 21 | global: 'globalThis', 22 | }, 23 | }, 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/auto-completion/auto-completion.md: -------------------------------------------------------------------------------- 1 | # Auto completion 2 | 3 | ## zsh auto-completion 4 | 5 | 1. Add the following line to your ~/.zshrc startup script: 6 | 7 | ```bash 8 | source <(easyp completion zsh) 9 | ``` 10 | 11 | 2. Re-launch your shell or run: 12 | 13 | ```bash 14 | source ~/.zshrc 15 | ``` 16 | 17 | ## Bash auto-completion 18 | 19 | 1. Install [bash-completion](https://github.com/scop/bash-completion#installation) and add the software to your `~/.bashrc`. 20 | 2. Add the following line to your ~/.bashrc startup script: 21 | 22 | ```bash 23 | source <(easyp completion bash) 24 | ``` 25 | 26 | 3. Re-launch your shell or run: 27 | 28 | ```bash 29 | source ~/.bashrc 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/auto-completion/auto-completion.md: -------------------------------------------------------------------------------- 1 | # Auto completion 2 | 3 | ## zsh auto-completion 4 | 5 | 1. Add the following line to your ~/.zshrc startup script: 6 | 7 | ```bash 8 | source <(easyp completion zsh) 9 | ``` 10 | 11 | 2. Re-launch your shell or run: 12 | 13 | ```bash 14 | source ~/.zshrc 15 | ``` 16 | 17 | ## Bash auto-completion 18 | 19 | 1. Install [bash-completion](https://github.com/scop/bash-completion#installation) and add the software to your `~/.bashrc`. 20 | 2. Add the following line to your ~/.bashrc startup script: 21 | 22 | ```bash 23 | source <(easyp completion bash) 24 | ``` 25 | 26 | 3. Re-launch your shell or run: 27 | 28 | ```bash 29 | source ~/.bashrc 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /internal/adapters/repository/git/read_file.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/easyp-tech/easyp/internal/core/models" 7 | ) 8 | 9 | func (r *gitRepo) ReadFile(ctx context.Context, revision models.Revision, fileName string) (string, error) { 10 | // g cat-file -p 8074ae2f42417345ef103d83fb62e4245010715d:buf.work.yaml 11 | fileRequest := revision.CommitHash + ":" + fileName 12 | content, err := r.console.RunCmd( 13 | ctx, r.cacheDir, "git", "cat-file", "-p", fileRequest, 14 | ) 15 | if err != nil { 16 | // It's too dificult to parse stderr from git 17 | // so decided that there is no file in that case 18 | return "", models.ErrFileNotFound 19 | } 20 | 21 | return content, nil 22 | } 23 | -------------------------------------------------------------------------------- /internal/core/module_path.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/easyp-tech/easyp/internal/core/models" 8 | ) 9 | 10 | // modulePath resolves install path for a module using lock file information. 11 | // It ensures the path exists to surface missing installs early. 12 | func (c *Core) modulePath(module models.Module) (string, error) { 13 | lockInfo, err := c.lockFile.Read(module.Name) 14 | if err != nil { 15 | return "", fmt.Errorf("lockFile.Read: %w", err) 16 | } 17 | 18 | modulePath := c.storage.GetInstallDir(lockInfo.Name, lockInfo.Version) 19 | if _, err := os.Stat(modulePath); err != nil { 20 | return "", fmt.Errorf("os.Stat: %w", err) 21 | } 22 | 23 | return modulePath, nil 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | pull_request: 8 | branches: 9 | - '*' 10 | 11 | jobs: 12 | 13 | test: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | 19 | - name: Install Go 20 | uses: actions/setup-go@v5 21 | with: 22 | go-version: '1.24' 23 | 24 | - name: Install Task 25 | uses: arduino/setup-task@v1 26 | with: 27 | version: 3.x 28 | repo-token: ${{ secrets.GITHUB_TOKEN }} 29 | 30 | - name: Prepare test. 31 | run: task init 32 | 33 | - name: Start test. 34 | run: task test 35 | -------------------------------------------------------------------------------- /internal/adapters/storage/get_installed_module_hash.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "golang.org/x/mod/sumdb/dirhash" 8 | 9 | "github.com/easyp-tech/easyp/internal/core/models" 10 | ) 11 | 12 | func (s *Storage) GetInstalledModuleHash(moduleName string, revisionVersion string) (models.ModuleHash, error) { 13 | installedDirPath := s.GetInstallDir(moduleName, revisionVersion) 14 | installedPackageHash, err := dirhash.HashDir(installedDirPath, "", dirhash.DefaultHash) 15 | if err != nil { 16 | if os.IsNotExist(err) { 17 | return "", models.ErrModuleNotInstalled 18 | } 19 | 20 | return "", fmt.Errorf("dirhash.HashDir: %w", err) 21 | } 22 | 23 | return models.ModuleHash(installedPackageHash), nil 24 | } 25 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/rpc-request-response-unique.md: -------------------------------------------------------------------------------- 1 | # RPC_REQUEST_RESPONSE_UNIQUE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all RPC request and response messages are unique. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc GetFoo (FooRequest) returns (FooResponse) {} 20 | rpc GetBar (FooRequest) returns (FooResponse) {} 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | service Foo { 30 | rpc GetFoo (FooRequest) returns (FooResponse) {} // [!code focus] 31 | rpc GetBar (BarRequest) returns (BarResponse) {} // [!code focus] 32 | } 33 | ``` 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/rpc-request-response-unique.md: -------------------------------------------------------------------------------- 1 | # RPC_REQUEST_RESPONSE_UNIQUE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all RPC request and response messages are unique. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc GetFoo (FooRequest) returns (FooResponse) {} 20 | rpc GetBar (FooRequest) returns (FooResponse) {} 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | service Foo { 30 | rpc GetFoo (FooRequest) returns (FooResponse) {} // [!code focus] 31 | rpc GetBar (BarRequest) returns (BarResponse) {} // [!code focus] 32 | } 33 | ``` 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/import-no-weak.md: -------------------------------------------------------------------------------- 1 | # IMPORT_NO_WEAK 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что в proto‑файле не используются weak‑импорты (`import weak "..."`). 9 | 10 | Weak import (синтаксис `import weak`) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный `import`. 11 | 12 | ## Примеры 13 | 14 | ### Bad 15 | 16 | ```proto 17 | syntax = "proto2"; 18 | 19 | package foo; 20 | 21 | import weak "bar.proto"; 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto2"; 28 | 29 | package foo; 30 | 31 | import "bar.proto"; // [!code focus] 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/import-no-weak.md: -------------------------------------------------------------------------------- 1 | # IMPORT_NO_WEAK 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что в proto‑файле не используются weak‑импорты (`import weak "..."`). 9 | 10 | Weak import (синтаксис `import weak`) допустим в proto2, но его использование усложняет анализ зависимостей и может приводить к неочевидным ошибкам при генерации кода. Рекомендуется всегда использовать обычный `import`. 11 | 12 | ## Примеры 13 | 14 | ### Bad 15 | 16 | ```proto 17 | syntax = "proto2"; 18 | 19 | package foo; 20 | 21 | import weak "bar.proto"; 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto2"; 28 | 29 | package foo; 30 | 31 | import "bar.proto"; // [!code focus] 32 | ``` 33 | -------------------------------------------------------------------------------- /internal/adapters/lock_file/read.go: -------------------------------------------------------------------------------- 1 | package lockfile 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core/models" 5 | ) 6 | 7 | // Read information about module by its name from lock file 8 | // github.com/grpc-ecosystem/grpc-gateway v0.0.0-20240502030614-85850831b7bad2b8b60cb09783d8095176f22d98 h1:hRu1vxAH6CVNmz12mpqKue5HVBQP2neoaM/q2DLm0i4= 9 | func (l *LockFile) Read(moduleName string) (models.LockFileInfo, error) { 10 | fileInfo, ok := l.cache[moduleName] 11 | if !ok { 12 | return models.LockFileInfo{}, models.ErrModuleNotFoundInLockFile 13 | } 14 | 15 | lockFileInfo := models.LockFileInfo{ 16 | Name: moduleName, 17 | Version: fileInfo.version, 18 | Hash: models.ModuleHash(fileInfo.hash), 19 | } 20 | return lockFileInfo, nil 21 | } 22 | -------------------------------------------------------------------------------- /internal/core/vendor.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | cp "github.com/otiai10/copy" 8 | 9 | "github.com/easyp-tech/easyp/internal/core/models" 10 | ) 11 | 12 | // Vendor copy all proto files from deps to local dir 13 | func (c *Core) Vendor(ctx context.Context) error { 14 | if err := c.Download(ctx, c.deps); err != nil { 15 | return fmt.Errorf("c.Download: %w", err) 16 | } 17 | 18 | for lockFileInfo := range c.lockFile.DepsIter() { 19 | depPath, err := c.modulePath(models.NewModule(lockFileInfo.Name)) 20 | if err != nil { 21 | return fmt.Errorf("modulePath: %w", err) 22 | } 23 | 24 | if err := cp.Copy(depPath, c.vendorDir); err != nil { 25 | return fmt.Errorf("c.Copy: %w", err) 26 | } 27 | } 28 | 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /internal/fs/fs/dir_walker.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "io" 5 | "io/fs" 6 | "os" 7 | ) 8 | 9 | type FS interface { 10 | Open(name string) (io.ReadCloser, error) 11 | Create(name string) (io.WriteCloser, error) 12 | } 13 | 14 | func NewFSWalker(root, path string) *FSWalker { 15 | if path == "" { 16 | path = "." 17 | } 18 | 19 | diskFS := os.DirFS(root) 20 | return &FSWalker{ 21 | FSAdapter: &FSAdapter{diskFS, root}, 22 | path: path, 23 | } 24 | } 25 | 26 | type FSWalker struct { 27 | *FSAdapter 28 | 29 | path string 30 | } 31 | 32 | func (w *FSWalker) WalkDir(callback func(path string, err error) error) error { 33 | err := fs.WalkDir(w.FS, w.path, func(path string, d fs.DirEntry, err error) error { 34 | return callback(path, err) 35 | }) 36 | 37 | return err 38 | } 39 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": [ 6 | "ES2020", 7 | "DOM", 8 | "DOM.Iterable" 9 | ], 10 | "module": "ESNext", 11 | "skipLibCheck": true, 12 | /* Bundler mode */ 13 | "moduleResolution": "bundler", 14 | "allowImportingTsExtensions": true, 15 | "isolatedModules": true, 16 | "moduleDetection": "force", 17 | "noEmit": true, 18 | "jsx": "react-jsx", 19 | /* Linting */ 20 | "strict": true, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "noFallthroughCasesInSwitch": true 24 | }, 25 | "include": [ 26 | "src" 27 | ] 28 | } -------------------------------------------------------------------------------- /docs/src/pages/HomePage.tsx: -------------------------------------------------------------------------------- 1 | import Navbar from '../components/Navbar' 2 | import Hero from '../components/Hero' 3 | // import TrustedBy from '../components/TrustedBy' // Temporarily hidden - waiting for permissions 4 | import FeatureSwitcher from '../components/FeatureSwitcher' 5 | import ArchitectureComparison from '../components/ArchitectureComparison' 6 | import Footer from '../components/Footer' 7 | 8 | export default function HomePage() { 9 | return ( 10 |
11 | 12 | 13 | {/* */} {/* Temporarily hidden - waiting for permissions */} 14 | 15 | 16 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /internal/adapters/storage/get_cache_download_paths_test.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "path/filepath" 5 | ) 6 | 7 | func (s *storageSuite) Test_GetCacheDownloadPaths() { 8 | module := getFakeModule() 9 | revision := getFakeRevision() 10 | 11 | // ref values 12 | expectedCacheDownloadDir := filepath.Join(s.rootDir, cacheDir, cacheDownloadDir, module.Name) 13 | expectedArchiveFile := filepath.Join(expectedCacheDownloadDir, revision.Version) + ".zip" 14 | expectedModuleInfoFile := filepath.Join(expectedCacheDownloadDir, revision.Version) + ".info" 15 | 16 | res := s.storage.GetCacheDownloadPaths(module.Name, revision.Version) 17 | 18 | s.Equal(expectedCacheDownloadDir, res.CacheDownloadDir) 19 | s.Equal(expectedArchiveFile, res.ArchiveFile) 20 | s.Equal(expectedModuleInfoFile, res.ModuleInfoFile) 21 | } 22 | -------------------------------------------------------------------------------- /internal/adapters/storage/get_cache_download_paths.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "path/filepath" 5 | 6 | "github.com/easyp-tech/easyp/internal/core/models" 7 | ) 8 | 9 | // GetDownloadArchivePath returns full path to download archive (include extension) 10 | func (s *Storage) GetCacheDownloadPaths(moduleName, version string) models.CacheDownloadPaths { 11 | cacheDownloadDir := filepath.Join(s.rootDir, cacheDir, cacheDownloadDir, moduleName) 12 | 13 | fileName := sanitizePath(version) 14 | 15 | archiveFile := filepath.Join(cacheDownloadDir, fileName) + ".zip" 16 | moduleInfoFile := filepath.Join(cacheDownloadDir, fileName) + ".info" 17 | 18 | return models.CacheDownloadPaths{ 19 | CacheDownloadDir: cacheDownloadDir, 20 | ArchiveFile: archiveFile, 21 | ModuleInfoFile: moduleInfoFile, 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /internal/rules/comment_message.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*CommentMessage)(nil) 8 | 9 | // CommentMessage this rule checks that messages have non-empty comments. 10 | type CommentMessage struct{} 11 | 12 | // Message implements lint.Rule. 13 | func (c *CommentMessage) Message() string { 14 | return "message comment is empty" 15 | } 16 | 17 | // Validate implements lint.Rule. 18 | func (c *CommentMessage) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 19 | var res []core.Issue 20 | 21 | for _, message := range protoInfo.Info.ProtoBody.Messages { 22 | if len(message.Comments) == 0 { 23 | res = core.AppendIssue(res, c, message.Meta.Pos, message.MessageName, message.Comments) 24 | } 25 | } 26 | 27 | return res, nil 28 | } 29 | -------------------------------------------------------------------------------- /testdata/breaking_check/broken/services.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package breaking; 4 | 5 | enum SomeEnum { 6 | CORPUS_UNSPECIFIED = 0; 7 | CORPUS_UNIVERSAL = 1; 8 | } 9 | 10 | message RPC2Request { 11 | string field_1 = 1; 12 | } 13 | 14 | message MessageForType { 15 | string message_for_type = 1; 16 | } 17 | 18 | message RPC2Response { 19 | message RPC2ResponseNested { 20 | }; 21 | 22 | optional MessageForType field_1 = 1; 23 | 24 | oneof login { 25 | string field = 3; 26 | string fff = 2; 27 | } 28 | } 29 | 30 | message AuthInfo { 31 | string username = 1; 32 | } 33 | 34 | message AuthResponse { 35 | 36 | } 37 | 38 | // Сервис-фасад для DAST сканнера 39 | service Service { 40 | rpc Auth(AuthInfo) returns(AuthResponse); 41 | // RPC1 42 | rpc RPC1(RPC1Request) returns(RPC1Response); 43 | } 44 | -------------------------------------------------------------------------------- /internal/rules/comment_service.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*CommentService)(nil) 8 | 9 | // CommentService this rule checks that services have non-empty comments. 10 | type CommentService struct{} 11 | 12 | // Message implements lint.Rule. 13 | func (c *CommentService) Message() string { 14 | return "service comments must not be empty" 15 | } 16 | 17 | // Validate implements lint.Rule. 18 | func (c *CommentService) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 19 | var res []core.Issue 20 | 21 | for _, service := range protoInfo.Info.ProtoBody.Services { 22 | if len(service.Comments) == 0 { 23 | res = core.AppendIssue(res, c, service.Meta.Pos, service.ServiceName, service.Comments) 24 | } 25 | } 26 | 27 | return res, nil 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/relator.yml: -------------------------------------------------------------------------------- 1 | name: Relator 2 | 3 | on: 4 | issues: 5 | types: [opened, reopened] 6 | pull_request_target: 7 | types: [opened, reopened] 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }} 11 | cancel-in-progress: true 12 | 13 | permissions: 14 | issues: read 15 | pull-requests: read 16 | 17 | jobs: 18 | notify: 19 | name: "Telegram notification" 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Send Telegram notification for new issue or pull request 23 | uses: reagento/relator@983edccef69ef9a25b97552daaeaf0f183b470f4 # v1.5.0 24 | with: 25 | tg-bot-token: ${{ secrets.TELEGRAM_BOT_TOKEN }} 26 | tg-chat-id: ${{ vars.TELEGRAM_CHAT_ID }} 27 | github-token: ${{ secrets.GITHUB_TOKEN }} 28 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/rpc-request-response-unique.md: -------------------------------------------------------------------------------- 1 | # RPC_REQUEST_RESPONSE_UNIQUE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары `Request` / `Response` у разных RPC). 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc GetFoo (FooRequest) returns (FooResponse) {} 20 | rpc GetBar (FooRequest) returns (FooResponse) {} 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | service Foo { 30 | rpc GetFoo (FooRequest) returns (FooResponse) {} // [!code focus] 31 | rpc GetBar (BarRequest) returns (BarResponse) {} // [!code focus] 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/rpc-request-response-unique.md: -------------------------------------------------------------------------------- 1 | # RPC_REQUEST_RESPONSE_UNIQUE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все сообщения запроса и ответа RPC уникальны: для каждого метода используются собственные (не переиспользуются одинаковые пары `Request` / `Response` у разных RPC). 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | syntax = "proto3"; 17 | 18 | service Foo { 19 | rpc GetFoo (FooRequest) returns (FooResponse) {} 20 | rpc GetBar (FooRequest) returns (FooResponse) {} 21 | } 22 | ``` 23 | 24 | ### Good 25 | 26 | ```proto 27 | syntax = "proto3"; 28 | 29 | service Foo { 30 | rpc GetFoo (FooRequest) returns (FooResponse) {} // [!code focus] 31 | rpc GetBar (BarRequest) returns (BarResponse) {} // [!code focus] 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /internal/rules/comment_rpc.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*CommentRPC)(nil) 8 | 9 | // CommentRPC this rule checks that RPCs have non-empty comments. 10 | type CommentRPC struct{} 11 | 12 | // Message implements lint.Rule. 13 | func (c *CommentRPC) Message() string { 14 | return "rpc comments must not be empty" 15 | } 16 | 17 | // Validate implements lint.Rule. 18 | func (c *CommentRPC) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 19 | var res []core.Issue 20 | 21 | for _, service := range protoInfo.Info.ProtoBody.Services { 22 | for _, rpc := range service.ServiceBody.RPCs { 23 | if len(service.Comments) == 0 { 24 | res = core.AppendIssue(res, c, rpc.Meta.Pos, rpc.RPCName, service.Comments) 25 | } 26 | } 27 | } 28 | 29 | return res, nil 30 | } 31 | -------------------------------------------------------------------------------- /internal/rules/package_defined.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/yoheimuta/go-protoparser/v4/parser/meta" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*PackageDefined)(nil) 10 | 11 | // PackageDefined this rule checks that all files have a package declaration. 12 | type PackageDefined struct{} 13 | 14 | // Message implements lint.Rule. 15 | func (p *PackageDefined) Message() string { 16 | return "package should be defined" 17 | } 18 | 19 | // Validate implements lint.Rule. 20 | func (p *PackageDefined) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 21 | var res []core.Issue 22 | 23 | if len(protoInfo.Info.ProtoBody.Packages) == 0 { 24 | res = core.AppendIssue(res, p, meta.Position{ 25 | Filename: protoInfo.Path, 26 | }, protoInfo.Path, nil) 27 | } 28 | 29 | return res, nil 30 | } 31 | -------------------------------------------------------------------------------- /internal/core/path_helpers/is_target_path.go: -------------------------------------------------------------------------------- 1 | package path_helpers 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | ) 8 | 9 | // IsTargetPath check if passed filePath is target 10 | // it has to be in targetPath dir 11 | func IsTargetPath(targetPath, filePath string) bool { 12 | rel, err := filepath.Rel(targetPath, filePath) 13 | if err != nil { 14 | return false 15 | } 16 | if !filepath.IsLocal(rel) { 17 | return false 18 | } 19 | 20 | return true 21 | } 22 | 23 | func IsIgnoredPath(path string, ignore []string) bool { 24 | up := ".." + string(os.PathSeparator) 25 | 26 | for _, ignorePath := range ignore { 27 | rel, err := filepath.Rel(ignorePath, path) 28 | if err != nil { 29 | continue 30 | } 31 | if strings.HasPrefix(rel, up) && rel != ".." { 32 | continue 33 | } 34 | return true 35 | } 36 | 37 | return false 38 | } 39 | -------------------------------------------------------------------------------- /internal/fs/go_git/dir_walker.go: -------------------------------------------------------------------------------- 1 | package go_git 2 | 3 | import ( 4 | "github.com/go-git/go-git/v5/plumbing/object" 5 | 6 | "github.com/easyp-tech/easyp/internal/core/path_helpers" 7 | ) 8 | 9 | func NewGitTreeWalker(tree *object.Tree, path string) *GitTreeWalker { 10 | return &GitTreeWalker{ 11 | GitTreeDiskAdapter: &GitTreeDiskAdapter{tree}, 12 | tree: tree, 13 | path: path, 14 | } 15 | } 16 | 17 | type GitTreeWalker struct { 18 | *GitTreeDiskAdapter 19 | 20 | tree *object.Tree 21 | path string 22 | } 23 | 24 | func (w *GitTreeWalker) WalkDir(callback func(path string, err error) error) error { 25 | err := w.tree.Files().ForEach(func(f *object.File) error { 26 | switch { 27 | case !path_helpers.IsTargetPath(w.path, f.Name): 28 | return nil 29 | } 30 | 31 | return callback(f.Name, nil) 32 | }) 33 | return err 34 | } 35 | -------------------------------------------------------------------------------- /internal/rules/comment_one_of.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*CommentOneof)(nil) 8 | 9 | // CommentOneof this rule checks that oneofs have non-empty comments. 10 | type CommentOneof struct{} 11 | 12 | // Message implements lint.Rule. 13 | func (c *CommentOneof) Message() string { 14 | return "oneof comments must not be empty" 15 | } 16 | 17 | // Validate implements lint.Rule. 18 | func (c *CommentOneof) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 19 | var res []core.Issue 20 | 21 | for _, msg := range protoInfo.Info.ProtoBody.Messages { 22 | for _, oneof := range msg.MessageBody.Oneofs { 23 | if len(oneof.Comments) == 0 { 24 | res = core.AppendIssue(res, c, oneof.Meta.Pos, oneof.OneofName, oneof.Comments) 25 | } 26 | } 27 | } 28 | 29 | return res, nil 30 | } 31 | -------------------------------------------------------------------------------- /docs/dist/favicon-16.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/public/favicon-16.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /internal/rules/comment_field_message.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*CommentField)(nil) 8 | 9 | // CommentField this rule checks that fields have non-empty comments. 10 | type CommentField struct{} 11 | 12 | // Message implements lint.Rule. 13 | func (c *CommentField) Message() string { 14 | return "field comments must not be empty" 15 | } 16 | 17 | // Validate implements lint.Rule. 18 | func (c *CommentField) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 19 | var res []core.Issue 20 | 21 | for _, message := range protoInfo.Info.ProtoBody.Messages { 22 | for _, field := range message.MessageBody.Fields { 23 | if len(field.Comments) == 0 { 24 | res = core.AppendIssue(res, c, field.Meta.Pos, field.FieldName, field.Comments) 25 | } 26 | } 27 | } 28 | 29 | return res, nil 30 | } 31 | -------------------------------------------------------------------------------- /internal/adapters/storage/storage.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core/models" 5 | ) 6 | 7 | const ( 8 | // root cache dir 9 | cacheDir = "cache" 10 | // dir for downloaded (check sum, archive) 11 | cacheDownloadDir = "download" 12 | // dir for installed packages 13 | installedDir = "mod" 14 | ) 15 | 16 | type ( 17 | // LockFile should implement adapter for lock file workflow 18 | LockFile interface { 19 | Read(moduleName string) (models.LockFileInfo, error) 20 | } 21 | 22 | // Storage implements workflows with directories 23 | Storage struct { 24 | rootDir string 25 | lockFile LockFile 26 | } 27 | ) 28 | 29 | func New(rootDir string, lockFile LockFile) *Storage { 30 | return &Storage{ 31 | rootDir: rootDir, 32 | lockFile: lockFile, 33 | } 34 | } 35 | 36 | const ( 37 | dirPerm = 0755 38 | infoFilePerm = 0644 39 | ) 40 | -------------------------------------------------------------------------------- /internal/adapters/lock_file/write.go: -------------------------------------------------------------------------------- 1 | package lockfile 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | 7 | "github.com/easyp-tech/easyp/internal/core/models" 8 | ) 9 | 10 | func (l *LockFile) Write( 11 | moduleName string, revisionVersion string, installedPackageHash models.ModuleHash, 12 | ) error { 13 | fp, err := l.dirWalker.Create(lockFileName) 14 | if err != nil { 15 | return fmt.Errorf("l.dirWalker.Create: %w", err) 16 | } 17 | 18 | fileInfo := fileInfo{ 19 | version: revisionVersion, 20 | hash: string(installedPackageHash), 21 | } 22 | 23 | l.cache[moduleName] = fileInfo 24 | 25 | keys := make([]string, 0, len(l.cache)) 26 | for k := range l.cache { 27 | keys = append(keys, k) 28 | } 29 | sort.Strings(keys) 30 | 31 | for _, k := range keys { 32 | r := fmt.Sprintf("%s %s %s\n", k, l.cache[k].version, l.cache[k].hash) 33 | _, _ = fp.Write([]byte(r)) 34 | } 35 | 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /docs/dist/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /internal/adapters/repository/git/get_files.go: -------------------------------------------------------------------------------- 1 | package git 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/easyp-tech/easyp/internal/core/models" 9 | ) 10 | 11 | func (r *gitRepo) GetFiles(ctx context.Context, revision models.Revision, dirs ...string) ([]string, error) { 12 | params := []string{ 13 | "ls-tree", "-r", revision.CommitHash, 14 | } 15 | params = append(params, dirs...) 16 | res, err := r.console.RunCmd(ctx, r.cacheDir, "git", params...) 17 | if err != nil { 18 | return nil, fmt.Errorf("utils.RunCmd: %w", err) 19 | } 20 | 21 | stats := strings.Split(res, "\n") 22 | 23 | files := make([]string, 0, len(stats)) 24 | for _, stat := range stats { 25 | stat := stat 26 | s := strings.Fields(stat) 27 | if len(s) != 4 { 28 | // TODO: write debug log that len is wrong 29 | continue 30 | } 31 | files = append(files, s[3]) 32 | } 33 | 34 | return files, nil 35 | } 36 | -------------------------------------------------------------------------------- /internal/rules/rpc_no_client_streaming.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*RPCNoClientStreaming)(nil) 8 | 9 | // RPCNoClientStreaming this rule checks that RPCs aren't client streaming. 10 | type RPCNoClientStreaming struct { 11 | } 12 | 13 | // Message implements lint.Rule. 14 | func (r *RPCNoClientStreaming) Message() string { 15 | return "client streaming RPCs are not allowed" 16 | } 17 | 18 | // Validate implements lint.Rule. 19 | func (r *RPCNoClientStreaming) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 20 | var res []core.Issue 21 | 22 | for _, service := range protoInfo.Info.ProtoBody.Services { 23 | for _, rpc := range service.ServiceBody.RPCs { 24 | if rpc.RPCRequest.IsStream { 25 | res = core.AppendIssue(res, r, rpc.Meta.Pos, rpc.RPCName, rpc.Comments) 26 | } 27 | } 28 | } 29 | 30 | return res, nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/rules/rpc_no_server_streaming.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*RPCNoServerStreaming)(nil) 8 | 9 | // RPCNoServerStreaming this rule checks that RPCs aren't server streaming. 10 | type RPCNoServerStreaming struct { 11 | } 12 | 13 | // Message implements lint.Rule. 14 | func (r *RPCNoServerStreaming) Message() string { 15 | return "server streaming RPCs are not allowed" 16 | } 17 | 18 | // Validate implements lint.Rule. 19 | func (r *RPCNoServerStreaming) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 20 | var res []core.Issue 21 | 22 | for _, service := range protoInfo.Info.ProtoBody.Services { 23 | for _, rpc := range service.ServiceBody.RPCs { 24 | if rpc.RPCResponse.IsStream { 25 | res = core.AppendIssue(res, r, rpc.Meta.Pos, rpc.RPCName, rpc.Comments) 26 | } 27 | } 28 | } 29 | 30 | return res, nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/adapters/storage/read_installed_module_info.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "os" 8 | 9 | "github.com/easyp-tech/easyp/internal/core/models" 10 | ) 11 | 12 | func (s *Storage) ReadInstalledModuleInfo( 13 | cacheDownloadPaths models.CacheDownloadPaths, 14 | ) (models.InstalledModuleInfo, error) { 15 | rawData, err := os.ReadFile(cacheDownloadPaths.ModuleInfoFile) 16 | if err != nil { 17 | if errors.Is(err, os.ErrNotExist) { 18 | return models.InstalledModuleInfo{}, models.ErrModuleInfoFileNotFound 19 | } 20 | 21 | return models.InstalledModuleInfo{}, fmt.Errorf("os.ReadFile: %w", err) 22 | } 23 | 24 | installedModuleInfo := models.InstalledModuleInfo{} 25 | if err := json.Unmarshal(rawData, &installedModuleInfo); err != nil { 26 | return models.InstalledModuleInfo{}, fmt.Errorf("json.Unmarshal: %w", err) 27 | } 28 | 29 | return installedModuleInfo, nil 30 | } 31 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-same-ruby-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_RUBY_PACKAGE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same Ruby package. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option ruby_package = "Foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option ruby_package = "Bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option ruby_package = "Foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option ruby_package = "Foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-same-swift-prefix.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_SWIFT_PREFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same Swift prefix. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option swift_prefix = "Foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option swift_prefix = "Bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option swift_prefix = "Foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option swift_prefix = "Foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /internal/rules/service_suffix.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*ServiceSuffix)(nil) 10 | 11 | // ServiceSuffix this rule enforces that all services are suffixed with Service. 12 | type ServiceSuffix struct { 13 | Suffix string 14 | } 15 | 16 | // Message implements lint.Rule. 17 | func (s *ServiceSuffix) Message() string { 18 | return "service name should have suffix" 19 | } 20 | 21 | // Validate enforces that all services are suffixed with Service. 22 | func (s *ServiceSuffix) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 23 | var res []core.Issue 24 | 25 | for _, service := range protoInfo.Info.ProtoBody.Services { 26 | if !strings.HasSuffix(service.ServiceName, s.Suffix) { 27 | res = core.AppendIssue(res, s, service.Meta.Pos, service.ServiceName, service.Comments) 28 | } 29 | } 30 | 31 | return res, nil 32 | } 33 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-same-ruby-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_RUBY_PACKAGE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same Ruby package. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option ruby_package = "Foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option ruby_package = "Bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option ruby_package = "Foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option ruby_package = "Foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-same-ruby-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_RUBY_PACKAGE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same Ruby package. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option ruby_package = "Foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option ruby_package = "Bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option ruby_package = "Foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option ruby_package = "Foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-same-swift-prefix.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_SWIFT_PREFIX 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same Swift prefix. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option swift_prefix = "Foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option swift_prefix = "Bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option swift_prefix = "Foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option swift_prefix = "Foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-same-ruby-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_RUBY_PACKAGE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same Ruby package. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option ruby_package = "Foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option ruby_package = "Bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option ruby_package = "Foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option ruby_package = "Foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /internal/rules/rpc_pascal_case.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "regexp" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*RPCPascalCase)(nil) 10 | 11 | // RPCPascalCase this rule checks that RPCs are PascalCase. 12 | type RPCPascalCase struct{} 13 | 14 | // Message implements lint.Rule. 15 | func (c *RPCPascalCase) Message() string { 16 | return "RPC names should be PascalCase" 17 | } 18 | 19 | // Validate implements lint.Rule. 20 | func (c *RPCPascalCase) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 21 | var res []core.Issue 22 | pascalCase := regexp.MustCompile("^[A-Z][a-zA-Z0-9]*$") 23 | for _, service := range protoInfo.Info.ProtoBody.Services { 24 | for _, rpc := range service.ServiceBody.RPCs { 25 | if !pascalCase.MatchString(rpc.RPCName) { 26 | res = core.AppendIssue(res, c, rpc.Meta.Pos, rpc.RPCName, rpc.Comments) 27 | } 28 | } 29 | } 30 | 31 | return res, nil 32 | } 33 | -------------------------------------------------------------------------------- /internal/rules/service_pascal_case.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "regexp" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*ServicePascalCase)(nil) 10 | 11 | // ServicePascalCase this rule checks that services are PascalCase. 12 | type ServicePascalCase struct{} 13 | 14 | // Message implements lint.Rule. 15 | func (c *ServicePascalCase) Message() string { 16 | return "service names must be PascalCase" 17 | } 18 | 19 | // Validate implements lint.Rule. 20 | func (c *ServicePascalCase) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 21 | var res []core.Issue 22 | 23 | pascalCase := regexp.MustCompile("^[A-Z][a-z]+([A-Z]|[a-z]+)*$") 24 | for _, service := range protoInfo.Info.ProtoBody.Services { 25 | if !pascalCase.MatchString(service.ServiceName) { 26 | res = core.AppendIssue(res, c, service.Meta.Pos, service.ServiceName, service.Comments) 27 | } 28 | } 29 | 30 | return res, nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/rules/package_lower_snake_case.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "regexp" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*PackageLowerSnakeCase)(nil) 10 | 11 | // PackageLowerSnakeCase his rule checks that packages are lower_snake_case. 12 | type PackageLowerSnakeCase struct{} 13 | 14 | // Message implements lint.Rule. 15 | func (c *PackageLowerSnakeCase) Message() string { 16 | return "package name should be lower_snake_case" 17 | } 18 | 19 | // Validate implements lint.Rule. 20 | func (c *PackageLowerSnakeCase) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 21 | var res []core.Issue 22 | lowerSnakeCase := regexp.MustCompile("^[a-z]+([_|[.][a-z0-9]+)*$") 23 | for _, pack := range protoInfo.Info.ProtoBody.Packages { 24 | if !lowerSnakeCase.MatchString(pack.Name) { 25 | res = core.AppendIssue(res, c, pack.Meta.Pos, pack.Name, pack.Comments) 26 | } 27 | } 28 | 29 | return res, nil 30 | } 31 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-same-swift-prefix.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_SWIFT_PREFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все файлы с одним и тем же package используют один и тот же `swift_prefix`. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option swift_prefix = "Foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option swift_prefix = "Bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option swift_prefix = "Foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option swift_prefix = "Foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-same-swift-prefix.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_SWIFT_PREFIX 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все файлы с одним и тем же package используют один и тот же `swift_prefix`. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option swift_prefix = "Foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option swift_prefix = "Bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option swift_prefix = "Foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option swift_prefix = "Foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /internal/rules/message_pascal_case.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "regexp" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*MessagePascalCase)(nil) 10 | 11 | // MessagePascalCase this rule checks that messages are PascalCase. 12 | type MessagePascalCase struct{} 13 | 14 | // Message implements lint.Rule. 15 | func (c *MessagePascalCase) Message() string { 16 | return "message name should be PascalCase" 17 | } 18 | 19 | // Validate implements lint.Rule. 20 | func (c *MessagePascalCase) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 21 | var res []core.Issue 22 | 23 | pascalCase := regexp.MustCompile("^[A-Z][a-zA-Z0-9]+(?:[A-Z][a-zA-Z0-9]+)*$") 24 | for _, message := range protoInfo.Info.ProtoBody.Messages { 25 | if !pascalCase.MatchString(message.MessageName) { 26 | res = core.AppendIssue(res, c, message.Meta.Pos, message.MessageName, message.Comments) 27 | } 28 | } 29 | 30 | return res, nil 31 | } 32 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-same-csharp-namespace.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_CSHARP_NAMESPACE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files with a given package are in the same C# namespace. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option csharp_namespace = "Foo.Bar"; 22 | ``` 23 | 24 | ```proto 25 | // File: pkg/bar.proto 26 | 27 | syntax = "proto3"; 28 | 29 | package pkg; 30 | 31 | option csharp_namespace = "Foo.Baz"; 32 | ``` 33 | 34 | ### Good 35 | 36 | ```proto 37 | // File: pkg/foo.proto 38 | 39 | syntax = "proto3"; 40 | 41 | package pkg; 42 | 43 | option csharp_namespace = "Foo.Bar"; 44 | ``` 45 | 46 | ```proto 47 | 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option csharp_namespace = "Foo.Bar"; // [!code focus] 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /internal/rules/import_no_public.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/yoheimuta/go-protoparser/v4/parser" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*ImportNoPublic)(nil) 10 | 11 | // ImportNoPublic this rule outlaws declaring imports as public. 12 | // If you didn't know that was possible, forget what you just learned in this sentence. 13 | type ImportNoPublic struct{} 14 | 15 | // Message implements lint.Rule. 16 | func (i *ImportNoPublic) Message() string { 17 | return "import should not be public" 18 | } 19 | 20 | // Validate implements lint.Rule. 21 | func (i *ImportNoPublic) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 22 | var res []core.Issue 23 | 24 | for _, imp := range protoInfo.Info.ProtoBody.Imports { 25 | if imp.Modifier == parser.ImportModifierPublic { 26 | res = core.AppendIssue(res, i, imp.Meta.Pos, imp.Location, imp.Comments) 27 | } 28 | } 29 | 30 | return res, nil 31 | } 32 | -------------------------------------------------------------------------------- /docs/dist/assets/prism-go-CyY0RbE6.js: -------------------------------------------------------------------------------- 1 | Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/});Prism.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}});delete Prism.languages.go["class-name"]; 2 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-same-php-namespace.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_PHP_NAMESPACE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same PHP namespace. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option php_namespace = "Foo\\Bar"; 23 | 24 | ``` 25 | 26 | ```proto 27 | // File: pkg/bar.proto 28 | 29 | syntax = "proto3"; 30 | 31 | package pkg; 32 | 33 | option php_namespace = "Foo\\Baz"; 34 | ``` 35 | 36 | ### Good 37 | 38 | ```proto 39 | // File: pkg/foo.proto 40 | 41 | syntax = "proto3"; 42 | 43 | package pkg; 44 | 45 | option php_namespace = "Foo\\Bar"; // [!code focus] 46 | ``` 47 | 48 | ```proto 49 | // File: pkg/bar.proto 50 | 51 | syntax = "proto3"; 52 | 53 | package pkg; 54 | 55 | option php_namespace = "Foo\\Bar"; // [!code focus] 56 | ``` 57 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-same-csharp-namespace.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_CSHARP_NAMESPACE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files with a given package are in the same C# namespace. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option csharp_namespace = "Foo.Bar"; 22 | ``` 23 | 24 | ```proto 25 | // File: pkg/bar.proto 26 | 27 | syntax = "proto3"; 28 | 29 | package pkg; 30 | 31 | option csharp_namespace = "Foo.Baz"; 32 | ``` 33 | 34 | ### Good 35 | 36 | ```proto 37 | // File: pkg/foo.proto 38 | 39 | syntax = "proto3"; 40 | 41 | package pkg; 42 | 43 | option csharp_namespace = "Foo.Bar"; 44 | ``` 45 | 46 | ```proto 47 | 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option csharp_namespace = "Foo.Bar"; // [!code focus] 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-same-php-namespace.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_PHP_NAMESPACE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same PHP namespace. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option php_namespace = "Foo\\Bar"; 23 | 24 | ``` 25 | 26 | ```proto 27 | // File: pkg/bar.proto 28 | 29 | syntax = "proto3"; 30 | 31 | package pkg; 32 | 33 | option php_namespace = "Foo\\Baz"; 34 | ``` 35 | 36 | ### Good 37 | 38 | ```proto 39 | // File: pkg/foo.proto 40 | 41 | syntax = "proto3"; 42 | 43 | package pkg; 44 | 45 | option php_namespace = "Foo\\Bar"; // [!code focus] 46 | ``` 47 | 48 | ```proto 49 | // File: pkg/bar.proto 50 | 51 | syntax = "proto3"; 52 | 53 | package pkg; 54 | 55 | option php_namespace = "Foo\\Bar"; // [!code focus] 56 | ``` 57 | -------------------------------------------------------------------------------- /internal/rules/import_no_weak.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/yoheimuta/go-protoparser/v4/parser" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*ImportNoWeak)(nil) 10 | 11 | // ImportNoWeak similar to the IMPORT_NO_PUBLIC rule, this rule outlaws declaring imports as weak. 12 | // If you didn't know that was possible, forget what you just learned in this sentence. 13 | type ImportNoWeak struct{} 14 | 15 | // Message implements lint.Rule. 16 | func (i *ImportNoWeak) Message() string { 17 | return "import should not be weak" 18 | } 19 | 20 | // Validate implements lint.Rule. 21 | func (i *ImportNoWeak) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 22 | var res []core.Issue 23 | 24 | for _, imp := range protoInfo.Info.ProtoBody.Imports { 25 | if imp.Modifier == parser.ImportModifierWeak { 26 | res = core.AppendIssue(res, i, imp.Meta.Pos, imp.Location, imp.Comments) 27 | } 28 | } 29 | 30 | return res, nil 31 | } 32 | -------------------------------------------------------------------------------- /docs/dist/assets/prism-protobuf-DiQ_z8B5.js: -------------------------------------------------------------------------------- 1 | (function(e){var s=/\b(?:bool|bytes|double|s?fixed(?:32|64)|float|[su]?int(?:32|64)|string)\b/;e.languages.protobuf=e.languages.extend("clike",{"class-name":[{pattern:/(\b(?:enum|extend|message|service)\s+)[A-Za-z_]\w*(?=\s*\{)/,lookbehind:!0},{pattern:/(\b(?:rpc\s+\w+|returns)\s*\(\s*(?:stream\s+)?)\.?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?=\s*\))/,lookbehind:!0}],keyword:/\b(?:enum|extend|extensions|import|message|oneof|option|optional|package|public|repeated|required|reserved|returns|rpc(?=\s+\w)|service|stream|syntax|to)\b(?!\s*=\s*\d)/,function:/\b[a-z_]\w*(?=\s*\()/i}),e.languages.insertBefore("protobuf","operator",{map:{pattern:/\bmap<\s*[\w.]+\s*,\s*[\w.]+\s*>(?=\s+[a-z_]\w*\s*[=;])/i,alias:"class-name",inside:{punctuation:/[<>.,]/,builtin:s}},builtin:s,"positional-class-name":{pattern:/(?:\b|\B\.)[a-z_]\w*(?:\.[a-z_]\w*)*(?=\s+[a-z_]\w*\s*[=;])/i,alias:"class-name",inside:{punctuation:/\./}},annotation:{pattern:/(\[\s*)[a-z_]\w*(?=\s*=)/i,lookbehind:!0}})})(Prism); 2 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-same-go-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_GO_PACKAGE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files with a given package are in the same Go package. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option go_package = "example.com/foo/bar"; 22 | 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option go_package = "example.com/foo/baz"; 33 | 34 | ``` 35 | 36 | ### Good 37 | 38 | ```proto 39 | // File: pkg/foo.proto 40 | 41 | syntax = "proto3"; 42 | 43 | package pkg; 44 | 45 | option go_package = "example.com/foo/bar"; // [!code focus] 46 | ``` 47 | 48 | ```proto 49 | // File: pkg/bar.proto 50 | 51 | syntax = "proto3"; 52 | 53 | package pkg; 54 | 55 | option go_package = "example.com/foo/bar"; // [!code focus] 56 | ``` 57 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-same-java-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_JAVA_PACKAGE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same Java package. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option java_package = "com.example.foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option java_package = "com.example.bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option java_package = "com.example.foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option java_package = "com.example.foo"; // [!code focus] 55 | ``` 56 | 57 | 58 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-same-go-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_GO_PACKAGE 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files with a given package are in the same Go package. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option go_package = "example.com/foo/bar"; 22 | 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option go_package = "example.com/foo/baz"; 33 | 34 | ``` 35 | 36 | ### Good 37 | 38 | ```proto 39 | // File: pkg/foo.proto 40 | 41 | syntax = "proto3"; 42 | 43 | package pkg; 44 | 45 | option go_package = "example.com/foo/bar"; // [!code focus] 46 | ``` 47 | 48 | ```proto 49 | // File: pkg/bar.proto 50 | 51 | syntax = "proto3"; 52 | 53 | package pkg; 54 | 55 | option go_package = "example.com/foo/bar"; // [!code focus] 56 | ``` 57 | -------------------------------------------------------------------------------- /docs/dist/docs/guide/cli/linter/rules/package-same-java-multiple-files.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_JAVA_MULTIPLE_FILES 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files with a given package are in the same Java package. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option java_package = "com.example.foo"; 22 | ``` 23 | 24 | ```proto 25 | 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option java_package = "com.example.bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option java_package = "com.example.foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option java_package = "com.example.foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-same-php-namespace.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_PHP_NAMESPACE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все файлы с одним и тем же `package` используют одно и то же значение опции `php_namespace`. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option php_namespace = "Foo\\Bar"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option php_namespace = "Foo\\Baz"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option php_namespace = "Foo\\Bar"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option php_namespace = "Foo\\Bar"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-same-java-multiple-files.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_JAVA_MULTIPLE_FILES 2 | 3 | Categories: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | This rule checks that all files with a given package are in the same Java package. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option java_package = "com.example.foo"; 22 | ``` 23 | 24 | ```proto 25 | 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option java_package = "com.example.bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option java_package = "com.example.foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option java_package = "com.example.foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/public/docs/guide/cli/linter/rules/package-same-java-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_JAVA_PACKAGE 2 | 3 | Categories: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | This rule checks that all files with a given package are in the same Java package. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option java_package = "com.example.foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option java_package = "com.example.bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option java_package = "com.example.foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option java_package = "com.example.foo"; // [!code focus] 55 | ``` 56 | 57 | 58 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-same-php-namespace.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_PHP_NAMESPACE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все файлы с одним и тем же `package` используют одно и то же значение опции `php_namespace`. 10 | 11 | ## Примеры 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option php_namespace = "Foo\\Bar"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option php_namespace = "Foo\\Baz"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option php_namespace = "Foo\\Bar"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option php_namespace = "Foo\\Bar"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/src/contexts/TocContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext, useState, ReactNode } from 'react' 2 | import type { TocItem } from '../lib/markdown/types' 3 | 4 | interface TocContextValue { 5 | toc: TocItem[] 6 | setToc: (toc: TocItem[]) => void 7 | activeId: string 8 | setActiveId: (id: string) => void 9 | } 10 | 11 | const TocContext = createContext(null) 12 | 13 | export function useToc() { 14 | const context = useContext(TocContext) 15 | return context 16 | } 17 | 18 | interface TocProviderProps { 19 | children: ReactNode 20 | } 21 | 22 | export function TocProvider({ children }: TocProviderProps) { 23 | const [toc, setToc] = useState([]) 24 | const [activeId, setActiveId] = useState('') 25 | 26 | const value: TocContextValue = { 27 | toc, 28 | setToc, 29 | activeId, 30 | setActiveId 31 | } 32 | 33 | return {children} 34 | } 35 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-same-csharp-namespace.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_CSHARP_NAMESPACE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (`csharp_namespace`). 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option csharp_namespace = "Foo.Bar"; 22 | ``` 23 | 24 | ```proto 25 | // File: pkg/bar.proto 26 | 27 | syntax = "proto3"; 28 | 29 | package pkg; 30 | 31 | option csharp_namespace = "Foo.Baz"; 32 | ``` 33 | 34 | ### Good 35 | 36 | ```proto 37 | // File: pkg/foo.proto 38 | 39 | syntax = "proto3"; 40 | 41 | package pkg; 42 | 43 | option csharp_namespace = "Foo.Bar"; // [!code focus] 44 | ``` 45 | 46 | ```proto 47 | // File: pkg/bar.proto 48 | 49 | syntax = "proto3"; 50 | 51 | package pkg; 52 | 53 | option csharp_namespace = "Foo.Bar"; // [!code focus] 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-same-go-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_GO_PACKAGE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции `go_package`. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option go_package = "example.com/foo/bar"; 22 | ``` 23 | 24 | ```proto 25 | // File: pkg/bar.proto 26 | 27 | syntax = "proto3"; 28 | 29 | package pkg; 30 | 31 | option go_package = "example.com/foo/baz"; 32 | ``` 33 | 34 | ### Good 35 | 36 | ```proto 37 | // File: pkg/foo.proto 38 | 39 | syntax = "proto3"; 40 | 41 | package pkg; 42 | 43 | option go_package = "example.com/foo/bar"; // [!code focus] 44 | ``` 45 | 46 | ```proto 47 | // File: pkg/bar.proto 48 | 49 | syntax = "proto3"; 50 | 51 | package pkg; 52 | 53 | option go_package = "example.com/foo/bar"; // [!code focus] 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-same-csharp-namespace.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_CSHARP_NAMESPACE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы с заданным пакетом используют одно и то же пространство имён C# (`csharp_namespace`). 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option csharp_namespace = "Foo.Bar"; 22 | ``` 23 | 24 | ```proto 25 | // File: pkg/bar.proto 26 | 27 | syntax = "proto3"; 28 | 29 | package pkg; 30 | 31 | option csharp_namespace = "Foo.Baz"; 32 | ``` 33 | 34 | ### Good 35 | 36 | ```proto 37 | // File: pkg/foo.proto 38 | 39 | syntax = "proto3"; 40 | 41 | package pkg; 42 | 43 | option csharp_namespace = "Foo.Bar"; // [!code focus] 44 | ``` 45 | 46 | ```proto 47 | // File: pkg/bar.proto 48 | 49 | syntax = "proto3"; 50 | 51 | package pkg; 52 | 53 | option csharp_namespace = "Foo.Bar"; // [!code focus] 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-same-go-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_GO_PACKAGE 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы с одним и тем же package используют одно и то же значение опции `go_package`. 9 | 10 | ## Примеры 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option go_package = "example.com/foo/bar"; 22 | ``` 23 | 24 | ```proto 25 | // File: pkg/bar.proto 26 | 27 | syntax = "proto3"; 28 | 29 | package pkg; 30 | 31 | option go_package = "example.com/foo/baz"; 32 | ``` 33 | 34 | ### Good 35 | 36 | ```proto 37 | // File: pkg/foo.proto 38 | 39 | syntax = "proto3"; 40 | 41 | package pkg; 42 | 43 | option go_package = "example.com/foo/bar"; // [!code focus] 44 | ``` 45 | 46 | ```proto 47 | // File: pkg/bar.proto 48 | 49 | syntax = "proto3"; 50 | 51 | package pkg; 52 | 53 | option go_package = "example.com/foo/bar"; // [!code focus] 54 | ``` 55 | -------------------------------------------------------------------------------- /internal/adapters/lock_file/lock_file.go: -------------------------------------------------------------------------------- 1 | package lockfile 2 | 3 | import ( 4 | "bufio" 5 | "strings" 6 | 7 | "github.com/easyp-tech/easyp/internal/core" 8 | ) 9 | 10 | const ( 11 | lockFileName = "easyp.lock" 12 | ) 13 | 14 | type fileInfo struct { 15 | version string 16 | hash string 17 | } 18 | 19 | type LockFile struct { 20 | dirWalker core.DirWalker 21 | cache map[string]fileInfo 22 | } 23 | 24 | func New(dirWalker core.DirWalker) *LockFile { 25 | cache := make(map[string]fileInfo) 26 | 27 | fp, err := dirWalker.Open(lockFileName) 28 | if err == nil { 29 | fscanner := bufio.NewScanner(fp) 30 | 31 | for fscanner.Scan() { 32 | parts := strings.Fields(fscanner.Text()) 33 | if len(parts) != 3 { 34 | continue 35 | } 36 | 37 | fileInfo := fileInfo{ 38 | version: parts[1], 39 | hash: parts[2], 40 | } 41 | cache[parts[0]] = fileInfo 42 | } 43 | } 44 | 45 | lockFile := &LockFile{ 46 | dirWalker: dirWalker, 47 | cache: cache, 48 | } 49 | return lockFile 50 | } 51 | -------------------------------------------------------------------------------- /internal/core/update.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "log/slog" 8 | 9 | "github.com/samber/lo" 10 | 11 | "github.com/easyp-tech/easyp/internal/core/models" 12 | ) 13 | 14 | // Update all packages from config 15 | // dependencies slice of strings format: origin@version: github.com/company/repository@v1.2.3 16 | // if version is absent use the latest commit 17 | func (c *Core) Update(ctx context.Context, dependencies []string) error { 18 | lo.Uniq(dependencies) 19 | 20 | for _, dependency := range dependencies { 21 | 22 | module := models.NewModule(dependency) 23 | 24 | c.logger.Debug("Updating dependency", "name", module.Name, "version", module.Version) 25 | 26 | if err := c.Get(ctx, module); err != nil { 27 | if errors.Is(err, models.ErrVersionNotFound) { 28 | slog.Error("Version not found", "dependency", dependency) 29 | return models.ErrVersionNotFound 30 | } 31 | 32 | return fmt.Errorf("c.Get: %w", err) 33 | } 34 | } 35 | 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-same-java-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_JAVA_PACKAGE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все файлы с одним и тем же `package` используют одно и то же значение опции `java_package`. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option java_package = "com.example.foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option java_package = "com.example.bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option java_package = "com.example.foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option java_package = "com.example.foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-same-java-package.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_JAVA_PACKAGE 2 | 3 | Категории: 4 | 5 | - **MINIMAL** 6 | - **BASIC** 7 | - **DEFAULT** 8 | 9 | Это правило проверяет, что все файлы с одним и тем же `package` используют одно и то же значение опции `java_package`. 10 | 11 | ## Examples 12 | 13 | ### Bad 14 | 15 | ```proto 16 | // File: pkg/foo.proto 17 | 18 | syntax = "proto3"; 19 | 20 | package pkg; 21 | 22 | option java_package = "com.example.foo"; 23 | ``` 24 | 25 | ```proto 26 | // File: pkg/bar.proto 27 | 28 | syntax = "proto3"; 29 | 30 | package pkg; 31 | 32 | option java_package = "com.example.bar"; 33 | ``` 34 | 35 | ### Good 36 | 37 | ```proto 38 | // File: pkg/foo.proto 39 | 40 | syntax = "proto3"; 41 | 42 | package pkg; 43 | 44 | option java_package = "com.example.foo"; // [!code focus] 45 | ``` 46 | 47 | ```proto 48 | // File: pkg/bar.proto 49 | 50 | syntax = "proto3"; 51 | 52 | package pkg; 53 | 54 | option java_package = "com.example.foo"; // [!code focus] 55 | ``` 56 | -------------------------------------------------------------------------------- /internal/rules/oneof_lower_snake_case.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "regexp" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*OneofLowerSnakeCase)(nil) 10 | 11 | // OneofLowerSnakeCase this rule checks that oneof names are lower_snake_case. 12 | type OneofLowerSnakeCase struct{} 13 | 14 | // Message implements lint.Rule. 15 | func (c *OneofLowerSnakeCase) Message() string { 16 | return "oneof name should be lower_snake_case" 17 | } 18 | 19 | // Validate implements lint.Rule. 20 | func (c *OneofLowerSnakeCase) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 21 | var res []core.Issue 22 | lowerSnakeCase := regexp.MustCompile("^[a-z]+(_[a-z]+)*$") 23 | for _, message := range protoInfo.Info.ProtoBody.Messages { 24 | for _, oneof := range message.MessageBody.Oneofs { 25 | if !lowerSnakeCase.MatchString(oneof.OneofName) { 26 | res = core.AppendIssue(res, c, oneof.Meta.Pos, oneof.OneofName, oneof.Comments) 27 | } 28 | } 29 | } 30 | 31 | return res, nil 32 | } 33 | -------------------------------------------------------------------------------- /docs/dist/docs/ru-guide/cli/linter/rules/package-same-java-multiple-files.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_JAVA_MULTIPLE_FILES 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы с одним и тем же `package` используют одинаковое значение опции `java_package`. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option java_package = "com.example.foo"; 22 | ``` 23 | 24 | ```proto 25 | // File: pkg/bar.proto 26 | 27 | syntax = "proto3"; 28 | 29 | package pkg; 30 | 31 | option java_package = "com.example.bar"; 32 | ``` 33 | 34 | ### Good 35 | 36 | ```proto 37 | // File: pkg/foo.proto 38 | 39 | syntax = "proto3"; 40 | 41 | package pkg; 42 | 43 | option java_package = "com.example.foo"; // [!code focus] 44 | ``` 45 | 46 | ```proto 47 | // File: pkg/bar.proto 48 | 49 | syntax = "proto3"; 50 | 51 | package pkg; 52 | 53 | option java_package = "com.example.foo"; // [!code focus] 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/public/docs/ru-guide/cli/linter/rules/package-same-java-multiple-files.md: -------------------------------------------------------------------------------- 1 | # PACKAGE_SAME_JAVA_MULTIPLE_FILES 2 | 3 | Категории: 4 | - **MINIMAL** 5 | - **BASIC** 6 | - **DEFAULT** 7 | 8 | Это правило проверяет, что все файлы с одним и тем же `package` используют одинаковое значение опции `java_package`. 9 | 10 | ## Examples 11 | 12 | ### Bad 13 | 14 | ```proto 15 | // File: pkg/foo.proto 16 | 17 | syntax = "proto3"; 18 | 19 | package pkg; 20 | 21 | option java_package = "com.example.foo"; 22 | ``` 23 | 24 | ```proto 25 | // File: pkg/bar.proto 26 | 27 | syntax = "proto3"; 28 | 29 | package pkg; 30 | 31 | option java_package = "com.example.bar"; 32 | ``` 33 | 34 | ### Good 35 | 36 | ```proto 37 | // File: pkg/foo.proto 38 | 39 | syntax = "proto3"; 40 | 41 | package pkg; 42 | 43 | option java_package = "com.example.foo"; // [!code focus] 44 | ``` 45 | 46 | ```proto 47 | // File: pkg/bar.proto 48 | 49 | syntax = "proto3"; 50 | 51 | package pkg; 52 | 53 | option java_package = "com.example.foo"; // [!code focus] 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/src/utils/extractHeadings.ts: -------------------------------------------------------------------------------- 1 | export interface Heading { 2 | id: string 3 | text: string 4 | level: number 5 | } 6 | 7 | export function extractHeadings(content: string): Heading[] { 8 | const headings: Heading[] = [] 9 | const lines = content.split('\n') 10 | 11 | // Simple regex for ## and ### headings 12 | // Ignoring # (h1) as it's usually the page title 13 | const headingRegex = /^(#{2,3})\s+(.+)$/ 14 | 15 | // Helper to generate ID from text 16 | const generateId = (text: string) => { 17 | return text 18 | .toLowerCase() 19 | .replace(/[^\w\s-]/g, '') 20 | .replace(/\s+/g, '-') 21 | } 22 | 23 | lines.forEach(line => { 24 | const match = line.match(headingRegex) 25 | if (match) { 26 | const level = match[1].length 27 | const text = match[2].trim() 28 | const id = generateId(text) 29 | headings.push({ id, text, level }) 30 | } 31 | }) 32 | 33 | return headings 34 | } 35 | -------------------------------------------------------------------------------- /internal/adapters/repository/repository.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/easyp-tech/easyp/internal/core/models" 7 | ) 8 | 9 | type Repo interface { 10 | // GetFiles returns list of all files in repository 11 | GetFiles(ctx context.Context, revision models.Revision, dirs ...string) ([]string, error) 12 | 13 | // ReadFile returns file's content from repository 14 | ReadFile(ctx context.Context, revision models.Revision, fileName string) (string, error) 15 | 16 | // Archive passed storage to archive and return full path to archive 17 | Archive( 18 | ctx context.Context, revision models.Revision, archiveFilePath string, 19 | ) error 20 | 21 | // ReadRevision reads commit's revision by passed version 22 | // or return the latest commit if version is empty 23 | ReadRevision(ctx context.Context, requestedVersion models.RequestedVersion) (models.Revision, error) 24 | 25 | // Fetch from remote repository specified version 26 | Fetch(ctx context.Context, revision models.Revision) error 27 | } 28 | -------------------------------------------------------------------------------- /internal/rules/package_no_import_cycle.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*PackageNoImportCycle)(nil) 8 | 9 | // PackageNoImportCycle this is an extra uncategorized rule that detects package import cycles. 10 | // The Protobuf compiler outlaws circular file imports, but it's still possible to introduce package cycles, such as these: 11 | type PackageNoImportCycle struct { 12 | // cache is a map of package name to a slice of package names that it imports 13 | cache map[string][]string 14 | } 15 | 16 | func (p *PackageNoImportCycle) lazyInit() { 17 | if p.cache == nil { 18 | p.cache = make(map[string][]string) 19 | } 20 | } 21 | 22 | // Message implements lint.Rule. 23 | func (p *PackageNoImportCycle) Message() string { 24 | return "package should not have import cycles" 25 | } 26 | 27 | // Validate implements lint.Rule. 28 | func (p *PackageNoImportCycle) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 29 | p.lazyInit() 30 | panic("implement me") 31 | } 32 | -------------------------------------------------------------------------------- /internal/rules/message_field_lower_snake_case.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "regexp" 5 | 6 | "github.com/easyp-tech/easyp/internal/core" 7 | ) 8 | 9 | var _ core.Rule = (*FieldLowerSnakeCase)(nil) 10 | 11 | // FieldLowerSnakeCase this rule checks that field names are lower_snake_case. 12 | type FieldLowerSnakeCase struct{} 13 | 14 | // Message implements lint.Rule. 15 | func (c *FieldLowerSnakeCase) Message() string { 16 | return "message field should be lower_snake_case" 17 | } 18 | 19 | // Validate implements lint.Rule. 20 | func (c *FieldLowerSnakeCase) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 21 | var res []core.Issue 22 | 23 | lowerSnakeCase := regexp.MustCompile("^[a-z0-9]+(_[a-z0-9]+)*$") 24 | for _, message := range protoInfo.Info.ProtoBody.Messages { 25 | for _, field := range message.MessageBody.Fields { 26 | if !lowerSnakeCase.MatchString(field.FieldName) { 27 | res = core.AppendIssue(res, c, field.Meta.Pos, field.FieldName, field.Comments) 28 | } 29 | } 30 | } 31 | 32 | return res, nil 33 | } 34 | -------------------------------------------------------------------------------- /internal/rules/comment_enum.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/easyp-tech/easyp/internal/core" 5 | ) 6 | 7 | var _ core.Rule = (*CommentEnum)(nil) 8 | 9 | // CommentEnum this rule checks that enums have non-empty comments. 10 | type CommentEnum struct{} 11 | 12 | // Message implements lint.Rule. 13 | func (c *CommentEnum) Message() string { 14 | return "enum comments must not be empty" 15 | } 16 | 17 | // Validate implements lint.Rule. 18 | func (c *CommentEnum) Validate(protoInfo core.ProtoInfo) ([]core.Issue, error) { 19 | var res []core.Issue 20 | 21 | for _, enum := range protoInfo.Info.ProtoBody.Enums { 22 | if len(enum.Comments) == 0 { 23 | res = core.AppendIssue(res, c, enum.Meta.Pos, enum.EnumName, enum.Comments) 24 | } 25 | } 26 | 27 | for _, msg := range protoInfo.Info.ProtoBody.Messages { 28 | for _, enum := range msg.MessageBody.Enums { 29 | if len(enum.Comments) == 0 { 30 | res = core.AppendIssue(res, c, enum.Meta.Pos, enum.EnumName, enum.Comments) 31 | } 32 | } 33 | } 34 | 35 | return res, nil 36 | } 37 | -------------------------------------------------------------------------------- /testdata/breaking_check/original/services.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package breaking; 4 | 5 | import "messages.proto"; 6 | 7 | enum SomeEnum { 8 | CORPUS_UNSPECIFIED = 0; 9 | CORPUS_UNIVERSAL = 1; 10 | CORPUS_WEB = 2; 11 | } 12 | 13 | message RPC2Request { 14 | string field_1 = 1; 15 | } 16 | 17 | message MessageForType { 18 | string message_for_type = 1; 19 | } 20 | 21 | message RPC2Response { 22 | message RPC2ResponseNested { 23 | string rpc2_response_nested_field = 1; 24 | }; 25 | 26 | optional MessageForType field_1 = 1; 27 | 28 | oneof login { 29 | string field = 3; 30 | string fff = 2; 31 | RPC2ResponseNested rrr = 4; 32 | } 33 | } 34 | 35 | message AuthInfo { 36 | string username = 1; 37 | string password = 2; 38 | } 39 | 40 | message AuthResponse { 41 | 42 | } 43 | 44 | // Сервис-фасад для DAST сканнера 45 | service Service { 46 | rpc Auth(AuthInfo) returns(AuthResponse); 47 | // RPC1 48 | rpc RPC1(RPC1Request) returns(RPC1Response); 49 | // RPC2 50 | rpc RPC2(RPC2Request) returns(RPC2Response); 51 | } 52 | --------------------------------------------------------------------------------