// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// @dart = 2.9

// Tests resolution of identifiers inside of extension methods

// Test an extension MyExt with no members against:
//   - a class A with only its own members
//   - and an extension ExtraExt which overlaps the global and class members

import "package:expect/expect.dart";

/////////////////////////////////////////////////////////////////////////
// Note: These imports may be deliberately unused.  They bring certain
// names into scope, in order to test that certain resolution choices are
// made even in the presence of other symbols.
/////////////////////////////////////////////////////////////////////////

// Do Not Delete.
// Bring global members into scope.
import "helpers/global_scope.dart";

// Do Not Delete.
// Bring a class A with instance members into scope.
import "helpers/class_no_shadow.dart";

// Do Not Delete.
// Bring an extension ExtraExt that overlaps the global and instance names
// into scope.
import "helpers/extension_global_instance.dart";

const bool extensionValue = true;

// An extension which defines no members of its own
extension MyExt on A {
  void testNakedIdentifiers() {
    // Globals should resolve to the global name space, and not to the members
    // of the other extension (when present)
    {
      int t0 = fieldInGlobalScope;
      checkGlobalValue(t0);
      int t1 = getterInGlobalScope;
      checkGlobalValue(t1);
      setterInGlobalScope = globalValue;
      int t2 = methodInGlobalScope();
      checkGlobalValue(t2);
    }

    // Instance members resolve to the instance methods and not the members
    // of the other extension (when present)
    {
      String t0 = fieldInInstanceScope;
      checkInstanceValue(t0);
      String t1 = getterInInstanceScope;
      checkInstanceValue(t0);
      setterInInstanceScope = instanceValue;
      String t2 = methodInInstanceScope();
      checkInstanceValue(t0);
    }

    // Extension members resolve to the extension methods in the other
    // extension (unresolved identifier "id" gets turned into "this.id",
    // which is then subject to extension method lookup).
    {
      double t0 = fieldInOtherExtensionScope;
      checkOtherExtensionValue(t0);
      double t1 = getterInOtherExtensionScope;
      checkOtherExtensionValue(t1);
      setterInOtherExtensionScope = otherExtensionValue;
      double t2 = methodInOtherExtensionScope();
      checkOtherExtensionValue(t2);
    }
  }

  void testIdentifiersOnThis() {
    // Global symbols prefixed by `this` resolve to the version on the other
    // extension
    {
      double t0 = this.fieldInGlobalScope;
      checkOtherExtensionValue(t0);
      double t1 = this.getterInGlobalScope;
      checkOtherExtensionValue(t1);
      this.setterInGlobalScope = otherExtensionValue;
      double t2 = this.methodInGlobalScope();
      checkOtherExtensionValue(t2);
    }

    // Instance members resolve to the instance methods and not the members
    // of the other extension (when present)
    {
      String t0 = this.fieldInInstanceScope;
      checkInstanceValue(t0);
      String t1 = this.getterInInstanceScope;
      checkInstanceValue(t0);
      this.setterInInstanceScope = instanceValue;
      String t2 = this.methodInInstanceScope();
      checkInstanceValue(t0);
    }

    // Extension members resolve to the extension methods in the other
    // extension.
    {
      double t0 = this.fieldInOtherExtensionScope;
      checkOtherExtensionValue(t0);
      double t1 = this.getterInOtherExtensionScope;
      checkOtherExtensionValue(t1);
      this.setterInOtherExtensionScope = otherExtensionValue;
      double t2 = this.methodInOtherExtensionScope();
      checkOtherExtensionValue(t2);
    }
  }

  void testIdentifiersOnInstance() {
    A self = this;

    // Global symbols on an instance resolve to the version on the other
    // extension
    {
      double t0 = self.fieldInGlobalScope;
      checkOtherExtensionValue(t0);
      double t1 = self.getterInGlobalScope;
      checkOtherExtensionValue(t1);
      self.setterInGlobalScope = otherExtensionValue;
      double t2 = self.methodInGlobalScope();
      checkOtherExtensionValue(t2);
    }
    // Instance members resolve to the instance methods and not the members
    // of the other extension (when present)
    {
      String t0 = self.fieldInInstanceScope;
      checkInstanceValue(t0);
      String t1 = self.getterInInstanceScope;
      checkInstanceValue(t1);
      self.setterInInstanceScope = instanceValue;
      String t2 = self.methodInInstanceScope();
      checkInstanceValue(t2);
    }

    // Extension members resolve to the extension methods in the other
    // extension.
    {
      double t0 = self.fieldInOtherExtensionScope;
      checkOtherExtensionValue(t0);
      double t1 = self.getterInOtherExtensionScope;
      checkOtherExtensionValue(t1);
      self.setterInOtherExtensionScope = otherExtensionValue;
      double t2 = self.methodInOtherExtensionScope();
      checkOtherExtensionValue(t2);
    }
  }

  void instanceTest() {
    MyExt(this).testNakedIdentifiers();
    MyExt(this).testIdentifiersOnThis();
    MyExt(this).testIdentifiersOnInstance();
  }
}

class B extends A {
  void testNakedIdentifiers() {
    // Globals should resolve to the global name space, and not to the members
    // of the other extension (when present)
    {
      int t0 = fieldInGlobalScope;
      checkGlobalValue(t0);
      int t1 = getterInGlobalScope;
      checkGlobalValue(t1);
      setterInGlobalScope = globalValue;
      int t2 = methodInGlobalScope();
      checkGlobalValue(t2);
    }

    // Instance members resolve to the instance methods and not the members
    // of the other extension (when present)
    {
      String t0 = fieldInInstanceScope;
      checkInstanceValue(t0);
      String t1 = getterInInstanceScope;
      checkInstanceValue(t0);
      setterInInstanceScope = instanceValue;
      String t2 = methodInInstanceScope();
      checkInstanceValue(t0);
    }

    // Extension members resolve to the extension methods in the other
    // extension (unresolved identifier "id" gets turned into "this.id",
    // which is then subject to extension method lookup).
    {
      double t0 = fieldInOtherExtensionScope;
      checkOtherExtensionValue(t0);
      double t1 = getterInOtherExtensionScope;
      checkOtherExtensionValue(t1);
      setterInOtherExtensionScope = otherExtensionValue;
      double t2 = methodInOtherExtensionScope();
      checkOtherExtensionValue(t2);
    }
  }
}

void main() {
  var a = new A();
  a.instanceTest();
  new B().testNakedIdentifiers();

  // Check external resolution as well while we're here

  // Global symbols on an instance resolve to the version on the other
  // extension
  {
    double t0 = a.fieldInGlobalScope;
    checkOtherExtensionValue(t0);
    double t1 = a.getterInGlobalScope;
    checkOtherExtensionValue(t1);
    a.setterInGlobalScope = otherExtensionValue;
    double t2 = a.methodInGlobalScope();
    checkOtherExtensionValue(t2);
  }

  // Instance members resolve to the instance methods and not the members
  // of the other extension (when present)
  {
    String t0 = a.fieldInInstanceScope;
    checkInstanceValue(t0);
    String t1 = a.getterInInstanceScope;
    checkInstanceValue(t1);
    a.setterInInstanceScope = instanceValue;
    String t2 = a.methodInInstanceScope();
    checkInstanceValue(t2);
  }

  // Extension members resolve to the extension methods in the other
  // extension.
  {
    double t0 = a.fieldInOtherExtensionScope;
    checkOtherExtensionValue(t0);
    double t1 = a.getterInOtherExtensionScope;
    checkOtherExtensionValue(t1);
    a.setterInOtherExtensionScope = otherExtensionValue;
    double t2 = a.methodInOtherExtensionScope();
    checkOtherExtensionValue(t2);
  }
}
