4646import org .jetbrains .annotations .Nullable ;
4747
4848import java .util .Collection ;
49+ import java .util .EnumSet ;
4950import java .util .List ;
5051import java .util .Optional ;
5152import java .util .Set ;
@@ -496,10 +497,45 @@ protected void addCompletions(@NotNull final CompletionParameters parameters, Pr
496497 protected void addCompletions (@ NotNull final CompletionParameters parameters , ProcessingContext context , @ NotNull CompletionResultSet result ) {
497498
498499 final PsiElement completionElement = Optional .ofNullable (parameters .getOriginalPosition ()).orElse (parameters .getPosition ());
500+ final TypeDefinitionRegistry registry = GraphQLTypeDefinitionRegistryServiceImpl .getService (completionElement .getProject ()).getRegistry (completionElement );
501+
502+ final Set <String > addedDirectiveNames = Sets .newHashSet ();
503+
504+ // directives declared - available even when schema validation errors are present, as in when typing/completing a directive name
505+ for (DirectiveDefinition directiveDefinition : registry .getDirectiveDefinitions ().values ()) {
506+ final EnumSet <Introspection .DirectiveLocation > validLocations = EnumSet .noneOf (Introspection .DirectiveLocation .class );
507+ for (DirectiveLocation directiveLocation : directiveDefinition .getDirectiveLocations ()) {
508+ try {
509+ validLocations .add (Introspection .DirectiveLocation .valueOf (directiveLocation .getName ()));
510+ } catch (IllegalArgumentException ignored ) {
511+ }
512+ }
513+ if (!isValidDirectiveLocation (validLocations , parameters .getPosition ())) {
514+ continue ;
515+ }
516+ LookupElementBuilder element = LookupElementBuilder .create (directiveDefinition .getName ());
517+ for (InputValueDefinition directiveArgument : directiveDefinition .getInputValueDefinitions ()) {
518+ if (directiveArgument .getType () instanceof GraphQLNonNull ) {
519+ // found a required argument so insert the '()' for arguments
520+ element = element .withInsertHandler ((ctx , item ) -> {
521+ ParenthesesInsertHandler .WITH_PARAMETERS .handleInsert (ctx , item );
522+ AutoPopupController .getInstance (ctx .getProject ()).autoPopupMemberLookup (ctx .getEditor (), null );
523+ });
524+ break ;
525+ }
526+ }
527+ addedDirectiveNames .add (directiveDefinition .getName ());
528+ result .addElement (element );
529+ }
530+
531+ // directive including the built-in ones from a valid and working schema
499532 final GraphQLSchema schema = GraphQLTypeDefinitionRegistryServiceImpl .getService (completionElement .getProject ()).getSchema (completionElement );
500533 if (schema != null ) {
501534 for (graphql .schema .GraphQLDirective graphQLDirective : schema .getDirectives ()) {
502- if (!isValidDirectiveLocation (graphQLDirective , parameters .getPosition ())) {
535+ if (!addedDirectiveNames .add (graphQLDirective .getName ())) {
536+ continue ;
537+ }
538+ if (!isValidDirectiveLocation (graphQLDirective .validLocations (), parameters .getPosition ())) {
503539 continue ;
504540 }
505541 LookupElementBuilder element = LookupElementBuilder .create (graphQLDirective .getName ());
@@ -515,7 +551,6 @@ protected void addCompletions(@NotNull final CompletionParameters parameters, Pr
515551 }
516552 result .addElement (element );
517553 }
518- // TODO: Also support SDL directives, e.g. auth annotations etc. for the endpoint implementation
519554 }
520555
521556 }
@@ -863,12 +898,12 @@ public boolean invokeAutoPopup(@NotNull PsiElement position, char typeChar) {
863898 return super .invokeAutoPopup (position , typeChar );
864899 }
865900
866- private boolean isValidDirectiveLocation (graphql . schema . GraphQLDirective graphQLDirective , PsiElement completionPosition ) {
901+ private boolean isValidDirectiveLocation (EnumSet < Introspection . DirectiveLocation > validLocations , PsiElement completionPosition ) {
867902 final GraphQLDirectivesAware directivesAware = PsiTreeUtil .getParentOfType (completionPosition , GraphQLDirectivesAware .class );
868903 if (directivesAware == null ) {
869904 return false ;
870905 }
871- for (Introspection .DirectiveLocation directiveLocation : graphQLDirective . validLocations () ) {
906+ for (Introspection .DirectiveLocation directiveLocation : validLocations ) {
872907 switch (directiveLocation ) {
873908 // Executable locations
874909 case QUERY :
0 commit comments