// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl.cache.impl.id;

import com.intellij.lang.cacheBuilder.VersionedWordsScanner;
import com.intellij.lang.cacheBuilder.WordOccurrence;
import com.intellij.lang.cacheBuilder.WordsScanner;
import com.intellij.psi.search.UsageSearchContext;
import com.intellij.util.Processor;
import com.intellij.util.indexing.FileContent;
import com.intellij.util.indexing.IdDataConsumer;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;

import java.util.Map;

/**
 * @author peter
 */
public abstract class ScanningIdIndexer implements IdIndexer {
  private volatile WordsScanner myScanner;

  protected abstract WordsScanner createScanner();

  private WordsScanner obtainScanner() {
    WordsScanner scanner = myScanner;
    if (scanner == null) {
      myScanner = scanner = createScanner();
    }
    return scanner;
  }

  @Override
  @NotNull
  public Map<IdIndexEntry, Integer> map(@NotNull final FileContent inputData) {
    final CharSequence chars = inputData.getContentAsText();
    final char[] charsArray = CharArrayUtil.fromSequenceWithoutCopying(chars);
    final IdDataConsumer consumer = new IdDataConsumer();
    obtainScanner().processWords(chars, new Processor<WordOccurrence>() {
      @Override
      public boolean process(final WordOccurrence t) {
        if (charsArray != null && t.getBaseText() == chars) {
          consumer.addOccurrence(charsArray, t.getStart(), t.getEnd(), convertToMask(t.getKind()));
        }
        else {
          consumer.addOccurrence(t.getBaseText(), t.getStart(), t.getEnd(), convertToMask(t.getKind()));
        }
        return true;
      }

      private int convertToMask(final WordOccurrence.Kind kind) {
        if (kind == null) {
          return UsageSearchContext.ANY;
        }
        if (kind == WordOccurrence.Kind.CODE) return UsageSearchContext.IN_CODE;
        if (kind == WordOccurrence.Kind.COMMENTS) return UsageSearchContext.IN_COMMENTS;
        if (kind == WordOccurrence.Kind.LITERALS) return UsageSearchContext.IN_STRINGS;
        if (kind == WordOccurrence.Kind.FOREIGN_LANGUAGE) return UsageSearchContext.IN_FOREIGN_LANGUAGES;
        return 0;
      }
    });
    return consumer.getResult();
  }

  @Override
  public int getVersion() {
    WordsScanner scanner = obtainScanner();
    return scanner instanceof VersionedWordsScanner ? ((VersionedWordsScanner)scanner).getVersion() : -1;
  }
}

@@ -733,51 +733,8 @@
 er %7B
-%0A  private volatile WordsScanner myScanner;
 %0A%0A  
@@ -787,190 +787,8 @@
 );%0A%0A
-  private WordsScanner obtainScanner() %7B%0A    WordsScanner scanner = myScanner;%0A    if (scanner == null) %7B%0A      myScanner = scanner = createScanner();%0A    %7D%0A    return scanner;%0A  %7D%0A%0A
   @O
@@ -1088,22 +1088,22 @@
 ();%0A    
-obtain
+create
 Scanner(
@@ -2213,14 +2213,14 @@
 r = 
-obtain
+create
 Scan

create a scanner each time afresh