Skip to content

Commit b43d3b6

Browse files
authored
Implemented a safe way to build a schema (#374)
Implemented a safe way to build a schema
1 parent e44c7d8 commit b43d3b6

File tree

89 files changed

+2326
-874
lines changed

Some content is hidden

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

89 files changed

+2326
-874
lines changed

resources/META-INF/plugin.xml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
<extensions defaultExtensionNs="com.intellij">
4141

42-
<applicationService serviceInterface="com.intellij.lang.jsgraphql.ide.references.GraphQLFindUsagesUtil" serviceImplementation="com.intellij.lang.jsgraphql.ide.references.GraphQLFindUsagesUtil" />
42+
<applicationService serviceImplementation="com.intellij.lang.jsgraphql.ide.references.GraphQLFindUsagesUtil" />
4343

4444
<!-- Language registration -->
4545
<fileTypeFactory implementation="com.intellij.lang.jsgraphql.GraphQLFileTypeFactory"/>
@@ -49,17 +49,17 @@
4949
<iconProvider implementation="com.intellij.lang.jsgraphql.GraphQLIconProvider" />
5050

5151
<!-- Project services -->
52-
<projectService serviceInterface="com.intellij.lang.jsgraphql.schema.GraphQLTypeDefinitionRegistryServiceImpl" serviceImplementation="com.intellij.lang.jsgraphql.schema.GraphQLTypeDefinitionRegistryServiceImpl" />
53-
<projectService serviceInterface="com.intellij.lang.jsgraphql.schema.SchemaIDLTypeDefinitionRegistry" serviceImplementation="com.intellij.lang.jsgraphql.schema.SchemaIDLTypeDefinitionRegistry" />
54-
<projectService serviceInterface="com.intellij.lang.jsgraphql.schema.GraphQLSchemaChangeListener" serviceImplementation="com.intellij.lang.jsgraphql.schema.GraphQLSchemaChangeListener" />
55-
<projectService serviceInterface="com.intellij.lang.jsgraphql.ide.project.GraphQLPsiSearchHelper" serviceImplementation="com.intellij.lang.jsgraphql.ide.project.GraphQLPsiSearchHelper" />
56-
<projectService serviceInterface="com.intellij.lang.jsgraphql.ide.references.GraphQLReferenceService" serviceImplementation="com.intellij.lang.jsgraphql.ide.references.GraphQLReferenceService" />
57-
<projectService serviceInterface="com.intellij.lang.jsgraphql.v1.ide.project.JSGraphQLLanguageUIProjectService" serviceImplementation="com.intellij.lang.jsgraphql.v1.ide.project.JSGraphQLLanguageUIProjectService" />
58-
<projectService serviceInterface="com.intellij.lang.jsgraphql.GraphQLSettings" serviceImplementation="com.intellij.lang.jsgraphql.GraphQLSettings" />
59-
<projectService serviceInterface="com.intellij.lang.jsgraphql.ide.project.graphqlconfig.GraphQLConfigManager" serviceImplementation="com.intellij.lang.jsgraphql.ide.project.graphqlconfig.GraphQLConfigManager" />
60-
<projectService serviceInterface="com.intellij.lang.jsgraphql.ide.editor.GraphQLIntrospectionService" serviceImplementation="com.intellij.lang.jsgraphql.ide.editor.GraphQLIntrospectionService" />
52+
<projectService serviceInterface="com.intellij.lang.jsgraphql.schema.GraphQLSchemaProvider" serviceImplementation="com.intellij.lang.jsgraphql.schema.GraphQLSchemaProviderImpl" />
53+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.schema.GraphQLRegistryProvider" />
54+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.schema.GraphQLSchemaChangeListener" />
55+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.ide.project.GraphQLPsiSearchHelper" />
56+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.ide.references.GraphQLReferenceService" />
57+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.v1.ide.project.JSGraphQLLanguageUIProjectService" />
58+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.GraphQLSettings" />
59+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.ide.project.graphqlconfig.GraphQLConfigManager" />
60+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.ide.editor.GraphQLIntrospectionService" />
6161
<projectService serviceInterface="com.intellij.lang.jsgraphql.ide.project.graphqlconfig.GraphQLConfigGlobMatcher" serviceImplementation="com.intellij.lang.jsgraphql.ide.project.graphqlconfig.GraphQLConfigGlobMatcherImpl" />
62-
<projectService serviceInterface="com.intellij.lang.jsgraphql.ide.GraphQLRelayModernAnnotationFilter" serviceImplementation="com.intellij.lang.jsgraphql.ide.GraphQLRelayModernAnnotationFilter" />
62+
<projectService serviceImplementation="com.intellij.lang.jsgraphql.ide.GraphQLRelayModernAnnotationFilter" />
6363

6464
<!-- Indexing -->
6565
<fileBasedIndex implementation="com.intellij.lang.jsgraphql.ide.project.indexing.GraphQLIdentifierIndex" />

src/main/com/intellij/lang/jsgraphql/endpoint/ide/project/JSGraphQLEndpointNamedTypeRegistry.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import com.intellij.lang.jsgraphql.ide.project.graphqlconfig.GraphQLNamedScope;
1616
import com.intellij.lang.jsgraphql.schema.GraphQLSchemaChangeListener;
1717
import com.intellij.lang.jsgraphql.schema.GraphQLSchemaEventListener;
18-
import com.intellij.lang.jsgraphql.schema.TypeDefinitionRegistryWithErrors;
18+
import com.intellij.lang.jsgraphql.schema.GraphQLValidatedTypeDefinitionRegistry;
1919
import com.intellij.lang.jsgraphql.v1.ide.configuration.JSGraphQLConfigurationProvider;
2020
import com.intellij.lang.jsgraphql.v1.schema.ide.type.JSGraphQLNamedType;
2121
import com.intellij.lang.jsgraphql.v1.schema.ide.type.JSGraphQLNamedTypeRegistry;
@@ -46,7 +46,7 @@ public class JSGraphQLEndpointNamedTypeRegistry implements JSGraphQLNamedTypeReg
4646

4747
private final Map<GraphQLNamedScope, Map<String, JSGraphQLNamedType>> endpointTypesByName = Maps.newConcurrentMap();
4848
private final Map<GraphQLNamedScope, PsiFile> endpointEntryPsiFile = Maps.newConcurrentMap();
49-
private final Map<GraphQLNamedScope, TypeDefinitionRegistryWithErrors> projectToRegistry = Maps.newConcurrentMap();
49+
private final Map<GraphQLNamedScope, GraphQLValidatedTypeDefinitionRegistry> projectToRegistry = Maps.newConcurrentMap();
5050

5151
public static JSGraphQLEndpointNamedTypeRegistry getService(@NotNull Project project) {
5252
return ServiceManager.getService(project, JSGraphQLEndpointNamedTypeRegistry.class);
@@ -93,10 +93,10 @@ public void enumerateTypes(PsiElement scopedElement, Consumer<JSGraphQLNamedType
9393
computeNamedTypes(scopedElement).forEach((key, jsGraphQLNamedType) -> consumer.accept(jsGraphQLNamedType));
9494
}
9595

96-
public TypeDefinitionRegistryWithErrors getTypesAsRegistry(PsiElement scopedElement) {
96+
public GraphQLValidatedTypeDefinitionRegistry getTypesAsRegistry(PsiElement scopedElement) {
9797
final GraphQLNamedScope schemaScope = getSchemaScope(scopedElement);
9898
if (schemaScope == null) {
99-
return new TypeDefinitionRegistryWithErrors(new TypeDefinitionRegistry(), Collections.emptyList(), false);
99+
return new GraphQLValidatedTypeDefinitionRegistry(new TypeDefinitionRegistry(), Collections.emptyList(), false);
100100
}
101101
return projectToRegistry.computeIfAbsent(schemaScope, p -> doGetTypesAsRegistry(scopedElement));
102102
}
@@ -110,7 +110,7 @@ private GraphQLNamedScope getSchemaScope(PsiElement scopedElement) {
110110
return virtualFile != null ? graphQLConfigManager.getSchemaScope(virtualFile) : null;
111111
}
112112

113-
private TypeDefinitionRegistryWithErrors doGetTypesAsRegistry(PsiElement scopedElement) {
113+
private GraphQLValidatedTypeDefinitionRegistry doGetTypesAsRegistry(PsiElement scopedElement) {
114114

115115
final TypeDefinitionRegistry registry = new TypeDefinitionRegistry();
116116
final List<GraphQLException> errors = Lists.newArrayList();
@@ -284,7 +284,7 @@ public void visitElement(PsiElement element) {
284284
}
285285
});
286286

287-
return new TypeDefinitionRegistryWithErrors(registry, errors, !namedTypes.isEmpty());
287+
return new GraphQLValidatedTypeDefinitionRegistry(registry, errors, !namedTypes.isEmpty());
288288
}
289289

290290
private Description getDescription(JSGraphQLEndpointNamedTypeDefinition typeDefinition, SourceLocation sourceLocation) {

src/main/com/intellij/lang/jsgraphql/ide/GraphQLValidationAnnotator.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
import com.intellij.lang.jsgraphql.psi.*;
2626
import com.intellij.lang.jsgraphql.psi.impl.GraphQLDescriptionAware;
2727
import com.intellij.lang.jsgraphql.psi.impl.GraphQLDirectivesAware;
28-
import com.intellij.lang.jsgraphql.schema.GraphQLSchemaWithErrors;
29-
import com.intellij.lang.jsgraphql.schema.GraphQLTypeDefinitionRegistryServiceImpl;
28+
import com.intellij.lang.jsgraphql.schema.GraphQLSchemaProvider;
3029
import com.intellij.lang.jsgraphql.schema.GraphQLTypeScopeProvider;
30+
import com.intellij.lang.jsgraphql.schema.GraphQLValidatedSchema;
3131
import com.intellij.lang.jsgraphql.utils.GraphQLUtil;
3232
import com.intellij.openapi.components.ServiceManager;
3333
import com.intellij.openapi.editor.Editor;
@@ -151,12 +151,12 @@ public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder a
151151
if (!fixes.isEmpty()) {
152152
final InspectionManager inspectionManager = InspectionManager.getInstance(psiElement.getProject());
153153
final ProblemDescriptor problemDescriptor = inspectionManager.createProblemDescriptor(
154-
psiElement,
155-
psiElement,
156-
message,
157-
ProblemHighlightType.ERROR,
158-
true,
159-
LocalQuickFix.EMPTY_ARRAY
154+
psiElement,
155+
psiElement,
156+
message,
157+
ProblemHighlightType.ERROR,
158+
true,
159+
LocalQuickFix.EMPTY_ARRAY
160160
);
161161
fixes.forEach(fix -> annotation.get().registerFix(fix, null, null, problemDescriptor));
162162
}
@@ -192,20 +192,20 @@ public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder a
192192
if (userData == null) {
193193

194194
try {
195-
final GraphQLSchemaWithErrors schema = GraphQLTypeDefinitionRegistryServiceImpl.getService(project).getSchemaWithErrors(psiElement);
195+
final GraphQLValidatedSchema schema = GraphQLSchemaProvider.getInstance(project).getValidatedSchema(psiElement);
196196
if (!schema.isErrorsPresent()) {
197197
// adjust source locations for injected GraphQL since the annotator works on the entire editor buffer (e.g. tsx with graphql tagged templates)
198198
int lineDelta = 0;
199-
int firsteLineColumDelta = 0;
199+
int firstLineColumnDelta = 0;
200200
if (containingFile.getContext() != null) {
201201
final LogicalPosition logicalPosition = getLogicalPositionFromOffset(containingFile, containingFile.getContext().getTextOffset());
202202
if (logicalPosition.line > 0 || logicalPosition.column > 0) {
203203
// logical positions can be used as deltas between graphql-java and intellij since graphql-java is 1-based and intellij is 0-based
204204
lineDelta = logicalPosition.line;
205-
firsteLineColumDelta = logicalPosition.column;
205+
firstLineColumnDelta = logicalPosition.column;
206206
}
207207
}
208-
final Document document = GraphQLUtil.parseDocument(replacePlaceholdersWithValidGraphQL(containingFile), lineDelta, firsteLineColumDelta);
208+
final Document document = GraphQLUtil.parseDocument(replacePlaceholdersWithValidGraphQL(containingFile), lineDelta, firstLineColumnDelta);
209209
userData = new Validator().validateDocument(schema.getSchema(), document);
210210
} else {
211211
final String currentFileName = GraphQLPsiUtil.getFileName(containingFile);
@@ -314,7 +314,7 @@ public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder a
314314
continue;
315315
}
316316
}
317-
if(validationErrorType == ValidationErrorType.SubSelectionRequired) {
317+
if (validationErrorType == ValidationErrorType.SubSelectionRequired) {
318318
// apollo client 2.5 doesn't require sub selections for client fields
319319
final GraphQLDirectivesAware directivesAware = PsiTreeUtil.getParentOfType(errorPsiElement, GraphQLDirectivesAware.class);
320320
if (directivesAware != null) {
@@ -352,8 +352,8 @@ public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder a
352352
*/
353353
boolean isInsideTemplateElement(PsiElement psiElement) {
354354
return PsiTreeUtil.findFirstParent(
355-
psiElement, false,
356-
el -> el instanceof GraphQLTemplateDefinition || el instanceof GraphQLTemplateSelection || el instanceof GraphQLTemplateVariable
355+
psiElement, false,
356+
el -> el instanceof GraphQLTemplateDefinition || el instanceof GraphQLTemplateSelection || el instanceof GraphQLTemplateVariable
357357
) != null;
358358
}
359359

@@ -435,7 +435,9 @@ public void visitElement(PsiElement element) {
435435
return buffer.toString();
436436
}
437437

438-
private Optional<Annotation> createErrorAnnotation(@NotNull AnnotationHolder annotationHolder, PsiElement errorPsiElement, String message) {
438+
private Optional<Annotation> createErrorAnnotation(@NotNull AnnotationHolder annotationHolder,
439+
PsiElement errorPsiElement,
440+
String message) {
439441
if (GraphQLRelayModernAnnotationFilter.getService(errorPsiElement.getProject()).errorIsIgnored(errorPsiElement)) {
440442
return Optional.empty();
441443
}
@@ -514,10 +516,10 @@ private List<String> getFieldNameSuggestions(String fieldName, graphql.schema.Gr
514516
@NotNull
515517
private List<String> getSuggestions(String text, List<String> candidates) {
516518
return candidates.stream()
517-
.map(suggestion -> new Pair<>(suggestion, EditDistance.optimalAlignment(text, suggestion, false)))
518-
.filter(p -> p.second <= 2)
519-
.sorted(Comparator.comparingInt(p -> p.second))
520-
.map(p -> p.first).collect(Collectors.toList());
519+
.map(suggestion -> new Pair<>(suggestion, EditDistance.optimalAlignment(text, suggestion, false)))
520+
.filter(p -> p.second <= 2)
521+
.sorted(Comparator.comparingInt(p -> p.second))
522+
.map(p -> p.first).collect(Collectors.toList());
521523

522524
}
523525

0 commit comments

Comments
 (0)