Skip to content

Commit

Permalink
[2.19] Clarify library usage for no-name declarations update (#4390)
Browse files Browse the repository at this point in the history
fixes #4314 

staged: https://lib-dir-docs.web.app

Changes:

- Added [code
sample](https://lib-dir-docs.web.app/guides/language/effective-dart/documentation#consider-writing-a-library-level-doc-comment)
to existing library-level doc comment section
- Added [Don't use library directives unless attaching doc comments or
annotations](https://lib-dir-docs.web.app/guides/language/effective-dart/usage#dont-use-library-directives-unless-attaching-doc-comments-or-annotations)
section
- Added [Don't explicitly name
libraries](https://lib-dir-docs.web.app/guides/language/effective-dart/usage#dont-explicitly-name-libraries)
section
- Reduced [`part
of`](https://lib-dir-docs.web.app/guides/language/effective-dart/usage#do-use-strings-in-part-of-directives)
section
- Removed / modified unnecessary notes about the library directive on
the [Creating
packages](https://lib-dir-docs.web.app/guides/libraries/create-library-packages)
page

I thought about completely removing the `part of` section in Effective
Dart: Usage, in favor of the more general new section "Don't explicitly
name libraries", because it's not even recommended to use `part of` at
all anymore.

The new section could add a code example similar to the one for `part
of` that more generally illustrates "Use URI strings to refer to
libraries", and the linter rule could point to that section instead.

Thoughts? @kevmoo @pq etc.

Co-authored-by: Parker Lougheed <parlough@gmail.com>
Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 20, 2022
1 parent 5008cf8 commit 458bcdb
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 52 deletions.
8 changes: 7 additions & 1 deletion examples/misc/lib/effective_dart/docs_good.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// ignore_for_file: type_annotate_public_apis, unused_element, strict_raw_type
// ignore_for_file: type_annotate_public_apis, unused_element, strict_raw_type, undefined_annotation, experiment_not_enabled, missing_identifier

This comment has been minimized.

Copy link
@pq

pq Dec 21, 2022

Member

I bet there's a good reason but I'm curious about these new ignores. What are the diagnostics they're suppressing? (It'd be nice to fix them better.)

// ignore_for_file: no_leading_underscores_for_local_identifiers, use_function_type_syntax_for_parameters

// #docregion library-doc
/// A really great test library.
@TestOn('browser')
library;
// #enddocregion library-doc

import 'package:examples_util/ellipsis.dart';

void miscDeclAnalyzedButNotTested() {
Expand Down
8 changes: 8 additions & 0 deletions examples/misc/lib/effective_dart/usage_bad.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
// ignore_for_file: prefer_adjacent_string_concatenation, prefer_is_not_empty, prefer_interpolation_to_compose_strings
// ignore_for_file: unnecessary_this, always_declare_return_types, no_leading_underscores_for_local_identifiers
// ignore_for_file: deprecated_colon_for_default_value
// ignore_for_file: experiment_not_enabled, missing_identifier

This comment has been minimized.

Copy link
@pq

pq Dec 21, 2022

Member

And here too.


// #docregion library-dir

library my_library;

// #enddocregion library-dir

import 'dart:async';
import 'dart:io';
import 'dart:math';
Expand Down
14 changes: 11 additions & 3 deletions src/_guides/language/effective-dart/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,17 @@ functionality provided within. Consider including:
* Links to the most important or most commonly used classes and functions.
* Links to external references on the domain the library is concerned with.

You document a library by placing a doc comment right above the `library`
directive at the start of the file. If the library doesn't have a `library`
directive, you can add one just to hang the doc comment off of it.
To document a library, place a doc comment before
the `library` directive and any annotations that might be attached
at the start of the file.

{:.good}
<?code-excerpt "docs_good.dart (library-doc)"?>
{% prettify dart tag=pre+code %}
/// A really great test library.
@TestOn('browser')
library;
{% endprettify %}

### CONSIDER writing doc comments for private APIs.

Expand Down
62 changes: 40 additions & 22 deletions src/_guides/language/effective-dart/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ extension SmartIterable<T> on Iterable<T> { ... }

[extensions]: /guides/language/extension-methods

### DO name libraries, packages, directories, and source files using `lowercase_with_underscores`. {#do-name-libraries-and-source-files-using-lowercase_with_underscores}
<a id="do-name-libraries-and-source-files-using-lowercase_with_underscores"></a>
### DO name packages, directories, and source files using `lowercase_with_underscores`. {#do-name-packages-and-file-system-entities-using-lowercase-with-underscores}

{% include linter-rule-mention.md rule1="library_names" rule2="file_names" %}
{% include linter-rule-mention.md rule1="file_names" rule2="package_names" %}
<!-- source for rules (update these if you update the guideline):
https://github.com/dart-lang/linter/blob/master/lib/src/rules/library_names.dart
https://github.com/dart-lang/linter/blob/master/lib/src/rules/file_names.dart -->

Some file systems are not case-sensitive, so many projects require filenames to
Expand All @@ -112,27 +112,20 @@ a valid Dart identifier, which may be helpful if the language later supports
symbolic imports.

{:.good}
<?code-excerpt "style_lib_good.dart" replace="/foo\///g"?>
{% prettify dart tag=pre+code %}
library peg_parser.source_scanner;

import 'file_system.dart';
import 'slider_menu.dart';
{% endprettify %}
```text
my_package
└─ lib
└─ file_system.dart
└─ slider_menu.dart
```

{:.bad}
<?code-excerpt "style_lib_good.dart" replace="/foo\///g;/file./file-/g;/slider_menu/SliderMenu/g;/source_scanner/SourceScanner/g;/peg_parser/pegparser/g"?>
{% prettify dart tag=pre+code %}
library pegparser.SourceScanner;

import 'file-system.dart';
import 'SliderMenu.dart';
{% endprettify %}

{{site.alert.note}}
This guideline specifies *how* to name a library *if you choose to name it*.
It is fine to _omit_ the library directive in a file if you want.
{{site.alert.end}}
```text
mypackage
└─ lib
└─ file-system.dart
└─ SliderMenu.dart
```


### DO name import prefixes using `lowercase_with_underscores`.
Expand Down Expand Up @@ -323,6 +316,31 @@ defaultTimeout
kDefaultTimeout
{% endprettify %}

### DON'T explicitly name libraries

Appending a name to the `library` directive is technically possible,
but is a legacy feature and discouraged.

Dart generates a unique tag for each library
based on its path and filename.
Naming libraries overrides this generated URI.
Without the URI, it can be harder for tools to find
the main library file in question.

{:.bad}
<?code-excerpt "usage_bad.dart (library-dir)"?>
{% prettify dart tag=pre+code %}

library my_library;
{% endprettify %}

{:.good}
<?code-excerpt "docs_good.dart (library-doc)"?>
{% prettify dart tag=pre+code %}
/// A really great test library.
@TestOn('browser')
library;
{% endprettify %}

## Ordering

Expand Down
24 changes: 14 additions & 10 deletions src/_guides/language/effective-dart/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,25 @@ but *maintainers* of it sure will.

These guidelines help you compose your program out of multiple files in a
consistent, maintainable way. To keep these guidelines brief, they use "import"
to cover `import` and `export` directives. The guidelines apply equally to both.
to cover `import` and `export` directives. The guidelines apply equally to both.

### DO use strings in `part of` directives.

Many Dart developers avoid using `part` entirely. They find it easier to reason
about their code when each library is a single file. If you do choose to use
`part` to split part of a library out into another file, Dart requires the other
file to in turn indicate which library it's a part of. For legacy reasons, Dart
allows this `part of` directive to use the *name* of the library it's a part of.
That makes it harder for tools to physically find the main library file, and can
make it ambiguous which library the part is actually part of.
file to in turn indicate which library it's a part of.

The preferred, modern syntax is to use a URI string that points directly to the
library file, just like you use in other directives. If you have some library,
`my_library.dart`, that contains:
Dart allows the `part of` directive to use the *name* of a library.
Naming libraries is a legacy feature that is now [discouraged][].
Library names can introduce ambiguity
when determining which library a part belongs to.

[discouraged]: /guides/language/effective-dart/style#dont-explicitly-name-libraries

The preferred syntax syntax is to use a URI string that points

This comment has been minimized.

Copy link
@pq

pq Dec 21, 2022

Member

=>

The preferred syntax is ...

(There's a rogue "syntax".)

directly to the library file.
If you have some library, `my_library.dart`, that contains:

<?code-excerpt "my_library.dart"?>
{% prettify dart tag=pre+code %}
Expand All @@ -42,15 +46,15 @@ library my_library;
part 'some/other/file.dart';
{% endprettify %}

Then the part file should look like:
Then the part file should use the library file's URI string:

{:.good}
<?code-excerpt "some/other/file.dart"?>
{% prettify dart tag=pre+code %}
part of '../../my_library.dart';
{% endprettify %}

And not:
Not the library name:

{:.bad}
<?code-excerpt "some/other/file_2.dart"?>
Expand Down
18 changes: 15 additions & 3 deletions src/_guides/language/language-tour.md
Original file line number Diff line number Diff line change
Expand Up @@ -4107,7 +4107,7 @@ The `import` and `library` directives can help you create a
modular and shareable code base. Libraries not only provide APIs, but
are a unit of privacy: identifiers that start with an underscore (`_`)
are visible only inside the library. *Every Dart app is a library*, even
if it doesn’t use a `library` directive.
if it doesn’t use a [`library`](#library-directive) directive.

Libraries can be distributed using [packages](/guides/packages).

Expand Down Expand Up @@ -4148,7 +4148,6 @@ import 'package:test/test.dart';
*URLs* (uniform resource locators) are a common kind of URI.
{{site.alert.end}}


#### Specifying a library prefix

If you import two libraries that have conflicting identifiers, then you
Expand Down Expand Up @@ -4241,6 +4240,20 @@ Keep in mind the following when you use deferred loading:
using <code>deferred as <em>namespace</em></code>.
The `loadLibrary()` function returns a [`Future`](/guides/libraries/library-tour#future).

#### The `library` directive {#library-directive}

To specify library-level [doc comments][] or [metadata annotations][],
attach them to a `library` declaration at the start of the file.

<?code-excerpt "misc/lib/effective_dart/docs_good.dart (library-doc)"?>
{% prettify dart tag=pre+code %}
/// A really great test library.
@TestOn('browser')
library;
{% endprettify %}

[doc comments]: /guides/language/effective-dart/documentation#consider-writing-a-library-level-doc-comment
[metadata annotations]: /guides/language/language-tour#metadata

### Implementing libraries

Expand All @@ -4251,7 +4264,6 @@ for advice on how to implement a library package, including:
* How to organize library source code.
* How to use the `export` directive.
* When to use the `part` directive.
* When to use the `library` directive.
* How to use conditional imports and exports to implement
a library that supports multiple platforms.

Expand Down
18 changes: 5 additions & 13 deletions src/_guides/libraries/create-library-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,6 @@ lib directory
To make APIs under lib/src public, you can export lib/src files
from a file that's directly under lib.

{{site.alert.note}}
When the `library` directive isn't specified, a unique
tag is generated for each library based on its path and filename.
Therefore, we suggest that you omit the `library` directive from
your code unless you plan to
[generate library-level documentation](#documenting-a-library).
{{site.alert.end}}

## Organizing a library package

Library packages are easiest to maintain, extend, and test
Expand Down Expand Up @@ -272,11 +264,11 @@ void updateBadge() {
For an example of generated docs, see the
[shelf documentation.]({{site.pub-api}}/shelf/latest)

{{site.alert.note}}
To include any library-level documentation in the generated docs,
you must specify the `library` directive.
See [issue 1082.](https://github.com/dart-lang/dartdoc/issues/1082)
{{site.alert.end}}
To include any *library-level* documentation in the generated docs,
add a `library` directive and attach the comment directly above it.
For the how-and-why of documenting libraries, see
[Effective Dart: Documentation](/guides/language/effective-dart/documentation#consider-writing-a-library-level-doc-comment).


## Distributing an open source library {#distributing-a-library}

Expand Down

0 comments on commit 458bcdb

Please sign in to comment.