sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Macro with explicit "dart:core" import doesn't work

Open Sadhorsephile opened this issue 1 year ago • 2 comments

Problem

Cannot launch the project with the following macro:

Macro

import 'dart:async';
import 'package:macros/macros.dart';

macro class ExampleMacro implements MethodDeclarationsMacro, MethodDefinitionMacro {
  const ExampleMacro();
  @override
  FutureOr<void> buildDeclarationsForMethod(MethodDeclaration method, MemberDeclarationBuilder builder) async {
    builder.declareInLibrary(DeclarationCode.fromString('import \'dart:core\';'));
  }

  @override
  FutureOr<void> buildDefinitionForMethod(MethodDeclaration method, FunctionDefinitionBuilder builder) async {
    builder.augment(FunctionBodyCode.fromString('{ final String foo = "foo";}'));
  }
}
Example
import 'package:test_macros/reproduce/macro.dart';

class SomeClass {
  @ExampleMacro()
  external void testMethod(String id);
}

void main() {
  SomeClass().testMethod('');
}

I have no analyzer errors, but I get errors when I run it:

org-dartlang-augmentation:/_/test_macros/lib/reproduce/example.dart-1:6:56: Error: 'String' isn't a type.
  augment void testMethod(prefix0.String id, ) { final String foo = "foo";}

As I see it, the problem is the use of twoString types - prefix0.String from 'dart:core' as prefix0 and String from dart:core.

Additional info

dart info output:

#### General info

- Dart 3.5.0-180.3.beta (beta) (Wed Jun 5 15:06:15 2024 +0000) on "macos_arm64"
- on macos / Version 14.4.1 (Build 23E224)
- locale is en-RU

#### Project info

- sdk constraint: '^3.5.0-180'
- dependencies: collection, dio, flutter, json, macros, provider
- dev_dependencies: flutter_lints, flutter_test

Sadhorsephile avatar Aug 15 '24 14:08 Sadhorsephile

Summary: The macro fails to correctly import dart:core when using DeclarationCode.fromString('import \'dart:core\';'). This results in a runtime error because the generated code references String from both dart:core and the imported dart:core as a prefix, leading to a type conflict.

dart-github-bot avatar Aug 15 '24 14:08 dart-github-bot

This does sound like a bug, relative to the current specification of part files with imports. It may be correct relative to the prior specification of augmentation libraries that this specification replaces.

The implicit import of dart:core of a library file only happens if you do not explicitly import dart:core in the library file, with or without a prefix. There is no implicit import of dart:core in part files, they inherit the imports of the parent file, and an explicit import of dart:core in a part file should not affect the import of dart:core in the library file. Imports in part files can always shadow imports inherited from the parent file, so there is no need to prevent the inheritance.

What looks to be happening here is that the import of dart:core with a prefix makes the implicit import of dart:core go away. (Which makes sense for the prior augmentation-library specification, where each augmentation library was treated as having its own implicit import of dart:core.)

It shouldn't work like that, but "parts with imports" is likely not implemented yet.

It's not that there are two string types, rather there is no String name imported into the top-level scope at all. That's why the error is "String is not a type".

lrhn avatar Aug 16 '24 09:08 lrhn