Skip to content

Commit 1114f0f

Browse files
committed
Added stub indexes, fixed exceptions during parsing
1 parent 1d4bebb commit 1114f0f

File tree

69 files changed

+1445
-192
lines changed

Some content is hidden

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

69 files changed

+1445
-192
lines changed

.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@ local.properties
66
/src/main/java/src/cz/juzna/intellij/neon/parser/_NeonLexer.flex
77

88
intellij-neon.iws
9-
out/
109
src/main/java/src/cz/juzna/intellij/neon/lexer/_NeonLexer.java
1110
src/main/java/src/cz/juzna/intellij/neon/lexer/_NeonTokenTypes.java
1211
src/main/java/src/cz/juzna/intellij/neon/parser/_NeonLexer.flex
1312
src/main/java/src/cz/juzna/intellij/neon/parser/NeonParser.java
1413
src/main/java/src/cz/juzna/intellij/neon/psi/generated/*
1514
src/main/java/src/cz/juzna/intellij/neon/psi/impl/generated/*
16-
gen/
1715

1816
/.idea
1917
/.gradle
20-
/build
21-
/out
18+
/build

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import org.jetbrains.grammarkit.tasks.*
22

33
plugins {
4-
id 'org.jetbrains.intellij' version "0.4.20"
5-
id "org.jetbrains.grammarkit" version "2020.2"
4+
id 'org.jetbrains.intellij' version "0.6.5"
5+
id "org.jetbrains.grammarkit" version "2020.3"
66
}
77

88
sourceSets {
@@ -19,7 +19,7 @@ properties.load(project.rootProject.file("local.properties").newDataInputStream(
1919
sourceCompatibility = 1.8
2020
targetCompatibility = 1.8
2121

22-
version '1.0.0-RC1'
22+
version '1.0.0-alfa2'
2323
group 'cz.juzna.intellij.neon'
2424

2525
jar {

gradle.properties

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
ideaVersion = 2020.2
2-
phpPluginVersion = 202.6397.115
3-
toolboxPluginVersion = 0.4.6
4-
annotationPluginVersion = 5.3
1+
ideaVersion = 2020.3
2+
phpPluginVersion = 203.5981.155

src/main/java/cz/juzna/intellij/neon/completion/NeonCompletionContributor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212
public class NeonCompletionContributor extends CompletionContributor {
1313
public NeonCompletionContributor() {
14-
extend(CompletionType.BASIC, StandardPatterns.instanceOf(PsiElement.class), new MethodCompletionProvider());
14+
extend(CompletionType.BASIC, StandardPatterns.instanceOf(PsiElement.class), new PhpCompletionProvider());
1515
extend(CompletionType.BASIC, StandardPatterns.instanceOf(PsiElement.class), new ParameterCompletionProvider());
1616
extend(CompletionType.BASIC, StandardPatterns.instanceOf(PsiElement.class), new ServiceCompletionProvider());
1717
extend(CompletionType.BASIC, StandardPatterns.instanceOf(PsiElement.class), new KeywordCompletionProvider());

src/main/java/cz/juzna/intellij/neon/completion/insert/PhpReferenceInsertHandler.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,19 @@ public void handleInsert(InsertionContext context, LookupElement lookupElement)
4646
}
4747

4848
String fqn = classNamespace;
49-
if (!existingNamespace.startsWith("\\") && fqn.startsWith("\\")) {
49+
if (!classNamespace.equals("\\") && !existingNamespace.startsWith("\\") && fqn.startsWith("\\")) {
5050
fqn = fqn.substring(1);
51+
} else if (classNamespace.equals("\\") && existingNamespace.length() == 0) {
52+
fqn = "\\";
5153
}
5254

53-
if (fqn.contains(existingNamespace)) {
55+
if (existingNamespace.length() > 0 && fqn.contains(existingNamespace)) {
5456
fqn = fqn.replace(existingNamespace, "");
5557
}
5658

5759
if (incompleteKey) {
58-
context.getDocument().insertString(context.getTailOffset(), ": ");
59-
context.getEditor().getCaretModel().moveToOffset(context.getEditor().getCaretModel().getOffset() + 2);
60+
//context.getDocument().insertString(context.getTailOffset(), ": ");
61+
//context.getEditor().getCaretModel().moveToOffset(context.getEditor().getCaretModel().getOffset() + 2);
6062
}
6163
context.getDocument().insertString(context.getStartOffset(), fqn);
6264
PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument());
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package cz.juzna.intellij.neon.completion.insert;
2+
3+
import com.intellij.codeInsight.completion.*;
4+
import com.intellij.codeInsight.lookup.LookupElement;
5+
import com.intellij.openapi.editor.CaretModel;
6+
import com.intellij.openapi.editor.Editor;
7+
import com.intellij.openapi.editor.EditorModificationUtil;
8+
import com.intellij.psi.PsiDocumentManager;
9+
import com.intellij.psi.PsiElement;
10+
import com.jetbrains.php.lang.parser.PhpElementTypes;
11+
import com.jetbrains.php.lang.psi.PhpPsiUtil;
12+
import com.jetbrains.php.lang.psi.elements.Variable;
13+
import cz.juzna.intellij.neon.NeonLanguage;
14+
import org.jetbrains.annotations.NotNull;
15+
16+
public class PhpVariableInsertHandler implements InsertHandler<LookupElement> {
17+
18+
private static final PhpVariableInsertHandler instance = new PhpVariableInsertHandler();
19+
20+
public PhpVariableInsertHandler() {
21+
super();
22+
}
23+
24+
public void handleInsert(@NotNull InsertionContext context, @NotNull LookupElement lookupElement) {
25+
PsiElement element = context.getFile().findElementAt(context.getStartOffset());
26+
if (element != null && element.getLanguage() == NeonLanguage.INSTANCE) {
27+
PsiElement parent = element.getParent();
28+
if (!(parent instanceof Variable) && !element.getText().startsWith("$")) {
29+
Editor editor = context.getEditor();
30+
CaretModel caretModel = editor.getCaretModel();
31+
int offset = caretModel.getOffset();
32+
caretModel.moveToOffset(element.getTextOffset() + (PhpPsiUtil.isOfType(parent, PhpElementTypes.CAST_EXPRESSION) ? 1 : 0));
33+
EditorModificationUtil.insertStringAtCaret(editor, "$");
34+
caretModel.moveToOffset(offset + 1);
35+
PsiDocumentManager.getInstance(context.getProject()).commitDocument(editor.getDocument());
36+
}
37+
}
38+
}
39+
40+
public static PhpVariableInsertHandler getInstance() {
41+
return instance;
42+
}
43+
}

src/main/java/cz/juzna/intellij/neon/completion/providers/ClassCompletionProvider.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,10 @@
33
import com.intellij.codeInsight.completion.CompletionParameters;
44
import com.intellij.codeInsight.completion.CompletionProvider;
55
import com.intellij.codeInsight.completion.CompletionResultSet;
6-
import com.intellij.codeInsight.completion.PrefixMatcher;
76
import com.intellij.openapi.project.Project;
87
import com.intellij.psi.PsiElement;
9-
import com.intellij.psi.util.PsiTreeUtil;
108
import com.intellij.util.ProcessingContext;
11-
import com.jetbrains.php.PhpIndex;
12-
import com.jetbrains.php.completion.PhpCompletionUtil;
139
import com.jetbrains.php.completion.PhpLookupElement;
14-
import com.jetbrains.php.completion.insert.PhpClassStaticInsertHandler;
15-
import com.jetbrains.php.completion.insert.PhpNamespaceInsertHandler;
1610
import com.jetbrains.php.lang.psi.elements.PhpClass;
1711
import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
1812
import cz.juzna.intellij.neon.completion.CompletionUtil;
@@ -22,10 +16,8 @@
2216
import cz.juzna.intellij.neon.psi.NeonNamespaceReference;
2317
import cz.juzna.intellij.neon.psi.NeonValue;
2418
import cz.juzna.intellij.neon.util.NeonPhpUtil;
25-
import gnu.trove.THashSet;
2619
import org.jetbrains.annotations.NotNull;
2720

28-
import java.util.ArrayList;
2921
import java.util.Collection;
3022
import java.util.HashSet;
3123
import java.util.Set;
@@ -72,15 +64,15 @@ protected void addCompletions(
7264

7365
Project project = params.getPosition().getProject();
7466
Collection<String> classNames = NeonPhpUtil.getAllExistingClassNames(project, results.getPrefixMatcher());
75-
Collection<PhpNamedElement> variants = NeonPhpUtil.getAllClassNamesAndInterfaces(project, classNames, namespace);
67+
Collection<PhpClass> variants = NeonPhpUtil.getAllClassNamesAndInterfaces(project, classNames, namespace);
7668

7769
// Add variants
7870
for (PhpNamedElement item : variants) {
7971
PhpLookupElement lookupItem = new PhpLookupElement(item) {
8072
@Override
8173
public Set<String> getAllLookupStrings() {
8274
Set<String> original = super.getAllLookupStrings();
83-
Set<String> strings = new HashSet<String>(original.size() + 1);
75+
Set<String> strings = new HashSet<>(original.size() + 1);
8476
strings.addAll(original);
8577
strings.add(this.getNamedElement().getFQN().substring(1));
8678
return strings;
Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
import com.intellij.psi.PsiElement;
77
import com.intellij.util.ProcessingContext;
88
import com.jetbrains.php.completion.PhpLookupElement;
9+
import com.jetbrains.php.completion.insert.PhpFieldInsertHandler;
910
import com.jetbrains.php.completion.insert.PhpMethodInsertHandler;
11+
import com.jetbrains.php.lang.psi.elements.Field;
1012
import com.jetbrains.php.lang.psi.elements.Method;
1113
import com.jetbrains.php.lang.psi.elements.PhpClass;
1214
import cz.juzna.intellij.neon.completion.CompletionUtil;
15+
import cz.juzna.intellij.neon.completion.insert.PhpVariableInsertHandler;
1316
import cz.juzna.intellij.neon.config.NeonConfiguration;
1417
import cz.juzna.intellij.neon.config.NeonService;
1518
import cz.juzna.intellij.neon.psi.*;
@@ -20,13 +23,13 @@
2023
/**
2124
* Complete parameters
2225
*/
23-
public class MethodCompletionProvider extends CompletionProvider<CompletionParameters> {
26+
public class PhpCompletionProvider extends CompletionProvider<CompletionParameters> {
2427
// current element
2528
PsiElement curr;
2629

2730
boolean isMagicPrefixed;
2831

29-
public MethodCompletionProvider() {
32+
public PhpCompletionProvider() {
3033
super();
3134
}
3235

@@ -43,68 +46,83 @@ protected void addCompletions(
4346

4447
isMagicPrefixed = results.getPrefixMatcher().getPrefix().startsWith("__");
4548

46-
boolean hasSomething = false;
49+
boolean isValid = false;
4750
String serviceName = NeonPsiImplUtil.getServiceName(curr);
48-
if (serviceName.length() > 0) {
49-
hasSomething = findServiceByName(serviceName, params, results);
50-
51-
} else if (curr.getParent() instanceof NeonPhpElementUsage) {
51+
if (curr.getParent() instanceof NeonPhpElementUsage) {
5252
NeonPhpStatementElement statement = ((NeonPhpElementUsage) curr.getParent()).getPhpStatement();
5353
if (statement != null) {
54-
hasSomething = findServiceInStatement((NeonPhpElementUsage) curr.getParent(), params, results);
54+
findServiceInStatement(statement.isStatic(), (NeonPhpElementUsage) curr.getParent(), params, results);
55+
isValid = true;
5556
}
5657

58+
} else if (serviceName.length() > 0) {
59+
findServiceByName(serviceName, params, results);
60+
isValid = true;
5761
}
5862

59-
if (hasSomething && params.getInvocationCount() <= 1) {
63+
if (isValid && params.getInvocationCount() <= 1) {
6064
results.stopHere();
6165
}
6266
}
6367

64-
private boolean findServiceInStatement(
68+
private void findServiceInStatement(
69+
boolean isStatic,
6570
@NotNull NeonPhpElementUsage usageElement,
6671
@NotNull CompletionParameters params,
6772
@NotNull CompletionResultSet results
6873
) {
69-
boolean hasSomething = false;
7074
for (PhpClass phpClass : usageElement.getPhpType().getPhpClasses(curr.getProject())) {
7175
for (Method method : phpClass.getMethods()) {
72-
if (method.getModifier().isPublic()) {
73-
if (attachMethod(method, params, results)) {
74-
hasSomething = true;
75-
}
76+
if (method.getModifier().isPublic() && ((isStatic && method.getModifier().isStatic()) || (!isStatic && !method.getModifier().isStatic()))) {
77+
attachMethod(method, params, results);
78+
}
79+
}
80+
81+
for (Field field : phpClass.getFields()) {
82+
if (!field.getModifier().isPublic()) {
83+
continue;
84+
}
85+
86+
if (isStatic && (field.isConstant() || field.getModifier().isStatic())) {
87+
attachField(field, results);
88+
} else if (!isStatic && !field.getModifier().isStatic()) {
89+
attachField(field, results);
7690
}
7791
}
7892
}
79-
return hasSomething;
8093
}
8194

82-
private boolean findServiceByName(@NotNull String serviceName, @NotNull CompletionParameters params, @NotNull CompletionResultSet results) {
83-
boolean hasSomething = false;
95+
private void findServiceByName(@NotNull String serviceName, @NotNull CompletionParameters params, @NotNull CompletionResultSet results) {
8496
NeonService service = NeonConfiguration.INSTANCE.findService(serviceName, curr.getProject());
8597
if (service != null && service.getPhpType().containsClasses()) {
8698
for (PhpClass phpClass : service.getPhpType().getPhpClasses(curr.getProject())) {
8799
for (Method method : phpClass.getMethods()) {
88100
if (!method.isStatic() && method.getModifier().isPublic()) {
89-
if (attachMethod(method, params, results)) {
90-
hasSomething = true;
91-
}
101+
attachMethod(method, params, results);
92102
}
93103
}
94104
}
95105
}
96-
return hasSomething;
97106
}
98107

99-
private boolean attachMethod(@NotNull Method method, @NotNull CompletionParameters params, @NotNull CompletionResultSet results) {
108+
private void attachMethod(@NotNull Method method, @NotNull CompletionParameters params, @NotNull CompletionResultSet results) {
100109
if (!isMagicPrefixed && params.getInvocationCount() <= 1 && NeonTypesUtil.isExcludedCompletion(method.getName())) {
101-
return false;
110+
return;
102111
}
103112

104113
PhpLookupElement lookupItem = new PhpLookupElement(method);
105114
lookupItem.handler = PhpMethodInsertHandler.getInstance();
106115
results.addElement(lookupItem);
107-
return true;
116+
}
117+
118+
private void attachField(@NotNull Field field, @NotNull CompletionResultSet results) {
119+
PhpLookupElement lookupItem = new PhpLookupElement(field);
120+
if (!field.isConstant() && field.getModifier().isStatic()) {
121+
lookupItem.handler = PhpVariableInsertHandler.getInstance();
122+
} else {
123+
lookupItem.handler = PhpFieldInsertHandler.getInstance();
124+
}
125+
results.addElement(lookupItem);
108126
}
109127

110128
private boolean isValidTarget() {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package cz.juzna.intellij.neon.indexes;
2+
3+
import com.intellij.openapi.project.Project;
4+
import com.intellij.psi.search.GlobalSearchScope;
5+
import cz.juzna.intellij.neon.indexes.extensions.*;
6+
import cz.juzna.intellij.neon.psi.*;
7+
import cz.juzna.intellij.neon.util.NeonPhpUtil;
8+
import org.jetbrains.annotations.NotNull;
9+
10+
import java.util.Collection;
11+
12+
public class NeonIndexUtil {
13+
public static Collection<NeonConstantUsage> findConstantsByName(@NotNull Project project, String name) {
14+
return NeonPhpConstantIndex.getInstance().get(name, project, GlobalSearchScope.allScope(project));
15+
}
16+
17+
public static Collection<NeonStaticVariable> findStaticVariablesByName(@NotNull Project project, String name) {
18+
return NeonPhpStaticVariableIndex.getInstance().get(
19+
NeonPhpUtil.normalizePhpVariable(name),
20+
project,
21+
GlobalSearchScope.allScope(project)
22+
);
23+
}
24+
25+
public static Collection<NeonNamespaceReference> findNamespacesByFqn(@NotNull Project project, String fqn) {
26+
return NeonPhpNamespaceIndex.getInstance().get(
27+
NeonPhpUtil.normalizeClassName(fqn),
28+
project,
29+
GlobalSearchScope.allScope(project)
30+
);
31+
}
32+
33+
public static Collection<NeonMethodUsage> findMethodsByName(@NotNull Project project, String name) {
34+
return NeonPhpMethodIndex.getInstance().get(name, project, GlobalSearchScope.allScope(project));
35+
}
36+
37+
public static Collection<NeonClassReference> getClassesByFqn(@NotNull Project project, String fqn) {
38+
return NeonPhpClassIndex.getInstance().get(
39+
NeonPhpUtil.normalizeClassName(fqn),
40+
project,
41+
GlobalSearchScope.allScope(project)
42+
);
43+
}
44+
45+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package cz.juzna.intellij.neon.indexes.extensions;
2+
3+
import com.intellij.openapi.project.Project;
4+
import com.intellij.psi.search.GlobalSearchScope;
5+
import com.intellij.psi.stubs.StringStubIndexExtension;
6+
import com.intellij.psi.stubs.StubIndex;
7+
import com.intellij.psi.stubs.StubIndexKey;
8+
import cz.juzna.intellij.neon.psi.NeonClassReference;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
import java.util.Collection;
12+
13+
public class NeonPhpClassIndex extends StringStubIndexExtension<NeonClassReference> {
14+
public static final StubIndexKey<String, NeonClassReference> KEY = StubIndexKey.createIndexKey("neon.phpClass.index");
15+
16+
private static final NeonPhpClassIndex ourInstance = new NeonPhpClassIndex();
17+
18+
public static NeonPhpClassIndex getInstance() {
19+
return ourInstance;
20+
}
21+
22+
@Override
23+
public int getVersion() {
24+
return super.getVersion() + 1;
25+
}
26+
27+
@Override
28+
@NotNull
29+
public StubIndexKey<String, NeonClassReference> getKey() {
30+
return KEY;
31+
}
32+
33+
@Override
34+
public Collection<NeonClassReference> get(@NotNull String key, @NotNull Project project, @NotNull GlobalSearchScope scope) {
35+
return StubIndex.getElements(getKey(), key, project, scope, NeonClassReference.class);
36+
}
37+
}

0 commit comments

Comments
 (0)