// Copyright 2000-2020 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.util.indexing;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.ThrowableComputable;
import org.jetbrains.annotations.NotNull;

import java.text.MessageFormat;

public final class IndexAccessValidator {
  private final ThreadLocal<ID<?, ?>> ourAlreadyProcessingIndices = new ThreadLocal<>();

  private void checkAccessingIndexDuringOtherIndexProcessing(@NotNull ID<?, ?> indexKey) {
    ID<?, ?> alreadyProcessingIndex = ourAlreadyProcessingIndices.get();
    if (alreadyProcessingIndex == null || alreadyProcessingIndex == indexKey) {
      return;
    }

    String message = MessageFormat.format("Accessing ''{0}'' during processing ''{1}''. Nested different indices processing may cause deadlock",
              indexKey.getName(),
              alreadyProcessingIndex.getName());
    if (ApplicationManager.getApplication().isUnitTestMode()) {
      throw new RuntimeException(message);
    }
    Logger.getInstance(FileBasedIndexImpl.class).error(message); // RuntimeException to skip rebuild
  }

  public <T, E extends Throwable> T validate(@NotNull ID<?, ?> indexKey, @NotNull ThrowableComputable<T, E> runnable) throws E {
    checkAccessingIndexDuringOtherIndexProcessing(indexKey);
    ourAlreadyProcessingIndices.set(indexKey);
    try {
      return runnable.compute();
    }
    finally {
      ourAlreadyProcessingIndices.set(null);
    }
  }
}

@@ -171,16 +171,64 @@
 exing;%0A%0A
+import com.intellij.diagnostic.PluginException;%0A
 import c
@@ -322,24 +322,73 @@
 tic.Logger;%0A
+import com.intellij.openapi.extensions.PluginId;%0A
 import com.i
@@ -1130,16 +1130,190 @@
 ame());%0A
+%0A    PluginId alreadyProcessingIndexOwner = alreadyProcessingIndex.getPluginId();%0A    PluginException exception = new PluginException(message, alreadyProcessingIndexOwner);%0A%0A
     if (
@@ -1384,45 +1384,25 @@
 row 
-new RuntimeException(message)
+exception
 ;%0A    %7D%0A
     
@@ -1393,24 +1393,25 @@
 tion;%0A    %7D%0A
+%0A
     Logger.g
@@ -1453,23 +1453,25 @@
 ).error(
-message
+exception
 ); // Ru

throw plugin exception on nested index processing