Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: feat: field and value def autocomplete #1758

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

stonexer
Copy link
Contributor

@stonexer stonexer commented Jan 10, 2021

New Functionality

This PR introduces "show all completion values" for an empty input for input types and object types. Before this, completion only appeared on the first typed character.

Once a user types fieldName: ▍ they should see all available values, including custom scalars defined in the schema, input types and inline defined input types

Testing

Check out either the graphiql 1 or monaco examples below, and try some basic SDL cases to explore the new functionality in the above features.

{ label: '__DirectiveLocation' },
{ label: '__TypeKind' },
{ label: 'Episode' },
{ label: 'InputType' },
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is probably an existing bug, as the InputType should probably not appear here

Copy link
Member

Choose a reason for hiding this comment

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

there's probably some simple logic we could add here for that if you want

image

to access the GraphQLObjectType in this case, I think you want state.prevState.type. you should be able to getFields() and then match the fieldname up to check the type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! But I don't seem to understand the role of field name here.

In my current thinking, since state.prevState.type(type Book) is a GraphQLObjectType, and InputType is a GraphQLInputObjectType, so it should not appear in the hintList.

Copy link
Member

Choose a reason for hiding this comment

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

my bad, misunderstood you before. i understand this bug better now. i’ll circle back after some sleep

@codecov
Copy link

codecov bot commented Jan 10, 2021

Codecov Report

Merging #1758 (0f33d7a) into main (2d91916) will increase coverage by 0.19%.
The diff coverage is 68.62%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1758      +/-   ##
==========================================
+ Coverage   65.70%   65.90%   +0.19%     
==========================================
  Files          85       86       +1     
  Lines        5106     5144      +38     
  Branches     1631     1640       +9     
==========================================
+ Hits         3355     3390      +35     
- Misses       1747     1750       +3     
  Partials        4        4              
Impacted Files Coverage Δ
...ackages/graphiql-toolkit/src/create-fetcher/lib.ts 50.90% <20.00%> (-8.67%) ⬇️
packages/graphiql/src/utility/HistoryStore.ts 62.26% <62.26%> (ø)
packages/graphiql/src/components/QueryHistory.tsx 73.91% <76.47%> (+6.69%) ⬆️
...iql/src/components/DocExplorer/MarkdownContent.tsx 100.00% <100.00%> (ø)
packages/graphiql/src/components/GraphiQL.tsx 58.34% <100.00%> (+0.83%) ⬆️
packages/graphiql/src/components/QueryEditor.tsx 63.96% <100.00%> (ø)
...ervice-interface/src/getAutocompleteSuggestions.ts 78.45% <100.00%> (+0.44%) ⬆️
...hql-language-service-server/src/findGraphQLTags.ts 64.89% <100.00%> (+4.25%) ⬆️
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 65c03d4...0f33d7a. Read the comment docs.

@@ -246,6 +248,16 @@ export function getAutocompleteSuggestions(
return getSuggestionsForVariableDefinition(token, schema, kind);
}

// Input value definition
if (kind === RuleKinds.INPUT_VALUE_DEF && step === 2) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not particularly sure what step means here, but I just found it to be representative of the current state. Hope to get some advice :)

Copy link
Member

@acao acao Jan 10, 2021

Choose a reason for hiding this comment

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

yep, that's it! it represents the step in the parser rule you're at. some parser Rules have only one step, others have two.

here's where the magic happens in parser:

this is probably the most straightforward implementation example. with ARGUMENT, step 1 is when we want argument name, and step 2 is when we want an input value.

so, if i wanted to implement autocompletion for field names for object types that extended interfaces, i would do that on OBJECT_TYPE step 1.

Copy link
Member

Choose a reason for hiding this comment

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

oh and i guess you found one that has three steps! :D

Copy link
Contributor

Choose a reason for hiding this comment

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

Just thinking aloud.. is it possible for the steps to have constants for referencing them? In order to give the steps meaning beyond just 2 for example? 🤔

Copy link
Member

Choose a reason for hiding this comment

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

good question! they have a different meaning in the context of each rule. we could have Step.First but that wouldn't be much more readable, or would it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Not really, it would pretty much be the same thing 😄 I'll think about it a bit more.

Copy link
Member

Choose a reason for hiding this comment

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

we could also specify enums for each rule that has multiple steps that are referenced, such as ObjectTypeSteps.Name = 1 and ObjectTypeSteps.Field = 2, and then FragmentDefintionSteps.Name = 1, etc

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe that would make sense, since the meaning of each step is defined by the GraphQL type being worked on. My only concern is that, since the values overlap, there might be an issue where they are mixed up. Typescript wouldn't complain since they are all numbers (except they are typed with the right enum type 🤔 ) but the behavior wouldn't be the expected behavior.

For example, InputObjectTypeSteps.Field might be equal to RuleKindStep.Name. Maybe my concern is a non-issue though. Perhaps if there is a way to type guard step to one of the enums, that would make step have just one meaning and remove ambiguity.

@stonexer stonexer changed the title [WIP] feat: field and value def autocomplete WIP: feat: field and value def autocomplete Jan 10, 2021
@acao
Copy link
Member

acao commented Jan 10, 2021

awesome work so far! really appreciate your help as always. works great for me with object type fields and input type fields.

would you like me to look into a way to make it so that the autocomplete can begin a space after the fieldName:, rather than immediately? we have the same issues where i improved this for argument. or while you're in there, feel free!

@stonexer
Copy link
Contributor Author

would you like me to look into a way to make it so that the autocomplete can begin a space after the fieldName:, rather than immediately?

Sure, that's what I want too.

I noticed that in the typescript file, when I type ...

interface Author {
  name: string;
}

interface Book {
  author:  ...
}

I don't get an active suggestion after I type : or : with a space. But then if I trigger ctrl+space manually, I can also have the full suggestion.

The difference is that when I type the first letter here, like A, there is an active suggestion directly.

I think it would be nice to have a similar logic here.

@acao
Copy link
Member

acao commented Jan 11, 2021

@stonexer that's so odd, because it works in graphiql and monaco-graphql:

image

when you say a typescript file, are you referring to vscode-graphql?

@stonexer
Copy link
Contributor Author

@acao Haha,it's not a bug here. Actually I mean the experience of using monaco to edit typescript files.

Copy link
Contributor

@imolorhe imolorhe left a comment

Choose a reason for hiding this comment

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

LGTM. Only concern I see would be the dropped test coverage. @acao is there a requirement for PRs not to reduce the test coverage?

@acao
Copy link
Member

acao commented Jan 14, 2021

@imolorhe that is definitely something to consider! I disabled that once because a PR dropped coverage because of a refactor (I deleted so much redundant code with good coverage that it caused overall coverage to go down). I evaluate it on a case-by-case basis as a maintainer, but for this PR I think we should have additive coverage, though we're adding three cases.

I don't think this PR is ready myself because of the issue with spaces @stonexer and I discussed in discord, unfortunately we didn't surface that discussion here so let me summarize:

desired behavior for this PR:

autocompletion for variables should be triggered on : , non-breaking space included. ideally, the mode/ide implementation should be configured to advance the cursor the extra space automatically.

current behavior in this PR:
autocomplete behavior is triggered immediately following a : character, however we want there to be an additional space. if the user adds a space after the : character, then the completion options vanish. this is essentially the opposite behaviour.

@imolorhe
Copy link
Contributor

Okay got it. Will un-approve and wait for that fix then 😄

@stonexer
Copy link
Contributor Author

autocompletion for variables should be triggered on : , non-breaking space included. ideally, the mode/ide implementation should be configured to advance the cursor the extra space automatically.

In https://github.com/graphql/graphiql/blob/main/packages/monaco-graphql/src/languageFeatures.ts#L196

Are there other situations where we need ':' to trigger? Can we simply remove the ':' from them

@acao
Copy link
Member

acao commented Jan 15, 2021

good question! we can experiment with that

@stonexer
Copy link
Contributor Author

good question! we can experiment with that

Tried it, I think it's not bad

@acao
Copy link
Member

acao commented Jan 17, 2021

this adjustment looks better for monaco editor, but it still doesn't fix the issue on the codemirror side. i wonder why? gonna keep looking into this!

@acao
Copy link
Member

acao commented Feb 10, 2021

so sad i didn't merge this sooner! this is incredible

@acao
Copy link
Member

acao commented Feb 10, 2021

@stonexer this is sooo close - maybe we can configure codemirror-graphql to handle the insertText param ourselves, since that's at this point only monaco specific?

@acao
Copy link
Member

acao commented Apr 18, 2021

image

i would like to have this case covered, as I think it's one of the most important ones for the LSP. Many tools implement their own autocompletion hack on top of this to achieve it here

@acao
Copy link
Member

acao commented Apr 18, 2021

@dwwoelfel this is another good place for the tokenizer

@changeset-bot
Copy link

changeset-bot bot commented Sep 3, 2021

⚠️ No Changeset found

Latest commit: 0f33d7a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Sep 3, 2021

CLA Signed

The committers are authorized under a signed CLA.

@stonexer stonexer force-pushed the feat/field-type-autocomplete branch from fef0417 to dc65988 Compare September 4, 2021 04:13
@stonexer
Copy link
Contributor Author

stonexer commented Sep 4, 2021

@acao I'm back haha :), sorry for disappearing for a long time before for personal reasons. I added \s in AUTO_COMPLETE_AFTER_KEY, and suggestions are auto triggered on typing space. Could you help to have a review again?

image

@acao
Copy link
Member

acao commented Sep 10, 2021

@stonexer so glad you are back! any help you can provide is always appreciated, no worries! definitely can review again soon, yes!

@stonexer
Copy link
Contributor Author

stonexer commented Oct 26, 2021

Currently, the graphql schema in the context is derived from the parameters and does not contain the current input of the editor, so it looks like such a completion on types' field is not possible. A larger modification to onlineParser may be needed.

Referrence #888 (comment), I did some experimentations on graphql schema(sdl) editor. I made a dumb parser with chevrotain(a powerful tool), and just implemented a little bit of language service (adding support for type name and inputType name completion). Here's the demo and the source code.

image

Maybe someday we can implement this in a better way. 😃

@acao
Copy link
Member

acao commented Oct 26, 2021

I will check this out locally and see how it’s working! This is such a valuable feature

@acao
Copy link
Member

acao commented Oct 29, 2021

@stonexer note to test with the monaco graphql mode, just run yarn start-monaco at the monorepo root :)

@acao
Copy link
Member

acao commented Apr 7, 2022

@stonexer I'd love to revive this effort soon! it's so close!

@acao
Copy link
Member

acao commented Apr 7, 2022

@stonexer I've been looking at chevrotain's grammar for graphql since last year, and it's enticing. Incredibly fault tolerant.

I think it's worth looking at replacing the language parser with this entirely moving forward. It would mean re-writing autocomplete and hover entirely, but it would be worth it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants