Skip to content

Commit 137a68d

Browse files
committed
Rework GraphQL type definitions provider
* Link external definitions as synthetic libraries visible in the project tool window * Generate directive definitions based on introspection result * Removed Scope.hashCode internal API violation * Prefer plugin PSI-based introspection types to graphql-java builtins
1 parent 0e6b8cd commit 137a68d

File tree

61 files changed

+124325
-534
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+124325
-534
lines changed

Diff for: .idea/codeStyles/Project.xml

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: resources/META-INF/plugin.xml

+3-4
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,14 @@
8484
<projectService
8585
serviceImplementation="com.intellij.lang.jsgraphql.ide.highlighting.query.GraphQLQueryContextCaretListener"/>
8686
<projectService serviceImplementation="com.intellij.lang.jsgraphql.GraphQLPluginDisposable"/>
87-
<projectService serviceImplementation="com.intellij.lang.jsgraphql.schema.GraphQLExternalTypeDefinitionsProvider"/>
87+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.schema.library.GraphQLLibraryManager"/>
8888

8989
<!-- Indexing -->
9090
<fileBasedIndex implementation="com.intellij.lang.jsgraphql.ide.project.indexing.GraphQLIdentifierIndex"/>
9191
<fileBasedIndex implementation="com.intellij.lang.jsgraphql.ide.project.indexing.GraphQLFragmentNameIndex"/>
9292

93+
<additionalLibraryRootsProvider implementation="com.intellij.lang.jsgraphql.schema.library.GraphQLLibraryRootsProvider"/>
94+
9395
<!-- Startup -->
9496
<postStartupActivity implementation="com.intellij.lang.jsgraphql.ide.startup.GraphQLStartupActivity"/>
9597
<postStartupActivity
@@ -141,9 +143,6 @@
141143
<!-- Search (find implementations etc.) -->
142144
<definitionsSearch implementation="com.intellij.lang.jsgraphql.ide.search.GraphQLDefinitionsSearchExecutor"/>
143145

144-
<!-- Renaming -->
145-
<vetoRenameCondition implementation="com.intellij.lang.jsgraphql.ide.rename.GraphQLRenameVetoCondition"/>
146-
147146
<!-- Settings -->
148147
<projectConfigurable id="settings.jsgraphql" groupId="language" instance="com.intellij.lang.jsgraphql.ui.GraphQLProjectConfigurable"/>
149148

Diff for: resources/META-INF/federation specification schema.graphql renamed to resources/definitions/Federation.graphql

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ scalar _Any
33
scalar _FieldSet
44

55
# a union of all types that use the @key directive
6-
# noinspection GraphQLEmptyType
76
union _Entity
87

98
type _Service {

Diff for: resources/messages/GraphQLMessages.properties

+6
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,9 @@ graphql.settings.introspection.query.tooltip=Use a different introspection query
8484
graphql.settings.introspection.default.values.label=Include argument default values in schema introspection
8585
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
8686
graphql.settings.introspection.open.editor.label=Open the editor with the introspection result
87+
88+
# Libraries
89+
graphql.library.prefix=GraphQL:
90+
graphql.library.built.in=Specification
91+
graphql.library.relay=Relay
92+
graphql.library.federation=Federation

Diff for: src/main/com/intellij/lang/jsgraphql/GraphQLConstants.java

-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ public final class GraphQLConstants {
1212
public static final String GraphQL = "GraphQL";
1313

1414
public static class Schema {
15-
public static final String __TYPENAME = "__typename";
1615
public static final String __TYPE = "__type";
1716
public static final String __SCHEMA = "__schema";
18-
public static final String __DIRECTIVE_LOCATION_ENUM = "__DirectiveLocation";
1917
}
2018
}

Diff for: src/main/com/intellij/lang/jsgraphql/GraphQLSettings.java

+18-7
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@
2323
@State(name = "GraphQLSettings", storages = {@Storage("graphql-settings.xml")})
2424
public class GraphQLSettings implements PersistentStateComponent<GraphQLSettings.GraphQLSettingsState> {
2525

26-
/**
27-
* Tracks only the changes which could affect schema building.
28-
*/
29-
private final SimpleModificationTracker mySchemaSettingsTracker = new SimpleModificationTracker();
26+
private final Project myProject;
3027

28+
private final SimpleModificationTracker myModificationTracker = new SimpleModificationTracker();
3129
private GraphQLSettingsState myState = new GraphQLSettingsState();
3230

31+
public GraphQLSettings(@NotNull Project project) {
32+
myProject = project;
33+
}
34+
3335
public static GraphQLSettings getSettings(Project project) {
3436
return ServiceManager.getService(project, GraphQLSettings.class);
3537
}
@@ -43,6 +45,7 @@ public GraphQLSettings.GraphQLSettingsState getState() {
4345
@Override
4446
public void loadState(@NotNull GraphQLSettings.GraphQLSettingsState state) {
4547
myState = state;
48+
incrementModificationCount();
4649
}
4750

4851
public String getIntrospectionQuery() {
@@ -51,6 +54,7 @@ public String getIntrospectionQuery() {
5154

5255
public void setIntrospectionQuery(String introspectionQuery) {
5356
myState.introspectionQuery = introspectionQuery;
57+
incrementModificationCount();
5458
}
5559

5660
public boolean isRelaySupportEnabled() {
@@ -59,6 +63,7 @@ public boolean isRelaySupportEnabled() {
5963

6064
public void setRelaySupportEnabled(boolean enableRelayModernFrameworkSupport) {
6165
myState.enableRelayModernFrameworkSupport = enableRelayModernFrameworkSupport;
66+
incrementModificationCount();
6267
}
6368

6469
public boolean isFederationSupportEnabled() {
@@ -67,15 +72,16 @@ public boolean isFederationSupportEnabled() {
6772

6873
public void setFederationSupportEnabled(boolean enableFederationSupport) {
6974
myState.enableFederationSupport = enableFederationSupport;
75+
incrementModificationCount();
7076
}
7177

7278
public boolean isEnableIntrospectionDefaultValues() {
7379
return myState.enableIntrospectionDefaultValues;
7480
}
7581

7682
public void setEnableIntrospectionDefaultValues(boolean enableIntrospectionDefaultValues) {
77-
mySchemaSettingsTracker.incModificationCount();
7883
myState.enableIntrospectionDefaultValues = enableIntrospectionDefaultValues;
84+
incrementModificationCount();
7985
}
8086

8187
public boolean isOpenEditorWithIntrospectionResult() {
@@ -84,10 +90,15 @@ public boolean isOpenEditorWithIntrospectionResult() {
8490

8591
public void setOpenEditorWithIntrospectionResult(boolean openEditorWithIntrospectionResult) {
8692
myState.openEditorWithIntrospectionResult = openEditorWithIntrospectionResult;
93+
incrementModificationCount();
94+
}
95+
96+
public ModificationTracker getModificationTracker() {
97+
return myModificationTracker;
8798
}
8899

89-
public ModificationTracker getSchemaSettingsModificationTracker() {
90-
return mySchemaSettingsTracker;
100+
private void incrementModificationCount() {
101+
myModificationTracker.incModificationCount();
91102
}
92103

93104
/**

Diff for: src/main/com/intellij/lang/jsgraphql/frameworks/relay/GraphQLRelayModernEnableStartupActivity.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
1111
import com.intellij.lang.jsgraphql.GraphQLSettings;
1212
import com.intellij.lang.jsgraphql.ide.notifications.GraphQLNotificationUtil;
13+
import com.intellij.lang.jsgraphql.schema.library.GraphQLLibraryManager;
1314
import com.intellij.notification.Notification;
1415
import com.intellij.notification.NotificationType;
1516
import com.intellij.notification.Notifications;
@@ -49,7 +50,7 @@ public void runActivity(@NotNull Project project) {
4950
}
5051
try {
5152
final GlobalSearchScope scope = GlobalSearchScope.projectScope(project);
52-
for (VirtualFile virtualFile : FilenameIndex.getVirtualFilesByName(project, "package.json", scope)) {
53+
for (VirtualFile virtualFile : FilenameIndex.getVirtualFilesByName(project, "package.json", true, scope)) {
5354
ProgressManager.checkCanceled();
5455
if (!virtualFile.isDirectory() && virtualFile.isInLocalFileSystem()) {
5556
try (InputStream inputStream = virtualFile.getInputStream()) {
@@ -64,8 +65,7 @@ public void runActivity(@NotNull Project project) {
6465
settings.setRelaySupportEnabled(true);
6566
ApplicationManager.getApplication().saveSettings();
6667
notification.expire();
67-
DaemonCodeAnalyzer.getInstance(project).restart();
68-
EditorNotifications.getInstance(project).updateAllNotifications();
68+
GraphQLLibraryManager.getInstance(project).notifyLibrariesChanged();
6969
});
7070
enableRelayModern.setImportant(true);
7171
if (isDisplayed.compareAndSet(false, true)) {

Diff for: src/main/com/intellij/lang/jsgraphql/icons/GraphQLIconProvider.java

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public class GraphQLIconProvider extends IconProvider {
2222
public Icon getIcon(@NotNull PsiElement element, int flags) {
2323

2424
if (element instanceof GraphQLElement) {
25+
if (element instanceof GraphQLFile) {
26+
return GraphQLIcons.FILE;
27+
}
2528

2629
if (element instanceof GraphQLSelectionSetOperationDefinition) {
2730
return GraphQLIcons.Schema.Query;

Diff for: src/main/com/intellij/lang/jsgraphql/ide/completion/GraphQLCompletionContributor.java

+14-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.intellij.codeInsight.lookup.LookupElementWeigher;
1818
import com.intellij.lang.jsgraphql.ide.documentation.GraphQLDocumentationMarkdownRenderer;
1919
import com.intellij.lang.jsgraphql.ide.project.GraphQLPsiSearchHelper;
20+
import com.intellij.lang.jsgraphql.ide.references.GraphQLResolveUtil;
2021
import com.intellij.lang.jsgraphql.psi.GraphQLArgument;
2122
import com.intellij.lang.jsgraphql.psi.GraphQLDirective;
2223
import com.intellij.lang.jsgraphql.psi.GraphQLEnumValueDefinition;
@@ -25,9 +26,10 @@
2526
import com.intellij.lang.jsgraphql.psi.*;
2627
import com.intellij.lang.jsgraphql.psi.impl.GraphQLDirectivesAware;
2728
import com.intellij.lang.jsgraphql.psi.impl.GraphQLObjectValueImpl;
28-
import com.intellij.lang.jsgraphql.schema.GraphQLExternalTypeDefinitionsProvider;
29+
import com.intellij.lang.jsgraphql.schema.GraphQLKnownTypes;
2930
import com.intellij.lang.jsgraphql.schema.GraphQLSchemaProvider;
3031
import com.intellij.lang.jsgraphql.schema.GraphQLSchemaUtil;
32+
import com.intellij.lang.jsgraphql.schema.library.GraphQLLibraryTypes;
3133
import com.intellij.lang.jsgraphql.types.introspection.Introspection;
3234
import com.intellij.lang.jsgraphql.types.language.*;
3335
import com.intellij.lang.jsgraphql.types.schema.GraphQLType;
@@ -47,7 +49,6 @@
4749
import com.intellij.psi.util.PsiTreeUtil;
4850
import com.intellij.psi.util.PsiUtilCore;
4951
import com.intellij.util.Consumer;
50-
import com.intellij.util.ObjectUtils;
5152
import com.intellij.util.ProcessingContext;
5253
import com.intellij.util.SmartList;
5354
import com.intellij.util.containers.ContainerUtil;
@@ -56,7 +57,6 @@
5657
import java.util.*;
5758
import java.util.stream.Collectors;
5859

59-
import static com.intellij.lang.jsgraphql.GraphQLConstants.Schema.__DIRECTIVE_LOCATION_ENUM;
6060
import static com.intellij.patterns.PlatformPatterns.psiComment;
6161
import static com.intellij.patterns.PlatformPatterns.psiElement;
6262

@@ -236,6 +236,7 @@ protected void addCompletions(@NotNull final CompletionParameters parameters,
236236
final String subscriptionName = schema.getSubscriptionType() != null ? schema.getSubscriptionType().getName() : "Subscription";
237237
final Set<String> nonOutputTypes = Sets.newLinkedHashSet(Lists.newArrayList(queryName, mutationName, subscriptionName));
238238
registry.types().values().forEach(type -> {
239+
if (GraphQLKnownTypes.isIntrospectionType(type.getName())) return;
239240
if (!(type instanceof InputObjectTypeDefinition) && !nonOutputTypes.contains(type.getName())) {
240241
result.addElement(LookupElementBuilder.create(type.getName()));
241242
}
@@ -472,6 +473,7 @@ private void addInputTypeCompletions(@NotNull CompletionResultSet result, TypeDe
472473
if (registry != null) {
473474
registry.scalars().values().forEach(scalar -> result.addElement(LookupElementBuilder.create(scalar.getName())));
474475
registry.types().values().forEach(type -> {
476+
if (GraphQLKnownTypes.isIntrospectionType(type.getName())) return;
475477
if (type instanceof EnumTypeDefinition || type instanceof InputObjectTypeDefinition) {
476478
result.addElement(LookupElementBuilder.create(type.getName()));
477479
}
@@ -507,15 +509,15 @@ protected void addCompletions(@NotNull final CompletionParameters parameters,
507509

508510
final Set<String> currentLocations = Sets.newHashSet();
509511
directiveLocations.getDirectiveLocationList().forEach(location -> currentLocations.add(location.getText()));
510-
final GraphQLFile builtInSchema = ObjectUtils.tryCast(
511-
GraphQLExternalTypeDefinitionsProvider.getInstance(completionElement.getProject()).getBuiltInSchema(), GraphQLFile.class);
512+
GraphQLFile builtInSchema = ContainerUtil.getFirstItem(
513+
GraphQLResolveUtil.getLibraryFiles(GraphQLLibraryTypes.SPECIFICATION, completionElement));
512514
if (builtInSchema == null) {
513515
return;
514516
}
515517

516518
for (GraphQLDefinition definition : ContainerUtil.filter(builtInSchema.getTypeDefinitions(), t -> t instanceof GraphQLEnumTypeDefinition)) {
517519
final GraphQLTypeNameDefinition enumTypeName = ((GraphQLEnumTypeDefinition) definition).getTypeNameDefinition();
518-
if (enumTypeName == null || !__DIRECTIVE_LOCATION_ENUM.equals(enumTypeName.getName())) {
520+
if (enumTypeName == null || !GraphQLKnownTypes.INTROSPECTION_DIRECTIVE_LOCATION.equals(enumTypeName.getName())) {
519521
continue;
520522
}
521523

@@ -837,11 +839,15 @@ protected void addCompletions(@NotNull final CompletionParameters parameters,
837839
}
838840

839841
fragmentTypes.forEach(fragmentType -> {
842+
String typeName = fragmentType.first.getName();
843+
if (GraphQLKnownTypes.isIntrospectionType(typeName)) return;
844+
840845
LookupElementBuilder element = LookupElementBuilder
841-
.create(fragmentType.first.getName())
846+
.create(typeName)
842847
.withBoldness(true);
843848
if (fragmentType.second != null) {
844-
final String documentation = GraphQLDocumentationMarkdownRenderer.getDescriptionAsPlainText(fragmentType.second.getContent(), true);
849+
final String documentation = GraphQLDocumentationMarkdownRenderer
850+
.getDescriptionAsPlainText(fragmentType.second.getContent(), true);
845851
element = element.withTailText(" - " + documentation, true);
846852
}
847853
result.addElement(element);

0 commit comments

Comments
 (0)