Skip to content

Commit

Permalink
feat: Python-like import syntax (#598)
Browse files Browse the repository at this point in the history
### Summary of Changes

Replace the old Java-like import syntax with a Python-like import
syntax:

Old:

```java
import myPackage.MyDeclaration
import myPackage.MyDeclaration2 as AnotherDeclaration
import myPackage2.*
```

New:

```py
from myPackage import MyDeclaration, MyDeclaration2 as AnotherDeclaration
from myPackage2 import *
```

The new syntax has several advantages:
1. It clearly separates the package name and the declaration name.
2. When importing multiple declarations from the same package, the
package name need not be repeated.
3. In a qualified import, the imported declarations are now
cross-references instead of plain text. Because of this, they get
updated, when the imported declaration is renamed.

Xtext had special handling of the Java-style imports, but Langium does
not, so it makes not difference for the implementation of the language.

---------

Co-authored-by: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com>
  • Loading branch information
lars-reimann and megalinter-bot authored Oct 2, 2023
1 parent 121f149 commit 4c61b8c
Show file tree
Hide file tree
Showing 149 changed files with 1,556 additions and 837 deletions.
36 changes: 26 additions & 10 deletions docs/language/common/imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,56 +9,72 @@ Safe-DS has two kinds of imports, namely a _qualified import_, which imports a s
A _qualified import_ makes a single declaration available. Here is an example that imports the [class][classes] `DecisionTree` in the [package][packages] `safeds.model.regression`:

```txt
import safeds.model.regression.DecisionTree
from safeds.model.regression import DecisionTree
```

The syntax consists of the following parts:

- The keyword `import`
- The _qualified name_ of the declaration to import (here `safeds.model.regression.DecisionTree`). The qualified name can be obtained by concatenating the name of the [package][packages] that contains the declaration (i.e. `safeds.model.regression`) with the name of the declaration (i.e. `DecisionTree`). The two parts are separated by a dot.
- The keyword `from`.
- The name of the [package][packages] that contains the declaration (here `safeds.model.regression`).
- The keyword `import`.
- The name of the declaration (i.e. `DecisionTree`).

Once the declaration is imported, we can refer to it by its _simple name_. This is the last segment of the qualified name, which is the name of the declaration. Here is, for example, a [call][calls] to the constructor of the `DecisionTree` class:
Once the declaration is imported, we can refer to it by its name. Here is, for example, a [call][calls] to the constructor of the `DecisionTree` class:

```txt
DecisionTree()
```

Multiple declarations can be imported from the same package in a single import statement by separating them with commas:

```txt
from safeds.model.regression import DecisionTree, RandomForest
```

### Qualified Imports with Alias

Sometimes the name of the imported declaration can conflict with other declarations that are imported or that are contained in the importing file. To counter this, declarations can be imported under an alias:

```txt
import safeds.model.regression.DecisionTree as StdlibDecisionTree
from safeds.model.regression import DecisionTree as StdlibDecisionTree
```

Let us take apart the syntax:

- The keyword `from`.
- The name of the [package][packages] that contains the declaration (here `safeds.model.regression`).
- The keyword `import`.
- The _qualified name_ of the declaration to import (here `safeds.model.regression.DecisionTree`). The qualified name can be obtained by concatenating the name of the [package][packages] that contains the declaration (i.e. `safeds.model.regression`) with the name of the declaration (i.e. `DecisionTree`). The two parts are separated by a dot.
- The name of the declaration (i.e. `DecisionTree`).
- The keyword `as`.
- The alias to use (here `StdlibDecisionTree`). This can be any combination of upper- and lowercase letters, underscores, and numbers, as long as it does not start with a number.

Afterwards, the declaration can **only** be accessed using the alias. The simple name cannot be used anymore. The next example shows how to create a new instance of the class now by invoking its constructor:
Afterwards, the declaration can **only** be accessed using the alias. The next example shows how to create a new instance of the class now by invoking its constructor:

```txt
StdlibDecisionTree()
```

Multiple declarations can be imported with or without an alias in a single import statement by separating them with commas:

```txt
from safeds.model.regression import DecisionTree as StdlibDecisionTree, RandomForest
```

## Wildcard Imports

We can also import all declarations in a [package][packages] with a single import. While this saves some typing, it also increases the likelihood of name conflicts and can make it harder for readers of the code to determine where a declaration comes from. Therefore, this should be used with caution.

Nevertheless, let us look at an example, which imports all declarations from the [package][packages] `safeds.model.regression`:

```txt
import safeds.model.regression.*
from safeds.model.regression import *
```

Here is the breakdown of the syntax:

- The keyword `import`.
- The keyword `from`.
- The name of the [package][packages] to import (here `safeds.model.regression`).
- A dot.
- The keyword `import`.
- A star.

Afterwards, we can again access declarations by their simple name, such as the [class][classes] `DecisionTree`:
Expand Down
2 changes: 1 addition & 1 deletion docs/language/common/packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ Here is a breakdown of this:
```txt
// Safe-DS
import safeds.model.regression.DecisionTree
from safeds.model.regression import DecisionTree
```

It is important to note that the `@PythonModule` annotation only affects the one Safe-DS file that contains it rather than the entire Safe-DS package. This allows different Safe-DS files in the same package to point to different [Python modules][python-modules].
Expand Down
Loading

0 comments on commit 4c61b8c

Please sign in to comment.