Skip to content
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

Dart Language Parser #91

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

Dart Language Parser #91

wants to merge 3 commits into from

Conversation

Attempt3035
Copy link

@Attempt3035 Attempt3035 commented Apr 21, 2024

Working on a dart language parser! 🎉

Using regex and simple step by step process as I couldn't find a good way to handle the relative vs package absolute imports with participle, and a simple step by step regex should do everything that's needed.

Note: This is my first time using the go language, apologies for the many oversights I may make!

Current status:

  • Basic prototype
  • Fix relative vs absolute imports
  • Conditional imports (import 'file_that_does_exist.dart' if (condition) 'file_that_also_does_exist.dart';)
  • Test exports
  • Test with import/export a.dart show a, b hide c, d
  • Clean up

@gabotechs
Copy link
Owner

Cool! Dart is a language that would be nice to have in dep-tree, I could even use it myself.

I see that the progress is still ongoing, let me know if you have any question along the process or if you want me to do a full review straight away.

@Attempt3035
Copy link
Author

Great! Thank you! Still definitely in prototype stage at the moment as I play around with it and wrap my head around go, but I'll definitely get you to have a further look a bit later down the track when I think it's working pretty properly! Quick question on exports though, firstly I don't really understand the role they play in the output entropy graph in languages like JS, secondly for dart to work properly I've been testing just treating exports as imports as they essentially import and re-export the file to be visible to other code when imported, doing this seems to make a correct output graph, what are your thoughts?

@gabotechs
Copy link
Owner

gabotechs commented Apr 28, 2024

I don't really understand the role they play in the output entropy graph in languages like JS

Imagine that we have three files: a.js, b.js and c.js

// a.js
import { foo } from 'b'
// b.js
export { foo } from 'c'
// c.js
export const foo = 'foo'

Given this situation, what would you say, that a.js depends on b.js or c.js? This question can only be answered knowing which names where exported from which file, and in this case, foo is actually declared on c.js, not b.js. This logic is handled for you by dep-tree's machinery, but while implementing a new language, you need to at least provide which names are exported from which file.


for dart to work properly I've been testing just treating exports as imports as they essentially import and re-export the file to be visible to other code when imported, doing this seems to make a correct output graph, what are your thoughts?

I think Dart's implementation should be very straight forward, as the import system is very simple. You basically import whole files without declaring which names are imported, and there is already a function for building that kind of import: language.EmptyImport:

// EmptyImport builds an ImportEntry where nothing specific is imported, like a side effect import.
func EmptyImport(absPath string) ImportEntry {
	return ImportEntry{AbsPath: absPath}
}

You should be able to not even care about exports in Dart, as everything is exported by default, so you are pretty much always importing whole files instead of specific names.

Another approach you could take is to build imports with language.AllImport, but then you need to declare for each file which symbols are exported, so you will need to do a full parsing of each file declaring all the classes, functions, constants, types, etc... seems like a harder path

@Attempt3035
Copy link
Author

Thank you so much for the detailed explanation! (and apologies for my late response!) That's a lot clearer now! I've updated the imports as you suggested, which does indeed make more sense. I'm still wondering about the exports, in the example that:

// a.dart
import 'b.dart';

print(foo);
// b.dart
export 'c.dart';
export 'd.dart';
export 'e.dart';
export 'f.dart';
// c.dart
final foo = 'foo';

If we were to try to use the same logic as JS, really, a.dart only depends on c.dart but unless we parse everything, we have no way to know this. Assuming we don't want to parse everything (for now at least, maybe in the future when I've got a bit more time or staff willing to have a crack we can extend), from my understanding we have two options:

  • Treat b.dart as it's own file and ignore the fact it exports anything. Parse each export as an import. Hence a.dart depends on b.dart which depends on c, d, e & f.
  • Parse b.dart's exports, but not know the members a.dart requires, so in the graph, a.dart requires c, d, e & f

Although it's probably not perfectly correct, option 1 does seem the best of the two...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants