1414import com .intellij .json .psi .JsonArray ;
1515import com .intellij .json .psi .JsonObject ;
1616import com .intellij .json .psi .JsonProperty ;
17+ import com .intellij .lang .jsgraphql .GraphQLBundle ;
1718import com .intellij .lang .jsgraphql .GraphQLSettings ;
19+ import com .intellij .lang .jsgraphql .ide .notifications .GraphQLNotificationUtil ;
1820import com .intellij .notification .Notification ;
19- import com .intellij .notification .NotificationAction ;
2021import com .intellij .notification .NotificationType ;
2122import com .intellij .notification .Notifications ;
22- import com .intellij .openapi .actionSystem .AnActionEvent ;
23- import com .intellij .openapi .application .ApplicationManager ;
2423import com .intellij .openapi .editor .markup .GutterIconRenderer ;
2524import com .intellij .openapi .project .Project ;
2625import com .intellij .openapi .util .Ref ;
2726import com .intellij .openapi .vfs .VirtualFile ;
2827import com .intellij .psi .PsiElement ;
2928import com .intellij .psi .util .PsiTreeUtil ;
30- import graphql .GraphQLException ;
3129import org .jetbrains .annotations .NotNull ;
3230import org .jetbrains .annotations .Nullable ;
3331
@@ -43,58 +41,59 @@ public LineMarkerInfo<?> getLineMarkerInfo(@NotNull PsiElement element) {
4341 // skip in-memory JSON files such as the query result viewer
4442 return null ;
4543 }
46- if (element instanceof JsonProperty ) {
47- final Project project = element .getProject ();
48- final JsonProperty parentProperty = PsiTreeUtil .getParentOfType (element , JsonProperty .class );
49- if (parentProperty == null || "data" .equals (parentProperty .getName ())) {
50- // top level property or inside data property
51- final JsonProperty jsonProperty = (JsonProperty ) element ;
52- final String propertyName = jsonProperty .getName ();
53- if ("__schema" .equals (propertyName ) && jsonProperty .getValue () instanceof JsonObject ) {
54- for (JsonProperty property : ((JsonObject ) jsonProperty .getValue ()).getPropertyList ()) {
55- if ("types" .equals (property .getName ()) && property .getValue () instanceof JsonArray ) {
56- // likely a GraphQL schema with a { __schema: { types: [] } }
57- final GraphQLIntrospectionService graphQLIntrospectionService = GraphQLIntrospectionService .getInstance (project );
58- final Ref <Runnable > generateAction = Ref .create ();
59- generateAction .set (() -> {
60- try {
61- final String introspectionJson = element .getContainingFile ().getText ();
62- final String schemaAsSDL = graphQLIntrospectionService .printIntrospectionJsonAsGraphQL (introspectionJson );
44+ if (!(element instanceof JsonProperty )) {
45+ return null ;
46+ }
47+ final Project project = element .getProject ();
48+ final JsonProperty parentProperty = PsiTreeUtil .getParentOfType (element , JsonProperty .class );
49+ if (parentProperty != null && !"data" .equals (parentProperty .getName ())) {
50+ return null ;
51+ }
6352
64- final VirtualFile jsonFile = element .getContainingFile ().getVirtualFile ();
65- final String outputFileName = jsonFile .getName () + ".graphql" ;
53+ // top level property or inside data property
54+ final JsonProperty jsonProperty = (JsonProperty ) element ;
55+ final String propertyName = jsonProperty .getName ();
56+ if (!"__schema" .equals (propertyName ) || !(jsonProperty .getValue () instanceof JsonObject )) {
57+ return null ;
58+ }
59+
60+ for (JsonProperty property : ((JsonObject ) jsonProperty .getValue ()).getPropertyList ()) {
61+ if ("types" .equals (property .getName ()) && property .getValue () instanceof JsonArray ) {
62+ // likely a GraphQL schema with a { __schema: { types: [] } }
63+ final GraphQLIntrospectionService graphQLIntrospectionService = GraphQLIntrospectionService .getInstance (project );
64+ final Ref <Runnable > generateAction = Ref .create ();
65+ generateAction .set (() -> {
66+ try {
67+ final String introspectionJson = element .getContainingFile ().getText ();
68+ final String schemaAsSDL = graphQLIntrospectionService .printIntrospectionJsonAsGraphQL (introspectionJson );
6669
67- graphQLIntrospectionService .createOrUpdateIntrospectionOutputFile (schemaAsSDL , GraphQLIntrospectionService .IntrospectionOutputFormat .SDL , jsonFile , outputFileName );
70+ final VirtualFile jsonFile = element .getContainingFile ().getVirtualFile ();
71+ final String outputFileName = jsonFile .getName () + ".graphql" ;
6872
69- } catch (Exception e ) {
70- Notification notification = new Notification ("GraphQL" , "Unable to create GraphQL SDL" , e .getMessage (), NotificationType .ERROR );
71- if (e instanceof GraphQLException ) {
72- final String content = "A valid schema could not be built using the introspection result. The endpoint may not follow the GraphQL Specification. The error was:\n \" " + e .getMessage () + "\" ." ;
73- notification .setContent (content );
74- if (GraphQLSettings .getSettings (project ).isEnableIntrospectionDefaultValues ()) {
75- // suggest retrying without the default values as they're a common cause of spec compliance issues
76- final NotificationAction retryWithoutDefaultValues = new NotificationAction ("Retry (skip default values from now on)" ) {
77- @ Override
78- public void actionPerformed (@ NotNull AnActionEvent e , @ NotNull Notification notification ) {
79- GraphQLSettings .getSettings (project ).setEnableIntrospectionDefaultValues (false );
80- ApplicationManager .getApplication ().saveSettings ();
81- notification .expire ();
82- generateAction .get ().run ();
83- }
84- };
85- notification .addAction (retryWithoutDefaultValues );
86- }
87- }
88- graphQLIntrospectionService .addIntrospectionStackTraceAction (notification , e );
89- Notifications .Bus .notify (notification .setImportant (true ));
90- }
91- });
92- return new LineMarkerInfo <>(jsonProperty , jsonProperty .getTextRange (), AllIcons .RunConfigurations .TestState .Run , Pass .UPDATE_ALL , o -> "Generate GraphQL SDL schema file" , (evt , elt ) -> {
93- generateAction .get ().run ();
94- }, GutterIconRenderer .Alignment .CENTER );
95- }
73+ graphQLIntrospectionService .createOrUpdateIntrospectionOutputFile (schemaAsSDL , GraphQLIntrospectionService .IntrospectionOutputFormat .SDL , jsonFile , outputFileName );
74+ } catch (Exception e ) {
75+ Notification notification = new Notification (
76+ GraphQLNotificationUtil .NOTIFICATION_GROUP_ID ,
77+ GraphQLBundle .message ("graphql.notification.introspection.error.title" ),
78+ GraphQLNotificationUtil .formatExceptionMessage (e ),
79+ NotificationType .ERROR
80+ );
81+
82+ GraphQLNotificationUtil .addRetryFailedSchemaIntrospectionAction (notification , GraphQLSettings .getSettings (project ), e , generateAction .get ());
83+ graphQLIntrospectionService .addIntrospectionStackTraceAction (notification , e );
84+ Notifications .Bus .notify (notification .setImportant (true ));
9685 }
97- }
86+ });
87+
88+ return new LineMarkerInfo <>(
89+ jsonProperty ,
90+ jsonProperty .getTextRange (),
91+ AllIcons .RunConfigurations .TestState .Run ,
92+ Pass .UPDATE_ALL ,
93+ o -> GraphQLBundle .message ("graphql.line.marker.generate.schema.file" ),
94+ (evt , elt ) -> generateAction .get ().run (),
95+ GutterIconRenderer .Alignment .CENTER
96+ );
9897 }
9998 }
10099 return null ;
0 commit comments