/*
 * Copyright 2013 The Error Prone Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.errorprone.refaster;

import static com.google.errorprone.refaster.Unifier.unifications;

import com.google.auto.value.AutoValue;
import com.sun.source.tree.InstanceOfTree;
import com.sun.source.tree.TreeVisitor;
import com.sun.tools.javac.tree.JCTree.JCInstanceOf;
import javax.annotation.Nullable;

/**
 * {@link UTree} representation of a {@link InstanceOfTree}.
 *
 * @author lowasser@google.com (Louis Wasserman)
 */
@AutoValue
abstract class UInstanceOf extends UExpression implements InstanceOfTree {
  public static UInstanceOf create(UExpression expression, UTree<?> type) {
    return new AutoValue_UInstanceOf(expression, type);
  }

  @Override
  public abstract UExpression getExpression();

  @Override
  public abstract UTree<?> getType();

  @Override
  public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
    return visitor.visitInstanceOf(this, data);
  }

  @Override
  public Kind getKind() {
    return Kind.INSTANCE_OF;
  }

  @Override
  public JCInstanceOf inline(Inliner inliner) throws CouldNotResolveImportException {
    return inliner.maker().TypeTest(getExpression().inline(inliner), getType().inline(inliner));
  }

  @Override
  @Nullable
  public Choice<Unifier> visitInstanceOf(InstanceOfTree instanceOf, @Nullable Unifier unifier) {
    return getExpression()
        .unify(instanceOf.getExpression(), unifier)
        .thenChoose(unifications(getType(), instanceOf.getType()));
  }
}

@@ -885,16 +885,48 @@
 anceOf;%0A
+import java.lang.reflect.Proxy;%0A
 import j
@@ -951,16 +951,16 @@
 llable;%0A
-
 %0A/**%0A * 
@@ -1135,34 +1135,8 @@
 ion 
-implements InstanceOfTree 
 %7B%0A  
@@ -1266,36 +1266,24 @@
 type);%0A  %7D%0A%0A
-  @Override%0A
   public abs
@@ -1314,36 +1314,24 @@
 ression();%0A%0A
-  @Override%0A
   public abs
@@ -1427,24 +1427,958 @@
 , D data) %7B%0A
+    InstanceOfTree proxy =%0A        (InstanceOfTree)%0A            Proxy.newProxyInstance(%0A                getClass().getClassLoader(),%0A                new Class%3C?%3E%5B%5D %7BInstanceOfTree.class%7D,%0A                (unused, method, args) -%3E %7B%0A                  switch (method.getName()) %7B%0A                    case %22getPattern%22:%0A                      // TOOD(cushon): support refaster template matching on instanceof patterns%0A                      return null;%0A                    case %22getExpression%22:%0A                      return getExpression();%0A                    case %22getType%22:%0A                      return getType();%0A                    default:%0A                      try %7B%0A                        return method.invoke(UInstanceOf.this, args);%0A                      %7D catch (IllegalArgumentException e) %7B%0A                        throw new LinkageError(method.getName(), e);%0A                      %7D%0A                  %7D%0A                %7D);%0A
     return v
@@ -2400,20 +2400,21 @@
 tanceOf(
-this
+proxy
 , data);

Work around a change to InstanceOfTree in JDK 14