Skip to content

Commit 355c746

Browse files
committed
Made plugin compatible with IntelliJ Community Edition and Android Studio (#164)
- Moved code that requires the JavaScript plugin into separate packages and graphql-javascript.xml
1 parent 21379ec commit 355c746

19 files changed

+151
-603
lines changed

build.gradle

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ intellij {
3737
plugins = ['JavaScriptLanguage', 'CSS']
3838
}
3939
patchPluginXml {
40-
changeNotes """
41-
Add change notes here.<br>
42-
<em>most HTML tags may be used</em>"""
40+
4341
}
4442

4543
sourceSets {
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
<idea-plugin>
22
<extensions defaultExtensionNs="com.intellij">
33

4+
<!-- Startup -->
5+
<postStartupActivity implementation="com.intellij.lang.jsgraphql.endpoint.ide.startup.javascript.GraphQLJavaScriptStartupActivity" />
6+
47
<!-- Formatting -->
5-
<lang.formatter language="JavaScript" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.GraphQLInjectedFormattingModelBuilder" />
6-
<lang.formatter language="TypeScript" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.GraphQLInjectedFormattingModelBuilder" /><!-- Own reg required -->
8+
<lang.formatter language="JavaScript" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.javascript.GraphQLInjectedFormattingModelBuilder" />
9+
<lang.formatter language="TypeScript" implementationClass="com.intellij.lang.jsgraphql.ide.formatter.javascript.GraphQLInjectedFormattingModelBuilder" /><!-- Own reg required -->
710

811
<!-- Language Injection -->
9-
<multiHostInjector implementation="com.intellij.lang.jsgraphql.ide.injection.GraphQLTemplateFragmentLanguageInjector" order="first" />
10-
<fileBasedIndex implementation="com.intellij.lang.jsgraphql.ide.injection.GraphQLInjectionIndex"/>
12+
<multiHostInjector implementation="com.intellij.lang.jsgraphql.ide.injection.javascript.GraphQLTemplateFragmentLanguageInjector" order="first" />
13+
<projectService serviceInterface="com.intellij.lang.jsgraphql.ide.project.GraphQLInjectionSearchHelper" serviceImplementation="com.intellij.lang.jsgraphql.ide.project.javascript.GraphQLJavascriptInjectionSearchHelper" />
1114

15+
<!-- Indexing -->
16+
<fileBasedIndex implementation="com.intellij.lang.jsgraphql.ide.project.javascript.GraphQLInjectionIndex"/>
1217
</extensions>
1318
</idea-plugin>

resources/META-INF/plugin.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,6 @@
207207
<!--
208208
<lang.formatter language="GraphQL" implementationClass="JSGraphQLFormattingModelBuilder"/>
209209
<lang.formatter language="GraphQL Schema" implementationClass="JSGraphQLFormattingModelBuilder"/>
210-
<lang.formatter language="JavaScript" implementationClass="JSGraphQLInjectedFormattingModelBuilder" />
211-
<lang.formatter language="TypeScript" implementationClass="JSGraphQLInjectedFormattingModelBuilder" /><!## Own reg required ##>
212210
-->
213211
<lang.formatter language="GraphQL Endpoint" implementationClass="com.intellij.lang.jsgraphql.endpoint.ide.formatter.JSGraphQLEndpointFormattingModelBuilder"/>
214212
<!--

src/main/com/intellij/lang/jsgraphql/endpoint/ide/startup/GraphQLStartupActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package com.intellij.lang.jsgraphql.endpoint.ide.startup;
99

1010
import com.intellij.lang.jsgraphql.v1.ide.project.JSGraphQLLanguageUIProjectService;
11+
import com.intellij.openapi.application.ApplicationManager;
1112
import com.intellij.openapi.project.DumbAware;
1213
import com.intellij.openapi.project.Project;
1314
import com.intellij.openapi.startup.StartupActivity;
@@ -20,6 +21,10 @@ public class GraphQLStartupActivity implements StartupActivity, DumbAware {
2021

2122
@Override
2223
public void runActivity(@NotNull Project project) {
24+
if(ApplicationManager.getApplication().isUnitTestMode()) {
25+
// don't create the UI when unit testing
26+
return;
27+
}
2328
// startup the UI service
2429
JSGraphQLLanguageUIProjectService.getService(project);
2530
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2018-present, Jim Kynde Meyer
3+
* All rights reserved.
4+
* <p>
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.endpoint.ide.startup.javascript;
9+
10+
import com.intellij.lang.javascript.DialectDetector;
11+
import com.intellij.lang.javascript.ecmascript6.TypeScriptUtil;
12+
import com.intellij.lang.jsgraphql.ide.references.GraphQLFindUsagesUtil;
13+
import com.intellij.openapi.project.DumbAware;
14+
import com.intellij.openapi.project.Project;
15+
import com.intellij.openapi.startup.StartupActivity;
16+
import org.jetbrains.annotations.NotNull;
17+
18+
public class GraphQLJavaScriptStartupActivity implements StartupActivity, DumbAware {
19+
@Override
20+
public void runActivity(@NotNull Project project) {
21+
22+
// register the JS file types for find usages
23+
GraphQLFindUsagesUtil.INCLUDED_FILE_TYPES.addAll(TypeScriptUtil.TYPESCRIPT_FILE_TYPES);
24+
GraphQLFindUsagesUtil.INCLUDED_FILE_TYPES.addAll(DialectDetector.JAVASCRIPT_FILE_TYPES);
25+
}
26+
}

src/main/com/intellij/lang/jsgraphql/ide/formatter/GraphQLBlockWrapper.java renamed to src/main/com/intellij/lang/jsgraphql/ide/formatter/javascript/GraphQLBlockWrapper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* This source code is licensed under the MIT license found in the
66
* LICENSE file in the root directory of this source tree.
77
*/
8-
package com.intellij.lang.jsgraphql.ide.formatter;
8+
package com.intellij.lang.jsgraphql.ide.formatter.javascript;
99

1010
import com.intellij.formatting.ASTBlock;
1111
import com.intellij.formatting.Alignment;
@@ -20,7 +20,7 @@
2020
import com.intellij.lang.Language;
2121
import com.intellij.lang.javascript.psi.ecma6.JSStringTemplateExpression;
2222
import com.intellij.lang.jsgraphql.GraphQLLanguage;
23-
import com.intellij.lang.jsgraphql.ide.injection.GraphQLLanguageInjectionUtil;
23+
import com.intellij.lang.jsgraphql.ide.injection.javascript.GraphQLLanguageInjectionUtil;
2424
import com.intellij.openapi.util.Ref;
2525
import com.intellij.openapi.util.TextRange;
2626
import com.intellij.psi.PsiDocumentManager;

src/main/com/intellij/lang/jsgraphql/ide/formatter/GraphQLInjectedFormattingModelBuilder.java renamed to src/main/com/intellij/lang/jsgraphql/ide/formatter/javascript/GraphQLInjectedFormattingModelBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* This source code is licensed under the MIT license found in the
66
* LICENSE file in the root directory of this source tree.
77
*/
8-
package com.intellij.lang.jsgraphql.ide.formatter;
8+
package com.intellij.lang.jsgraphql.ide.formatter.javascript;
99

1010
import com.intellij.formatting.Block;
1111
import com.intellij.formatting.CustomFormattingModelBuilder;
@@ -17,7 +17,7 @@
1717
import com.intellij.lang.LanguageFormatting;
1818
import com.intellij.lang.javascript.psi.JSFile;
1919
import com.intellij.lang.javascript.psi.ecma6.JSStringTemplateExpression;
20-
import com.intellij.lang.jsgraphql.ide.injection.GraphQLLanguageInjectionUtil;
20+
import com.intellij.lang.jsgraphql.ide.injection.javascript.GraphQLLanguageInjectionUtil;
2121
import com.intellij.openapi.util.Key;
2222
import com.intellij.openapi.util.TextRange;
2323
import com.intellij.psi.PsiElement;

src/main/com/intellij/lang/jsgraphql/ide/formatter/GraphQLInjectedLanguageBlockBuilder.java renamed to src/main/com/intellij/lang/jsgraphql/ide/formatter/javascript/GraphQLInjectedLanguageBlockBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* This source code is licensed under the MIT license found in the
66
* LICENSE file in the root directory of this source tree.
77
*/
8-
package com.intellij.lang.jsgraphql.ide.formatter;
8+
package com.intellij.lang.jsgraphql.ide.formatter.javascript;
99

1010
import com.google.common.collect.Lists;
1111
import com.intellij.formatting.Alignment;

src/main/com/intellij/lang/jsgraphql/ide/injection/GraphQLLanguageInjectionUtil.java renamed to src/main/com/intellij/lang/jsgraphql/ide/injection/javascript/GraphQLLanguageInjectionUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* This source code is licensed under the MIT license found in the
66
* LICENSE file in the root directory of this source tree.
77
*/
8-
package com.intellij.lang.jsgraphql.ide.injection;
8+
package com.intellij.lang.jsgraphql.ide.injection.javascript;
99

1010
import com.google.common.collect.Sets;
1111
import com.intellij.ide.util.PropertiesComponent;

src/main/com/intellij/lang/jsgraphql/ide/injection/GraphQLTemplateFragmentLanguageInjector.java renamed to src/main/com/intellij/lang/jsgraphql/ide/injection/javascript/GraphQLTemplateFragmentLanguageInjector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* This source code is licensed under the MIT license found in the
66
* LICENSE file in the root directory of this source tree.
77
*/
8-
package com.intellij.lang.jsgraphql.ide.injection;
8+
package com.intellij.lang.jsgraphql.ide.injection.javascript;
99

1010
import com.google.common.collect.Lists;
1111
import com.intellij.lang.ASTNode;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) 2018-present, Jim Kynde Meyer
3+
* All rights reserved.
4+
* <p>
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.project;
9+
10+
import com.intellij.psi.PsiElement;
11+
import com.intellij.psi.PsiFile;
12+
import com.intellij.psi.search.GlobalSearchScope;
13+
14+
import java.util.function.Consumer;
15+
16+
public interface GraphQLInjectionSearchHelper {
17+
18+
/**
19+
* Process injected GraphQL PsiFiles
20+
*
21+
* @param scopedElement the starting point of the enumeration settings the scopedElement of the processing
22+
* @param schemaScope the search scope to use for limiting the schema definitions
23+
* @param consumer a consumer that will be invoked for each injected GraphQL PsiFile
24+
*/
25+
void processInjectedGraphQLPsiFiles(PsiElement scopedElement, GlobalSearchScope schemaScope, Consumer<PsiFile> consumer);
26+
27+
}

src/main/com/intellij/lang/jsgraphql/ide/project/GraphQLPsiSearchHelper.java

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
import com.google.common.collect.Lists;
1212
import com.google.common.collect.Maps;
1313
import com.intellij.ide.plugins.PluginManager;
14-
import com.intellij.lang.injection.InjectedLanguageManager;
1514
import com.intellij.lang.jsgraphql.GraphQLLanguage;
16-
import com.intellij.lang.jsgraphql.ide.injection.GraphQLInjectionIndex;
17-
import com.intellij.lang.jsgraphql.ide.injection.GraphQLLanguageInjectionUtil;
1815
import com.intellij.lang.jsgraphql.ide.references.GraphQLFindUsagesUtil;
1916
import com.intellij.lang.jsgraphql.psi.GraphQLElementTypes;
2017
import com.intellij.lang.jsgraphql.psi.GraphQLFragmentDefinition;
@@ -42,7 +39,6 @@
4239
import com.intellij.psi.search.scope.packageSet.NamedScope;
4340
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
4441
import com.intellij.psi.util.PsiTreeUtil;
45-
import com.intellij.util.indexing.FileBasedIndex;
4642
import org.apache.commons.compress.utils.IOUtils;
4743
import org.jetbrains.annotations.NotNull;
4844

@@ -64,8 +60,6 @@ public class GraphQLPsiSearchHelper {
6460

6561
private final static Logger log = Logger.getInstance(GraphQLPsiSearchHelper.class);
6662

67-
private static final FileType[] FILE_TYPES = GraphQLFindUsagesUtil.INCLUDED_FILE_TYPES.toArray(new FileType[GraphQLFindUsagesUtil.INCLUDED_FILE_TYPES.size()]);
68-
6963
private final Project myProject;
7064
private PluginDescriptor pluginDescriptor;
7165
private final Map<String, GraphQLFragmentDefinition> fragmentDefinitionsByName = Maps.newConcurrentMap();
@@ -81,7 +75,8 @@ public GraphQLPsiSearchHelper(@NotNull final Project project) {
8175
myProject = project;
8276
pluginDescriptor = PluginManager.getPlugin(PluginId.getId("com.intellij.lang.jsgraphql"));
8377
builtInSchemaScope = GlobalSearchScope.fileScope(project, getBuiltInSchema().getVirtualFile());
84-
searchScope = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.projectScope(myProject), FILE_TYPES).union(builtInSchemaScope);
78+
final FileType[] searchScopeFileTypes = GraphQLFindUsagesUtil.INCLUDED_FILE_TYPES.toArray(new FileType[GraphQLFindUsagesUtil.INCLUDED_FILE_TYPES.size()]);
79+
searchScope = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.projectScope(myProject), searchScopeFileTypes).union(builtInSchemaScope);
8580
project.getMessageBus().connect().subscribe(PsiManagerImpl.ANY_PSI_CHANGE_TOPIC, new AnyPsiChangeListener.Adapter() {
8681
@Override
8782
public void beforePsiChanged(boolean isPhysical) {
@@ -137,6 +132,7 @@ public GlobalSearchScope getUseScope(PsiElement element) {
137132
* Finds all fragment definition across files in the project
138133
*
139134
* @param scopedElement the starting point for finding known fragment definitions
135+
*
140136
* @return a list of known fragment definitions, or an empty list if the index is not yet ready
141137
*/
142138
public List<GraphQLFragmentDefinition> getKnownFragmentDefinitions(PsiElement scopedElement) {
@@ -162,6 +158,7 @@ public List<GraphQLFragmentDefinition> getKnownFragmentDefinitions(PsiElement sc
162158
* Gets a resolved reference or null if no reference or resolved element is found
163159
*
164160
* @param psiElement the element to get a resolved reference for
161+
*
165162
* @return the resolved reference, or null if non is available
166163
*/
167164
public static GraphQLIdentifier getResolvedReference(GraphQLNamedElement psiElement) {
@@ -232,45 +229,28 @@ public PsiFile getBuiltInSchema() {
232229
}
233230

234231
/**
235-
* Uses the {@link GraphQLInjectionIndex} to process injected GraphQL PsiFiles
232+
* Process injected GraphQL PsiFiles
236233
*
237234
* @param scopedElement the starting point of the enumeration settings the scopedElement of the processing
235+
* @param schemaScope the search scope to use for limiting the schema definitions
238236
* @param consumer a consumer that will be invoked for each injected GraphQL PsiFile
239237
*/
240-
public void processInjectedGraphQLPsiFiles(PsiElement scopedElement, Consumer<PsiFile> consumer) {
241-
final PsiManager psiManager = PsiManager.getInstance(scopedElement.getProject());
242-
final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(scopedElement.getProject());
243-
FileBasedIndex.getInstance().getFilesWithKey(GraphQLInjectionIndex.NAME, Collections.singleton(GraphQLInjectionIndex.DATA_KEY), virtualFile -> {
244-
final PsiFile fileWithInjection = psiManager.findFile(virtualFile);
245-
if (fileWithInjection != null) {
246-
fileWithInjection.accept(new PsiRecursiveElementVisitor() {
247-
@Override
248-
public void visitElement(PsiElement element) {
249-
if (GraphQLLanguageInjectionUtil.isJSGraphQLLanguageInjectionTarget(element)) {
250-
injectedLanguageManager.enumerate(element, (injectedPsi, places) -> {
251-
consumer.accept(injectedPsi);
252-
});
253-
} else {
254-
// visit deeper until injection found
255-
super.visitElement(element);
256-
}
257-
}
258-
});
259-
}
260-
return true;
261-
}, getSchemaScope(scopedElement));
262-
238+
public void processInjectedGraphQLPsiFiles(PsiElement scopedElement, GlobalSearchScope schemaScope, Consumer<PsiFile> consumer) {
239+
GraphQLInjectionSearchHelper graphQLInjectionSearchHelper = ServiceManager.getService(myProject, GraphQLInjectionSearchHelper.class);
240+
if (graphQLInjectionSearchHelper != null) {
241+
graphQLInjectionSearchHelper.processInjectedGraphQLPsiFiles(scopedElement, schemaScope, consumer);
242+
}
263243
}
264244

265245
/**
266246
* Gets the virtual file system path of a PSI file
267247
*/
268248
public static String getFileName(PsiFile psiFile) {
269249
VirtualFile virtualFile = psiFile.getVirtualFile();
270-
if(virtualFile == null) {
250+
if (virtualFile == null) {
271251
virtualFile = psiFile.getOriginalFile().getVirtualFile();
272252
}
273-
if(virtualFile != null) {
253+
if (virtualFile != null) {
274254
return virtualFile.getPath();
275255
}
276256
return psiFile.getName();

src/main/com/intellij/lang/jsgraphql/ide/injection/GraphQLInjectionIndex.java renamed to src/main/com/intellij/lang/jsgraphql/ide/project/javascript/GraphQLInjectionIndex.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
* This source code is licensed under the MIT license found in the
66
* LICENSE file in the root directory of this source tree.
77
*/
8-
package com.intellij.lang.jsgraphql.ide.injection;
8+
package com.intellij.lang.jsgraphql.ide.project.javascript;
99

1010
import com.intellij.lang.jsgraphql.GraphQLFileType;
11+
import com.intellij.lang.jsgraphql.ide.injection.javascript.GraphQLLanguageInjectionUtil;
1112
import com.intellij.lang.jsgraphql.ide.references.GraphQLFindUsagesUtil;
1213
import com.intellij.openapi.util.Ref;
1314
import com.intellij.psi.PsiElement;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) 2018-present, Jim Kynde Meyer
3+
* All rights reserved.
4+
* <p>
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.project.javascript;
9+
10+
import com.intellij.lang.injection.InjectedLanguageManager;
11+
import com.intellij.lang.jsgraphql.ide.injection.javascript.GraphQLLanguageInjectionUtil;
12+
import com.intellij.lang.jsgraphql.ide.project.GraphQLInjectionSearchHelper;
13+
import com.intellij.psi.PsiElement;
14+
import com.intellij.psi.PsiFile;
15+
import com.intellij.psi.PsiManager;
16+
import com.intellij.psi.PsiRecursiveElementVisitor;
17+
import com.intellij.psi.search.GlobalSearchScope;
18+
import com.intellij.util.indexing.FileBasedIndex;
19+
20+
import java.util.Collections;
21+
import java.util.function.Consumer;
22+
23+
public class GraphQLJavascriptInjectionSearchHelper implements GraphQLInjectionSearchHelper {
24+
25+
/**
26+
* Uses the {@link GraphQLInjectionIndex} to process injected GraphQL PsiFiles
27+
*
28+
* @param scopedElement the starting point of the enumeration settings the scopedElement of the processing
29+
* @param schemaScope the search scope to use for limiting the schema definitions
30+
* @param consumer a consumer that will be invoked for each injected GraphQL PsiFile
31+
*/
32+
public void processInjectedGraphQLPsiFiles(PsiElement scopedElement, GlobalSearchScope schemaScope, Consumer<PsiFile> consumer) {
33+
final PsiManager psiManager = PsiManager.getInstance(scopedElement.getProject());
34+
final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(scopedElement.getProject());
35+
FileBasedIndex.getInstance().getFilesWithKey(GraphQLInjectionIndex.NAME, Collections.singleton(GraphQLInjectionIndex.DATA_KEY), virtualFile -> {
36+
final PsiFile fileWithInjection = psiManager.findFile(virtualFile);
37+
if (fileWithInjection != null) {
38+
fileWithInjection.accept(new PsiRecursiveElementVisitor() {
39+
@Override
40+
public void visitElement(PsiElement element) {
41+
if (GraphQLLanguageInjectionUtil.isJSGraphQLLanguageInjectionTarget(element)) {
42+
injectedLanguageManager.enumerate(element, (injectedPsi, places) -> {
43+
consumer.accept(injectedPsi);
44+
});
45+
} else {
46+
// visit deeper until injection found
47+
super.visitElement(element);
48+
}
49+
}
50+
});
51+
}
52+
return true;
53+
}, schemaScope);
54+
55+
}
56+
}

src/main/com/intellij/lang/jsgraphql/ide/references/GraphQLFindUsagesUtil.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
package com.intellij.lang.jsgraphql.ide.references;
99

1010
import com.google.common.collect.Sets;
11-
import com.intellij.lang.javascript.DialectDetector;
12-
import com.intellij.lang.javascript.ecmascript6.TypeScriptUtil;
1311
import com.intellij.lang.jsgraphql.GraphQLFileType;
1412
import com.intellij.openapi.fileTypes.FileType;
1513

@@ -21,9 +19,6 @@ public class GraphQLFindUsagesUtil {
2119

2220
static {
2321
INCLUDED_FILE_TYPES.add(GraphQLFileType.INSTANCE);
24-
// TODO JKM optional dep on JavaScript plugin
25-
INCLUDED_FILE_TYPES.addAll(TypeScriptUtil.TYPESCRIPT_FILE_TYPES);
26-
INCLUDED_FILE_TYPES.addAll(DialectDetector.JAVASCRIPT_FILE_TYPES);
2722
}
2823

2924

0 commit comments

Comments
 (0)