-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Which creates a strongly-typed sig for `#context`, if the context class was customized via the `context_class` DSL.
- Loading branch information
1 parent
71b495d
commit c0216ac
Showing
4 changed files
with
201 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# typed: strict | ||
# frozen_string_literal: true | ||
|
||
begin | ||
gem("graphql", ">= 1.13") | ||
require "graphql" | ||
rescue LoadError | ||
return | ||
end | ||
|
||
require "tapioca/dsl/helpers/graphql_type_helper" | ||
|
||
module Tapioca | ||
module Dsl | ||
module Compilers | ||
# `Tapioca::Dsl::Compilers::GraphqlSchema` generates RBI files for subclasses of | ||
# [`GraphQL::Schema`](https://graphql-ruby.org/api-doc/2.1.7/GraphQL/Schema). | ||
# | ||
# For example, with the following `GraphQL::Schema` subclass: | ||
# | ||
# ~~~rb | ||
# class MySchema> < GraphQL::Schema | ||
# class MyContext < GraphQL::Query::Context; end | ||
# | ||
# context_class MyContext | ||
# | ||
# # ... | ||
# end | ||
# ~~~ | ||
# | ||
# this compiler will produce the RBI file `my_schema.rbi` with the following content: | ||
# | ||
# ~~~rbi | ||
# # my_schema.rbi | ||
# # typed: true | ||
# class MySchema | ||
# sig { returns(MySchema::MyContext) } | ||
# def context; end | ||
# end | ||
# ~~~ | ||
class GraphqlSchema < Compiler | ||
extend T::Sig | ||
|
||
ConstantType = type_member { { fixed: T.class_of(GraphQL::Schema) } } | ||
|
||
sig { override.void } | ||
def decorate | ||
custom_context_class = constant.context_class | ||
# Skip decoration if the context class hasn't been customized | ||
return if custom_context_class == GraphQL::Query::Context | ||
|
||
return if constant.method_defined?(:context, false) # Skip if the Schema overrides the `#context` getter. | ||
|
||
root.create_path(constant) do |schema| | ||
schema.create_method("context", return_type: T.must(name_of(custom_context_class))) | ||
end | ||
end | ||
|
||
class << self | ||
extend T::Sig | ||
|
||
sig { override.returns(T::Enumerable[Module]) } | ||
def gather_constants | ||
all_classes.select { |c| c < GraphQL::Schema && c != GraphQL::Query::NullContext::NullSchema } | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
## GraphqlSchema | ||
|
||
`Tapioca::Dsl::Compilers::GraphqlSchema` generates RBI files for subclasses of | ||
[`GraphQL::Schema`](https://graphql-ruby.org/api-doc/2.1.7/GraphQL/Schema). | ||
|
||
For example, with the following `GraphQL::Schema` subclass: | ||
|
||
~~~rb | ||
class MySchema> < GraphQL::Schema | ||
class MyContext < GraphQL::Query::Context; end | ||
|
||
context_class MyContext | ||
|
||
# ... | ||
end | ||
~~~ | ||
|
||
this compiler will produce the RBI file `my_schema.rbi` with the following content: | ||
|
||
~~~rbi | ||
# my_schema.rbi | ||
# typed: true | ||
class MySchema | ||
sig { returns(MySchema::MyContext) } | ||
def context; end | ||
end | ||
~~~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# typed: strict | ||
# frozen_string_literal: true | ||
|
||
require "spec_helper" | ||
|
||
module Tapioca | ||
module Dsl | ||
module Compilers | ||
class GraphqlSchemaSpec < ::DslSpec | ||
describe "Tapioca::Dsl::Compilers::GraphqlSchema" do | ||
describe "initialize" do | ||
it "gathers no constants if there are no GraphQL::Schema subclasses" do | ||
assert_empty(gathered_constants) | ||
end | ||
|
||
it "gathers only GraphQL::Schema subclasses" do | ||
add_ruby_file("content.rb", <<~RUBY) | ||
class MySchema < GraphQL::Schema | ||
end | ||
class User | ||
end | ||
RUBY | ||
|
||
assert_equal(["MySchema"], gathered_constants) | ||
end | ||
|
||
it "gathers subclasses of GraphQL::Schema subclasses" do | ||
add_ruby_file("content.rb", <<~RUBY) | ||
class MyBaseSchema < GraphQL::Schema | ||
end | ||
class MySchema < MyBaseSchema | ||
end | ||
RUBY | ||
|
||
assert_equal(["MyBaseSchema", "MySchema"], gathered_constants) | ||
end | ||
end | ||
|
||
describe "decorate" do | ||
it "generates an empty RBI file if there is no custom context_class is set" do | ||
add_ruby_file("create_comment.rb", <<~RUBY) | ||
class MySchema < GraphQL::Schema | ||
end | ||
RUBY | ||
|
||
expected = <<~RBI | ||
# typed: strong | ||
RBI | ||
|
||
assert_equal(expected, rbi_for(:MySchema)) | ||
end | ||
|
||
it "generates correct RBI file for subclass that sets context_class" do | ||
add_ruby_file("create_comment.rb", <<~RUBY) | ||
class MySchema < GraphQL::Schema | ||
class MyContext < GraphQL::Query::Context; end | ||
context_class MyContext | ||
end | ||
RUBY | ||
|
||
expected = <<~RBI | ||
# typed: strong | ||
class MySchema | ||
sig { returns(MySchema::MyContext) } | ||
def context; end | ||
end | ||
RBI | ||
|
||
assert_equal(expected, rbi_for(:MySchema)) | ||
end | ||
|
||
it "generates an empty RBI file if there is an inline signature" do | ||
add_ruby_file("create_comment.rb", <<~RUBY) | ||
class MySchema < GraphQL::Schema | ||
extend T::Sig | ||
class MyContext < GraphQL::Query::Context; end | ||
context_class MyContext | ||
sig { returns(SomethingElse) } | ||
def context | ||
# ... | ||
end | ||
end | ||
RUBY | ||
|
||
expected = <<~RBI | ||
# typed: strong | ||
RBI | ||
|
||
assert_equal(expected, rbi_for(:MySchema)) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |