[performance optimization] use VirtualFile.getNameSequence() instead of VirtualFile...
[idea/community.git] / python / src / com / jetbrains / python / psi / stubs / PySetuptoolsNamespaceIndex.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python.psi.stubs;
17
18 import com.intellij.openapi.project.Project;
19 import com.intellij.openapi.util.text.StringUtil;
20 import com.intellij.openapi.vfs.VirtualFile;
21 import com.intellij.psi.search.GlobalSearchScope;
22 import com.intellij.util.indexing.*;
23 import com.intellij.util.io.EnumeratorStringDescriptor;
24 import com.intellij.util.io.KeyDescriptor;
25 import com.jetbrains.python.psi.search.PyProjectScopeBuilder;
26 import org.jetbrains.annotations.NotNull;
27
28 import java.util.Collection;
29 import java.util.HashMap;
30 import java.util.Map;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34 /**
35  * @author vlan
36  */
37 public class PySetuptoolsNamespaceIndex extends ScalarIndexExtension<String> {
38   public static final ID<String, Void> NAME = ID.create("Py.setuptools.namespace");
39   private static final Pattern RE_NAMESPACE = Pattern.compile("sys\\.modules\\.setdefault\\('([^']*)'");
40   private static final String NAMESPACE_FILE_SUFFIX = "-nspkg.pth";
41
42   private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor();
43
44   private final DataIndexer<String, Void, FileContent> myDataIndexer = new DataIndexer<String, Void, FileContent>() {
45     @NotNull
46     @Override
47     public Map<String, Void> map(@NotNull FileContent inputData) {
48       final CharSequence content = inputData.getContentAsText();
49       final Matcher matcher = RE_NAMESPACE.matcher(content);
50       final Map<String, Void> results = new HashMap<String, Void>();
51       while (matcher.find()) {
52         final String packageName = matcher.group(1);
53         results.put(packageName, null);
54       }
55       return results;
56     }
57   };
58
59   private FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
60     @Override
61     public boolean acceptInput(@NotNull VirtualFile file) {
62       return StringUtil.endsWith(file.getNameSequence(), NAMESPACE_FILE_SUFFIX);
63     }
64   };
65
66   @NotNull
67   @Override
68   public ID<String, Void> getName() {
69     return NAME;
70   }
71
72   @NotNull
73   @Override
74   public DataIndexer<String, Void, FileContent> getIndexer() {
75     return myDataIndexer;
76   }
77
78   @NotNull
79   @Override
80   public KeyDescriptor<String> getKeyDescriptor() {
81     return myKeyDescriptor;
82   }
83
84   @NotNull
85   @Override
86   public FileBasedIndex.InputFilter getInputFilter() {
87     return myInputFilter;
88   }
89
90   @Override
91   public boolean dependsOnFileContent() {
92     return true;
93   }
94
95   @Override
96   public int getVersion() {
97     return 0;
98   }
99
100   @NotNull
101   public static Collection<VirtualFile> find(@NotNull String name, @NotNull Project project) {
102     final GlobalSearchScope scope = PyProjectScopeBuilder.excludeSdkTestsScope(project);
103     return FileBasedIndex.getInstance().getContainingFiles(NAME, name, scope);
104   }
105 }