Skip to content

Commit 3ec554d

Browse files
committed
Add a setting for the repeatable directives introspection
1 parent 5dbffeb commit 3ec554d

File tree

12 files changed

+1242
-84
lines changed

12 files changed

+1242
-84
lines changed

resources/messages/GraphQLMessages.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ graphql.settings.introspection.query.label=Introspection Query (leave blank for
8282
graphql.settings.introspection.query.tooltip=Use a different introspection query for cases where the GraphQL endpoint is incompatible with the plugin introspection query
8383
graphql.settings.introspection.default.values.label=Include argument default values in schema introspection
8484
graphql.settings.introspection.default.values.tooltip=Skipping default values improves interoperability with endpoints that don't follow the GraphQL specification for default values. The schema can still be used, but information about the default values will be unavailable
85+
graphql.settings.introspection.repeatable.directives.label=Request the "repeatable" property for directives
86+
graphql.settings.introspection.repeatable.directives.tooltip=Repeatable directives are a relatively new feature and may not be supported by some GraphQL implementations
8587
graphql.settings.introspection.open.editor.label=Open the editor with the introspection result
8688

8789
# Libraries

src/main/com/intellij/lang/jsgraphql/GraphQLSettings.java

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,34 +45,26 @@ public GraphQLSettings.GraphQLSettingsState getState() {
4545
@Override
4646
public void loadState(@NotNull GraphQLSettings.GraphQLSettingsState state) {
4747
myState = state;
48-
incrementModificationCount();
48+
settingsChanged();
4949
}
5050

51-
public String getIntrospectionQuery() {
52-
return myState.introspectionQuery;
53-
}
54-
55-
public void setIntrospectionQuery(String introspectionQuery) {
56-
myState.introspectionQuery = introspectionQuery;
57-
incrementModificationCount();
51+
public ModificationTracker getModificationTracker() {
52+
return myModificationTracker;
5853
}
5954

60-
public boolean isRelaySupportEnabled() {
61-
return myState.enableRelayModernFrameworkSupport;
55+
private void settingsChanged() {
56+
myModificationTracker.incModificationCount();
6257
}
6358

64-
public void setRelaySupportEnabled(boolean enableRelayModernFrameworkSupport) {
65-
myState.enableRelayModernFrameworkSupport = enableRelayModernFrameworkSupport;
66-
incrementModificationCount();
67-
}
59+
/* Introspection */
6860

69-
public boolean isFederationSupportEnabled() {
70-
return myState.enableFederationSupport;
61+
public String getIntrospectionQuery() {
62+
return myState.introspectionQuery;
7163
}
7264

73-
public void setFederationSupportEnabled(boolean enableFederationSupport) {
74-
myState.enableFederationSupport = enableFederationSupport;
75-
incrementModificationCount();
65+
public void setIntrospectionQuery(String introspectionQuery) {
66+
myState.introspectionQuery = introspectionQuery;
67+
settingsChanged();
7668
}
7769

7870
public boolean isEnableIntrospectionDefaultValues() {
@@ -81,7 +73,16 @@ public boolean isEnableIntrospectionDefaultValues() {
8173

8274
public void setEnableIntrospectionDefaultValues(boolean enableIntrospectionDefaultValues) {
8375
myState.enableIntrospectionDefaultValues = enableIntrospectionDefaultValues;
84-
incrementModificationCount();
76+
settingsChanged();
77+
}
78+
79+
public boolean isEnableIntrospectionRepeatableDirectives() {
80+
return myState.enableIntrospectionRepeatableDirectives;
81+
}
82+
83+
public void setEnableIntrospectionRepeatableDirectives(boolean enableIntrospectionRepeatableDirectives) {
84+
myState.enableIntrospectionRepeatableDirectives = enableIntrospectionRepeatableDirectives;
85+
settingsChanged();
8586
}
8687

8788
public boolean isOpenEditorWithIntrospectionResult() {
@@ -90,15 +91,27 @@ public boolean isOpenEditorWithIntrospectionResult() {
9091

9192
public void setOpenEditorWithIntrospectionResult(boolean openEditorWithIntrospectionResult) {
9293
myState.openEditorWithIntrospectionResult = openEditorWithIntrospectionResult;
93-
incrementModificationCount();
94+
settingsChanged();
9495
}
9596

96-
public ModificationTracker getModificationTracker() {
97-
return myModificationTracker;
97+
/* Frameworks */
98+
99+
public boolean isRelaySupportEnabled() {
100+
return myState.enableRelayModernFrameworkSupport;
98101
}
99102

100-
private void incrementModificationCount() {
101-
myModificationTracker.incModificationCount();
103+
public void setRelaySupportEnabled(boolean enableRelayModernFrameworkSupport) {
104+
myState.enableRelayModernFrameworkSupport = enableRelayModernFrameworkSupport;
105+
settingsChanged();
106+
}
107+
108+
public boolean isFederationSupportEnabled() {
109+
return myState.enableFederationSupport;
110+
}
111+
112+
public void setFederationSupportEnabled(boolean enableFederationSupport) {
113+
myState.enableFederationSupport = enableFederationSupport;
114+
settingsChanged();
102115
}
103116

104117
/**
@@ -108,7 +121,9 @@ private void incrementModificationCount() {
108121
public static class GraphQLSettingsState {
109122
public String introspectionQuery = "";
110123
public boolean enableIntrospectionDefaultValues = true;
124+
public boolean enableIntrospectionRepeatableDirectives = false;
111125
public boolean openEditorWithIntrospectionResult = true;
126+
112127
public boolean enableRelayModernFrameworkSupport;
113128
public boolean enableFederationSupport = false;
114129
}

src/main/com/intellij/lang/jsgraphql/types/introspection/IntrospectionQuery.java renamed to src/main/com/intellij/lang/jsgraphql/ide/introspection/GraphQLIntrospectionQuery.java

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,6 @@
1-
/*
2-
The MIT License (MIT)
1+
package com.intellij.lang.jsgraphql.ide.introspection;
32

4-
Copyright (c) 2015 Andreas Marek and Contributors
5-
6-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
7-
(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
8-
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
9-
so, subject to the following conditions:
10-
11-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12-
13-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
14-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
15-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17-
*/
18-
package com.intellij.lang.jsgraphql.types.introspection;
19-
20-
import com.intellij.lang.jsgraphql.types.PublicApi;
21-
22-
@PublicApi
23-
public interface IntrospectionQuery {
3+
public interface GraphQLIntrospectionQuery {
244

255
String INTROSPECTION_QUERY = "\n" +
266
" query IntrospectionQuery {\n" +
@@ -38,8 +18,7 @@ public interface IntrospectionQuery {
3818
" args {\n" +
3919
" ...InputValue\n" +
4020
" }\n" +
41-
// TODO: [intellij] support repeatable directive in introspection query
42-
// " isRepeatable\n" +
21+
" isRepeatable\n" +
4322
" }\n" +
4423
" }\n" +
4524
" }\n" +

src/main/com/intellij/lang/jsgraphql/ide/introspection/GraphQLIntrospectionResultToSchema.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,15 @@ private DirectiveDefinition createDirectiveDefinition(@NotNull Map<String, Objec
336336
.description(getDescription(definition))
337337
.directiveLocations(createDirectiveLocations((List<String>) definition.get("locations")))
338338
.inputValueDefinitions(inputValueDefinitions)
339-
// .repeatable() TODO: [vepanimas] repeatable
339+
.repeatable(isRepeatable(definition))
340340
.build();
341341
}
342342

343+
private boolean isRepeatable(@NotNull Map<String, Object> definition) {
344+
Object isRepeatable = definition.get("isRepeatable");
345+
return isRepeatable instanceof Boolean && (boolean) isRepeatable;
346+
}
347+
343348
@NotNull
344349
private static List<DirectiveLocation> createDirectiveLocations(@NotNull List<String> locations) {
345350
return ContainerUtil.mapNotNull(

src/main/com/intellij/lang/jsgraphql/ide/introspection/GraphQLIntrospectionService.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.intellij.lang.jsgraphql.schema.GraphQLSchemaInfo;
2424
import com.intellij.lang.jsgraphql.schema.GraphQLSchemaKeys;
2525
import com.intellij.lang.jsgraphql.types.GraphQLError;
26-
import com.intellij.lang.jsgraphql.types.introspection.IntrospectionQuery;
2726
import com.intellij.lang.jsgraphql.types.language.Document;
2827
import com.intellij.lang.jsgraphql.types.schema.idl.SchemaParser;
2928
import com.intellij.lang.jsgraphql.types.schema.idl.SchemaPrinter;
@@ -148,13 +147,7 @@ public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification noti
148147

149148
try {
150149
final GraphQLSettings graphQLSettings = GraphQLSettings.getSettings(myProject);
151-
String query = graphQLSettings.getIntrospectionQuery();
152-
if (StringUtils.isBlank(query)) {
153-
query = IntrospectionQuery.INTROSPECTION_QUERY;
154-
}
155-
if (!graphQLSettings.isEnableIntrospectionDefaultValues()) {
156-
query = query.replace("defaultValue", "");
157-
}
150+
String query = buildIntrospectionQuery(graphQLSettings);
158151

159152
final String requestJson = "{\"query\":\"" + StringEscapeUtils.escapeJavaScript(query) + "\"}";
160153
HttpPost request = createRequest(endpoint, url, requestJson);
@@ -165,6 +158,23 @@ public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification noti
165158
}
166159
}
167160

161+
@NotNull
162+
private String buildIntrospectionQuery(@NotNull GraphQLSettings settings) {
163+
String query = settings.getIntrospectionQuery();
164+
if (!StringUtil.isEmptyOrSpaces(query)) {
165+
return query;
166+
}
167+
168+
query = GraphQLIntrospectionQuery.INTROSPECTION_QUERY;
169+
if (!settings.isEnableIntrospectionRepeatableDirectives()) {
170+
query = query.replace("isRepeatable", "");
171+
}
172+
if (!settings.isEnableIntrospectionDefaultValues()) {
173+
query = query.replace("defaultValue", "");
174+
}
175+
return query;
176+
}
177+
168178
@NotNull
169179
public static HttpPost createRequest(@NotNull GraphQLConfigVariableAwareEndpoint endpoint,
170180
@NotNull String url,

src/main/com/intellij/lang/jsgraphql/types/schema/diff/DiffSet.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,7 @@ The MIT License (MIT)
2121

2222
import java.util.Map;
2323

24-
/**
25-
* Represents 2 schemas that can be diffed. The {@link SchemaDiff} code
26-
* assumes that that schemas to be diffed are the result of a
27-
* {@link com.intellij.lang.jsgraphql.types.introspection.IntrospectionQuery}.
28-
*/
24+
2925
@PublicApi
3026
public class DiffSet {
3127

src/main/com/intellij/lang/jsgraphql/ui/GraphQLProjectConfigurable.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import com.intellij.lang.jsgraphql.GraphQLSettings;
1313
import com.intellij.lang.jsgraphql.schema.library.GraphQLLibraryManager;
1414
import com.intellij.openapi.application.ApplicationManager;
15-
import com.intellij.openapi.application.WriteAction;
1615
import com.intellij.openapi.options.ConfigurationException;
1716
import com.intellij.openapi.options.SearchableConfigurable;
1817
import com.intellij.openapi.project.Project;
@@ -58,19 +57,19 @@ public JComponent createComponent() {
5857
public void apply() throws ConfigurationException {
5958
if (myProject.isDefault()) {
6059
myForm.apply();
61-
} else {
62-
boolean fireLibrariesChanged = myForm.shouldUpdateLibraries();
60+
return;
61+
}
6362

64-
WriteAction.run(() -> myForm.apply());
63+
boolean fireLibrariesChanged = myForm.librarySettingsChanged();
6564

66-
if (fireLibrariesChanged) {
67-
GraphQLLibraryManager.getInstance(myProject).notifyLibrariesChanged();
68-
} else {
69-
ApplicationManager.getApplication().invokeLater(() -> {
70-
DaemonCodeAnalyzer.getInstance(myProject).restart();
71-
EditorNotifications.getInstance(myProject).updateAllNotifications();
72-
}, myProject.getDisposed());
73-
}
65+
myForm.apply();
66+
if (fireLibrariesChanged) {
67+
GraphQLLibraryManager.getInstance(myProject).notifyLibrariesChanged();
68+
} else {
69+
ApplicationManager.getApplication().invokeLater(() -> {
70+
DaemonCodeAnalyzer.getInstance(myProject).restart();
71+
EditorNotifications.getInstance(myProject).updateAllNotifications();
72+
}, myProject.getDisposed());
7473
}
7574
}
7675

src/main/com/intellij/lang/jsgraphql/ui/GraphQLProjectSettingsForm.form

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
1414
</constraints>
1515
</vspacer>
16-
<grid id="5f9ac" binding="introspectionPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
16+
<grid id="5f9ac" binding="introspectionPanel" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
1717
<margin top="0" left="0" bottom="0" right="0"/>
1818
<constraints>
1919
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -51,12 +51,21 @@
5151
</component>
5252
<component id="880f9" class="javax.swing.JCheckBox" binding="openEditorWithIntrospectionResult">
5353
<constraints>
54-
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
54+
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
5555
</constraints>
5656
<properties>
5757
<text resource-bundle="messages/GraphQLMessages" key="graphql.settings.introspection.open.editor.label"/>
5858
</properties>
5959
</component>
60+
<component id="f9e30" class="javax.swing.JCheckBox" binding="enableIntrospectionRepeatableDirectives">
61+
<constraints>
62+
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
63+
</constraints>
64+
<properties>
65+
<text resource-bundle="messages/GraphQLMessages" key="graphql.settings.introspection.repeatable.directives.label"/>
66+
<toolTipText resource-bundle="messages/GraphQLMessages" key="graphql.settings.introspection.repeatable.directives.tooltip"/>
67+
</properties>
68+
</component>
6069
</children>
6170
</grid>
6271
<grid id="ed16d" binding="frameworksPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">

src/main/com/intellij/lang/jsgraphql/ui/GraphQLProjectSettingsForm.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class GraphQLProjectSettingsForm {
3232
private JCheckBox enableRelay;
3333
private JCheckBox enableFederation;
3434
private JCheckBox openEditorWithIntrospectionResult;
35+
private JCheckBox enableIntrospectionRepeatableDirectives;
3536

3637
private GraphQLSettings mySettings;
3738

@@ -53,29 +54,36 @@ JPanel getComponent() {
5354

5455
void apply() {
5556
mySettings.setIntrospectionQuery(introspectionQueryTextField.getText());
56-
mySettings.setRelaySupportEnabled(enableRelay.isSelected());
57-
mySettings.setFederationSupportEnabled(enableFederation.isSelected());
5857
mySettings.setEnableIntrospectionDefaultValues(enableIntrospectionDefaultValues.isSelected());
58+
mySettings.setEnableIntrospectionRepeatableDirectives(enableIntrospectionRepeatableDirectives.isSelected());
5959
mySettings.setOpenEditorWithIntrospectionResult(openEditorWithIntrospectionResult.isSelected());
60+
61+
mySettings.setRelaySupportEnabled(enableRelay.isSelected());
62+
mySettings.setFederationSupportEnabled(enableFederation.isSelected());
6063
}
6164

6265
void reset() {
6366
introspectionQueryTextField.setText(mySettings.getIntrospectionQuery());
6467
enableIntrospectionDefaultValues.setSelected(mySettings.isEnableIntrospectionDefaultValues());
68+
enableIntrospectionRepeatableDirectives.setSelected(mySettings.isEnableIntrospectionRepeatableDirectives());
69+
openEditorWithIntrospectionResult.setSelected(mySettings.isOpenEditorWithIntrospectionResult());
70+
6571
enableRelay.setSelected(mySettings.isRelaySupportEnabled());
6672
enableFederation.setSelected(mySettings.isFederationSupportEnabled());
67-
openEditorWithIntrospectionResult.setSelected(mySettings.isOpenEditorWithIntrospectionResult());
6873
}
6974

7075
boolean isModified() {
76+
return introspectionSettingsChanged() || librarySettingsChanged();
77+
}
78+
79+
boolean introspectionSettingsChanged() {
7180
return !Objects.equals(mySettings.getIntrospectionQuery(), introspectionQueryTextField.getText()) ||
7281
mySettings.isEnableIntrospectionDefaultValues() != enableIntrospectionDefaultValues.isSelected() ||
73-
mySettings.isOpenEditorWithIntrospectionResult() != openEditorWithIntrospectionResult.isSelected() ||
74-
shouldUpdateLibraries();
75-
82+
mySettings.isEnableIntrospectionRepeatableDirectives() != enableIntrospectionRepeatableDirectives.isSelected() ||
83+
mySettings.isOpenEditorWithIntrospectionResult() != openEditorWithIntrospectionResult.isSelected();
7684
}
7785

78-
boolean shouldUpdateLibraries() {
86+
boolean librarySettingsChanged() {
7987
return mySettings.isRelaySupportEnabled() != enableRelay.isSelected() ||
8088
mySettings.isFederationSupportEnabled() != enableFederation.isSelected();
8189
}

src/test/com/intellij/lang/jsgraphql/ide/editor/GraphQLIntrospectionServiceTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ public void testPrintIntrospectionWithNullFields() {
4040
doTest("schemaWithNullFields.json", "schemaWithNullFields.graphql");
4141
}
4242

43+
public void testPrintIntrospectionRepeatableDirectives() {
44+
doTest("schemaWithRepeatableDirectives.json", "schemaWithRepeatableDirectives.graphql");
45+
}
46+
4347
public void testGithubSchema() {
4448
// test only for being successful, file comparison doesn't give a meaningful result for files of this size
4549
assertNoThrowable(() -> new GraphQLIntrospectionService(getProject())

0 commit comments

Comments
 (0)