Skip to content

Commit

Permalink
Flesh out documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jackfirth committed Sep 11, 2016
1 parent 0149d7a commit 59ccf25
Show file tree
Hide file tree
Showing 13 changed files with 303 additions and 135 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ install:
- raco pkg install --auto --link ${PACKAGES}
script:
- raco test -p ${PACKAGES}
- raco doc-coverage warn
- raco doc-coverage warn racket/base/warn
- raco setup --check-pkg-deps --pkgs ${PACKAGES}
- '[[ $SKIP_COVER ]] || raco cover -f coveralls -d $TRAVIS_BUILD_DIR/coverage -p ${PACKAGES}'
after_success:
Expand Down
14 changes: 6 additions & 8 deletions syntax-warn-base/warn/private/warn.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@

(provide
(contract-out
[anonymous-warning warning-kind?]
[syntax-warning? predicate/c]
[syntax-warning/fix? predicate/c]
[syntax-warning-message (-> syntax-warning? string?)]
[syntax-warning-kind (-> syntax-warning? warning-kind?)]
[syntax-warning-stx (-> syntax-warning? syntax?)]
[syntax-warning-kind (-> syntax-warning? (or/c warning-kind? #f))]
[syntax-warning-fix (-> syntax-warning? (or/c syntax? #f))]
[syntax-warning
(->* (#:message string? #:stx syntax?)
Expand All @@ -30,12 +29,11 @@
(define-simple-macro (define-warning-kind name:id)
(define name (warning-kind 'name)))

(define-warning-kind anonymous-warning)

(module+ test
(define-warning-kind test-warning)
(test-case "define-warning-kind"
(check-pred warning-kind? anonymous-warning)
(check-equal? (warning-kind-name anonymous-warning) 'anonymous-warning)))
(check-pred warning-kind? test-warning)
(check-equal? (warning-kind-name test-warning) 'test-warning)))

(struct syntax-warning
(message kind stx fix)
Expand All @@ -45,7 +43,7 @@

(define (syntax-warning #:message message
#:stx stx
#:kind [kind anonymous-warning]
#:kind [kind #f]
#:fix [fix #f])
(make-syntax-warning message kind stx fix))

Expand All @@ -59,8 +57,8 @@
(syntax-warning #:message "Test warning" #:stx here-stx))
(check-pred syntax-warning? test-warning)
(check-equal? (syntax-warning-message test-warning) "Test warning")
(check-equal? (syntax-warning-kind test-warning) anonymous-warning)
(check-equal? (syntax-warning-stx test-warning) here-stx)
(check-false (syntax-warning-kind test-warning))
(check-false (syntax-warning-fix test-warning)))
(test-case "with fix and kind"
(define-warning-kind test-kind)
Expand Down
2 changes: 1 addition & 1 deletion syntax-warn-cli/warn/raco-fix.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
#:num-deltas num-deltas
#:run-mode mode)
(cond [(zero? num-fixes)
(write-string (format "raco warn: ~a\n" mod))]
(write-string (format "raco fix: ~a\n" mod))]
[else
(define one-warning? (= num-warnings 1))
(define dry-run? (equal? mode 'dry))
Expand Down
3 changes: 1 addition & 2 deletions syntax-warn-cli/warn/raco-warn.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
(define fix (syntax-warning-fix warning))
(define kind (syntax-warning-kind warning))
(define kind-prefix
(and (not (equal? kind anonymous-warning))
(format "[~a]" (warning-kind-name kind))))
(and kind (format "[~a]" (warning-kind-name kind))))
(define message-part
(string-join (list/filter kind-prefix message)))
(define warning-part
Expand Down
56 changes: 56 additions & 0 deletions syntax-warn-doc/base.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#lang racket/base

(provide document-syntax-parameter
kind-tech
kind-tech-definition
phase-order-tech
phase-order-tech-definition
source-code-link
warn-examples
warn-tech
warn-tech-definition)

(require scribble/base
scribble/example
scribble/manual
scribble/text
syntax/parse/define)


(define-simple-macro
(define-techs [key:str use-id:id def-id:id] ...)
(begin
(begin
(define (def-id . pre-flow)
(apply deftech #:key key pre-flow))
(define (use-id . pre-flow)
(apply tech #:key key #:doc warn-doc pre-flow)))
...))

(define warn-doc
'(lib "syntax/warn/main.scrbl"))

(define-techs
["syntax warning" warn-tech warn-tech-definition]
["warning kind" kind-tech kind-tech-definition]
["phase order" phase-order-tech phase-order-tech-definition])

(define (source-code-link url-str)
(begin/text "Source code for this library is avaible at "
(url url-str)))

(define warn-requires
'(syntax/warn))

(define (make-warn-eval)
(make-base-eval #:lang 'racket/base
(cons 'require warn-requires)))

(define (make-warn-lang-eval)
(make-base-eval #:lang 'racket/base/warn))

(define-syntax-rule (warn-examples example ...)
(examples #:eval (make-warn-eval) example ...))

(define-syntax-rule (document-syntax-parameter id pre-flow ...)
(defform #:kind "syntax parameter" #:id id id pre-flow ...))
70 changes: 70 additions & 0 deletions syntax-warn-doc/cli.scrbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#lang scribble/manual

@(require "base.rkt")

@title[#:tag "syntax-warn-cli"]{The Syntax Warning Command Line Interface}

This document describes the @exec{raco warn} and @exec{raco fix}
commands. This commands allow a programmer to check for
@warn-tech{syntax warnings} and, where possible, automatically fix
them. The two commands are designed to work together - when
@exec{raco warn} outputs no warnings, @exec{raco fix} makes no
changes to any modules. Additionally, both commands accept the same
flags for specifying which modules to check.

@section{@exec{raco warn}: Checking Syntax Warnings}

The @exec{raco warn} command searches for @warn-tech{syntax warnings}
in a specified set of modules. Any found warnings are displayed with
a message, the offending source code, and a suggested fix (if present).
If any warnings are found the command exits as a failure, making it
suitable for use in continuous integration systems.

The @exec{raco warn} command accepts any number of arguments along with
the following flags:

@itemize[
@item{@DFlag{arg-kind} --- Sets how to interpret the given arguments.
Defaults to "file". Valid interpretation modes are:
@itemize[@item{file: Each argument is interpreted as a relative
or absolute file path to a module.}
@item{directory: Each argument is interpreted as a
relative or absolute directory path, which is
recursively scanned for modules. All files in
the given directories are assumed to be modules.}
@item{collection: Each argument is interpreted as a
collection, whose modules are checked recursively.}
@item{package: Each argument is interpreted as a
package, whose modules are checked recursively.}]}
@item{@Flag{f} or @DFlag{file} --- Shorthand for @exec{--arg-kind file}.}
@item{@Flag{d} or @DFlag{directory} --- Shorthand for @exec{--arg-kind
directory}.}
@item{@Flag{c} or @DFlag{collection} --- Shorthand for @exec{--arg-kind
collection}.}
@item{@Flag{p} or @DFlag{package} --- Shorthand for @exec{--arg-kind
package}.}]

@section{@exec{raco fix}: Fixing Syntax Warnings}

The @exec{raco fix} command searches for @warn-tech{syntax warnings}
in a specified set of modules and fixes them, if possible. For each
module checked, the set of warnings is filtered to only warnings with
suggested fixes that won't interfere with each other. For instance, if
two warnings suggest changing the same piece of code, @exec{raco fix}
will either fix one of the warnings if its affected source code fully
encompasses the other warning's source code, or fix neither warning if
they only partially overlap. The @exec{raco fix} command also accepts
a @italic{run mode} argument that can configure how @exec{raco fix}
applies changes, if at all.

The @exec{raco fix} command accepts any number of arguments along with
the following flags:

@itemize[
@item{@DFlag{arg-kind} --- Sets how to interpret the given arguments.
This flag accepts the same values and has the same default as it does
for @exec{raco warn}. Additionally, the same shorthand flags for the
various values are accepted.}
@item{@Flag{D} or @DFlag{dry-run} --- Sets the run mode to @italic{
dry run}. In a dry run, @exec{raco fix} performs no file writes and
merely outputs what it would fix in which modules.}]
4 changes: 3 additions & 1 deletion syntax-warn-doc/info.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
(define name "syntax-warn-doc")
(define scribblings
'(("main.scrbl" () (library) "syntax-warn")))
(define deps '("base"))
(define deps '("scribble-lib"
"scribble-text-lib"
"base"))
(define build-deps '("racket-doc"
"scribble-lib"
"syntax-warn-base"))
41 changes: 41 additions & 0 deletions syntax-warn-doc/lang.scrbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#lang scribble/manual

@(require "base.rkt")

@title[#:tag "syntax-warn-lang"]{The Syntax Warnings Language}
@defmodule[racket/base/warn #:packages ("syntax-warn" "syntax-warn-lang")]

This library provides a variant of the @racketmodname[racket/base]
language that adds @warn-tech{syntax warning} wrappers around various
forms. For example, the @racket[require] binding introduced by this
language enforces a few "good style" practices around require clauses.

@section{Warnings as a @hash-lang[]}

When @racketmodname[racket/base/warn] is used as a @hash-lang[] language,
everything from @racketmodname[racket/base] is provided. Various forms
are adjusted to attach @warn-tech{syntax warnings} in certain cases.
These adjustments are documented here.

@defform[(require require-spec ...)]{
Like in @racketmodname[racket/base], but warns @racket[require:phase-order]
when the given @racket[require-spec] forms are not in
@phase-order-tech-definition{phase order}. Phase order is @racket[for-syntax]
first, @racket[for-template] second, @racket[for-label] third,
@racket[for-meta] fourth, and all other forms fifth.}

@section{Warnings as a module}

When @racketmodname[racket/base/warn] is @racket[require]'d as a module,
it provides warning kinds and functions for adding warnings that @hash-lang[]
@racketmodname[racket/base/warn] uses. These are documented here.

@defthing[require:phase-order warning-kind?]{
A @kind-tech{warning kind} for when @racket[require] clauses are not
@phase-order-tech{phase ordered}.}

@defproc[(syntax-warn/require-phase-order [require-syntax syntax?]) syntax?]{
Examines @racket[require-syntax], which is expected to be a
@racket[(require clause ...)] syntax object, and returns it with warnings
attached in the same way as @racket[require] does in @hash-lang[]
@racketmodname[racket/base/warn].}
129 changes: 33 additions & 96 deletions syntax-warn-doc/main.scrbl
Original file line number Diff line number Diff line change
@@ -1,101 +1,38 @@
#lang scribble/manual

@(require scribble/examples (for-label syntax/warn racket/base racket/stxparam racket/contract racket/function))
@(require "base.rkt")

@(define (warn-tech . pre-content)
(apply tech #:key "syntax-warning" #:normalize? #f pre-content))
@(define-syntax-rule (syntax-warn-examples example ...)
(examples #:eval (make-base-eval #:lang 'racket/base '(require syntax/warn)) example ...))
@(define-syntax-rule (document-syntax-parameter id pre-flow ...)
(defform #:kind "syntax parameter" #:id id id pre-flow ...))

@title{Syntax Warnings}
@defmodule[syntax/warn]
@title[#:style '(toc)]{Syntax Warnings}
@author[@author+email["Jack Firth" "jackhfirth@gmail.com"]]

This library provides forms for working with @warn-tech{syntax warnings}. Library
and language developers can make deprecation notices, optimizations, simplifications,
and style rules visible to users, and users can suppress warnings and warning
categories in both individual code snippets and package-wide configuration.

@section{Warnings}

A @deftech[#:key "syntax-warning" #:normalize? #f]{syntax warning} is an expansion
time annotation that draws attention to a potential defect in a program's syntax.
Such defects are not technically incorrect behavior, but signal a likely problem.
Examples include using a deprecated library feature, naming variables in a way
that's considered bad style, using a particular language feature in a way known to
cause subtle bugs, and so on. Syntax warnings are first class values attached to
source code at compile time through syntax properties, and can be inspected by
other code and tools.

@defproc[(syntax-warning [#:message message string?]
[#:stx stx syntax?]
[#:kind kind warning-kind? anonymous-warning]
[#:fix fix syntax? #f])
syntax-warning?]{
Constructs a @warn-tech{syntax warning} of kind @racket[kind] that identifies
@racket[stx] as the syntax to blame and @racket[fix] as a suggested replacement
to use in place of @racket[stx]. If @racket[fix] is not provided, the warning
makes no suggestions about how to resolve it.}

@defproc[(syntax-warning? [v any/c]) boolean?]{
Predicate that recognizes @warn-tech{syntax warnings}.}

@defproc[(syntax-warning/fix? [v any/c]) boolean?]{
Predicate that recognizes @warn-tech{syntax warnings} that include a suggested
fix.}

@deftogether[
(@defproc[(syntax-warning-message [warning syntax-warning?]) string?]
@defproc[(syntax-warning-kind [warning syntax-warning?]) warning-kind?]
@defproc[(syntax-warning-stx [warning syntax-warning?]) syntax?]
@defproc[(syntax-warning-fix [warning syntax-warning?]) (or/c syntax? #f)])]{
Accessors for fields of @warn-tech{syntax warnings}.}

@defthing[warning-kind? predicate/c]{
Predicate recognizing warning kinds.}
}

@defform[(define-warning-kind id)]{
Binds @racket[id] as a @racket[warning-kind?] value whose name is the quoted
form of @racket[id]. @warn-tech{Syntax warnings} often have similar sources
and causes, and it can be helpful to group them under a warning kind.}

@defproc[(warning-kind-name [kind warning-kind?]) symbol?]{
Returns the name of @racket[kind].}

@defthing[anonymous-warning warning-kind?]{
The default warning kind for warnings that don't declare themselves as having
a particular kind.}

@defproc[(syntax-warn [stx syntax?] [warning syntax-warning?]) syntax?]{
Returns a syntax object equivalent to @racket[stx], but with @racket[warning]
attached as a @warn-tech{syntax warning}. The syntax warning need not blame
@racket[stx] as the source of the problem, this procedure merely provides the
ability to attach warnings to syntax objects via syntax properties.
@syntax-warn-examples[
(define-warning-kind identifier-capitalization-warning)
(syntax-warn #'(foo Bar)
(syntax-warning #:message "Don't capitalize the \"Bar\" identifier"
#:kind identifier-capitalization-warning
#:stx #'foo))]}

@defproc[(syntax-warnings [stx syntax?]) (listof syntax?)]{
Returns a list of all syntax warnings present in @racket[stx]. This includes
syntax warnings in any syntax objects nested within @racket[stx].}

@defproc[(read-syntax-warnings [#:input-port in input-port? (current-input-port)]
[#:source-name source any/c (object-name in)]
[#:namespace namespace namespace? (current-namespace)])
(listof syntax-warning?)]{
Constructs a syntax object from @racket[in] using @racket[read-syntax], fully
expands it using @racket[expand-syntax] in @racket[namespace], and returns a
list of all syntax warnings found in the fully expanded module.}

@defproc[(read-syntax-warnings/file [filepath path-string?]
[#:namespace namespace namespace? (current-namespace)])
(listof syntax-warning?)]{
Like @racket[read-syntax-warnings], but reads @racket[filepath] as a module.
Sets the @racket[current-directory] to the directory part of @racket[filepath]
and uses @racket[filepath] as the source name.}
This library includes forms and functions for working with
@warn-tech-definition{syntax warnings}. A syntax warning is a
compile-time source code annotation meant to draw attention to
potential defects. Syntax warnings can be used to point out bad
code style, sub-optimal constructs, excessively verbose code, or
use of deprecated features. Additionally included in this library
are the @exec{raco warn} and @exec{raco fix} commands for finding
and fixing warnings, and the @hash-lang[] @racketmodname[racket/base/warn]
language which provides many forms in @racketmodname[racket/base]
with warnings attached in various ways.

@source-code-link{https://github.com/jackfirth/syntax-warn}

This library is provided as several packages. These packages are
organized as follows:

@itemize[
@item{@code{syntax-warn-base} --- The core API of syntax warnings,
as defined by the @racketmodname[syntax/warn] module.}
@item{@code{syntax-warn-cli} --- The @exec{raco} command line tools
for working with warnings.}
@item{@code{syntax-warn-lang} --- The @racketmodname[racket/base/warn]
language.}
@item{@code{syntax-warn-doc} --- The documentation part of the library.}
@item{@code{syntax-warn} --- A wrapper package that implies installation
of all of the above packages.}]

@table-of-contents[]
@include-section["reference.scrbl"]
@include-section["cli.scrbl"]
@include-section["lang.scrbl"]

0 comments on commit 59ccf25

Please sign in to comment.