8000 CompilationUnit.directive.stringValue Strips Path Separators on Windows · Issue #59629 · dart-lang/sdk · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

CompilationUnit.directive.stringValue Strips Path Separators on Windows #59629

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
BenAuerDev opened this issue Nov 28, 2024 · 10 comments
Open
Labels
area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@BenAuerDev
Copy link

CompilationUnit.directives.uri.stringValue behaves inconsistently across platforms. On Windows, path separators in part and part of directives are stripped, whereas on Linux, they are preserved.

Current Behavior
For the following directives in Dart code:

part '../filename.dart';
part 'sub_dir/filename.dart';

part of '../filename.dart';
part of 'sub_dir/filename.dart';
  • Linux Output:
    ../filename.dart and sub_dir/filename.dart

  • Windows Output:
    ..filename.dart and sub_dirfilename.dart

Expected Behavior
For the above directives:

  • Linux Output (unchanged):
    ../filename.dart and sub_dir/filename.dart

  • Windows Output:
    ..\filename.dart and sub_dir\filename.dart

sdk version: '>=3.3.0 <4.0.0'
analyzer: '^6.0.0'

Related Work:
I encountered this while I was working on a PR at serverpod where I tested generated code using CompilationUnit and comparing CompilationUnit.directives.uri.stringValue to the expected path.

This test worked fine on Linux but failed on Windows due to the inconsistency.

Log of the directives of the CompilationUnit in windows:
selection_060_720

Log of directive.uri.stringValue on windows:
selection_064_360

Log of directive.uri.stringValue on Linux:
selection_065_360

If I can help with any further information, you can holla at me any time 💪

@BenAuerDev BenAuerDev added the legacy-area-analyzer Use area-devexp instead. label Nov 28, 2024
@bwilkerson
Copy link
Member

I don't know why it would be behaving differently under Windows, but it shouldn't be, so there's definitely a bug.

But there might also be an incorrect expectation. When you execute compilationUnit.directives[i].uri.stringValue (I added an index operator because directives returns a list, and uri isn't defined on List) it should return the content of the string literal without any change based on what platform you're running on. In other words, I would expect that you would get ../filename.dart and sub_dir/filename.dart on both Linux and Windows.

@srawlins srawlins added the type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) label Dec 2, 2024
@srawlins
Copy link
Member
srawlins commented Dec 2, 2024

(Side note: also interesting to get the literal string content as the string can be a concatenation of adjacent strings. E.g. this is legal: import 'package:path/' """path.dart""";)

@srawlins
Copy link
Member
srawlins commented Dec 2, 2024

@BenAuerDev thanks for the detailed report. Is there a way to get a minimal reproduction case? I'd basically like to see "Here's the Dart source with an import with a slash in it" and "Here's what compilationUnit.directives[i].uri.stringValue returns for that source." It seems like this bug would have been caught by our unit tests, which are run on both UNIX systems and Windows.

@BenAuerDev
Copy link
Author

I don't know why it would be behaving differently under Windows, but it shouldn't be, so there's definitely a bug.

But there might also be an incorrect expectation. When you execute compilationUnit.directives[i].uri.stringValue (I added an index operator because directives returns a list, and uri isn't defined on List) it should return the content of the string literal without any change based on what platform you're running on. In other words, I would expect that you would get ../filename.dart and sub_dir/filename.dart on both Linux and Windows.

Ah 💪 That would make my use case even easier if the returned value is the same on windows and linux

@BenAuerDev
Copy link
Author

@srawlins Unfortunately I don't have access to a windows machine currently. I only came across it when running a test at serverpod which worked locally on linux, in the pipeline on linux but failed on windows in the pipeline.

I can see if I'll be able to set up a VM with windows and try it there, or maybe borrow a windows machine when I'm visiting family over the holidays 💪

@bwilkerson bwilkerson added the P2 A bug or feature request we're likely to work on label Dec 16, 2024
@BenAuerDev
Copy link
Author

Hello @srawlins,

I managed to get a minimal reproduction case, I tested it via the serverpod pipeline:

test(
    'CompilationUnit.directives[i].uri.stringValue returns relative path without separators on Windows.',
    () {
  var content = Platform.isWindows
      ? "part 'sub_dir\\example_child.dart';"
      : "part 'sub_dir/example_child.dart';";

  var unit = parseString(content: content).unit;

  var directive = unit.directives.whereType<PartDirective>().first;

  var directiveStringValue = directive.uri.stringValue;

  var expectedPath = Platform.isWindows
      ? 'sub_direxample_child.dart'
      : 'sub_dir/example_child.dart';

  expect(directiveStringValue == expectedPath, isTrue);
  });

@johnniwinther johnniwinther added area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. and removed legacy-area-analyzer Use area-devexp instead. labels Mar 5, 2025
@lrhn
Copy link
Member
lrhn commented Apr 10, 2025

(Just for the record, the part 'sub_dir\\example_child.dart'; is not a valid part directive. Or at least not equivalent to part 'sub_dir/example_child.dart';. The strings should contain an RFC 3986 URI reference, and those only allow / as path separators. A backslash is not allowed in RFC 3986 URIs at all. The Dart Uri class is a little more forgiving and replaces \s with /s in most cases, and since the compilers use that class, some invalid URIs are accepted. That doesn't mean that they're valid. Don't use backslashes in import, export or part directives!)

@BenAuerDev
Copy link
Author

Thanks for the information about URI standards, @lrhn. That's a helpful clarification regarding best practices for cross-platform compatibility.

To clarify the issue I'm seeing, it's not so much about the validity of backslashes themselves in the string literal. Instead, on Windows, CompilationUnit.directives.uri.stringValue seems to be actively removing the path separators (both forward and backslashes), resulting in a string without them. This inconsistent behavior, where separators are preserved on Linux, is what's causing the unexpected test failures.

@lrhn
Copy link
Member
lrhn commented Apr 11, 2025

ACK. I'm not saying there is no problem, just that the reproduction example has an issue. Whether that issue has any effect is uncertain, just something to be wary of.

@BenAuerDev
Copy link
Author

Understood, @lrhn. Thanks for pointing that out. I'll keep that in mind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

5 participants
2ABC
0