// Copyright (c) 2018, 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.

library kernel.external_name;

import 'ast.dart';

/// Returns external (native) name of given [Member].
String getExternalName(Member procedure) {
  // Native procedures are marked as external and have an annotation,
  // which looks like this:
  //
  //    import 'dart:_internal' as internal;
  //
  //    @internal.ExternalName("<name-of-native>")
  //    external Object foo(arg0, ...);
  //
  if (!procedure.isExternal) {
    return null;
  }
  for (final Expression annotation in procedure.annotations) {
    if (annotation is ConstructorInvocation) {
      if (_isExternalName(annotation.target.enclosingClass)) {
        return (annotation.arguments.positional.single as StringLiteral).value;
      }
    } else if (annotation is ConstantExpression) {
      final constant = annotation.constant;
      if (constant is InstanceConstant) {
        if (_isExternalName(constant.klass)) {
          return (constant.fieldValues.values.single as StringConstant).value;
        }
      }
    }
  }
  return null;
}

bool _isExternalName(Class klass) =>
    klass.name == 'ExternalName' &&
    klass.enclosingLibrary.importUri.toString() == 'dart:_internal';
