private void dropUnregisteredIndices() {
    final Set<String> indicesToDrop =
        new HashSet<String>(
            myPreviouslyRegistered != null
                ? myPreviouslyRegistered.registeredIndices
                : Collections.<String>emptyList());
    for (ID<?, ?> key : myIndices.keySet()) {
      indicesToDrop.remove(key.toString());
    }

    for (String s : indicesToDrop) {
      FileUtil.delete(IndexInfrastructure.getIndexRootDir(ID.create(s)));
    }
  }
/** @author Eugene Zhuravlev Date: Apr 28, 2008 */
public class AntImportsIndex extends ScalarIndexExtension<Integer> {
  public static final ID<Integer, Void> INDEX_NAME = ID.create("ant-imports");
  private static final int VERSION = 5;
  public static final Integer ANT_FILES_WITH_IMPORTS_KEY = new Integer(0);

  private static final DataIndexer<Integer, Void, FileContent> DATA_INDEXER =
      new DataIndexer<Integer, Void, FileContent>() {
        @NotNull
        public Map<Integer, Void> map(final FileContent inputData) {
          final Map<Integer, Void> map = new HashMap<Integer, Void>();

          NanoXmlUtil.parse(
              new StringReader(inputData.getContentAsText().toString()),
              new NanoXmlUtil.IXMLBuilderAdapter() {
                private boolean isFirstElement = true;

                public void startElement(
                    final String elemName,
                    final String nsPrefix,
                    final String nsURI,
                    final String systemID,
                    final int lineNr)
                    throws Exception {
                  if (isFirstElement) {
                    if (!"project".equalsIgnoreCase(elemName)) {
                      stop();
                    }
                    isFirstElement = false;
                  } else {
                    if ("import".equalsIgnoreCase(elemName)
                        || "include".equalsIgnoreCase(elemName)) {
                      map.put(ANT_FILES_WITH_IMPORTS_KEY, null);
                      stop();
                    }
                  }
                }

                public void addAttribute(
                    final String key,
                    final String nsPrefix,
                    final String nsURI,
                    final String value,
                    final String type)
                    throws Exception {
                  // if (myAttributes != null) {
                  //  myAttributes.add(key);
                  // }
                }

                public void elementAttributesProcessed(
                    final String name, final String nsPrefix, final String nsURI) throws Exception {
                  // if (myAttributes != null) {
                  //  if (!(myAttributes.contains("name") && myAttributes.contains("default"))) {
                  //    stop();
                  //  }
                  //  myAttributes = null;
                  // }
                }
              });
          return map;
        }
      };
  private static final FileBasedIndex.InputFilter INPUT_FILTER =
      new FileBasedIndex.InputFilter() {
        public boolean acceptInput(final VirtualFile file) {
          return file.getFileType() instanceof XmlFileType;
        }
      };

  public int getVersion() {
    return VERSION;
  }

  public ID<Integer, Void> getName() {
    return INDEX_NAME;
  }

  public DataIndexer<Integer, Void, FileContent> getIndexer() {
    return DATA_INDEXER;
  }

  public KeyDescriptor<Integer> getKeyDescriptor() {
    return EnumeratorIntegerDescriptor.INSTANCE;
  }

  public FileBasedIndex.InputFilter getInputFilter() {
    return INPUT_FILTER;
  }

  public boolean dependsOnFileContent() {
    return true;
  }
}
예제 #3
0
public final class KotlinClassFileIndex extends ScalarIndexExtension<FqName> {

  private static final Logger LOG = Logger.getInstance(KotlinClassFileIndex.class);
  private static final int VERSION = 2;
  public static final ID<FqName, Void> KEY =
      ID.create(KotlinClassFileIndex.class.getCanonicalName());

  private static final KeyDescriptor<FqName> KEY_DESCRIPTOR =
      new KeyDescriptor<FqName>() {
        @Override
        public void save(DataOutput out, FqName value) throws IOException {
          out.writeUTF(value.asString());
        }

        @Override
        public FqName read(DataInput in) throws IOException {
          return new FqName(in.readUTF());
        }

        @Override
        public int getHashCode(FqName value) {
          return value.asString().hashCode();
        }

        @Override
        public boolean isEqual(FqName val1, FqName val2) {
          if (val1 == null) {
            return val2 == null;
          }
          return val1.equals(val1);
        }
      };

  private static final FileBasedIndex.InputFilter INPUT_FILTER =
      new FileBasedIndex.InputFilter() {
        @Override
        public boolean acceptInput(VirtualFile file) {
          return file.getFileType() == StdFileTypes.CLASS;
        }
      };
  public static final DataIndexer<FqName, Void, FileContent> INDEXER =
      new DataIndexer<FqName, Void, FileContent>() {
        @NotNull
        @Override
        public Map<FqName, Void> map(FileContent inputData) {
          try {
            KotlinJvmBinaryClass kotlinClass =
                VirtualFileFinder.SERVICE
                    .getInstance(inputData.getProject())
                    .createKotlinClass(inputData.getFile());
            KotlinClassHeader header = kotlinClass.getClassHeader();
            if (header != null
                && header.getKind() != KotlinClassHeader.Kind.INCOMPATIBLE_ABI_VERSION) {
              return Collections.singletonMap(
                  kotlinClass.getClassName().getFqNameForClassNameWithoutDollars(), null);
            }
          } catch (Throwable e) {
            LOG.warn("Error while indexing file " + inputData.getFileName(), e);
          }
          return Collections.emptyMap();
        }
      };

  @NotNull
  @Override
  public ID<FqName, Void> getName() {
    return KEY;
  }

  @NotNull
  @Override
  public DataIndexer<FqName, Void, FileContent> getIndexer() {
    return INDEXER;
  }

  @Override
  public KeyDescriptor<FqName> getKeyDescriptor() {
    return KEY_DESCRIPTOR;
  }

  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return INPUT_FILTER;
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return VERSION;
  }
}
public class GroovyTraitMethodsFileIndex extends SingleEntryFileBasedIndexExtension<PsiJavaFileStub>
    implements DataExternalizer<PsiJavaFileStub> {
  public static final ID<Integer, PsiJavaFileStub> INDEX_ID = ID.create("groovy.trait.methods");
  public static final String HELPER_SUFFIX = "$Trait$Helper.class";

  private static final Logger LOG = Logger.getInstance(GroovyTraitMethodsFileIndex.class);

  private final InputFilter myFilter;
  private final SingleEntryIndexer<PsiJavaFileStub> myIndexer;
  private final SerializationManagerEx mySerializer;

  public GroovyTraitMethodsFileIndex(@NotNull SerializationManagerEx serializer) {
    myFilter =
        new DefaultFileTypeSpecificInputFilter(JavaClassFileType.INSTANCE) {
          @Override
          public boolean acceptInput(@NotNull VirtualFile file) {
            return StringUtil.endsWith(file.getNameSequence(), HELPER_SUFFIX);
          }
        };
    myIndexer =
        new SingleEntryIndexer<PsiJavaFileStub>(true) {
          @Override
          protected PsiJavaFileStub computeValue(@NotNull FileContent inputData) {
            return index(inputData.getFile(), inputData.getContent());
          }
        };
    mySerializer = serializer;
  }

  @NotNull
  @Override
  public ID<Integer, PsiJavaFileStub> getName() {
    return INDEX_ID;
  }

  @Override
  public int getVersion() {
    return ClassFileStubBuilder.STUB_VERSION;
  }

  @NotNull
  @Override
  public InputFilter getInputFilter() {
    return myFilter;
  }

  @NotNull
  @Override
  public SingleEntryIndexer<PsiJavaFileStub> getIndexer() {
    return myIndexer;
  }

  @NotNull
  @Override
  public DataExternalizer<PsiJavaFileStub> getValueExternalizer() {
    return this;
  }

  private static PsiJavaFileStub index(VirtualFile file, byte[] content) {
    try {
      PsiJavaFileStub root = new PsiJavaFileStubImpl("", true);
      new ClassReader(content)
          .accept(new GrTraitMethodVisitor(file, root), EMPTY_ATTRIBUTES, ClassReader.SKIP_CODE);
      return root;
    } catch (Exception e) {
      LOG.info(file.getPath(), e);
      return null;
    }
  }

  @Override
  public void save(@NotNull DataOutput out, PsiJavaFileStub value) throws IOException {
    BufferExposingByteArrayOutputStream buffer = new BufferExposingByteArrayOutputStream();
    mySerializer.serialize(value, buffer);
    out.writeInt(buffer.size());
    out.write(buffer.getInternalBuffer(), 0, buffer.size());
  }

  @Override
  public PsiJavaFileStub read(@NotNull DataInput in) throws IOException {
    try {
      byte[] buffer = new byte[in.readInt()];
      in.readFully(buffer);
      return (PsiJavaFileStub) mySerializer.deserialize(new ByteArrayInputStream(buffer));
    } catch (SerializerNotFoundException e) {
      throw new IOException(e);
    }
  }

  private static class GrTraitMethodVisitor extends StubBuildingVisitor<VirtualFile> {
    public GrTraitMethodVisitor(VirtualFile file, StubElement root) {
      super(file, null, root, 0, null);
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      super.visit(version, access, "gr_trait_helper", null, null, null);
    }

    @Override
    public void visitSource(String source, String debug) {}

    @Override
    public void visitOuterClass(String owner, String name, String desc) {}

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      return null;
    }

    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {}

    @Nullable
    @Override
    public FieldVisitor visitField(
        int access, String name, String desc, String signature, Object value) {
      return null;
    }

    @Nullable
    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      if ((access & ACC_SYNTHETIC) == 0 && (access & ACC_STATIC) != 0 && name != null) {
        Type[] args = Type.getArgumentTypes(desc);
        if (args.length > 0
            && args[0].getSort() == Type.OBJECT
            && CommonClassNames.JAVA_LANG_CLASS.equals(args[0].getClassName())) {
          return super.visitMethod(access, name, desc, signature, exceptions);
        }
      }

      return null;
    }
  }
}
예제 #5
0
/** @author Eugene Zhuravlev Date: Jan 16, 2008 */
public class IdIndex extends FileBasedIndexExtension<IdIndexEntry, Integer> {
  @NonNls public static final ID<IdIndexEntry, Integer> NAME = ID.create("IdIndex");

  private final FileBasedIndex.InputFilter myInputFilter =
      new FileBasedIndex.InputFilter() {
        @Override
        public boolean acceptInput(final VirtualFile file) {
          final FileType fileType = file.getFileType();
          return isIndexable(fileType) && !ProjectUtil.isProjectOrWorkspaceFile(file, fileType);
        }
      };

  private final DataExternalizer<Integer> myValueExternalizer =
      new DataExternalizer<Integer>() {
        @Override
        public void save(final DataOutput out, final Integer value) throws IOException {
          out.writeByte(value.intValue());
        }

        @Override
        public Integer read(final DataInput in) throws IOException {
          return Integer.valueOf(in.readByte());
        }
      };

  private final KeyDescriptor<IdIndexEntry> myKeyDescriptor =
      new InlineKeyDescriptor<IdIndexEntry>() {
        @Override
        public IdIndexEntry fromInt(int n) {
          return new IdIndexEntry(n);
        }

        @Override
        public int toInt(IdIndexEntry idIndexEntry) {
          return idIndexEntry.getWordHashCode();
        }
      };

  private final DataIndexer<IdIndexEntry, Integer, FileContent> myIndexer =
      new DataIndexer<IdIndexEntry, Integer, FileContent>() {
        @Override
        @NotNull
        public Map<IdIndexEntry, Integer> map(final FileContent inputData) {
          final FileTypeIdIndexer indexer =
              IdTableBuilding.getFileTypeIndexer(inputData.getFileType());
          if (indexer != null) {
            return indexer.map(inputData);
          }

          return Collections.emptyMap();
        }
      };

  @Override
  public int getVersion() {
    return 9; // TODO: version should enumerate all word scanner versions and build version upon
    // that set
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @NotNull
  @Override
  public ID<IdIndexEntry, Integer> getName() {
    return NAME;
  }

  @NotNull
  @Override
  public DataIndexer<IdIndexEntry, Integer, FileContent> getIndexer() {
    return myIndexer;
  }

  @Override
  public DataExternalizer<Integer> getValueExternalizer() {
    return myValueExternalizer;
  }

  @Override
  public KeyDescriptor<IdIndexEntry> getKeyDescriptor() {
    return myKeyDescriptor;
  }

  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return myInputFilter;
  }

  private static boolean isIndexable(FileType fileType) {
    return fileType instanceof LanguageFileType
        || fileType instanceof CustomSyntaxTableFileType
        || IdTableBuilding.isIdIndexerRegistered(fileType)
        || CacheBuilderRegistry.getInstance().getCacheBuilder(fileType) != null;
  }
}
public class JavaFxControllerClassIndex extends ScalarIndexExtension<String> {
  @NonNls public static final ID<String, Void> NAME = ID.create("JavaFxControllerClassIndex");
  private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor();
  private final MyInputFilter myInputFilter = new MyInputFilter();
  private final MyDataIndexer myDataIndexer = new MyDataIndexer();

  @Override
  @NotNull
  public ID<String, Void> getName() {
    return NAME;
  }

  @Override
  @NotNull
  public DataIndexer<String, Void, FileContent> getIndexer() {
    return myDataIndexer;
  }

  @Override
  public KeyDescriptor<String> getKeyDescriptor() {
    return myKeyDescriptor;
  }

  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return myInputFilter;
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return 0;
  }

  private static class MyDataIndexer implements DataIndexer<String, Void, FileContent> {
    private static final SAXParser SAX_PARSER = createParser();

    private static SAXParser createParser() {
      try {
        return SAXParserFactory.newInstance().newSAXParser();
      } catch (Exception e) {
        return null;
      }
    }

    @Override
    @NotNull
    public Map<String, Void> map(final FileContent inputData) {
      final String className = getControllerClassName(inputData.getContentAsText().toString());
      if (className != null) {
        return Collections.singletonMap(className, null);
      }
      return Collections.emptyMap();
    }

    @Nullable
    private static String getControllerClassName(String content) {
      if (!content.contains(JavaFXNamespaceProvider.JAVAFX_NAMESPACE)) {
        return null;
      }

      final String[] className = new String[] {null};
      try {
        SAX_PARSER.parse(
            new InputSource(new StringReader(content)),
            new DefaultHandler() {
              public void startElement(
                  String uri, String localName, String qName, Attributes attributes)
                  throws SAXException {
                className[0] = attributes.getValue("", FxmlConstants.FX_CONTROLLER);
                throw new SAXException("controllers are accepted on top level only");
              }
            });
      } catch (Exception e) {
        // Do nothing.
      }

      return className[0];
    }
  }

  private static class MyInputFilter implements FileBasedIndex.InputFilter {
    @Override
    public boolean acceptInput(final VirtualFile file) {
      return JavaFxFileTypeFactory.isFxml(file);
    }
  }

  public static List<PsiFile> findFxmlWithController(final Project project, String className) {
    return findFxmlWithController(
        project,
        className,
        new Function<VirtualFile, PsiFile>() {
          @Override
          public PsiFile fun(VirtualFile file) {
            return PsiManager.getInstance(project).findFile(file);
          }
        },
        ProjectScope.getAllScope(project));
  }

  public static List<VirtualFile> findFxmlsWithController(
      final Project project, @NotNull String className) {
    return findFxmlWithController(
        project, className, Function.ID, ProjectScope.getAllScope(project));
  }

  public static <T> List<T> findFxmlWithController(
      final Project project,
      final String className,
      final Function<VirtualFile, T> f,
      final GlobalSearchScope scope) {
    return ApplicationManager.getApplication()
        .runReadAction(
            new Computable<List<T>>() {
              @Override
              public List<T> compute() {
                final Collection<VirtualFile> files;
                try {
                  files =
                      FileBasedIndex.getInstance()
                          .getContainingFiles(
                              NAME,
                              className,
                              GlobalSearchScope.projectScope(project).intersectWith(scope));
                } catch (IndexNotReadyException e) {
                  return Collections.emptyList();
                }
                if (files.isEmpty()) return Collections.emptyList();
                List<T> result = new ArrayList<T>();
                for (VirtualFile file : files) {
                  if (!file.isValid()) continue;
                  final T fFile = f.fun(file);
                  if (fFile != null) {
                    result.add(fFile);
                  }
                }
                return result;
              }
            });
  }
}
예제 #7
0
/** Indexes .mps files and makes an index model-&gt;List &lt;SNodeDescriptor&gt; */
public class RootNodeNameIndex extends SingleEntryFileBasedIndexExtension<List<SNodeDescriptor>> {
  @NonNls
  public static final ID<Integer, List<SNodeDescriptor>> NAME = ID.create("RootNodeNameIndex2");

  private static final Logger LOG = LogManager.getLogger(RootNodeNameIndex.class);
  private static final Key<SModel> PARSED_MODEL = new Key<SModel>("parsed-model");

  public static SModel doModelParsing(FileContent inputData) {
    SModel model = inputData.getUserData(PARSED_MODEL);

    if (model == null) {
      String ext = FileUtil.getExtension(inputData.getFileName());
      if (MPSFileTypeFactory.MPS_ROOT_FILE_TYPE.equals(inputData.getFile().getFileType())) {
        ext = MPSFileTypeFactory.MPS_HEADER_FILE_TYPE.getDefaultExtension();
      }
      ModelFactory factory = PersistenceFacade.getInstance().getModelFactory(ext);
      if (factory == null) {
        return null;
      }
      if (factory instanceof FolderModelFactory) {
        model =
            PersistenceUtil.loadModel(
                VirtualFileUtils.toIFile(
                    MPSFileTypeFactory.MPS_ROOT_FILE_TYPE.equals(inputData.getFile().getFileType())
                        ? inputData.getFile().getParent().findChild(MPSExtentions.DOT_MODEL_HEADER)
                        : inputData.getFile()));
      } else {
        model =
            factory.isBinary()
                ? PersistenceUtil.loadModel(inputData.getContent(), ext)
                : PersistenceUtil.loadModel(inputData.getContentAsText().toString(), ext);
      }
      if (model == null) {
        return null;
      }
      inputData.putUserData(PARSED_MODEL, model);
    }
    return model;
  }

  @Override
  @NotNull
  public ID<Integer, List<SNodeDescriptor>> getName() {
    return NAME;
  }

  public static Iterable<SNode> getRootsToIterate(SModel model) {
    if (SModelStereotype.isStubModelStereotype(
        jetbrains.mps.util.SNodeOperations.getModelStereotype(model)))
      return new EmptyIterable<SNode>();
    return new ConditionalIterable<SNode>(model.getRootNodes(), new MyCondition());
  }

  @Override
  public DataExternalizer<List<SNodeDescriptor>> getValueExternalizer() {
    return new SNodeDescriptorListEnumerator();
  }

  @NotNull
  @Override
  public SingleEntryIndexer<List<SNodeDescriptor>> getIndexer() {
    return new MyIndexer();
  }

  @Override
  public InputFilter getInputFilter() {
    return new MyInputFilter();
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return 6;
  }

  @Override
  public int getCacheSize() {
    return DEFAULT_CACHE_SIZE;
  }

  private static class MyCondition implements Condition<SNode> {
    @Override
    public boolean met(SNode node) {
      return !node.getNodeId().toString().contains("$");
    }
  }

  private static class MyInputFilter implements FileBasedIndex.InputFilter {
    @Override
    public boolean acceptInput(VirtualFile file) {
      FileType fileType = file.getFileType();
      return MPSFileTypeFactory.MPS_FILE_TYPE.equals(fileType)
          || MPSFileTypeFactory.MPS_BINARY_FILE_TYPE.equals(fileType);
    }
  }

  private class MyIndexer extends SingleEntryIndexer<List<SNodeDescriptor>> {
    private MyIndexer() {
      super(false);
    }

    @Override
    protected List<SNodeDescriptor> computeValue(@NotNull final FileContent inputData) {
      final List<SNodeDescriptor> descriptors = new ArrayList<SNodeDescriptor>();
      ModelAccess.instance()
          .runIndexing(
              new Runnable() {
                @Override
                public void run() {
                  try {
                    SModel model = doModelParsing(inputData);

                    for (final SNode node : getRootsToIterate(model)) {
                      String persistentName =
                          node.getProperty(SNodeUtil.property_INamedConcept_name);
                      String nodeName = (persistentName == null) ? "null" : persistentName;
                      String conceptFqName = node.getConcept().getQualifiedName();
                      SModelReference modelRef = model.getReference();
                      SNodeId id = node.getNodeId();
                      SNodeDescriptor value =
                          SNodeDescriptor.fromModelReference(nodeName, conceptFqName, modelRef, id);
                      descriptors.add(value);
                    }
                  } catch (Exception e) {
                    LOG.error(
                        "Cannot index model file "
                            + inputData.getFileName()
                            + "; "
                            + e.getMessage());
                  }
                }
              });
      return descriptors;
    }
  }
}
예제 #8
0
/** @author Eugene Zhuravlev Date: Jan 20, 2008 */
public class TodoIndex extends FileBasedIndexExtension<TodoIndexEntry, Integer> {
  @NonNls public static final ID<TodoIndexEntry, Integer> NAME = ID.create("TodoIndex");

  public TodoIndex(MessageBus messageBus) {
    messageBus
        .connect()
        .subscribe(
            IndexPatternProvider.INDEX_PATTERNS_CHANGED,
            new PropertyChangeListener() {
              @Override
              public void propertyChange(PropertyChangeEvent evt) {
                FileBasedIndex.requestRebuild(NAME);
              }
            });
  }

  private final KeyDescriptor<TodoIndexEntry> myKeyDescriptor =
      new KeyDescriptor<TodoIndexEntry>() {
        @Override
        public int getHashCode(final TodoIndexEntry value) {
          return value.hashCode();
        }

        @Override
        public boolean isEqual(final TodoIndexEntry val1, final TodoIndexEntry val2) {
          return val1.equals(val2);
        }

        @Override
        public void save(final DataOutput out, final TodoIndexEntry value) throws IOException {
          out.writeUTF(value.pattern);
          out.writeBoolean(value.caseSensitive);
        }

        @Override
        public TodoIndexEntry read(final DataInput in) throws IOException {
          final String pattern = in.readUTF();
          final boolean caseSensitive = in.readBoolean();
          return new TodoIndexEntry(pattern, caseSensitive);
        }
      };

  private final DataExternalizer<Integer> myValueExternalizer =
      new DataExternalizer<Integer>() {
        @Override
        public void save(final DataOutput out, final Integer value) throws IOException {
          out.writeInt(value.intValue());
        }

        @Override
        public Integer read(final DataInput in) throws IOException {
          return Integer.valueOf(in.readInt());
        }
      };

  private final DataIndexer<TodoIndexEntry, Integer, FileContent> myIndexer =
      new DataIndexer<TodoIndexEntry, Integer, FileContent>() {
        @Override
        @NotNull
        public Map<TodoIndexEntry, Integer> map(final FileContent inputData) {
          final VirtualFile file = inputData.getFile();
          final DataIndexer<TodoIndexEntry, Integer, FileContent> indexer =
              IdTableBuilding.getTodoIndexer(inputData.getFileType(), file);
          if (indexer != null) {
            return indexer.map(inputData);
          }
          return Collections.emptyMap();
        }
      };

  private final FileBasedIndex.InputFilter myInputFilter =
      new FileBasedIndex.InputFilter() {
        @Override
        public boolean acceptInput(final VirtualFile file) {
          if (!(file.getFileSystem() instanceof LocalFileSystem)) {
            return false; // do not index TODOs in library sources
          }

          final FileType fileType = file.getFileType();
          if (ProjectUtil.isProjectOrWorkspaceFile(file, fileType)) {
            return false;
          }

          if (fileType instanceof LanguageFileType) {
            final Language lang = ((LanguageFileType) fileType).getLanguage();
            final ParserDefinition parserDef = LanguageParserDefinitions.INSTANCE.forLanguage(lang);
            final TokenSet commentTokens = parserDef != null ? parserDef.getCommentTokens() : null;
            return commentTokens != null;
          }

          return IdTableBuilding.isTodoIndexerRegistered(fileType)
              || fileType instanceof AbstractFileType;
        }
      };

  @Override
  public int getVersion() {
    return 4;
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @NotNull
  @Override
  public ID<TodoIndexEntry, Integer> getName() {
    return NAME;
  }

  @NotNull
  @Override
  public DataIndexer<TodoIndexEntry, Integer, FileContent> getIndexer() {
    return myIndexer;
  }

  @Override
  public KeyDescriptor<TodoIndexEntry> getKeyDescriptor() {
    return myKeyDescriptor;
  }

  @Override
  public DataExternalizer<Integer> getValueExternalizer() {
    return myValueExternalizer;
  }

  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return myInputFilter;
  }
}
예제 #9
0
/** @author Alexei Vasin */
public class IniDirectiveIndex extends ScalarIndexExtension<String> {
  private static final Logger LOG = Logger.getInstance("#ini4idea.lang.psi.IniDirectiveIndex");
  @NonNls public static final ID<String, Void> NAME = ID.create("IniDirectiveIndex");
  private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor();
  private final MyInputFilter myInputFilter = new MyInputFilter();
  private final MyDataIndexer myDataIndexer = new MyDataIndexer();

  @NotNull
  @Override
  public ID<String, Void> getName() {
    return NAME;
  }

  @NotNull
  @Override
  public DataIndexer<String, Void, FileContent> getIndexer() {
    return myDataIndexer;
  }

  @NotNull
  @Override
  public KeyDescriptor<String> getKeyDescriptor() {
    return myKeyDescriptor;
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return myInputFilter;
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return 1;
  }

  private static class MyDataIndexer implements DataIndexer<String, Void, FileContent> {
    @Override
    @NotNull
    public Map<String, Void> map(@NotNull final FileContent inputData) {
      String className;
      Map<String, Void> result = new HashMap<String, Void>();
      try {
        className = inputData.getContentAsText().toString();
        String a[] = className.split("\n");
        for (String s : a) {
          if (s.contains("=")) {
            result.put(s.substring(0, s.indexOf("=")), null);
          }
        }
      } catch (Exception e) {
        // ignore
        LOG.error(e.toString());
      }
      return result;
      /*
                  if (className != null) {
                      return Collections.singletonMap(className, null);
                  }
      */
      //            return Collections.emptyMap();
    }
  }

  private static class MyInputFilter implements FileBasedIndex.InputFilter {
    @Override
    public boolean acceptInput(@NotNull final VirtualFile file) {
      return file.getFileType() == IniFileType.INSTANCE;
    }
  }

  /*
      public static Collection<NavigationItem> getItemsByName(final String name, Project project) {
          Collection<VirtualFile> files = FileBasedIndex.getInstance().getContainingFiles(NAME, name, GlobalSearchScope.projectScope(project));
          final Collection<NavigationItem> result = new ArrayList<NavigationItem>();
          for (VirtualFile vFile : files) {
              PsiFile file = PsiManager.getInstance(project).findFile(vFile);
              if (!(file instanceof IniFile)) {
                  continue;
              }
              process((IniFile)file, new Consumer<PsiElement>() {
                  @Override
                  public void consume(PsiElement element) {
                      if (name.equals(getName(element))) {
                          result.add((NavigationItem) element);
                      }                     }
              }, true);
          }
          return result;
      }
  */

}
/*
 * @author max
 */
public class StubUpdatingIndex
    extends CustomImplementationFileBasedIndexExtension<Integer, SerializedStubTree, FileContent> {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubUpdatingIndex");

  public static final ID<Integer, SerializedStubTree> INDEX_ID = ID.create("Stubs");

  private static final int VERSION = 20;

  private static final DataExternalizer<SerializedStubTree> KEY_EXTERNALIZER =
      new DataExternalizer<SerializedStubTree>() {
        @Override
        public void save(final DataOutput out, @NotNull final SerializedStubTree v)
            throws IOException {
          v.write(out);
        }

        @NotNull
        @Override
        public SerializedStubTree read(final DataInput in) throws IOException {
          return new SerializedStubTree(in);
        }
      };

  private static final FileBasedIndex.InputFilter INPUT_FILTER =
      new FileBasedIndex.InputFilter() {
        @Override
        public boolean acceptInput(@NotNull final VirtualFile file) {
          return canHaveStub(file);
        }
      };

  public static boolean canHaveStub(@NotNull VirtualFile file) {
    final FileType fileType = file.getFileType();
    if (fileType instanceof LanguageFileType) {
      Language l = ((LanguageFileType) fileType).getLanguage();
      ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(l);
      if (parserDefinition == null) return false;

      final IFileElementType elementType = parserDefinition.getFileNodeType();
      return elementType instanceof IStubFileElementType
          && (((IStubFileElementType) elementType).shouldBuildStubFor(file)
              || IndexingStamp.isFileIndexed(
                  file, INDEX_ID, IndexInfrastructure.getIndexCreationStamp(INDEX_ID)));
    }
    if (fileType.isBinary()) {
      final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType);
      return builder != null && builder.acceptsFile(file);
    }

    return false;
  }

  private static final KeyDescriptor<Integer> DATA_DESCRIPTOR = new IntInlineKeyDescriptor();

  @NotNull
  @Override
  public ID<Integer, SerializedStubTree> getName() {
    return INDEX_ID;
  }

  @Override
  public int getCacheSize() {
    return 5; // no need to cache many serialized trees
  }

  @Override
  public boolean isKeyHighlySelective() {
    return true;
  }

  @NotNull
  @Override
  public DataIndexer<Integer, SerializedStubTree, FileContent> getIndexer() {
    return new DataIndexer<Integer, SerializedStubTree, FileContent>() {
      @Override
      @NotNull
      public Map<Integer, SerializedStubTree> map(@NotNull final FileContent inputData) {
        final Map<Integer, SerializedStubTree> result = new HashMap<Integer, SerializedStubTree>();

        ApplicationManager.getApplication()
            .runReadAction(
                new Runnable() {
                  @Override
                  public void run() {
                    final StubElement rootStub = StubTreeBuilder.buildStubTree(inputData);
                    if (rootStub == null) return;

                    final BufferExposingByteArrayOutputStream bytes =
                        new BufferExposingByteArrayOutputStream();
                    SerializationManagerEx.getInstanceEx().serialize(rootStub, bytes);

                    final int key = Math.abs(FileBasedIndex.getFileId(inputData.getFile()));
                    result.put(
                        key,
                        new SerializedStubTree(bytes.getInternalBuffer(), bytes.size(), rootStub));
                  }
                });

        return result;
      }
    };
  }

  @NotNull
  @Override
  public KeyDescriptor<Integer> getKeyDescriptor() {
    return DATA_DESCRIPTOR;
  }

  @NotNull
  @Override
  public DataExternalizer<SerializedStubTree> getValueExternalizer() {
    return KEY_EXTERNALIZER;
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return INPUT_FILTER;
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return getCumulativeVersion();
  }

  private static int getCumulativeVersion() {
    int version = VERSION;
    for (final FileType fileType : FileTypeManager.getInstance().getRegisteredFileTypes()) {
      if (fileType instanceof LanguageFileType) {
        Language l = ((LanguageFileType) fileType).getLanguage();
        ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(l);
        if (parserDefinition != null) {
          final IFileElementType type = parserDefinition.getFileNodeType();
          if (type instanceof IStubFileElementType) {
            version += ((IStubFileElementType) type).getStubVersion();
          }
        }
      } else if (fileType.isBinary()) {
        final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType);
        if (builder != null) {
          version += builder.getStubVersion();
        }
      }
    }
    return version;
  }

  @NotNull
  @Override
  public UpdatableIndex<Integer, SerializedStubTree, FileContent> createIndexImplementation(
      final ID<Integer, SerializedStubTree> indexId,
      @NotNull final FileBasedIndex owner,
      @NotNull IndexStorage<Integer, SerializedStubTree> storage)
      throws StorageException {
    if (storage instanceof MemoryIndexStorage) {
      final MemoryIndexStorage<Integer, SerializedStubTree> memStorage =
          (MemoryIndexStorage<Integer, SerializedStubTree>) storage;
      memStorage.addBufferingStateListsner(
          new MemoryIndexStorage.BufferingStateListener() {
            @Override
            public void bufferingStateChanged(final boolean newState) {
              ((StubIndexImpl) StubIndexImpl.getInstance()).setDataBufferingEnabled(newState);
            }

            @Override
            public void memoryStorageCleared() {
              ((StubIndexImpl) StubIndexImpl.getInstance()).cleanupMemoryStorage();
            }
          });
    }
    return new MyIndex(indexId, storage, getIndexer());
  }

  private static void updateStubIndices(
      @NotNull final Collection<StubIndexKey> indexKeys,
      final int inputId,
      @NotNull final Map<StubIndexKey, Map<Object, int[]>> oldStubTree,
      @NotNull final Map<StubIndexKey, Map<Object, int[]>> newStubTree) {
    final StubIndexImpl stubIndex = (StubIndexImpl) StubIndex.getInstance();
    for (StubIndexKey key : indexKeys) {
      final Map<Object, int[]> oldMap = oldStubTree.get(key);
      final Map<Object, int[]> newMap = newStubTree.get(key);

      final Map<Object, int[]> _oldMap =
          oldMap != null ? oldMap : Collections.<Object, int[]>emptyMap();
      final Map<Object, int[]> _newMap =
          newMap != null ? newMap : Collections.<Object, int[]>emptyMap();

      stubIndex.updateIndex(key, inputId, _oldMap, _newMap);
    }
  }

  @NotNull
  private static Collection<StubIndexKey> getAffectedIndices(
      @NotNull final Map<StubIndexKey, Map<Object, int[]>> oldStubTree,
      @NotNull final Map<StubIndexKey, Map<Object, int[]>> newStubTree) {
    Set<StubIndexKey> allIndices = new HashSet<StubIndexKey>();
    allIndices.addAll(oldStubTree.keySet());
    allIndices.addAll(newStubTree.keySet());
    return allIndices;
  }

  private static class MyIndex extends MapReduceIndex<Integer, SerializedStubTree, FileContent> {
    private StubIndexImpl myStubIndex;

    public MyIndex(
        final ID<Integer, SerializedStubTree> indexId,
        final IndexStorage<Integer, SerializedStubTree> storage,
        final DataIndexer<Integer, SerializedStubTree, FileContent> indexer)
        throws StorageException {
      super(indexId, indexer, storage);
      checkNameStorage();
    }

    @Override
    public void flush() throws StorageException {
      final StubIndexImpl stubIndex = getStubIndex();
      try {
        for (StubIndexKey key : stubIndex.getAllStubIndexKeys()) {
          stubIndex.flush(key);
        }
      } finally {
        super.flush();
      }
    }

    @Override
    protected void updateWithMap(
        final int inputId,
        @NotNull final Map<Integer, SerializedStubTree> newData,
        @NotNull Callable<Collection<Integer>> oldKeysGetter)
        throws StorageException {

      checkNameStorage();
      final Map<StubIndexKey, Map<Object, int[]>> newStubTree = getStubTree(newData);

      final StubIndexImpl stubIndex = getStubIndex();
      final Collection<StubIndexKey> allStubIndices = stubIndex.getAllStubIndexKeys();
      try {
        // first write-lock affected stub indices to avoid deadlocks
        for (StubIndexKey key : allStubIndices) {
          stubIndex.getWriteLock(key).lock();
        }

        try {
          getWriteLock().lock();

          final Map<Integer, SerializedStubTree> oldData = readOldData(inputId);
          final Map<StubIndexKey, Map<Object, int[]>> oldStubTree = getStubTree(oldData);

          super.updateWithMap(inputId, newData, oldKeysGetter);

          updateStubIndices(
              getAffectedIndices(oldStubTree, newStubTree), inputId, oldStubTree, newStubTree);
        } finally {
          getWriteLock().unlock();
        }
      } finally {
        for (StubIndexKey key : allStubIndices) {
          stubIndex.getWriteLock(key).unlock();
        }
      }
    }

    private StubIndexImpl getStubIndex() {
      StubIndexImpl index = myStubIndex;
      if (index == null) {
        index = myStubIndex = (StubIndexImpl) StubIndex.getInstance();
      }
      return index;
    }

    private static void checkNameStorage() throws StorageException {
      final SerializationManagerEx serializationManager = SerializationManagerEx.getInstanceEx();
      if (serializationManager.isNameStorageCorrupted()) {
        serializationManager.repairNameStorage();
        //noinspection ThrowFromFinallyBlock
        throw new StorageException("NameStorage for stubs serialization has been corrupted");
      }
    }

    private static Map<StubIndexKey, Map<Object, int[]>> getStubTree(
        @NotNull final Map<Integer, SerializedStubTree> data) {
      final Map<StubIndexKey, Map<Object, int[]>> stubTree;
      if (!data.isEmpty()) {
        final SerializedStubTree stub = data.values().iterator().next();
        stubTree = new StubTree((PsiFileStub) stub.getStub(true), false).indexStubTree();
      } else {
        stubTree = Collections.emptyMap();
      }
      return stubTree;
    }

    /*MUST be called under the WriteLock*/
    @NotNull
    private Map<Integer, SerializedStubTree> readOldData(final int key) throws StorageException {
      final Map<Integer, SerializedStubTree> result = new HashMap<Integer, SerializedStubTree>();

      IndexStorage<Integer, SerializedStubTree> indexStorage = myStorage;
      if (indexStorage instanceof MemoryIndexStorage) {
        final MemoryIndexStorage<Integer, SerializedStubTree> memIndexStorage =
            (MemoryIndexStorage<Integer, SerializedStubTree>) indexStorage;
        if (!memIndexStorage.isBufferingEnabled()) {
          // if buffering is not enabled, use backend storage to make sure
          // the returned stub tree contains no data corresponding to unsaved documents.
          // This will ensure that correct set of old keys is used for update
          indexStorage = memIndexStorage.getBackendStorage();
        }
      }
      try {
        final ValueContainer<SerializedStubTree> valueContainer = indexStorage.read(key);
        if (valueContainer.size() != 1) {
          LOG.assertTrue(valueContainer.size() == 0);
          return result;
        }

        result.put(key, valueContainer.getValueIterator().next());
        return result;
      } catch (RuntimeException e) {
        final Throwable cause = e.getCause();
        if (cause instanceof IOException) {
          throw new StorageException(cause);
        }
        throw e;
      }
    }

    @Override
    public void clear() throws StorageException {
      final StubIndexImpl stubIndex = StubIndexImpl.getInstanceOrInvalidate();
      final Collection<StubIndexKey> allStubIndexKeys =
          stubIndex != null
              ? stubIndex.getAllStubIndexKeys()
              : Collections.<StubIndexKey>emptyList();
      try {
        for (StubIndexKey key : allStubIndexKeys) {
          //noinspection ConstantConditions
          stubIndex.getWriteLock(key).lock();
        }
        getWriteLock().lock();
        if (stubIndex != null) {
          stubIndex.clearAllIndices();
        }
        super.clear();
      } finally {
        getWriteLock().unlock();
        for (StubIndexKey key : allStubIndexKeys) {
          //noinspection ConstantConditions
          stubIndex.getWriteLock(key).unlock();
        }
      }
    }

    @Override
    public void dispose() {
      try {
        super.dispose();
      } finally {
        getStubIndex().dispose();
      }
    }
  }
}
/** @author vlan */
public class PyModuleNameIndex extends ScalarIndexExtension<String> {
  public static final ID<String, Void> NAME = ID.create("Py.module.name");

  private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor();
  private final DataIndexer<String, Void, FileContent> myDataIndexer =
      new DataIndexer<String, Void, FileContent>() {
        @NotNull
        @Override
        public Map<String, Void> map(@NotNull FileContent inputData) {
          final VirtualFile file = inputData.getFile();
          final String name = file.getName();
          if (PyNames.INIT_DOT_PY.equals(name)) {
            final VirtualFile parent = file.getParent();
            if (parent != null && parent.isDirectory()) {
              return Collections.singletonMap(parent.getName(), null);
            }
          } else {
            return Collections.singletonMap(FileUtil.getNameWithoutExtension(name), null);
          }
          return Collections.emptyMap();
        }
      };

  @NotNull
  @Override
  public ID<String, Void> getName() {
    return NAME;
  }

  @NotNull
  @Override
  public DataIndexer<String, Void, FileContent> getIndexer() {
    return myDataIndexer;
  }

  @NotNull
  @Override
  public KeyDescriptor<String> getKeyDescriptor() {
    return myKeyDescriptor;
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return new DefaultFileTypeSpecificInputFilter(PythonFileType.INSTANCE);
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return 0;
  }

  @NotNull
  public static Collection<String> getAllKeys(@NotNull Project project) {
    return FileBasedIndex.getInstance().getAllKeys(NAME, project);
  }

  @NotNull
  public static List<PyFile> find(
      @NotNull String name, @NotNull Project project, boolean includeNonProjectItems) {
    final List<PyFile> results = new ArrayList<PyFile>();
    final GlobalSearchScope scope =
        includeNonProjectItems
            ? PyProjectScopeBuilder.excludeSdkTestsScope(project)
            : GlobalSearchScope.projectScope(project);
    final Collection<VirtualFile> files =
        FileBasedIndex.getInstance().getContainingFiles(NAME, name, scope);
    for (VirtualFile virtualFile : files) {
      final PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
      if (psiFile instanceof PyFile) {
        if (!PyUserSkeletonsUtil.isUnderUserSkeletonsDirectory(psiFile)) {
          results.add((PyFile) psiFile);
        }
      }
    }
    return results;
  }
}
 public static <K, V> ID<K, V> generateIndexId(final String indexName, final Project project) {
   return ID.create(
       String.format(
           "compilerOutputIndex.%s.%d", indexName, Math.abs(project.getBasePath().hashCode())));
 }
public class JavaFxControllerClassIndex extends ScalarIndexExtension<String> {
  @NonNls public static final ID<String, Void> NAME = ID.create("JavaFxControllerClassIndex");
  private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor();
  private final MyInputFilter myInputFilter = new MyInputFilter();
  private final MyDataIndexer myDataIndexer = new MyDataIndexer();

  @Override
  @NotNull
  public ID<String, Void> getName() {
    return NAME;
  }

  @Override
  @NotNull
  public DataIndexer<String, Void, FileContent> getIndexer() {
    return myDataIndexer;
  }

  @NotNull
  @Override
  public KeyDescriptor<String> getKeyDescriptor() {
    return myKeyDescriptor;
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return myInputFilter;
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return 1;
  }

  private static class MyDataIndexer implements DataIndexer<String, Void, FileContent> {
    @Override
    @NotNull
    public Map<String, Void> map(@NotNull final FileContent inputData) {
      final String className = getControllerClassName(inputData.getContentAsText().toString());
      if (className != null) {
        return Collections.singletonMap(className, null);
      }
      return Collections.emptyMap();
    }

    @Nullable
    private static String getControllerClassName(String content) {
      if (!content.contains(JavaFxNamespaceDataProvider.JAVAFX_NAMESPACE)) {
        return null;
      }

      final String[] className = new String[] {null};

      class StopException extends RuntimeException {}

      try {
        NanoXmlUtil.parse(
            new StringReader(content),
            new NanoXmlUtil.IXMLBuilderAdapter() {
              private boolean myFxRootUsed = false;

              @Override
              public void addAttribute(
                  String key, String nsPrefix, String nsURI, String value, String type)
                  throws Exception {
                if (value != null
                    && (FxmlConstants.FX_CONTROLLER.equals(nsPrefix + ":" + key)
                        || FxmlConstants.TYPE.equals(key) && myFxRootUsed)) {
                  className[0] = value;
                }
              }

              @Override
              public void elementAttributesProcessed(String name, String nsPrefix, String nsURI)
                  throws Exception {
                throw new StopException();
              }

              @Override
              public void startElement(
                  String name, String nsPrefix, String nsURI, String systemID, int lineNr)
                  throws Exception {
                myFxRootUsed = FxmlConstants.FX_ROOT.equals(nsPrefix + ":" + name);
              }
            });
      } catch (StopException ignore) {
      }
      return className[0];
    }
  }

  public static class MyInputFilter extends DefaultFileTypeSpecificInputFilter {
    public MyInputFilter() {
      super(StdFileTypes.XML);
    }

    @Override
    public boolean acceptInput(@NotNull final VirtualFile file) {
      return JavaFxFileTypeFactory.isFxml(file);
    }
  }

  public static List<PsiFile> findFxmlWithController(
      final Project project, @NotNull String className) {
    return findFxmlWithController(
        project,
        className,
        new Function<VirtualFile, PsiFile>() {
          @Override
          public PsiFile fun(VirtualFile file) {
            return PsiManager.getInstance(project).findFile(file);
          }
        },
        ProjectScope.getAllScope(project));
  }

  public static List<VirtualFile> findFxmlsWithController(
      final Project project, @NotNull String className) {
    return findFxmlWithController(
        project, className, Function.ID, ProjectScope.getAllScope(project));
  }

  public static <T> List<T> findFxmlWithController(
      final Project project,
      @NotNull final String className,
      final Function<VirtualFile, T> f,
      final GlobalSearchScope scope) {
    return ApplicationManager.getApplication()
        .runReadAction(
            new Computable<List<T>>() {
              @Override
              public List<T> compute() {
                final Collection<VirtualFile> files;
                try {
                  files =
                      FileBasedIndex.getInstance()
                          .getContainingFiles(
                              NAME,
                              className,
                              GlobalSearchScope.projectScope(project).intersectWith(scope));
                } catch (IndexNotReadyException e) {
                  return Collections.emptyList();
                }
                if (files.isEmpty()) return Collections.emptyList();
                List<T> result = new ArrayList<T>();
                for (VirtualFile file : files) {
                  if (!file.isValid()) continue;
                  final T fFile = f.fun(file);
                  if (fFile != null) {
                    result.add(fFile);
                  }
                }
                return result;
              }
            });
  }
}
예제 #14
0
/** @author spleaner */
public class HtmlLinkTagIndex
    extends SingleEntryFileBasedIndexExtension<
        HtmlLinkTagIndex.InfoHolder<HtmlLinkTagIndex.LinkInfo>> {
  public static final ID<Integer, InfoHolder<LinkInfo>> INDEX_ID = ID.create("HtmlLinkTagIndex");

  @NonNls private static final String LINK = "link";
  @NonNls private static final String HREF_ATTR = "href";
  @NonNls private static final String MEDIA_ATTR = "media";
  @NonNls private static final String REL_ATTR = "rel";
  @NonNls private static final String TITLE_ATTR = "title";
  @NonNls private static final String TYPE_ATTR = "type";

  private final FileBasedIndex.InputFilter myInputFilter =
      new FileBasedIndex.InputFilter() {
        public boolean acceptInput(final VirtualFile file) {
          if (!(file.getFileSystem() instanceof LocalFileSystem)) {
            return false;
          }

          final FileType fileType = file.getFileType();
          if (!(fileType instanceof LanguageFileType)) {
            return false;
          }

          final LanguageFileType languageFileType = (LanguageFileType) fileType;
          final Language language = languageFileType.getLanguage();

          return language instanceof TemplateLanguage
              || (language instanceof XMLLanguage && language != XMLLanguage.INSTANCE);
        }
      };
  private final DataExternalizer<InfoHolder<LinkInfo>> myValueExternalizer =
      new DataExternalizer<InfoHolder<LinkInfo>>() {
        public void save(DataOutput out, InfoHolder<LinkInfo> value) throws IOException {
          out.writeInt(value.myValues.length);
          for (final LinkInfo linkInfo : value.myValues) {
            out.writeInt(linkInfo.offset);
            out.writeBoolean(linkInfo.scripted);

            if (!linkInfo.scripted) {
              writeString(linkInfo.value, out);
            }

            writeString(linkInfo.media, out);
            writeString(linkInfo.type, out);
            writeString(linkInfo.rel, out);
            writeString(linkInfo.title, out);
          }
        }

        private void writeString(String s, DataOutput out) throws IOException {
          out.writeBoolean(s != null);
          if (s != null) {
            out.writeUTF(s);
          }
        }

        public InfoHolder<LinkInfo> read(DataInput in) throws IOException {
          final int size = in.readInt();
          final List<LinkInfo> list = new ArrayList<LinkInfo>(size);
          for (int i = 0; i < size; i++) {
            final int offset = in.readInt();
            final boolean scripted = in.readBoolean();

            final String href = !scripted ? (in.readBoolean() ? in.readUTF() : null) : null;
            final String media = in.readBoolean() ? in.readUTF() : null;
            final String type = in.readBoolean() ? in.readUTF() : null;
            final String rel = in.readBoolean() ? in.readUTF() : null;
            final String title = in.readBoolean() ? in.readUTF() : null;

            list.add(new LinkInfo(offset, scripted, href, media, type, rel, title));
          }

          return new InfoHolder<LinkInfo>(list.toArray(new LinkInfo[list.size()]));
        }
      };

  public ID<Integer, InfoHolder<LinkInfo>> getName() {
    return INDEX_ID;
  }

  public interface LinkReferenceResult {
    @Nullable
    PsiFile getReferencedFile();

    @Nullable
    PsiFile resolve();

    boolean isScriptedReference();

    @Nullable
    String getMediaValue();

    @Nullable
    String getRelValue();

    @Nullable
    String getTitleValue();
  }

  @NotNull
  public static List<LinkReferenceResult> getReferencedFiles(
      @NotNull final VirtualFile _file, @NotNull final Project project) {
    final List<LinkReferenceResult> result = new ArrayList<LinkReferenceResult>();
    if (!(_file.getFileSystem() instanceof LocalFileSystem)) {
      return result;
    }

    FileBasedIndex.getInstance()
        .processValues(
            INDEX_ID,
            FileBasedIndex.getFileId(_file),
            null,
            new FileBasedIndex.ValueProcessor<InfoHolder<LinkInfo>>() {
              public boolean process(final VirtualFile file, final InfoHolder<LinkInfo> value) {
                final PsiManager psiManager = PsiManager.getInstance(project);
                final PsiFile psiFile = psiManager.findFile(file);
                if (psiFile != null) {
                  for (final LinkInfo linkInfo : value.myValues) {
                    if (linkInfo.value != null || linkInfo.scripted) {
                      final PsiFileSystemItem[] item = new PsiFileSystemItem[] {null};
                      if (linkInfo.value != null) {
                        final LeafElement newValueElement =
                            Factory.createSingleLeafElement(
                                XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN,
                                "\"" + linkInfo.value + "\"",
                                0,
                                linkInfo.value.length() + 2,
                                null,
                                psiManager,
                                psiFile);
                        final PsiElement element = newValueElement.getPsi();
                        final FileReferenceSet set =
                            new FileReferenceSet(
                                StringUtil.stripQuotesAroundValue(element.getText()),
                                element,
                                1,
                                null,
                                true);

                        final FileReference lastReference = set.getLastReference();

                        if (lastReference != null) {
                          final PsiFileSystemItem resolved = lastReference.resolve();
                          if (resolved instanceof PsiFile) {
                            item[0] = resolved;
                          }
                        }
                      }

                      result.add(new MyLinkReferenceResult(item, linkInfo, psiFile));
                    }
                  }
                }
                return true;
              }
            },
            GlobalSearchScope.allScope(project));

    return result;
  }

  public SingleEntryIndexer<InfoHolder<LinkInfo>> getIndexer() {
    return new SingleEntryIndexer<InfoHolder<LinkInfo>>(false) {
      protected InfoHolder<LinkInfo> computeValue(@NotNull FileContent inputData) {
        final Language language = ((LanguageFileType) inputData.getFileType()).getLanguage();

        final List<LinkInfo> result = new ArrayList<LinkInfo>();

        if (HTMLLanguage.INSTANCE == language || XHTMLLanguage.INSTANCE == language) {
          mapHtml(inputData, language, result);
        } else {
          mapJsp(inputData, result);
        }

        return new InfoHolder<LinkInfo>(result.toArray(new LinkInfo[result.size()]));
      }
    };
  }

  private static void mapJsp(FileContent inputData, final List<LinkInfo> result) {
    final FileViewProvider viewProvider = inputData.getPsiFile().getViewProvider();

    PsiFile psiFile = null;
    if (viewProvider instanceof TemplateLanguageFileViewProvider) {
      final Language dataLanguage =
          ((TemplateLanguageFileViewProvider) viewProvider).getTemplateDataLanguage();
      if (dataLanguage == HTMLLanguage.INSTANCE || dataLanguage == XHTMLLanguage.INSTANCE) {
        psiFile = viewProvider.getPsi(dataLanguage);
      }
    } else {
      psiFile = viewProvider.getPsi(viewProvider.getBaseLanguage());
    }

    if (psiFile != null) {
      final XmlRecursiveElementVisitor visitor =
          new XmlRecursiveElementVisitor() {
            @Override
            public void visitXmlTag(XmlTag tag) {
              if (LINK.equalsIgnoreCase(tag.getLocalName())) {

                final String href = getAttributeValue(tag, HREF_ATTR);
                final String media = getAttributeValue(tag, MEDIA_ATTR);
                final String type = getAttributeValue(tag, TYPE_ATTR);
                final String rel = getAttributeValue(tag, REL_ATTR);
                final String title = getAttributeValue(tag, TITLE_ATTR);

                addResult(
                    result,
                    tag.getTextOffset(),
                    href,
                    media,
                    type,
                    rel,
                    title,
                    isHrefScripted(tag));
              }

              super.visitXmlTag(tag);
            }
          };

      psiFile.accept(visitor);
    }
  }

  private static void mapHtml(FileContent inputData, Language language, List<LinkInfo> result) {
    final Lexer original =
        HTMLLanguage.INSTANCE == language
            ? new HtmlHighlightingLexer()
            : new XHtmlHighlightingLexer();
    final Lexer lexer =
        new FilterLexer(
            original,
            new FilterLexer.Filter() {
              public boolean reject(final IElementType type) {
                return XmlElementType.XML_WHITE_SPACE == type;
              }
            });

    final CharSequence data = inputData.getContentAsText();
    lexer.start(data);

    IElementType tokenType = lexer.getTokenType();
    boolean linkTag = false;
    while (tokenType != null) {
      if (XmlElementType.XML_TAG_NAME == tokenType) {
        final String tagName =
            data.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
        linkTag = LINK.equalsIgnoreCase(tagName);
        // if (BODY_TAG.equalsIgnoreCase(tagName)) {
        //  break; // there are no LINK tags under the body
        // }
      }

      if (linkTag && XmlElementType.XML_NAME == tokenType) {
        int linkTagOffset = lexer.getTokenStart();
        String href = null;
        String type = null;
        String media = null;
        String rel = null;
        String title = null;

        while (true) {
          if (tokenType == null
              || tokenType == XmlTokenType.XML_END_TAG_START
              || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END
              || tokenType == XmlTokenType.XML_START_TAG_START) {
            break;
          }

          if (XmlElementType.XML_NAME == tokenType) {
            final String attrName =
                data.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
            if (HREF_ATTR.equalsIgnoreCase(attrName)) {
              href = parseAttributeValue(lexer, data);
            } else if (MEDIA_ATTR.equalsIgnoreCase(attrName)) {
              media = parseAttributeValue(lexer, data);
            } else if (TYPE_ATTR.equalsIgnoreCase(attrName)) {
              type = parseAttributeValue(lexer, data);
            } else if (REL_ATTR.equalsIgnoreCase(attrName)) {
              rel = parseAttributeValue(lexer, data);
            } else if (TITLE_ATTR.equalsIgnoreCase(attrName)) {
              title = parseAttributeValue(lexer, data);
            }
          }

          lexer.advance();
          tokenType = lexer.getTokenType();
        }

        addResult(result, linkTagOffset, href, media, type, rel, title, false);
      }

      lexer.advance();
      tokenType = lexer.getTokenType();
    }
  }

  private static boolean isHrefScripted(final XmlTag tag) {
    final XmlAttribute attribute = tag.getAttribute(HREF_ATTR);
    if (attribute != null) {
      final XmlAttributeValue value = attribute.getValueElement();
      if (value != null) {
        if (PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) != null) {
          return true;
        }
      }
    }

    return false;
  }

  @Nullable
  private static String getAttributeValue(final XmlTag tag, final String attrName) {
    final XmlAttribute attribute = tag.getAttribute(attrName);
    if (attribute != null) {
      final XmlAttributeValue value = attribute.getValueElement();
      if (value != null) {
        if (PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) == null) {
          return value.getValue();
        }
      }
    }

    return null;
  }

  @Nullable
  private static String parseAttributeValue(final Lexer lexer, CharSequence data) {
    lexer.advance();
    IElementType tokenType = lexer.getTokenType();
    if (XmlElementType.XML_EQ == tokenType) {
      lexer.advance();
      tokenType = lexer.getTokenType();

      if (tokenType == XmlElementType.XML_ATTRIBUTE_VALUE_START_DELIMITER) {
        lexer.advance();
        tokenType = lexer.getTokenType();

        if (XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN == tokenType) {
          return data.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
        }
      } else if (tokenType != XmlTokenType.XML_TAG_END
          && tokenType != XmlTokenType.XML_EMPTY_ELEMENT_END) {
        return data.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
      }
    }

    return null;
  }

  private static void addResult(
      final List<LinkInfo> result,
      final int offset,
      final String hrefValue,
      final String mediaValue,
      final String typeValue,
      final String relValue,
      final String titleValue,
      final boolean scripted) {
    result.add(
        new LinkInfo(offset, scripted, hrefValue, mediaValue, typeValue, relValue, titleValue));
  }

  public DataExternalizer<InfoHolder<LinkInfo>> getValueExternalizer() {
    return myValueExternalizer;
  }

  public FileBasedIndex.InputFilter getInputFilter() {
    return myInputFilter;
  }

  public int getVersion() {
    return 4;
  }

  public static class LinkInfo {
    public int offset;
    public String value;
    public String media;
    public String type;
    public String rel;
    public String title;
    public boolean scripted;

    public LinkInfo(
        final int textOffset,
        final boolean scriptedRef,
        @Nullable final String hrefValue,
        @Nullable final String mediaValue,
        @Nullable final String typeValue,
        @Nullable final String relValue,
        @Nullable final String titleValue) {
      offset = textOffset;
      scripted = scriptedRef;
      value = hrefValue;
      media = mediaValue;
      type = typeValue;
      rel = relValue;
      title = titleValue;
    }

    @Override
    public boolean equals(final Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      final LinkInfo linkInfo = (LinkInfo) o;

      if (offset != linkInfo.offset) return false;
      if (scripted != linkInfo.scripted) return false;
      if (media != null ? !media.equals(linkInfo.media) : linkInfo.media != null) return false;
      if (rel != null ? !rel.equals(linkInfo.rel) : linkInfo.rel != null) return false;
      if (title != null ? !title.equals(linkInfo.title) : linkInfo.title != null) return false;
      if (type != null ? !type.equals(linkInfo.type) : linkInfo.type != null) return false;
      if (value != null ? !value.equals(linkInfo.value) : linkInfo.value != null) return false;

      return true;
    }

    @Override
    public int hashCode() {
      int result = offset;
      result = 31 * result + (value != null ? value.hashCode() : 0);
      result = 31 * result + (media != null ? media.hashCode() : 0);
      result = 31 * result + (type != null ? type.hashCode() : 0);
      result = 31 * result + (rel != null ? rel.hashCode() : 0);
      result = 31 * result + (title != null ? title.hashCode() : 0);
      result = 31 * result + (scripted ? 1 : 0);
      return result;
    }
  }

  private static class MyLinkReferenceResult implements LinkReferenceResult {
    private final PsiFileSystemItem[] myItem;
    private final LinkInfo myLinkInfo;
    private final PsiFile myPsiFile;

    public MyLinkReferenceResult(
        final PsiFileSystemItem[] item, final LinkInfo linkInfo, final PsiFile psiFile) {
      myItem = item;
      myLinkInfo = linkInfo;
      myPsiFile = psiFile;
    }

    public PsiFile getReferencedFile() {
      return (PsiFile) myItem[0];
    }

    public PsiFile resolve() {
      final PsiFile referencedFile = getReferencedFile();
      if (referencedFile != null) {
        return referencedFile;
      }

      if (myPsiFile != null) {
        final PsiElement psiElement = myPsiFile.findElementAt(myLinkInfo.offset);
        if (psiElement != null) {
          final PsiElement parent = psiElement.getParent();
          if (parent instanceof XmlTag) {
            final XmlAttribute attribute = ((XmlTag) parent).getAttribute(HREF_ATTR);
            if (attribute != null) {
              final XmlAttributeValue value = attribute.getValueElement();
              if (value != null) {
                final PsiReference[] references = value.getReferences();
                for (PsiReference reference : references) {
                  final PsiElement element = reference.resolve();
                  if (element instanceof PsiFile) {
                    return (PsiFile) element;
                  }
                }
              }
            }
          }
        }
      }

      return null;
    }

    public boolean isScriptedReference() {
      return myLinkInfo.scripted;
    }

    public String getMediaValue() {
      return myLinkInfo.media;
    }

    public String getRelValue() {
      return myLinkInfo.rel;
    }

    public String getTitleValue() {
      return myLinkInfo.title;
    }
  }

  static class InfoHolder<T> {
    public T[] myValues;

    InfoHolder(final T[] values) {
      myValues = values;
    }

    @Override
    public boolean equals(final Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      final InfoHolder that = (InfoHolder) o;

      if (!Arrays.equals(myValues, that.myValues)) return false;

      return true;
    }

    @Override
    public int hashCode() {
      return myValues != null ? Arrays.hashCode(myValues) : 0;
    }
  }
}
 private ID<Integer, Long> getFileTimestampsIndexId() {
   return ID.create(
       String.format(
           "advisor.ext.ClassFilesTimeStamps.%d", Math.abs(myProject.getBasePath().hashCode())));
 }
/** @author Dmitry Avdeev */
public class XmlNamespaceIndex extends XmlIndex<String> {

  @Nullable
  public static String getNamespace(@NotNull VirtualFile file, final Project project) {
    final List<String> list =
        FileBasedIndex.getInstance().getValues(NAME, file.getUrl(), createFilter(project));
    return list.size() == 0 ? null : list.get(0);
  }

  public static List<IndexedRelevantResource<String, String>> getResourcesByNamespace(
      String namespace, final Project project, Module module) {
    List<IndexedRelevantResource<String, String>> resources =
        IndexedRelevantResource.getResources(NAME, namespace, module, project, null);
    Collections.sort(resources);
    return resources;
  }

  public static List<IndexedRelevantResource<String, String>> getAllResources(
      @NotNull final Module module) {
    return getAllResources(module, null);
  }

  public static List<IndexedRelevantResource<String, String>> getAllResources(
      @NotNull final Module module,
      @Nullable
          NullableFunction<
                  List<IndexedRelevantResource<String, String>>,
                  IndexedRelevantResource<String, String>>
              chooser) {
    return IndexedRelevantResource.getAllResources(NAME, module, chooser);
  }

  private static final ID<String, String> NAME = ID.create("XmlNamespaces");

  @Override
  @NotNull
  public ID<String, String> getName() {
    return NAME;
  }

  @Override
  @NotNull
  public DataIndexer<String, String, FileContent> getIndexer() {
    return new DataIndexer<String, String, FileContent>() {
      @Override
      @NotNull
      public Map<String, String> map(final FileContent inputData) {
        final String ns =
            XsdNamespaceBuilder.computeNamespace(
                new UnsyncByteArrayInputStream(inputData.getContent()));
        final HashMap<String, String> map = new HashMap<String, String>(2);
        if (ns != null) {
          map.put(ns, "");
        }
        map.put(inputData.getFile().getUrl(), ns == null ? "" : ns);
        return map;
      }
    };
  }

  @Override
  public DataExternalizer<String> getValueExternalizer() {
    return KEY_DESCRIPTOR;
  }
}
예제 #17
0
/** @author peter */
public class DomFileIndex extends ScalarIndexExtension<String> {
  public static final ID<String, Void> NAME = ID.create("DomFileIndex");
  private static final FileBasedIndex.InputFilter INPUT_FILTER =
      new FileBasedIndex.InputFilter() {
        public boolean acceptInput(final VirtualFile file) {
          return file.getFileType() == StdFileTypes.XML;
        }
      };
  private final DataIndexer<String, Void, FileContent> myDataIndexer;

  public DomFileIndex() {
    myDataIndexer =
        new DataIndexer<String, Void, FileContent>() {
          @NotNull
          public Map<String, Void> map(final FileContent inputData) {
            final Set<String> namespaces = new THashSet<String>();
            final XmlFileHeader header =
                NanoXmlUtil.parseHeader(new ByteArrayInputStream(inputData.getContent()));
            ContainerUtil.addIfNotNull(header.getPublicId(), namespaces);
            ContainerUtil.addIfNotNull(header.getSystemId(), namespaces);
            ContainerUtil.addIfNotNull(header.getRootTagNamespace(), namespaces);
            final String tagName = header.getRootTagLocalName();
            if (StringUtil.isNotEmpty(tagName)) {
              final THashMap<String, Void> result = new THashMap<String, Void>();
              final DomApplicationComponent component = DomApplicationComponent.getInstance();
              for (final DomFileDescription description : component.getFileDescriptions(tagName)) {
                final String[] strings = description.getAllPossibleRootTagNamespaces();
                if (strings.length == 0
                    || ContainerUtil.intersects(Arrays.asList(strings), namespaces)) {
                  result.put(description.getRootElementClass().getName(), null);
                }
              }
              for (final DomFileDescription description :
                  component.getAcceptingOtherRootTagNameDescriptions()) {
                final String[] strings = description.getAllPossibleRootTagNamespaces();
                if (strings.length == 0
                    || ContainerUtil.intersects(Arrays.asList(strings), namespaces)) {
                  result.put(description.getRootElementClass().getName(), null);
                }
              }
              return result;
            }
            return Collections.emptyMap();
          }
        };
  }

  public ID<String, Void> getName() {
    return NAME;
  }

  public DataIndexer<String, Void, FileContent> getIndexer() {
    return myDataIndexer;
  }

  public KeyDescriptor<String> getKeyDescriptor() {
    return new EnumeratorStringDescriptor();
  }

  public FileBasedIndex.InputFilter getInputFilter() {
    return INPUT_FILTER;
  }

  public boolean dependsOnFileContent() {
    return true;
  }

  public int getVersion() {
    final DomApplicationComponent component = DomApplicationComponent.getInstance();
    int result = 0;
    for (DomFileDescription description : component.getAllFileDescriptions()) {
      result += description.getVersion();
      result +=
          description
              .getRootTagName()
              .hashCode(); // so that a plugin enabling/disabling could trigger the reindexing
    }
    return result;
  }
}
/** @by Maxim.Mossienko on 12/11/13. */
public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayList>
    implements PsiDependentIndex {
  static boolean ourEnabled =
      SystemProperties.getBooleanProperty("idea.enable.duplicates.online.calculation", true);
  static final boolean ourEnabledLightProfiles = true;
  private static boolean ourEnabledOldProfiles = false;

  @NonNls public static final ID<Integer, TIntArrayList> NAME = ID.create("DuplicatesIndex");
  private static final int myBaseVersion = 25;

  private final FileBasedIndex.InputFilter myInputFilter =
      new FileBasedIndex.InputFilter() {
        @Override
        public boolean acceptInput(@NotNull final VirtualFile file) {
          return ourEnabled
              && findDuplicatesProfile(file.getFileType()) != null
              && file.isInLocalFileSystem() // skip library sources
          ;
        }
      };

  private final DataExternalizer<TIntArrayList> myValueExternalizer =
      new DataExternalizer<TIntArrayList>() {
        @Override
        public void save(@NotNull DataOutput out, TIntArrayList list) throws IOException {
          if (list.size() == 2) {
            DataInputOutputUtil.writeINT(out, list.getQuick(0));
            DataInputOutputUtil.writeINT(out, list.getQuick(1));
          } else {
            DataInputOutputUtil.writeINT(out, -list.size());
            int prev = 0;
            for (int i = 0, len = list.size(); i < len; i += 2) {
              int value = list.getQuick(i);
              DataInputOutputUtil.writeINT(out, value - prev);
              prev = value;
              DataInputOutputUtil.writeINT(out, list.getQuick(i + 1));
            }
          }
        }

        @Override
        public TIntArrayList read(@NotNull DataInput in) throws IOException {
          int capacityOrValue = DataInputOutputUtil.readINT(in);
          if (capacityOrValue >= 0) {
            TIntArrayList list = new TIntArrayList(2);
            list.add(capacityOrValue);
            list.add(DataInputOutputUtil.readINT(in));
            return list;
          }
          capacityOrValue = -capacityOrValue;
          TIntArrayList list = new TIntArrayList(capacityOrValue);
          int prev = 0;
          while (capacityOrValue > 0) {
            int value = DataInputOutputUtil.readINT(in) + prev;
            list.add(value);
            prev = value;
            list.add(DataInputOutputUtil.readINT(in));
            capacityOrValue -= 2;
          }
          return list;
        }
      };

  private final DataIndexer<Integer, TIntArrayList, FileContent> myIndexer =
      new DataIndexer<Integer, TIntArrayList, FileContent>() {
        @Override
        @NotNull
        public Map<Integer, TIntArrayList> map(@NotNull final FileContent inputData) {
          FileType type = inputData.getFileType();

          DuplicatesProfile profile = findDuplicatesProfile(type);
          if (profile == null || !profile.acceptsContentForIndexing(inputData))
            return Collections.emptyMap();

          try {
            FileContentImpl fileContent = (FileContentImpl) inputData;

            if (profile instanceof LightDuplicateProfile && ourEnabledLightProfiles) {
              final THashMap<Integer, TIntArrayList> result = new THashMap<>();
              LighterAST ast = fileContent.getLighterASTForPsiDependentIndex();

              ((LightDuplicateProfile) profile)
                  .process(
                      ast,
                      new LightDuplicateProfile.Callback() {
                        @Override
                        public void process(
                            int hash,
                            int hash2,
                            @NotNull LighterAST ast,
                            @NotNull LighterASTNode... nodes) {
                          TIntArrayList list = result.get(hash);
                          if (list == null) {
                            result.put(hash, list = new TIntArrayList(2));
                          }
                          list.add(nodes[0].getStartOffset());
                          list.add(hash2);
                        }
                      });
              return result;
            }
            MyFragmentsCollector collector =
                new MyFragmentsCollector(profile, ((LanguageFileType) type).getLanguage());
            DuplocateVisitor visitor = profile.createVisitor(collector, true);

            visitor.visitNode(fileContent.getPsiFileForPsiDependentIndex());

            return collector.getMap();
          } catch (StackOverflowError ae) {
            return Collections.emptyMap(); // todo Maksim
          }
        }
      };

  @Nullable
  public static DuplicatesProfile findDuplicatesProfile(FileType fileType) {
    if (!(fileType instanceof LanguageFileType)) return null;
    Language language = ((LanguageFileType) fileType).getLanguage();
    DuplicatesProfile profile = DuplicatesProfile.findProfileForLanguage(language);
    return profile != null
            && (ourEnabledOldProfiles && profile.supportDuplicatesIndex()
                || profile instanceof LightDuplicateProfile)
        ? profile
        : null;
  }

  @Override
  public int getVersion() {
    return myBaseVersion
        + (ourEnabled ? 0xFF : 0)
        + (ourEnabledLightProfiles ? 0x7F : 0)
        + (ourEnabledOldProfiles ? 0x21 : 0);
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @NotNull
  @Override
  public ID<Integer, TIntArrayList> getName() {
    return NAME;
  }

  @NotNull
  @Override
  public DataIndexer<Integer, TIntArrayList, FileContent> getIndexer() {
    return myIndexer;
  }

  @NotNull
  @Override
  public DataExternalizer<TIntArrayList> getValueExternalizer() {
    return myValueExternalizer;
  }

  @NotNull
  @Override
  public KeyDescriptor<Integer> getKeyDescriptor() {
    return EnumeratorIntegerDescriptor.INSTANCE;
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return myInputFilter;
  }

  // private static final TracingData myTracingData = new TracingData();
  private static final TracingData myTracingData = null;

  private static class MyFragmentsCollector implements FragmentsCollector {
    private final THashMap<Integer, TIntArrayList> myMap = new THashMap<>();
    private final DuplicatesProfile myProfile;
    private final DuplocatorState myDuplocatorState;

    public MyFragmentsCollector(DuplicatesProfile profile, Language language) {
      myProfile = profile;
      myDuplocatorState = profile.getDuplocatorState(language);
    }

    @Override
    public void add(int hash, int cost, @Nullable PsiFragment frag) {
      if (!isIndexedFragment(frag, cost, myProfile, myDuplocatorState)) {
        return;
      }

      if (myTracingData != null) myTracingData.record(hash, cost, frag);

      TIntArrayList list = myMap.get(hash);
      if (list == null) {
        myMap.put(hash, list = new TIntArrayList());
      }
      list.add(frag.getStartOffset());
      list.add(0);
    }

    public THashMap<Integer, TIntArrayList> getMap() {
      return myMap;
    }
  }

  static boolean isIndexedFragment(
      @Nullable PsiFragment frag,
      int cost,
      DuplicatesProfile profile,
      DuplocatorState duplocatorState) {
    if (frag == null) return false;
    return profile.shouldPutInIndex(frag, cost, duplocatorState);
  }

  @TestOnly
  public static boolean setEnabled(boolean value) {
    boolean old = ourEnabled;
    ourEnabled = value;
    return old;
  }

  @TestOnly
  public static boolean setEnabledOldProfiles(boolean value) {
    boolean old = ourEnabledOldProfiles;
    ourEnabledOldProfiles = value;
    return old;
  }

  @Override
  public boolean hasSnapshotMapping() {
    return true;
  }
}
/** @author Daniel Espendiller <*****@*****.**> */
public class YamlTranslationStubIndex extends FileBasedIndexExtension<String, Set<String>> {

  public static final ID<String, Set<String>> KEY =
      ID.create("fr.adrienbrault.idea.symfony2plugin.translations");
  private final KeyDescriptor<String> myKeyDescriptor = new EnumeratorStringDescriptor();

  @NotNull
  @Override
  public DataIndexer<String, Set<String>, FileContent> getIndexer() {

    return new DataIndexer<String, Set<String>, FileContent>() {
      @NotNull
      @Override
      public Map<String, Set<String>> map(@NotNull FileContent inputData) {

        Map<String, Set<String>> map = new THashMap<>();

        if (!Symfony2ProjectComponent.isEnabledForIndex(inputData.getProject())) {
          return map;
        }

        String extension = inputData.getFile().getExtension();
        if ("xlf".equalsIgnoreCase(extension) || "xliff".equalsIgnoreCase(extension)) {
          return getXlfStringMap(inputData, map);
        }

        PsiFile psiFile = inputData.getPsiFile();
        if (!(psiFile instanceof YAMLFile)) {
          return map;
        }

        // check physical file position
        if (!isValidTranslationFile(inputData, psiFile)) {
          return map;
        }

        String domainName = this.getDomainName(inputData.getFileName());
        if (domainName == null) {
          return map;
        }

        final Set<String> translationKeySet = new HashSet<>();
        YamlTranslationVistor.collectFileTranslations(
            (YAMLFile) psiFile,
            (keyName, yamlKeyValue) -> {
              translationKeySet.add(keyName);
              return true;
            });

        if (translationKeySet.size() == 0) {
          return map;
        }

        map.put(domainName, translationKeySet);

        return map;
      }

      private boolean isValidTranslationFile(FileContent inputData, PsiFile psiFile) {

        // dont index all yaml files; "Resources/translations" should be good for now
        String relativePath =
            VfsUtil.getRelativePath(inputData.getFile(), psiFile.getProject().getBaseDir(), '/');
        if (relativePath != null) {
          return relativePath.contains("Resources/translations");
        }

        // Resources/translations/messages.de.yml
        // @TODO: Resources/translations/de/messages.yml
        String path = inputData.getFile().getPath();
        if (path.endsWith("Resources/translations/" + inputData.getFileName())) {
          return true;
        }

        return false;
      }

      private Map<String, Set<String>> getXlfStringMap(
          FileContent inputData, Map<String, Set<String>> map) {

        // testing files are not that nice
        String relativePath =
            VfsUtil.getRelativePath(inputData.getFile(), inputData.getProject().getBaseDir(), '/');
        if (relativePath != null
            && (relativePath.contains("/Test/")
                || relativePath.contains("/Tests/")
                || relativePath.contains("/Fixture/")
                || relativePath.contains("/Fixtures/"))) {
          return map;
        }

        String domainName = this.getDomainName(inputData.getFileName());
        if (domainName == null) {
          return map;
        }

        InputStream inputStream;
        try {
          inputStream = inputData.getFile().getInputStream();
        } catch (IOException e) {
          return map;
        }

        Set<String> set = TranslationUtil.getXliffTranslations(inputStream);
        if (set.size() > 0) {
          map.put(domainName, set);
        }

        return map;
      }

      @Nullable
      private String getDomainName(@NotNull String fileName) {
        // foo.fr.yml
        // dont index fr.yml
        int domainSplit = fileName.indexOf(".");
        if (domainSplit <= 2) {
          return null;
        }

        return fileName.substring(0, domainSplit);
      }
    };
  }

  @NotNull
  @Override
  public ID<String, Set<String>> getName() {
    return KEY;
  }

  @NotNull
  @Override
  public KeyDescriptor<String> getKeyDescriptor() {
    return this.myKeyDescriptor;
  }

  @NotNull
  public DataExternalizer<Set<String>> getValueExternalizer() {
    return new StringSetDataExternalizer();
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return file ->
        file.getFileType() == YAMLFileType.YML
            || "xlf".equalsIgnoreCase(file.getExtension())
            || "xliff".equalsIgnoreCase(file.getExtension());
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return 4;
  }
}