// Copyright 2000-2019 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 org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path;

import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.AtomicNullableLazyValue;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.NullableLazyValue;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyReference;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyIndexPropertyUtil;
import org.jetbrains.plugins.groovy.lang.resolve.api.Argument;
import org.jetbrains.plugins.groovy.lang.resolve.references.GrGetAtReference;
import org.jetbrains.plugins.groovy.lang.resolve.references.GrIndexPropertyReference;
import org.jetbrains.plugins.groovy.lang.resolve.references.GrPutAtReference;

import static org.jetbrains.plugins.groovy.lang.psi.GroovyElementTypes.T_Q;
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyIndexPropertyUtil.isClassLiteral;
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyIndexPropertyUtil.isSimpleArrayAccess;
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyLValueUtil.getRValue;
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyLValueUtil.isRValue;
import static org.jetbrains.plugins.groovy.lang.resolve.ReferencesKt.referenceArray;

/**
 * @author ilyas
 */
public class GrIndexPropertyImpl extends GrExpressionImpl implements GrIndexProperty {

  private final NullableLazyValue<GrIndexPropertyReference> myRValueReference = AtomicNullableLazyValue.createValue(
    () -> isRValue(this) && isIndexAccess() ? new GrGetAtReference(this) : null
  );

  private final NullableLazyValue<GrIndexPropertyReference> myLValueReference = AtomicNullableLazyValue.createValue(() -> {
    if (!isIndexAccess()) return null;
    Argument rValue = getRValue(this);
    return rValue == null ? null : new GrPutAtReference(this, rValue);
  });

  private final NotNullLazyValue<GroovyReference[]> myReferences = AtomicNotNullLazyValue.createValue(
    () -> referenceArray(getRValueReference(), getLValueReference())
  );

  @Nullable
  @Override
  public GroovyReference getRValueReference() {
    return myRValueReference.getValue();
  }

  @Nullable
  @Override
  public GroovyReference getLValueReference() {
    return myLValueReference.getValue();
  }

  @NotNull
  @Override
  public GroovyReference[] getReferences() {
    return myReferences.getValue();
  }

  public GrIndexPropertyImpl(@NotNull ASTNode node) {
    super(node);
  }

  @Override
  public void accept(@NotNull GroovyElementVisitor visitor) {
    visitor.visitIndexProperty(this);
  }

  @Override
  public String toString() {
    return "Property by index";
  }

  @Override
  @NotNull
  public GrExpression getInvokedExpression() {
    return findNotNullChildByClass(GrExpression.class);
  }

  @Nullable
  @Override
  public PsiElement getSafeAccessToken() {
    return findChildByType(T_Q);
  }

  @Override
  @NotNull
  public GrArgumentList getArgumentList() {
    return findNotNullChildByClass(GrArgumentList.class);
  }

  @Nullable
  @Override
  public PsiType getNominalType() {
    return GroovyIndexPropertyUtil.getSimpleArrayAccessType(this);
  }

  private boolean isIndexAccess() {
    return !isClassLiteral(this) && !isSimpleArrayAccess(this);
  }
}

@@ -273,100 +273,54 @@
 lij.
-openapi.util.AtomicNotNullLazyValue;%0Aimport com.intellij.openapi.util.AtomicNullableLazyValu
+psi.PsiElement;%0Aimport com.intellij.psi.PsiTyp
 e;%0Ai
@@ -342,32 +342,23 @@
 lij.
-opena
 p
+s
 i.util.
-NotNullLazy
+Cached
 Valu
@@ -384,73 +384,42 @@
 lij.
-opena
 p
+s
 i.util.
-NullableLazyValue;%0Aimport com.intellij.psi.PsiElemen
+CachedValueProvider.Resul
 t;%0Ai
@@ -433,39 +433,56 @@
 om.intellij.psi.
-PsiType
+util.CachedValuesManager
 ;%0Aimport org.jet
@@ -2078,36 +2078,30 @@
 ivate final 
-NullableLazy
+Cached
 Value%3CGrInde
@@ -2141,57 +2141,335 @@
 ence
- = AtomicNullableLazyValue.createValue(%0A    () -%3E
+;%0A  private final CachedValue%3CGrIndexPropertyReference%3E myLValueReference;%0A%0A  public GrIndexPropertyImpl(@NotNull ASTNode node) %7B%0A    super(node);%0A    CachedValuesManager manager = CachedValuesManager.getManager(getProject());%0A    myRValueReference = manager.createCachedValue(() -%3E %7B%0A      GrIndexPropertyReference reference =
  isR
@@ -2538,125 +2538,107 @@
 null
+;
 %0A  
-);%0A%0A  private final NullableLazyValue%3CGrIndexPropertyReference%3E myLValueReference = AtomicNullableLazyValue
+    return Result.create(reference, this);%0A    %7D);%0A    myLValueReference = manager
 .create
+Cached
 Valu
@@ -2653,45 +2653,8 @@
 %7B%0A  
-  if (!isIndexAccess()) return null;%0A
     
@@ -2696,22 +2696,54 @@
     
-return
+  GrIndexPropertyReference reference =
  rValue 
 == n
@@ -2742,24 +2742,36 @@
 lue 
-=
+!
 = null 
-? null :
+&& isIndexAccess() ?
  new
@@ -2805,193 +2805,73 @@
 lue)
-;%0A  %7D);%0A%0A  private final NotNullLazyValue%3CGroovyReference%5B%5D%3E myReferences = AtomicNotNullLazyValue.createValue(%0A    () -%3E referenceArray(getRValueReference(), getLValueReference())%0A  );
+ : null;%0A      return Result.create(reference, this);%0A    %7D);%0A  %7D
 %0A%0A  
@@ -3187,19 +3187,17 @@
 urn 
-myR
+r
 eference
 s.ge
@@ -3196,95 +3196,56 @@
 ence
-s.
+Array(
 get
+R
 Value
-();%0A  %7D%0A%0A  public GrIndexPropertyImpl(@NotNull ASTNode node) %7B%0A    super(node
+Reference(), getLValueReference()
 );%0A 

fix deadlock in GrIndexPropertyImpl