Package com.jetbrains.lang.dart.ide.index

Source Code of com.jetbrains.lang.dart.ide.index.DartLibraryIndex

package com.jetbrains.lang.dart.ide.index;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.BidirectionalMap;
import com.intellij.util.indexing.*;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
import com.jetbrains.lang.dart.DartLanguage;
import com.jetbrains.lang.dart.psi.*;
import com.jetbrains.lang.dart.sdk.DartSdk;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.*;

public class DartLibraryIndex extends ScalarIndexExtension<String> {
  public static final ID<String, Void> DART_LIBRARY_INDEX = ID.create("DartLibraryIndex");
  private static final int INDEX_VERSION = 2;

  private static final Key<Pair<Long, BidirectionalMap<String, String>>> LIBRARIES_TIME_AND_MAP_KEY = Key.create("dart.internal.libraries");

  private DataIndexer<String, Void, FileContent> myDataIndexer = new MyDataIndexer();

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

  @Override
  public int getVersion() {
    return DartIndexUtil.BASE_VERSION + INDEX_VERSION;
  }

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

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

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

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

  public static List<VirtualFile> findLibraryClass(@NotNull PsiElement context, String libraryName) {
    if (libraryName.startsWith("dart:")) {
      String stdLibName = libraryName.substring("dart:".length());
      VirtualFile stdLibFile = getStandardLibraryFromSdk(context.getProject(), stdLibName);
      if (stdLibFile != null) {
        return Arrays.asList(stdLibFile);
      }
    }
    return new ArrayList<VirtualFile>(findSingleLibraryClass(context.getProject(), libraryName));
  }

  private static Collection<VirtualFile> findSingleLibraryClass(Project project, String libraryName) {
    return FileBasedIndex.getInstance().getContainingFiles(DART_LIBRARY_INDEX, libraryName, GlobalSearchScope.allScope(project));
  }

  public static Collection<VirtualFile> findSingleLibraryClass(String libraryName, GlobalSearchScope scope) {
    return FileBasedIndex.getInstance().getContainingFiles(DART_LIBRARY_INDEX, libraryName, scope);
  }

  @NotNull
  public static Set<String> getAllLibraryNames(Project project) {
    final Collection<String> allKeys = FileBasedIndex.getInstance().getAllKeys(DART_LIBRARY_INDEX, project);
    return new THashSet<String>(allKeys);
  }

  private static class MyDataIndexer implements DataIndexer<String, Void, FileContent> {
    @Override
    @NotNull
    public Map<String, Void> map(@NotNull final FileContent inputData) {
      final DartFileIndexData indexData = DartIndexUtil.indexFile(inputData);

      return indexData.isPart() ? Collections.<String, Void>emptyMap()
                                : Collections.<String, Void>singletonMap(indexData.getLibraryName(), null);
    }
  }

  @Nullable
  public static String getStandardLibraryNameByRelativePath(final @NotNull Project project, final @NotNull String relativePath) {
    final DartSdk sdk = DartSdk.getGlobalDartSdk();
    final List<String> libNames = sdk == null ? null : getLibraryNameToRelativePathMap(project, sdk).getKeysByValue(relativePath);
    return libNames == null || libNames.isEmpty() ? null : libNames.get(0);
  }

  @Nullable
  public static VirtualFile getStandardLibraryFromSdk(final @NotNull Project project, final @NotNull String libraryName) {
    final DartSdk sdk = DartSdk.getGlobalDartSdk();
    final String relativeLibPath = sdk == null ? null : getLibraryNameToRelativePathMap(project, sdk).get(libraryName);
    return relativeLibPath == null ? null : LocalFileSystem.getInstance().findFileByPath(sdk.getHomePath() + "/lib/" + relativeLibPath);
  }

  public static Collection<String> getAllStandardLibrariesFromSdk(final @NotNull Project project) {
    final DartSdk sdk = DartSdk.getGlobalDartSdk();
    return sdk == null ? Collections.<String>emptyList() : getLibraryNameToRelativePathMap(project, sdk).keySet();
  }

  @NotNull
  private static BidirectionalMap<String, String> getLibraryNameToRelativePathMap(final @NotNull Project project,
                                                                                  final @NotNull DartSdk sdk) {
    final VirtualFile librariesDartFile = LocalFileSystem.getInstance().findFileByPath(sdk.getHomePath() + "/lib/_internal/libraries.dart");
    if (librariesDartFile == null) return new BidirectionalMap<String, String>();

    final Pair<Long, BidirectionalMap<String, String>> data = librariesDartFile.getUserData(LIBRARIES_TIME_AND_MAP_KEY);
    final Long cachedTimestamp = data == null ? null : data.first;
    final long modificationCount = librariesDartFile.getModificationCount();

    if (cachedTimestamp != null && cachedTimestamp.equals(modificationCount)) {
      return data.second;
    }

    return ApplicationManager.getApplication().runReadAction(new Computable<BidirectionalMap<String, String>>() {
      public BidirectionalMap<String, String> compute() {
        try {
          final String contents = StringUtil.convertLineSeparators(VfsUtilCore.loadText(librariesDartFile));
          final PsiFile psiFile =
            PsiFileFactory.getInstance(project).createFileFromText("libraries.dart", DartLanguage.INSTANCE, contents);
          if (!(psiFile instanceof DartFile)) {
            return new BidirectionalMap<String, String>();
          }

          final Pair<Long, BidirectionalMap<String, String>> data =
            Pair.create(modificationCount, computeLibraryNameToRelativePathMap((DartFile)psiFile));
          librariesDartFile.putUserData(LIBRARIES_TIME_AND_MAP_KEY, data);
          return data.second;
        }
        catch (IOException e) {
          return new BidirectionalMap<String, String>();
        }
      }
    });
  }

  private static BidirectionalMap<String, String> computeLibraryNameToRelativePathMap(final @NotNull DartFile librariesDartFile) {
/*
const Map<String, LibraryInfo> LIBRARIES = const {

  "async": const LibraryInfo(
      "async/async.dart",
      maturity: Maturity.STABLE,
      dart2jsPatchPath: "_internal/lib/async_patch.dart"),

  "_chrome": const LibraryInfo(
      "_chrome/dart2js/chrome_dart2js.dart",
      documented: false,
      category: "Client"),

*/
    final BidirectionalMap<String, String> result = new BidirectionalMap<String, String>();

    librariesDartFile.acceptChildren(new DartRecursiveVisitor() {
      public void visitMapLiteralEntry(final @NotNull DartMapLiteralEntry mapLiteralEntry) {
        final List<DartExpression> expressions = mapLiteralEntry.getExpressionList();
        if (expressions.size() != 2 ||
            !(expressions.get(0) instanceof DartStringLiteralExpression) ||
            !(expressions.get(1) instanceof DartConstConstructorExpression)) {
          return;
        }

        final DartStringLiteralExpression keyExpression = (DartStringLiteralExpression)expressions.get(0);
        final DartConstConstructorExpression constructorExpression = (DartConstConstructorExpression)expressions.get(1);

        final String libraryName = StringUtil.unquoteString(keyExpression.getText());
        if (libraryName.startsWith("_")) return;

        final DartType dartType = constructorExpression.getType();
        if (dartType == null || !"LibraryInfo".equals(dartType.getText())) return;

        final DartArguments arguments = constructorExpression.getArguments();
        final DartArgumentList argumentList = arguments != null ? arguments.getArgumentList() : null;
        final List<DartExpression> expressionList = argumentList != null ? argumentList.getExpressionList() : null;
        final DartExpression firstExpression = expressionList == null || expressionList.isEmpty() ? null : expressionList.get(0);
        final String libraryRelativePath = firstExpression instanceof DartStringLiteralExpression
                                           ? StringUtil.unquoteString(firstExpression.getText())
                                           : null;

        if (libraryRelativePath != null) {
          result.put(libraryName, libraryRelativePath);
        }
      }
    });

    return result;
  }
}
TOP

Related Classes of com.jetbrains.lang.dart.ide.index.DartLibraryIndex

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.