2988922415d21ade35303d86bdf6f38c1f3166aa
[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.vfs.VirtualFile;
20 import com.intellij.psi.search.GlobalSearchScope;
21 import com.intellij.util.indexing.*;
22 import com.intellij.util.io.EnumeratorStringDescriptor;
23 import com.intellij.util.io.KeyDescriptor;
24 import com.jetbrains.python.psi.search.PyProjectScopeBuilder;
25 import org.jetbrains.annotations.NotNull;
26
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32
33 /**
34  * @author vlan
35  */
36 public class PySetuptoolsNamespaceIndex extends ScalarIndexExtension<String> {
37   public static final ID<String, Void> NAME = ID.create("Py.setuptools.namespace");
38   private static final Pattern RE_NAMESPACE = Pattern.compile("sys\\.modules\\.setdefault\\('([^']*)'");
39   private static final String NAMESPACE_FILE_SUFFIX = "-nspkg.pth";
40
41   private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor();
42
43   private final DataIndexer<String, Void, FileContent> myDataIndexer = new DataIndexer<String, Void, FileContent>() {
44     @NotNull
45     @Override
46     public Map<String, Void> map(@NotNull FileContent inputData) {
47       final CharSequence content = inputData.getContentAsText();
48       final Matcher matcher = RE_NAMESPACE.matcher(content);
49       final Map<String, Void> results = new HashMap<String, Void>();
50       while (matcher.find()) {
51         final String packageName = matcher.group(1);
52         results.put(packageName, null);
53       }
54       return results;
55     }
56   };
57
58   private FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
59     @Override
60     public boolean acceptInput(@NotNull VirtualFile file) {
61       return file.getName().endsWith(NAMESPACE_FILE_SUFFIX);
62     }
63   };
64
65   @NotNull
66   @Override
67   public ID<String, Void> getName() {
68     return NAME;
69   }
70
71   @NotNull
72   @Override
73   public DataIndexer<String, Void, FileContent> getIndexer() {
74     return myDataIndexer;
75   }
76
77   @NotNull
78   @Override
79   public KeyDescriptor<String> getKeyDescriptor() {
80     return myKeyDescriptor;
81   }
82
83   @NotNull
84   @Override
85   public FileBasedIndex.InputFilter getInputFilter() {
86     return myInputFilter;
87   }
88
89   @Override
90   public boolean dependsOnFileContent() {
91     return true;
92   }
93
94   @Override
95   public int getVersion() {
96     return 0;
97   }
98
99   @NotNull
100   public static Collection<VirtualFile> find(@NotNull String name, @NotNull Project project) {
101     final GlobalSearchScope scope = PyProjectScopeBuilder.excludeSdkTestsScope(project);
102     return FileBasedIndex.getInstance().getContainingFiles(NAME, name, scope);
103   }
104 }