Skip to content

Commit c35f5ca

Browse files
committed
fix equals / hashCode violation for services tags index; introduce set to array value migration #737
1 parent a5b0aa7 commit c35f5ca

File tree

5 files changed

+74
-45
lines changed

5 files changed

+74
-45
lines changed

src/fr/adrienbrault/idea/symfony2plugin/stubs/indexes/ServicesTagStubIndex.java

+21-33
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import com.intellij.util.io.KeyDescriptor;
1010
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
1111
import fr.adrienbrault.idea.symfony2plugin.form.util.FormUtil;
12-
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.externalizer.ArrayDataExternalizer;
12+
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.externalizer.StringSetDataExternalizer;
1313
import gnu.trove.THashMap;
1414
import org.jetbrains.annotations.NotNull;
1515
import org.jetbrains.yaml.YAMLFileType;
@@ -19,55 +19,43 @@
1919
import java.util.Set;
2020

2121

22-
public class ServicesTagStubIndex extends FileBasedIndexExtension<String, String[]> {
22+
public class ServicesTagStubIndex extends FileBasedIndexExtension<String, Set<String>> {
2323

24-
public static final ID<String, String[]> KEY = ID.create("fr.adrienbrault.idea.symfony2plugin.service_tags");
24+
public static final ID<String, Set<String>> KEY = ID.create("fr.adrienbrault.idea.symfony2plugin.service_tags");
2525
private final KeyDescriptor<String> myKeyDescriptor = new EnumeratorStringDescriptor();
2626

2727
@NotNull
2828
@Override
29-
public DataIndexer<String, String[], FileContent> getIndexer() {
29+
public DataIndexer<String, Set<String>, FileContent> getIndexer() {
3030

31-
return new DataIndexer<String, String[], FileContent>() {
32-
@NotNull
33-
@Override
34-
public Map<String, String[]> map(@NotNull FileContent inputData) {
31+
return inputData -> {
3532

36-
Map<String, String[]> map = new THashMap<String, String[]>();
33+
Map<String, Set<String>> map = new THashMap<>();
3734

38-
PsiFile psiFile = inputData.getPsiFile();
39-
if(!Symfony2ProjectComponent.isEnabledForIndex(psiFile.getProject())) {
40-
return map;
41-
}
42-
43-
if (!ServicesDefinitionStubIndex.isValidForIndex(inputData, psiFile)) {
44-
return map;
45-
}
46-
47-
if(psiFile instanceof YAMLFile) {
48-
this.attachSet(FormUtil.getTags((YAMLFile) psiFile), map);
49-
}
50-
51-
if(psiFile instanceof XmlFile) {
52-
this.attachSet(FormUtil.getTags((XmlFile) psiFile), map);
53-
}
35+
PsiFile psiFile = inputData.getPsiFile();
36+
if(!Symfony2ProjectComponent.isEnabledForIndex(psiFile.getProject())) {
37+
return map;
38+
}
5439

40+
if (!ServicesDefinitionStubIndex.isValidForIndex(inputData, psiFile)) {
5541
return map;
5642
}
5743

58-
private void attachSet(Map<String, Set<String>> source, Map<String, String[]> target) {
59-
for(Map.Entry<String, Set<String>> entry: source.entrySet()) {
60-
Set<String> key = entry.getValue();
61-
target.put(entry.getKey(), key.toArray(new String[key.size()]));
62-
}
44+
if(psiFile instanceof YAMLFile) {
45+
map.putAll(FormUtil.getTags((YAMLFile) psiFile));
46+
}
47+
48+
if(psiFile instanceof XmlFile) {
49+
map.putAll(FormUtil.getTags((XmlFile) psiFile));
6350
}
6451

52+
return map;
6553
};
6654
}
6755

6856
@NotNull
6957
@Override
70-
public ID<String, String[]> getName() {
58+
public ID<String, Set<String>> getName() {
7159
return KEY;
7260
}
7361

@@ -78,8 +66,8 @@ public KeyDescriptor<String> getKeyDescriptor() {
7866
}
7967

8068
@NotNull
81-
public DataExternalizer<String[]> getValueExternalizer() {
82-
return new ArrayDataExternalizer();
69+
public DataExternalizer<Set<String>> getValueExternalizer() {
70+
return new StringSetDataExternalizer();
8371
}
8472

8573
@NotNull
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package fr.adrienbrault.idea.symfony2plugin.stubs.indexes.externalizer;
2+
3+
import com.intellij.util.io.DataExternalizer;
4+
import com.intellij.util.io.EnumeratorStringDescriptor;
5+
import gnu.trove.THashSet;
6+
import org.jetbrains.annotations.NotNull;
7+
8+
import java.io.DataInput;
9+
import java.io.DataOutput;
10+
import java.io.IOException;
11+
import java.util.Iterator;
12+
import java.util.Set;
13+
14+
/**
15+
* @author Daniel Espendiller <daniel@espendiller.net>
16+
*
17+
* @see com.jetbrains.php.lang.psi.stubs.indexes.PhpTraitUsageIndex
18+
* @see com.jetbrains.php.lang.psi.stubs.indexes.StringSetDataExternalizer
19+
*/
20+
public class StringSetDataExternalizer implements DataExternalizer<Set<String>> {
21+
22+
public synchronized void save(@NotNull DataOutput out, Set<String> value) throws IOException {
23+
out.writeInt(value.size());
24+
Iterator var = value.iterator();
25+
26+
while(var.hasNext()) {
27+
String s = (String)var.next();
28+
EnumeratorStringDescriptor.INSTANCE.save(out, s);
29+
}
30+
}
31+
32+
public synchronized Set<String> read(@NotNull DataInput in) throws IOException {
33+
Set<String> set = new THashSet<>();
34+
35+
for(int r = in.readInt(); r > 0; --r) {
36+
set.add(EnumeratorStringDescriptor.INSTANCE.read(in));
37+
}
38+
39+
return set;
40+
}
41+
}

src/fr/adrienbrault/idea/symfony2plugin/util/completion/TagNameCompletionProvider.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ public static Collection<LookupElement> getTagLookupElements(Project project) {
4747
FileBasedIndexImpl.getInstance().processAllKeys(ServicesTagStubIndex.KEY, projectUniqueKeysStrong, project);
4848

4949
for(String serviceName: projectUniqueKeysStrong.getResult()) {
50-
List<String[]> tags = FileBasedIndexImpl.getInstance().getValues(ServicesTagStubIndex.KEY, serviceName, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), XmlFileType.INSTANCE, YAMLFileType.YML));
51-
for(String[] tagDef: tags) {
50+
List<Set<String>> tags = FileBasedIndexImpl.getInstance().getValues(ServicesTagStubIndex.KEY, serviceName, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), XmlFileType.INSTANCE, YAMLFileType.YML));
51+
for(Set<String> tagDef: tags) {
5252
for(String tag: tagDef) {
5353
if(!uniqueTags.contains(tag)) {
5454
uniqueTags.add(tag);

src/fr/adrienbrault/idea/symfony2plugin/util/dict/ServiceUtil.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,15 @@ public static Set<String> getPhpClassTags(@NotNull PhpClass phpClass) {
208208
for (String serviceName : result) {
209209

210210
// get service where we found our tags
211-
List<String[]> values = FileBasedIndexImpl.getInstance().getValues(ServicesTagStubIndex.KEY, serviceName, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), XmlFileType.INSTANCE, YAMLFileType.YML));
211+
List<Set<String>> values = FileBasedIndexImpl.getInstance().getValues(ServicesTagStubIndex.KEY, serviceName, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), XmlFileType.INSTANCE, YAMLFileType.YML));
212212
if(values.size() == 0) {
213213
continue;
214214
}
215215

216216
// create unique tag list
217217
Set<String> tags = new HashSet<String>();
218-
for(String[] tagValue: values) {
219-
Collections.addAll(tags, tagValue);
218+
for(Set<String> tagValue: values) {
219+
tags.addAll(tagValue);
220220
}
221221

222222
if(collector == null) {
@@ -275,9 +275,9 @@ public static Set<String> getTaggedServices(Project project, String tagName) {
275275

276276
for(String serviceName: projectUniqueKeysStrong.getResult()) {
277277

278-
List<String[]> serviceDefinitions = FileBasedIndexImpl.getInstance().getValues(ServicesTagStubIndex.KEY, serviceName, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), XmlFileType.INSTANCE, YAMLFileType.YML));
279-
for(String[] strings: serviceDefinitions) {
280-
if(Arrays.asList(strings).contains(tagName)) {
278+
List<Set<String>> serviceDefinitions = FileBasedIndexImpl.getInstance().getValues(ServicesTagStubIndex.KEY, serviceName, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), XmlFileType.INSTANCE, YAMLFileType.YML));
279+
for(Set<String> strings: serviceDefinitions) {
280+
if(strings.contains(tagName)) {
281281
service.add(serviceName);
282282
}
283283
}

tests/fr/adrienbrault/idea/symfony2plugin/tests/stubs/indexes/ServicesTagStubIndexTest.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.ServicesTagStubIndex;
44
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
5-
import org.apache.commons.lang.ArrayUtils;
65
import org.jetbrains.annotations.NotNull;
76

87
import java.io.File;
8+
import java.util.Set;
99

1010
/**
1111
* @author Daniel Espendiller <daniel@espendiller.net>
@@ -34,7 +34,7 @@ public void testTaggedServiceValueInIndex() {
3434
assertIndexContainsKeyWithValue(ServicesTagStubIndex.KEY, "foo.tagged.yaml_type", new MyStringContainsAssert("yaml_type_tag"));
3535
}
3636

37-
private static class MyStringContainsAssert implements IndexValue.Assert<String[]> {
37+
private static class MyStringContainsAssert implements IndexValue.Assert<Set<String>> {
3838
@NotNull
3939
private final String find;
4040

@@ -43,8 +43,8 @@ public MyStringContainsAssert(@NotNull String find) {
4343
}
4444

4545
@Override
46-
public boolean match(@NotNull String[] value) {
47-
return ArrayUtils.contains(value, this.find);
46+
public boolean match(@NotNull Set<String> value) {
47+
return value.contains(this.find);
4848
}
4949
}
5050
}

0 commit comments

Comments
 (0)