Skip to content

Commit 5b9f223

Browse files
committed
Upgrade to Language Service v1.2.0 (#22)
- Basic editor support for GraphQL Schema files (.graphqls) - Improved brace matching and completion - Tweaked new GraphQL (Schema) file action to not require existing files - Warnings on using schema IDL in graphql and vice versa - Simplified project schema virtual file -- now uses editor color provider and manual project tree selection instead of file system wrapper (cherry picked from commit 756146e)
1 parent 499e6ec commit 5b9f223

39 files changed

+823
-239
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1+
## 1.4.0 (2016-08-28)
2+
3+
Features:
4+
5+
- Language Service 1.2.0 based on graphql 0.7.0 and codemirror-graphql 0.5.4 (#22)
6+
- Basic editor support for GraphQL Schema files (.graphqls) (#22)
7+
18
## 1.3.2 (2016-06-23)
29

310
Changes:
411

5-
- Closes #14 Remove GraphQL schema from scratch file formats
12+
- Remove GraphQL schema from scratch file formats (#14)
613

714
## 1.3.1 (2016-06-09)
815

916
Changes:
1017

11-
- Closes #13 JSLanguageCompilerToolWindowManager: NoClassDefFoundError in WebStorm 2016.2 EAP
18+
- JSLanguageCompilerToolWindowManager: NoClassDefFoundError in WebStorm 2016.2 EAP (#13)
1219
- Language Service 1.1.2 increases maximum size of JSON schema from 100kb to 32mb
1320

1421
## 1.3.0 (2016-05-21)
@@ -28,7 +35,7 @@ Features:
2835

2936
Changes:
3037

31-
- Closes #4 Completion after ... fragment spread operator.
38+
- Completion after ... fragment spread operator. (#4)
3239
- Language Service 1.1.1 based on graphql 0.4.16 and codemirror-graphql 0.2.2
3340

3441
## 1.1.0 (2016-01-31)

resources/META-INF/plugin.xml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<idea-plugin version="2">
1111
<id>com.intellij.lang.jsgraphql</id>
1212
<name>JS GraphQL</name>
13-
<version>1.3.2.143-145</version>
13+
<version>1.4.0.143-145</version>
1414
<vendor>Jim Kynde Meyer - [email protected]</vendor>
1515

1616
<description><![CDATA[
@@ -29,6 +29,7 @@
2929

3030
<change-notes><![CDATA[
3131
<ul>
32+
<li>1.4.0: Language Service 1.2.0 based on graphql 0.7.0 and codemirror-graphql 0.5.4. Basic editor support for GraphQL Schema (.graphqls)</li>
3233
<li>1.3.2: Removes GraphQL schema from scratch file formats.</li>
3334
<li>1.3.1: Fixes compatibility issue with WebStorm 2016.2 EAP.</li>
3435
<li>1.3.0: Adds support for GraphQL Scratch Files. Query results are now formatted.</li>
@@ -74,7 +75,9 @@
7475
<lang.syntaxHighlighterFactory language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.highlighting.JSGraphQLSyntaxHighlighterFactory"/>
7576
<lang.syntaxHighlighterFactory language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.ide.highlighting.JSGraphQLSyntaxHighlighterFactory"/>
7677
<lang.commenter language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLCommenter"/>
78+
<lang.commenter language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLCommenter"/>
7779
<lang.braceMatcher language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLBraceMatcher" />
80+
<lang.braceMatcher language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLBraceMatcher" />
7881
<lang.fileViewProviderFactory language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.schema.psi.JSGraphQLSchemaFileViewProviderFactory" />
7982
<lang.psiStructureViewFactory language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.structureView.JSGraphQLPsiStructureViewFactory"/>
8083
<lang.psiStructureViewFactory language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.ide.structureView.JSGraphQLPsiStructureViewFactory"/>
@@ -85,6 +88,7 @@
8588

8689
<!-- Error highlighting and annotations -->
8790
<externalAnnotator language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.annotator.JSGraphQLAnnotator" />
91+
<externalAnnotator language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.ide.annotator.JSGraphQLAnnotator" />
8892
<externalAnnotator language="JavaScript" implementationClass="com.intellij.lang.jsgraphql.ide.annotator.JSGraphQLAnnotator" />
8993
<externalAnnotator language="TypeScript" implementationClass="com.intellij.lang.jsgraphql.ide.annotator.JSGraphQLAnnotator" /><!-- Own reg required -->
9094
<annotator language="JavaScript" implementationClass="com.intellij.lang.jsgraphql.ide.annotator.JSGraphQLRelayTemplateAnnotator" /><!-- Using the JSX dialect overwrites the default annotator -->
@@ -96,12 +100,14 @@
96100

97101

98102
<!-- Formatting -->
99-
<lang.formatter language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.JSGraphQLFormattingModelBuilder"/>
103+
<lang.formatter language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.JSGraphQLFormattingModelBuilder"/>
104+
<lang.formatter language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.JSGraphQLFormattingModelBuilder"/>
100105
<lang.formatter language="JavaScript" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.JSGraphQLInjectedFormattingModelBuilder" />
101106
<lang.formatter language="TypeScript" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.JSGraphQLInjectedFormattingModelBuilder" /><!-- Own reg required -->
102107
<lang.foldingBuilder language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLFoldingBuilder"/>
103108
<lang.foldingBuilder language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLFoldingBuilder"/>
104109
<lang.quoteHandler language="GraphQL" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLQuoteHandler" />
110+
<lang.quoteHandler language="GraphQL Schema" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLQuoteHandler" />
105111
<enterHandlerDelegate implementation="com.intellij.lang.jsgraphql.ide.formatter.JSGraphQLEnterHandlerDelegate" />
106112

107113

@@ -127,6 +133,7 @@
127133
<editorNotificationProvider implementation="com.intellij.lang.jsgraphql.ide.notifications.JSGraphQLConfigEditorNotificationProvider"/>
128134
<codeInsight.lineMarkerProvider language="JavaScript" implementationClass="com.intellij.lang.jsgraphql.ide.editor.JSGraphQLLineMarkerProvider" />
129135

136+
<editorTabColorProvider implementation="com.intellij.lang.jsgraphql.schema.ide.project.JSGraphQLSchemaEditorTabColorProvider" />
130137

131138
<!-- Language injection -->
132139
<multiHostInjector implementation="com.intellij.lang.jsgraphql.ide.injection.JSGraphQLTemplateFragmentLanguageInjector" order="first" />
@@ -151,6 +158,10 @@
151158
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewTypeScriptFile"/>
152159
</action>
153160

161+
<action id="com.intellij.lang.jsgraphql.schema.ide.actions.JSGraphQLSchemaNewFileAction" class="com.intellij.lang.jsgraphql.schema.ide.actions.JSGraphQLSchemaNewFileAction">
162+
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewTypeScriptFile"/>
163+
</action>
164+
154165
<action class="com.intellij.lang.jsgraphql.ide.actions.JSGraphQLExecuteEditorAction" id="com.intellij.lang.jsgraphql.ide.actions.JSGraphQLExecuteEditorAction">
155166
<keyboard-shortcut first-keystroke="control ENTER" keymap="$default"/>
156167
<keyboard-shortcut first-keystroke="meta ENTER" keymap="Mac OS X"/>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
schema {
2+
query: Query
3+
mutation: Mutation
4+
}
5+
6+
type Query {
7+
8+
}
9+
10+
type Mutation {
11+
12+
}

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.intellij.ide.scratch.ScratchFileType;
1111
import com.intellij.lang.jsgraphql.icons.JSGraphQLIcons;
1212
import com.intellij.openapi.fileTypes.LanguageFileType;
13+
import com.intellij.openapi.progress.ProcessCanceledException;
1314
import com.intellij.openapi.project.Project;
1415
import com.intellij.openapi.vfs.VirtualFile;
1516
import com.intellij.psi.PsiFile;
@@ -59,9 +60,13 @@ public Icon getIcon() {
5960
public static boolean isGraphQLScratchFile(Project project, VirtualFile file) {
6061
if(file.getFileType() instanceof ScratchFileType) {
6162
final PsiManager psiManager = PsiManager.getInstance(project);
62-
final PsiFile psiFile = psiManager.findFile(file);
63-
if(psiFile != null && psiFile.getFileType() == JSGraphQLFileType.INSTANCE) {
64-
return true;
63+
try {
64+
final PsiFile psiFile = psiManager.findFile(file);
65+
if (psiFile != null && psiFile.getFileType() == JSGraphQLFileType.INSTANCE) {
66+
return true;
67+
}
68+
} catch (ProcessCanceledException e) {
69+
// can be thrown from psiManager.findFile
6570
}
6671
}
6772
return false;

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

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@
77
*/
88
package com.intellij.lang.jsgraphql;
99

10+
import com.google.common.collect.Sets;
11+
12+
import java.util.Set;
13+
1014
public interface JSGraphQLKeywords {
1115

1216
// graphql
1317
String QUERY = "query";
1418
String FRAGMENT = "fragment";
15-
String FRAGMENT_DOTS = "...";
19+
String FRAGMENT_DOTS = "...";
1620
String FRAGMENT_ON = "on";
1721
String MUTATION = "mutation";
1822
String SUBSCRIPTION = "subscription";
19-
23+
2024
// graphql schema
2125
String TYPE = "type";
2226
String INTERFACE = "interface";
@@ -25,6 +29,43 @@ public interface JSGraphQLKeywords {
2529
String ENUM = "enum";
2630
String INPUT = "input";
2731
String EXTEND = "extend";
28-
29-
32+
String SCHEMA = "schema";
33+
String DIRECTIVE = "directive";
34+
35+
Set<String> ALL = Sets.newHashSet(
36+
QUERY,
37+
FRAGMENT,
38+
FRAGMENT_DOTS,
39+
FRAGMENT_ON,
40+
MUTATION,
41+
SUBSCRIPTION,
42+
TYPE,
43+
INTERFACE,
44+
UNION,
45+
SCALAR,
46+
ENUM,
47+
INPUT,
48+
EXTEND,
49+
SCHEMA,
50+
DIRECTIVE
51+
);
52+
53+
Set<String> GRAPHQL_ROOT_KEYWORDS = Sets.newHashSet(
54+
QUERY,
55+
FRAGMENT,
56+
MUTATION,
57+
SUBSCRIPTION
58+
);
59+
60+
Set<String> SCHEMA_DEFINITION_KEYWORDS = Sets.newHashSet(
61+
TYPE,
62+
INTERFACE,
63+
UNION,
64+
SCALAR,
65+
ENUM,
66+
INPUT,
67+
EXTEND,
68+
SCHEMA,
69+
DIRECTIVE
70+
);
3071
}

src/main/com/intellij/lang/jsgraphql/ide/actions/JSGraphQLNewFileAction.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,35 @@
11
/**
2-
* Copyright (c) 2015-present, Jim Kynde Meyer
3-
* All rights reserved.
2+
* Copyright (c) 2015-present, Jim Kynde Meyer
3+
* All rights reserved.
44
*
5-
* This source code is licensed under the MIT license found in the
6-
* LICENSE file in the root directory of this source tree.
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
77
*/
88
package com.intellij.lang.jsgraphql.ide.actions;
99

1010
import com.intellij.ide.actions.CreateFileFromTemplateAction;
1111
import com.intellij.ide.actions.CreateFileFromTemplateDialog;
12-
import com.intellij.lang.jsgraphql.JSGraphQLFileType;
1312
import com.intellij.lang.jsgraphql.icons.JSGraphQLIcons;
1413
import com.intellij.openapi.actionSystem.DataContext;
1514
import com.intellij.openapi.actionSystem.LangDataKeys;
1615
import com.intellij.openapi.module.Module;
1716
import com.intellij.openapi.project.DumbAware;
1817
import com.intellij.openapi.project.Project;
1918
import com.intellij.psi.PsiDirectory;
20-
import com.intellij.psi.search.FileTypeIndex;
2119

22-
public class JSGraphQLNewFileAction extends CreateFileFromTemplateAction implements DumbAware {
20+
public class JSGraphQLNewFileAction extends CreateFileFromTemplateAction implements DumbAware {
2321

2422
public JSGraphQLNewFileAction() {
2523
super("GraphQL File", "Creates a new GraphQL file", JSGraphQLIcons.Files.GraphQL);
2624
}
2725

2826
@Override
2927
protected boolean isAvailable(DataContext dataContext) {
30-
if(!super.isAvailable(dataContext)) {
28+
if (!super.isAvailable(dataContext)) {
3129
return false;
3230
}
3331
final Module module = LangDataKeys.MODULE.getData(dataContext);
34-
return module != null && FileTypeIndex.containsFileOfType(JSGraphQLFileType.INSTANCE, module.getModuleContentScope());
32+
return module != null;
3533
}
3634

3735
@Override

src/main/com/intellij/lang/jsgraphql/ide/annotator/JSGraphQLAnnotator.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@
2121
import com.intellij.lang.jsgraphql.languageservice.api.AnnotationsResponse;
2222
import com.intellij.lang.jsgraphql.languageservice.api.Pos;
2323
import com.intellij.lang.jsgraphql.psi.JSGraphQLFile;
24+
import com.intellij.lang.jsgraphql.schema.psi.JSGraphQLSchemaFile;
2425
import com.intellij.openapi.diagnostic.Logger;
2526
import com.intellij.openapi.editor.Editor;
2627
import com.intellij.openapi.editor.LogicalPosition;
2728
import com.intellij.openapi.progress.ProcessCanceledException;
2829
import com.intellij.openapi.util.TextRange;
30+
import com.intellij.psi.PsiElement;
2931
import com.intellij.psi.PsiFile;
32+
import com.intellij.psi.PsiRecursiveElementVisitor;
3033
import com.intellij.psi.util.PsiTreeUtil;
3134
import org.apache.commons.lang.StringUtils;
3235
import org.jetbrains.annotations.NotNull;
@@ -55,6 +58,9 @@ public JSGraphQLAnnotationResult collectInformation(@NotNull PsiFile file, @NotN
5558
final AnnotationsResponse annotations = JSGraphQLNodeLanguageServiceClient.getAnnotations(buffer.toString(), file.getProject(), relay);
5659
return new JSGraphQLAnnotationResult(annotations, editor);
5760
}
61+
} else if(file instanceof JSGraphQLSchemaFile) {
62+
// no external annotation support yet for schema files
63+
return new JSGraphQLAnnotationResult(new AnnotationsResponse(), editor);
5864
}
5965
} catch (Throwable e) {
6066
if(e instanceof ProcessCanceledException) {
@@ -77,12 +83,24 @@ public void apply(@NotNull PsiFile file, JSGraphQLAnnotationResult annotationRes
7783
if(annotationResult != null) {
7884
try {
7985
final Editor editor = annotationResult.getEditor();
86+
final String fileName = file.getVirtualFile().getPath();
87+
final List<JSGraphQLErrorResult> errors = Lists.newArrayList();
88+
final JSGraphQLLanguageWarningAnnotator internalAnnotator = new JSGraphQLLanguageWarningAnnotator();
89+
file.accept(new PsiRecursiveElementVisitor() {
90+
@Override
91+
public void visitElement(PsiElement element) {
92+
final com.intellij.lang.annotation.Annotation annotation = internalAnnotator.annotate(file, element, holder);
93+
if(annotation != null) {
94+
final LogicalPosition pos = editor.offsetToLogicalPosition(element.getTextOffset());
95+
errors.add(new JSGraphQLErrorResult(annotation.getMessage(), fileName, annotation.getSeverity().myName, pos.line + 1, pos.column + 1));
96+
}
97+
super.visitElement(element);
98+
}
99+
});
80100
AnnotationsResponse annotationsReponse = annotationResult.getAnnotationsReponse();
81101
if(annotationsReponse == null) {
82102
return;
83103
}
84-
final List<JSGraphQLErrorResult> errors = Lists.newArrayList();
85-
final String fileName = file.getVirtualFile().getPath();
86104
for (Annotation annotation : annotationsReponse.getAnnotations()) {
87105
LogicalPosition from = getLogicalPosition(annotation.getFrom());
88106
LogicalPosition to = getLogicalPosition(annotation.getTo());
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Copyright (c) 2015-present, Jim Kynde Meyer
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
package com.intellij.lang.jsgraphql.ide.annotator;
9+
10+
import com.intellij.lang.annotation.Annotation;
11+
import com.intellij.lang.annotation.AnnotationHolder;
12+
import com.intellij.lang.jsgraphql.JSGraphQLKeywords;
13+
import com.intellij.lang.jsgraphql.JSGraphQLTokenTypes;
14+
import com.intellij.lang.jsgraphql.psi.JSGraphQLElementType;
15+
import com.intellij.lang.jsgraphql.psi.JSGraphQLFile;
16+
import com.intellij.lang.jsgraphql.psi.JSGraphQLPsiElement;
17+
import com.intellij.lang.jsgraphql.schema.psi.JSGraphQLSchemaFile;
18+
import com.intellij.psi.PsiElement;
19+
import com.intellij.psi.PsiFile;
20+
import com.intellij.psi.util.PsiTreeUtil;
21+
import org.jetbrains.annotations.NotNull;
22+
23+
/**
24+
* Warns about using the Schema IDL in regular GraphQL files, and vice versa.
25+
*/
26+
public class JSGraphQLLanguageWarningAnnotator {
27+
28+
public Annotation annotate(PsiFile file, @NotNull PsiElement element, @NotNull AnnotationHolder holder) {
29+
if (file instanceof JSGraphQLFile) {
30+
if (element.getNode().getElementType() == JSGraphQLTokenTypes.KEYWORD) {
31+
if (JSGraphQLKeywords.SCHEMA_DEFINITION_KEYWORDS.contains(element.getNode().getText())) {
32+
return holder.createWarningAnnotation(element, "Schema definitions should be written in GraphQL Schema files (.graphqls)");
33+
}
34+
}
35+
} else if (file instanceof JSGraphQLSchemaFile) {
36+
if (element.getNode().getElementType() == JSGraphQLTokenTypes.KEYWORD) {
37+
if (JSGraphQLKeywords.GRAPHQL_ROOT_KEYWORDS.contains(element.getNode().getText())) {
38+
JSGraphQLPsiElement parent = PsiTreeUtil.getParentOfType(element, JSGraphQLPsiElement.class);
39+
while (parent != null) {
40+
if (JSGraphQLElementType.SCHEMA_DEF_KIND.equals(((JSGraphQLElementType) parent.getNode().getElementType()).getKind())) {
41+
// ignore operation keywords inside schema {}
42+
return null;
43+
}
44+
parent = PsiTreeUtil.getParentOfType(parent, JSGraphQLPsiElement.class);
45+
}
46+
return holder.createWarningAnnotation(element, "Operations and fragments should be written in GraphQL files (.graphql)");
47+
}
48+
}
49+
}
50+
return null;
51+
}
52+
}

src/main/com/intellij/lang/jsgraphql/ide/completion/JSGraphQLCompletionContributor.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ protected void addCompletions(@NotNull final CompletionParameters parameters, Pr
136136
}
137137

138138
}
139+
140+
if(JSGraphQLKeywords.ALL.contains(text)) {
141+
// add a whitespace after completion of a keyword
142+
element = element.withInsertHandler(AddSpaceInsertHandler.INSTANCE_WITH_AUTO_POPUP);
143+
}
144+
139145
result.addElement(element);
140146
}
141147
}

0 commit comments

Comments
 (0)