Skip to content

Commit

Permalink
WIP: Document roxygen tags in referenced topics
Browse files Browse the repository at this point in the history
  • Loading branch information
lionel- committed Nov 5, 2020
1 parent c73def4 commit eb6f82a
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 91 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ revdep/library
docs/
/r-packages
/.Rprofile
doc
Meta
18 changes: 18 additions & 0 deletions R/doc-namespace.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#' Exports tags
#'
#' ```{r, child = "man/doc/tags-namespace-exports.md"}
#' ```
#'
#' @name @@export
#' @aliases @@exportClass @@exportMethod @@exportPattern
NULL

#' Imports tags
#'
#' ```{r, child = "man/doc/tags-namespace-imports.md"}
#' ```
#'
#' @name @@import
#' @aliases @@importFrom @@importClassesFrom @@importMethodsFrom
#' @@useDynLib
NULL
5 changes: 5 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ home:
href: https://r-pkgs.org/man.html

reference:
- title: Roxygen tags
contents:
- starts_with("@")
- -update_collate

- title: Roclets
contents:
- ends_with("roclet")
Expand Down
68 changes: 68 additions & 0 deletions man/at-export.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions man/at-import.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 66 additions & 0 deletions man/doc/tags-namespace-exports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

For a function to be usable outside of your package, you must __export__ it. By default roxygen2 doesn't export anything from your package. If you want an object to be publicly available, you must explicitly tag it with `@export`.

Use the following guidelines to decide what to export:

* Functions: export functions that you want to make available. Exported
functions must be documented, and you must be cautious when changing their
interface.

* Datasets: all datasets are publicly available. They exist outside of the
package namespace and should not be exported.

* S3 classes: if you want others to be able to create instances of the class
`@export` the constructor function.

* S3 generics: the generic is a function so `@export` if you want it to
be usable outside the package

* S3 methods: every S3 method _must_ be exported, even if the generic is not.
Otherwise the S3 method table will not be generated correctly and internal
generics will not find the correct method.

If you are providing a method for a generic defined in another package,
you must also import that generic.

* S4 classes: if you want others to be able to extend your class, `@export` it.
If you want others to create instances of your class, but not extend it,
`@export` the constructor function, but not the class.

```R
# Can extend and create
#' @export
setClass("A")

# Can extend, but constructor not exported
#' @export
B <- setClass("B")

# Can create, but not extend
#' @export C
C <- setClass("C")

# Can create and extend
#' @export D
#' @exportClass D
D <- setClass("D")
```

* S4 generics: `@export` if you want the generic to be publicly usable.

* S4 methods: you only need to `@export` methods for generics that you
did not define.

* RC classes: the same principles apply as for S4 classes. `@export`
will only export the class.

### Specialised exports

Generally, roxygen2 can generate the correct namespace directive when `@export`ing a specific object. However, you may want to override the defaults and exercise greater control. In this case you can use the more specialised tags described below:

* `@export foo` generates `export(foo)`
* `@exportClass foo` generates `exportClasses(foo)`
* `@exportMethod foo` generates `exportMethods(foo)`
* `@exportPattern foo` generates `exportPattern(foo)`

For even more specialised cases you can use `@rawNamespace code` which inserts `code` literally into the `NAMESPACE`. If you need to automate this, `@evalNamespace foo()` will evaluate the `foo()` in the package environment and insert the results into `NAMESPACE`. Because `evalNamespace()` is run in the package environment, it can only generate exports, not imports.
25 changes: 25 additions & 0 deletions man/doc/tags-namespace-imports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

The `NAMESPACE` also controls which functions from other packages are made available to your package. Only unique directives are saved to the `NAMESPACE` file, so you can repeat them as needed to maintain a close link between the functions where they are needed and the namespace file.

If you are using just a few functions from another package, the recommended option is to note the package name in the `Imports:` field of the `DESCRIPTION` file and call the function(s) explicitly using `::`, e.g., `pkg::fun()`. Alternatively, though no longer recommended due to its poorer readability, use `@importFrom`, e.g., `@importFrom pgk fun`, and call the function(s) without `::`.

If you are using many functions from another package, use `@import package` to import them all and make available without using `::`.

If you want to add a new method to an S3 generic, import it with `@importFrom pkg generic`.

If you are using S4 you may also need:

* `@importClassesFrom package classa classb ...` to import selected S4 classes.

* `@importMethodsFrom package methoda methodb ...` to import selected S4
methods.

To import compiled code from another package, use `@useDynLib`

* `@useDynLib package` imports all compiled functions.

* `@useDynLib package routinea routineb` imports selected compiled functions.

* Any `@useDynLib` specification containing a comma, e.g.
`@useDynLib mypackage, .registration = TRUE` will be inserted as is
into the the NAMESPACE, e.g. `useDynLib(mypackage, .registration = TRUE)`
94 changes: 4 additions & 90 deletions vignettes/namespace.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -15,96 +15,10 @@ The package `NAMESPACE` is one of the most confusing parts of building a package

## Exports

For a function to be usable outside of your package, you must __export__ it. By default roxygen2 doesn't export anything from your package. If you want an object to be publicly available, you must explicitly tag it with `@export`.

Use the following guidelines to decide what to export:

* Functions: export functions that you want to make available. Exported
functions must be documented, and you must be cautious when changing their
interface.

* Datasets: all datasets are publicly available. They exist outside of the
package namespace and should not be exported.

* S3 classes: if you want others to be able to create instances of the class
`@export` the constructor function.

* S3 generics: the generic is a function so `@export` if you want it to
be usable outside the package

* S3 methods: every S3 method _must_ be exported, even if the generic is not.
Otherwise the S3 method table will not be generated correctly and internal
generics will not find the correct method.

If you are providing a method for a generic defined in another package,
you must also import that generic.

* S4 classes: if you want others to be able to extend your class, `@export` it.
If you want others to create instances of your class, but not extend it,
`@export` the constructor function, but not the class.

```R
# Can extend and create
#' @export
setClass("A")

# Can extend, but constructor not exported
#' @export
B <- setClass("B")

# Can create, but not extend
#' @export C
C <- setClass("C")

# Can create and extend
#' @export D
#' @exportClass D
D <- setClass("D")
```

* S4 generics: `@export` if you want the generic to be publicly usable.

* S4 methods: you only need to `@export` methods for generics that you
did not define.

* RC classes: the same principles apply as for S4 classes. `@export`
will only export the class.

### Specialised exports

Generally, roxygen2 can generate the correct namespace directive when `@export`ing a specific object. However, you may want to override the defaults and exercise greater control. In this case you can use the more specialised tags described below:

* `@export foo` generates `export(foo)`
* `@exportClass foo` generates `exportClasses(foo)`
* `@exportMethod foo` generates `exportMethods(foo)`
* `@exportPattern foo` generates `exportPattern(foo)`

For even more specialised cases you can use `@rawNamespace code` which inserts `code` literally into the `NAMESPACE`. If you need to automate this, `@evalNamespace foo()` will evaluate the `foo()` in the package environment and insert the results into `NAMESPACE`. Because `evalNamespace()` is run in the package environment, it can only generate exports, not imports.
```{r, child = "../man/doc/tags-namespace-exports.md"}
```

## Imports

The `NAMESPACE` also controls which functions from other packages are made available to your package. Only unique directives are saved to the `NAMESPACE` file, so you can repeat them as needed to maintain a close link between the functions where they are needed and the namespace file.

If you are using just a few functions from another package, the recommended option is to note the package name in the `Imports:` field of the `DESCRIPTION` file and call the function(s) explicitly using `::`, e.g., `pkg::fun()`. Alternatively, though no longer recommended due to its poorer readability, use `@importFrom`, e.g., `@importFrom pgk fun`, and call the function(s) without `::`.

If you are using many functions from another package, use `@import package` to import them all and make available without using `::`.

If you want to add a new method to an S3 generic, import it with `@importFrom pkg generic`.

If you are using S4 you may also need:

* `@importClassesFrom package classa classb ...` to import selected S4 classes.

* `@importMethodsFrom package methoda methodb ...` to import selected S4
methods.

To import compiled code from another package, use `@useDynLib`

* `@useDynLib package` imports all compiled functions.

* `@useDynLib package routinea routineb` imports selected compiled functions.

* Any `@useDynLib` specification containing a comma, e.g.
`@useDynLib mypackage, .registration = TRUE` will be inserted as is
into the the NAMESPACE, e.g. `useDynLib(mypackage, .registration = TRUE)`

```{r, child = "../man/doc/tags-namespace-imports.md"}
```

0 comments on commit eb6f82a

Please sign in to comment.