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

Import syntax including namespace #1806

Merged
merged 14 commits into from
Jun 24, 2021
Merged

Import syntax including namespace #1806

merged 14 commits into from
Jun 24, 2021

Conversation

kustosz
Copy link
Contributor

@kustosz kustosz commented Jun 18, 2021

Pull Request Description

Modifies the import syntax to include the author/namespace prefix in project names. Also introduces a special project keyword for imports of modules from the current project.

Important Notes

This introduces a namespace field to package.yaml. This is a temporary solution, as this is supposed to be mediated by the libraries repository in the future.
It's a very breaking change.
Also introduces a breaking change to the refactoring/renameProject method of the language server, requiring the namespace to be provided for project identification.

Checklist

Please include the following checklist in your PR:

  • The documentation has been updated if necessary.
  • All code conforms to the Scala, Java, and Rust style guides.
  • All documentation and configuration conforms to the markdown and YAML style guides.
  • All code has been tested where possible.

@kustosz kustosz added Type: Enhancement --breaking Important: a change that will break a public API or user-facing behaviour p-highest Should be completed ASAP labels Jun 18, 2021
@kustosz kustosz self-assigned this Jun 18, 2021
Copy link
Contributor

@iamrecursion iamrecursion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't include the image at distribution/std-lib/Examples/data/image.png. It was ignored in .gitignore but its path has changed. Please adapt .gitignore.

Additionally, please test and confirm that we still get the suggestions in the IDE as expected.

Finally, you're missing a changelog entry. Please put one in RELEASES.md.

@@ -169,7 +169,7 @@ case object DocumentationComments extends IRPass {
case expr: IR.Expression => resolveExpression(expr)
case df: IR.Module.Scope.Definition => resolveDefinition(df)
case imp: IR.Module.Scope.Import => imp
case exp: IR.Module.Scope.Export => exp
case exp: IR.Module.Scope.Export.Module => exp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting.

Comment on lines +57 to +59
val exp = ir.exports
.collect { case ex: IR.Module.Scope.Export.Module => ex }
.find(_.name.name == impName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given you're touching the imports resolver, how much work would it be to fix #1569?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More than I can spend :P Probably ~2 days.

@@ -1,3 +1,4 @@
import Cycle_Test.Sub.Imp
import project.Sub.Imp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we still import by the project name itself?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think so, because the desugar process converts to exactly that, so there should be no reason why that would be disallowed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Project name + name space. So the original import here is invalid, but you could write import local.Cycle_Test.Sub.Imp

Comment on lines +279 to +282
.collect {
case AST.Ident.Cons.any(n) => n
case AST.Ident.Var.any(n) => n
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to implicitly ignore anything that somehow slips through to here? .collect will discard things that don't match.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think given how the qualNamePat is defined, nothing else could show up here, right?
But then if it is ever changed, indeed an error could be introduced that will go unnoticed here, so I think I'd +1 that it would be good to somehow handle the unexpected (currently, but not necessarily forever, impossible) case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also contains the Opr('.') segments, this is a way of filtering them.

@@ -1,3 +1,3 @@
from Builtins import all
from Standard.Builtins import all

main = IO.println "Test successful."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing line ending.

Copy link
Member

@radeusgd radeusgd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall

Below are some comments

Comment on lines 31 to 39

## Returns the namespace of the project.

> Example
Get the name of the current project.

Enso_Project.namespace
Builtins.Project_Description.namespace : Text
Builtins.Project_Description.namespace = this.prim_config.namespace
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc is unclear to me about what is the behaviour if I do the following:
Library Foo.Bar defines a method baz = Builtins.Project_Description.namespace and then in a project radeusgd.Hmm I do import Foo.Bar and then IO.println Foo.Bar.baz. Will it return Hmm or Foo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Project_Descritption is just an atom, so you call namespace on its instance, obtained through calling the enso_project method of some module. The wording is unclear indeed, I'll fix this (and the method above, as this one is a copy-paste :P )

@@ -10,7 +10,7 @@ object RefactoringApi {

case object RenameProject extends Method("refactoring/renameProject") {

case class Params(oldName: String, newName: String)
case class Params(namespace: String, oldName: String, newName: String)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may be worth noting somewhere explicitly that the rename can (currently) only change the project name, but not the namespace.

Comment on lines 1245 to 1251
/** Signals that project has been renamed.
*
* @param newName the new project name
*/
case class ProjectRenamed(newName: String) extends ApiResponse
case class ProjectRenamed(namespace: String, newName: String)
extends ApiResponse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing doc for namespace

Comment on lines 92 to 97
* @param name the qualified name of this module.
* @param sourceFile the module's source file.
*/
public Module(QualifiedName name, TruffleFile sourceFile) {
public Module(QualifiedName name, Package<TruffleFile> pkg, TruffleFile sourceFile) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing doc for the added parameter

def copy(
name: IR.Name.Qualified = name,
rename: Option[IR.Name.Literal] = rename,
isAll: Boolean = isAll,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that this is not part of this PR, but this name isAll seems a bit confusing to me, especially as below there are special cases where isAll does not really mean all. Maybe it could be renamed to something more appropriate, like isQualified?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it maybe could, when someone works on this

* @param dependencies a list of package dependencies
* @param originalJson a Json object holding the original values that this
* Config was created from, used to preserve configuration
* keys that are not known
*/
case class Config(
name: String,
namespace: String,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Namespace is not documented.

I think it's important to note here that this is just a temporary workaround that will be removed once it is possible.
Also that it falls back to local if not provided.

Comment on lines 896 to 897
"from Foo.Bar.Quux import Baz",
"from Foo.Bar.Test import Baz, Spam",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these two are not prefixed by username? Or is Foo meant to be the username here? It's a bit confusing as in other examples Foo is used as project/module name. If this is meant to test capitalised usernames, I'd suggest making this Username instead of Foo.

Comment on lines -46 to +47
val id1 = meta.addItem(33, 36)
val id2 = meta.addItem(58, 8)
val id1 = meta.addItem(42, 36)
val id2 = meta.addItem(67, 8)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worrying to me that so many of our tests rely on these locations.
Because, if the tests are being updated it's so extremely tempting to just run them, see what are the new locations and paste them here without checking if they correspond to the right entities.
It's certainly not within scope of this PR to fix that, but just wanted to mention that maybe at some point we could consider taking some other approach, which could maybe be based on identifying the locations by some infix or something more readable than just an integer location.

cc: @iamrecursion

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because, if the tests are being updated it's so extremely tempting to just run them, see what are the new locations and paste them here without checking if they correspond to the right entities.

Would be very tempting, if that was possible... But the only feedback these give you is "the node you want doesn't exist". Nonetheless, the idea of having special markers for metadata is awesome (and I'm pretty sure @mwu-tow already has something like that in the IDE?)

Comment on lines -34 to +35
this.copy(path = newName :: path.tail)
val namespace = path.head
this.copy(path = namespace :: newName :: path.drop(2))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that we can assume that the project sugar is already not present here, correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

Comment on lines +279 to +282
.collect {
case AST.Ident.Cons.any(n) => n
case AST.Ident.Var.any(n) => n
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think given how the qualNamePat is defined, nothing else could show up here, right?
But then if it is ever changed, indeed an error could be introduced that will go unnoticed here, so I think I'd +1 that it would be good to somehow handle the unexpected (currently, but not necessarily forever, impossible) case.

builtins -> standard.builtins

progress towards tests fixing

more tests

more tests

more tests

(almost) all tests

untangle std

untangle std

all e2e tests

error handling

licenses

CR feedback

remove image.png
RELEASES.md Outdated
Comment on lines 3 to 5
- Implemented changes to the import and export syntax, requiring to provide the
project namespace, or use the new `project` keyword to import from the current
project.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put this under Interpreter/Runtime and add the PR number.

Comment on lines 915 to 917
"from Username.Bar export all",
"from Username.Bar as Eggs export all hiding Spam",
"from Username.Bar export all hiding Spam, eggs"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should test with project and lowercase username.

@@ -324,7 +324,9 @@ polyglot java import org.enso.base.Text_Utils
Token::line(
vec![
Token::variable("from", 0),
Token::referent("Builtins", 1),
Token::referent("Standard", 1),
Token::operator(".",0),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Token::operator(".",0),
Token::operator(".", 0),

@farmaazon
Copy link
Contributor

farmaazon commented Jun 23, 2021

@kustosz I think the change in the import syntax should be reflected in docs: https://enso.org/docs/developer/enso/syntax/imports.html#imports-and-exports or https://enso.org/docs/developer/enso/semantics/modules.html#referring-to-modules

What namespace will the stdlib have?

The developer documentation for the Enso compiler, runtime, and IDE..
The developer documentation for the Enso compiler, runtime, and IDE..

@kustosz kustosz merged commit 334a022 into main Jun 24, 2021
@kustosz kustosz deleted the wip/mk/namespace-import branch June 24, 2021 10:42
iamrecursion pushed a commit that referenced this pull request Jul 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
--breaking Important: a change that will break a public API or user-facing behaviour p-highest Should be completed ASAP
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants