Skip to content

Commit 0889d1a

Browse files
committed
Resolve tests
* long (byte)strings with newlines in them can now be broken up onto multiple lines. * 'tests' README is updated * 'pretty' now resolves automatically, updated the tests to match this * rustc-tests now check that the parsed output does not change when resolved * a bunch of resolve bugs are fixed (including a nasty one around expressions) so that all tests pass
1 parent 79f3bc4 commit 0889d1a

File tree

9 files changed

+269
-193
lines changed

9 files changed

+269
-193
lines changed

aa.rs

Lines changed: 0 additions & 2 deletions
This file was deleted.

language-rust.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ test-suite rustc-tests
106106
default-language: Haskell2010
107107
build-depends: base >=4.9 && <5.0
108108
, process >= 1.3
109+
, prettyprinter >=1.1
109110
, bytestring >=0.10
110111
, aeson >= 1.0.0.0
111112
, directory >= 1.3.0.0

src/Language/Rust/Parser/Internal.y

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,25 @@ gen_expression(lhs,rhs,rhs2) :: { Expr Span }
918918
| lambda_args rhs %prec LAMBDA
919919
{ Closure [] Ref (FnDecl (unspan $1) Nothing False (spanOf $1)) $> ($1 # $>) }
920920

921+
-- Postfix expressions that can come after an expression block, in a 'stmt'
922+
--
923+
-- * `{ 1 }[0]` isn't here because it is treated as `{ 1 }; [0]`
924+
-- * `{ 1 }(0)` isn't here because it is treated as `{ 1 }; (0)`
925+
--
926+
postfix_blockexpr(lhs) :: { Expr Span }
927+
: lhs '?' { Try [] $1 ($1 # $>) }
928+
| lhs '.' ident %prec FIELD { FieldAccess [] $1 (unspan $3) ($1 # $>) }
929+
| lhs '.' ident '(' sep_byT(expr,',') ')'
930+
{ MethodCall [] $1 (unspan $3) Nothing $5 ($1 # $>) }
931+
| lhs '.' ident '::' '<' sep_byT(ty,',') '>' '(' sep_byT(expr,',') ')'
932+
{ MethodCall [] $1 (unspan $3) (Just $6) $9 ($1 # $>) }
933+
| lhs '.' int {%
934+
case lit $3 of
935+
Int Dec i Unsuffixed _ -> pure (TupField [] $1 (fromIntegral i) ($1 # $3))
936+
_ -> parseError $3
937+
}
938+
939+
921940

922941
-- Then, we instantiate this general production into the following families of rules:
923942
--
@@ -1024,7 +1043,7 @@ comma_arms :: { [Arm Span] }
10241043
-- An expression followed by match arms. If there is a comma needed, it is added
10251044
expr_arms :: { (Expr Span, [Arm Span]) }
10261045
: nonblock_expr comma_arms { ($1, $2) }
1027-
| postfix_block_expr comma_arms { ($1, $2) }
1046+
| blockpostfix_expr comma_arms { ($1, $2) }
10281047
| vis_safety_block comma_arms { ($1, $2) }
10291048
| vis_safety_block arms { ($1, $2) }
10301049
| block_like_expr comma_arms { ($1, $2) }
@@ -1079,24 +1098,6 @@ field :: { Field Span }
10791098
----------------
10801099
-- Statements --
10811100
----------------
1082-
-- Postfix expressions that can come after an expression block, in a 'stmt'
1083-
--
1084-
-- * `{ 1 }[0]` isn't here because it is treated as `{ 1 }; [0]`
1085-
-- * `{ 1 }(0)` isn't here because it is treated as `{ 1 }; (0)`
1086-
--
1087-
postfix_block(lhs) :: { Expr Span }
1088-
-- postfix expressions
1089-
: lhs '?' { Try [] $1 ($1 # $>) }
1090-
| lhs '.' ident %prec FIELD { FieldAccess [] $1 (unspan $3) ($1 # $>) }
1091-
| lhs '.' ident '(' sep_byT(expr,',') ')'
1092-
{ MethodCall [] $1 (unspan $3) Nothing $5 ($1 # $>) }
1093-
| lhs '.' ident '::' '<' sep_byT(ty,',') '>' '(' sep_byT(expr,',') ')'
1094-
{ MethodCall [] $1 (unspan $3) (Just $6) $9 ($1 # $>) }
1095-
| lhs '.' int {%
1096-
case lit $3 of
1097-
Int Dec i Unsuffixed _ -> pure (TupField [] $1 (fromIntegral i) ($1 # $3))
1098-
_ -> parseError $3
1099-
}
11001101
11011102
gen_expression_block(lhs,rhs,rhs2) :: { Expr Span }
11021103
: lhs '?' { Try [] $1 ($1 # $>) }
@@ -1153,11 +1154,14 @@ gen_expression_block(lhs,rhs,rhs2) :: { Expr Span }
11531154
| lhs '&=' rhs { AssignOp [] BitAndOp $1 $3 ($1 # $>) }
11541155
| lhs '%=' rhs { AssignOp [] RemOp $1 $3 ($1 # $>) }
11551156
1156-
1157-
postfix_block_expr :: { Expr Span }
1158-
: postfix_block(block_like_expr) { $1 }
1159-
| postfix_block(vis_safety_block) { $1 }
1160-
| gen_expression_block(postfix_block_expr,expr,expr) { $1 }
1157+
--
1158+
-- ['blockpostfix_expr'] Allows expressions starting with blocks (things such as '{ 1 }? + 1')
1159+
-- but only when the leading block is itself a postfix expression.
1160+
--
1161+
blockpostfix_expr :: { Expr Span }
1162+
: postfix_blockexpr(block_like_expr) { $1 }
1163+
| postfix_blockexpr(vis_safety_block) { $1 }
1164+
| gen_expression_block(blockpostfix_expr,expr,expr) { $1 }
11611165

11621166
vis_safety_block :: { Expr Span }
11631167
: pub_or_inherited safety inner_attrs_block {%
@@ -1168,7 +1172,8 @@ vis_safety_block :: { Expr Span }
11681172

11691173

11701174
{-
1171-
-- TODO: Just uncommenting these rules (without using them anywhere), causes everything to start failing
1175+
-- TODO: Just uncommenting these rules (without using them anywhere), causes everything to start
1176+
failing, but moving them to the top of the file causes everything to start working again...
11721177

11731178
vis_union_nonblock_expr :: { Expr Span }
11741179
: union_expr { $1 }
@@ -1186,7 +1191,7 @@ stmt :: { Stmt Span }
11861191
| many(outer_attribute) let pat initializer ';' { Local $3 Nothing $4 $1 ($1 # $2 # $>) }
11871192
| many(outer_attribute) nonblock_expr ';' { toStmt ($1 `addAttrs` $2) True False ($1 # $2 # $3) }
11881193
| many(outer_attribute) block_like_expr ';' { toStmt ($1 `addAttrs` $2) True True ($1 # $2 # $3) }
1189-
| many(outer_attribute) postfix_block_expr ';' { toStmt ($1 `addAttrs` $2) True True ($1 # $2 # $3) }
1194+
| many(outer_attribute) blockpostfix_expr ';' { toStmt ($1 `addAttrs` $2) True True ($1 # $2 # $3) }
11901195
-- | many(outer_attribute) vis_union_nonblock_expr ';' { toStmt ($1 `addAttrs` $2) True False ($1 # $2 # $3) }
11911196
| many(outer_attribute) block_like_expr %prec NOSEMI { toStmt ($1 `addAttrs` $2) False True ($1 # $2) }
11921197
| many(outer_attribute) vis_safety_block ';' { toStmt ($1 `addAttrs` $2) True True ($1 # $2 # $>) }
@@ -1212,7 +1217,7 @@ stmts_possibly_no_semi :: { [Maybe (Stmt Span)] }
12121217
: stmtOrSemi stmts_possibly_no_semi { $1 : $2 }
12131218
| stmtOrSemi { [$1] }
12141219
| many(outer_attribute) nonblock_expr { [Just (toStmt ($1 `addAttrs` $2) False False ($1 # $2))] }
1215-
| many(outer_attribute) postfix_block_expr { [Just (toStmt ($1 `addAttrs` $2) False True ($1 # $2))] }
1220+
| many(outer_attribute) blockpostfix_expr { [Just (toStmt ($1 `addAttrs` $2) False True ($1 # $2))] }
12161221

12171222
initializer :: { Maybe (Expr Span) }
12181223
: '=' expr { Just $2 }

src/Language/Rust/Pretty.hs

Lines changed: 98 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ it :: Doc a
2424
{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
2525

2626
module Language.Rust.Pretty (
27-
Pretty(..), PrettyAnnotated(..), Resolve(..), Doc, writeSourceFile
27+
Pretty(..), pretty, PrettyAnnotated(..), prettyAnnotated, Resolve(..), Issue(..), Severity(..),
28+
runResolve, Doc, writeSourceFile
2829
) where
2930

3031
import Language.Rust.Data.Position
@@ -36,94 +37,110 @@ import Language.Rust.Syntax.Ident
3637
import Language.Rust.Pretty.Internal
3738
import Language.Rust.Pretty.Resolve
3839

39-
import Data.Text.Prettyprint.Doc (Doc, Pretty(..), unAnnotate, layoutPretty, LayoutOptions(..), PageWidth(..))
40+
import Data.Text.Prettyprint.Doc (Doc)
41+
import qualified Data.Text.Prettyprint.Doc as PP
4042
import Data.Text.Prettyprint.Doc.Render.Text (renderIO)
4143
import System.IO (Handle)
44+
import Data.Typeable (Typeable)
4245

4346
-- | Given a handle, write into it the given 'SourceFile' (with file width will be 100).
44-
writeSourceFile :: Handle -> SourceFile a -> IO ()
45-
writeSourceFile hdl = renderIO hdl . layoutPretty (LayoutOptions (AvailablePerLine 100 1.0)) . pretty
46-
47-
instance Pretty Abi where pretty = printAbi
48-
instance Pretty BindingMode where pretty = printBindingMode
49-
instance Pretty BinOp where pretty = printBinOp
50-
instance Pretty Ident where pretty = printIdent
51-
instance Pretty ImplPolarity where pretty = printPolarity
52-
instance Pretty LitTok where pretty = printLitTok
53-
instance Pretty Mutability where pretty = printMutability
54-
instance Pretty RangeLimits where pretty = printRangeLimits
55-
instance Pretty Token where pretty = printToken
56-
instance Pretty TokenTree where pretty = printTt
57-
instance Pretty TokenStream where pretty = printTokenStream
58-
instance Pretty UnOp where pretty = printUnOp
59-
instance Pretty Unsafety where pretty = printUnsafety
60-
instance Pretty (Attribute a) where pretty = unAnnotate . prettyAnn
61-
instance Pretty (Block a) where pretty = unAnnotate . prettyAnn
62-
instance Pretty (SourceFile a) where pretty = unAnnotate . prettyAnn
63-
instance Pretty (Expr a) where pretty = unAnnotate . prettyAnn
64-
instance Pretty (Field a) where pretty = unAnnotate . prettyAnn
65-
instance Pretty (FieldPat a) where pretty = unAnnotate . prettyAnn
66-
instance Pretty (FnDecl a) where pretty = unAnnotate . prettyAnn
67-
instance Pretty (ForeignItem a) where pretty = unAnnotate . prettyAnn
68-
instance Pretty (Generics a) where pretty = unAnnotate . prettyAnn
69-
instance Pretty (ImplItem a) where pretty = unAnnotate . prettyAnn
70-
instance Pretty (Item a) where pretty = unAnnotate . prettyAnn
71-
instance Pretty (Lifetime a) where pretty = unAnnotate . prettyAnn
72-
instance Pretty (LifetimeDef a) where pretty = unAnnotate . prettyAnn
73-
instance Pretty (Lit a) where pretty = unAnnotate . prettyAnn
74-
instance Pretty (Nonterminal a) where pretty = unAnnotate . prettyAnn
75-
instance Pretty (Pat a) where pretty = unAnnotate . prettyAnn
76-
instance Pretty (Path a) where pretty = unAnnotate . prettyAnn
77-
instance Pretty (PolyTraitRef a) where pretty = unAnnotate . prettyAnn
78-
instance Pretty (Stmt a) where pretty = unAnnotate . prettyAnn
79-
instance Pretty (StructField a) where pretty = unAnnotate . prettyAnn
80-
instance Pretty (TraitItem a) where pretty = unAnnotate . prettyAnn
81-
instance Pretty (TraitRef a) where pretty = unAnnotate . prettyAnn
82-
instance Pretty (Ty a) where pretty = unAnnotate . prettyAnn
83-
instance Pretty (TyParam a) where pretty = unAnnotate . prettyAnn
84-
instance Pretty (TyParamBound a) where pretty = unAnnotate . prettyAnn
85-
instance Pretty (Variant a) where pretty = unAnnotate . prettyAnn
86-
instance Pretty (ViewPath a) where pretty = unAnnotate . prettyAnn
87-
instance Pretty (Visibility a) where pretty = unAnnotate . prettyAnn
88-
instance Pretty (WhereClause a) where pretty = unAnnotate . prettyAnn
89-
instance Pretty (WherePredicate a) where pretty = unAnnotate . prettyAnn
90-
instance Pretty Position where pretty = pretty . prettyPosition
91-
instance Pretty Span where pretty = pretty . prettySpan
47+
writeSourceFile :: (Monoid a, Typeable a) => Handle -> SourceFile a -> IO ()
48+
writeSourceFile hdl = renderIO hdl . PP.layoutPretty (PP.LayoutOptions (PP.AvailablePerLine 100 1.0)) . pretty
49+
50+
pretty :: (Resolve a, Pretty a) => a -> Doc b
51+
pretty x = case resolve x of
52+
Left desc -> error ("Failed to resolve: " ++ desc)
53+
Right y -> prettyUnresolved y
54+
55+
prettyAnnotated :: (Resolve (f a), PrettyAnnotated f) => f a -> Doc a
56+
prettyAnnotated x = case resolve x of
57+
Left desc -> error ("Failed to resolve: " ++ desc)
58+
Right y -> prettyAnnUnresolved y
59+
60+
class Pretty a where
61+
-- | Pretty-print the given value
62+
prettyUnresolved :: a -> Doc b
63+
64+
instance Pretty Abi where prettyUnresolved = printAbi
65+
instance Pretty BindingMode where prettyUnresolved = printBindingMode
66+
instance Pretty BinOp where prettyUnresolved = printBinOp
67+
instance Pretty Ident where prettyUnresolved = printIdent
68+
instance Pretty ImplPolarity where prettyUnresolved = printPolarity
69+
instance Pretty LitTok where prettyUnresolved = printLitTok
70+
instance Pretty Mutability where prettyUnresolved = printMutability
71+
instance Pretty RangeLimits where prettyUnresolved = printRangeLimits
72+
instance Pretty Token where prettyUnresolved = printToken
73+
instance Pretty TokenTree where prettyUnresolved = printTt
74+
instance Pretty TokenStream where prettyUnresolved = printTokenStream
75+
instance Pretty UnOp where prettyUnresolved = printUnOp
76+
instance Pretty Unsafety where prettyUnresolved = printUnsafety
77+
instance Pretty (Attribute a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
78+
instance Pretty (Block a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
79+
instance Pretty (SourceFile a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
80+
instance Pretty (Expr a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
81+
instance Pretty (Field a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
82+
instance Pretty (FieldPat a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
83+
instance Pretty (FnDecl a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
84+
instance Pretty (ForeignItem a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
85+
instance Pretty (Generics a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
86+
instance Pretty (ImplItem a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
87+
instance Pretty (Item a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
88+
instance Pretty (Lifetime a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
89+
instance Pretty (LifetimeDef a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
90+
instance Pretty (Lit a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
91+
instance Pretty (Nonterminal a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
92+
instance Pretty (Pat a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
93+
instance Pretty (Path a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
94+
instance Pretty (PolyTraitRef a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
95+
instance Pretty (Stmt a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
96+
instance Pretty (StructField a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
97+
instance Pretty (TraitItem a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
98+
instance Pretty (TraitRef a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
99+
instance Pretty (Ty a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
100+
instance Pretty (TyParam a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
101+
instance Pretty (TyParamBound a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
102+
instance Pretty (Variant a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
103+
instance Pretty (ViewPath a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
104+
instance Pretty (Visibility a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
105+
instance Pretty (WhereClause a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
106+
instance Pretty (WherePredicate a) where prettyUnresolved = PP.unAnnotate . prettyAnnUnresolved
107+
instance Pretty Position where prettyUnresolved = PP.pretty . prettyPosition
108+
instance Pretty Span where prettyUnresolved = PP.pretty . prettySpan
92109

93110
-- | Similar to 'Pretty', but for types which are parametrized over an annotation type.
94111
class PrettyAnnotated p where
95112
-- | Pretty-print the given value, adding annotations in the 'Doc' whenever possible.
96-
prettyAnn :: p a -> Doc a
113+
prettyAnnUnresolved :: p a -> Doc a
97114

98115
-- | This instance prints attributes inline
99-
instance PrettyAnnotated Attribute where prettyAnn = flip printAttr True
100-
instance PrettyAnnotated Block where prettyAnn = printBlock
101-
instance PrettyAnnotated SourceFile where prettyAnn = printSourceFile
102-
instance PrettyAnnotated Expr where prettyAnn = printExpr
103-
instance PrettyAnnotated Field where prettyAnn = printField
104-
instance PrettyAnnotated FieldPat where prettyAnn = printFieldPat
105-
instance PrettyAnnotated FnDecl where prettyAnn = printFnArgsAndRet
106-
instance PrettyAnnotated ForeignItem where prettyAnn = printForeignItem
107-
instance PrettyAnnotated Generics where prettyAnn = printGenerics
108-
instance PrettyAnnotated ImplItem where prettyAnn = printImplItem
109-
instance PrettyAnnotated Item where prettyAnn = printItem
110-
instance PrettyAnnotated Lifetime where prettyAnn = printLifetime
111-
instance PrettyAnnotated LifetimeDef where prettyAnn = printLifetimeDef
112-
instance PrettyAnnotated Lit where prettyAnn = printLit
113-
instance PrettyAnnotated Nonterminal where prettyAnn = printNonterminal
114-
instance PrettyAnnotated Pat where prettyAnn = printPat
115-
instance PrettyAnnotated Path where prettyAnn = flip printPath False
116-
instance PrettyAnnotated PolyTraitRef where prettyAnn = printPolyTraitRef
117-
instance PrettyAnnotated Stmt where prettyAnn = printStmt
118-
instance PrettyAnnotated StructField where prettyAnn = printStructField
119-
instance PrettyAnnotated TraitItem where prettyAnn = printTraitItem
120-
instance PrettyAnnotated TraitRef where prettyAnn = printTraitRef
121-
instance PrettyAnnotated Ty where prettyAnn = printType
122-
instance PrettyAnnotated TyParam where prettyAnn = printTyParam
123-
instance PrettyAnnotated TyParamBound where prettyAnn = printBound
124-
instance PrettyAnnotated Variant where prettyAnn = printVariant
125-
instance PrettyAnnotated ViewPath where prettyAnn = printViewPath
126-
instance PrettyAnnotated Visibility where prettyAnn = printVis
127-
instance PrettyAnnotated WhereClause where prettyAnn = printWhereClause True
128-
instance PrettyAnnotated WherePredicate where prettyAnn = printWherePredicate
116+
instance PrettyAnnotated Attribute where prettyAnnUnresolved = flip printAttr True
117+
instance PrettyAnnotated Block where prettyAnnUnresolved = printBlock
118+
instance PrettyAnnotated SourceFile where prettyAnnUnresolved = printSourceFile
119+
instance PrettyAnnotated Expr where prettyAnnUnresolved = printExpr
120+
instance PrettyAnnotated Field where prettyAnnUnresolved = printField
121+
instance PrettyAnnotated FieldPat where prettyAnnUnresolved = printFieldPat
122+
instance PrettyAnnotated FnDecl where prettyAnnUnresolved = printFnArgsAndRet
123+
instance PrettyAnnotated ForeignItem where prettyAnnUnresolved = printForeignItem
124+
instance PrettyAnnotated Generics where prettyAnnUnresolved = printGenerics
125+
instance PrettyAnnotated ImplItem where prettyAnnUnresolved = printImplItem
126+
instance PrettyAnnotated Item where prettyAnnUnresolved = printItem
127+
instance PrettyAnnotated Lifetime where prettyAnnUnresolved = printLifetime
128+
instance PrettyAnnotated LifetimeDef where prettyAnnUnresolved = printLifetimeDef
129+
instance PrettyAnnotated Lit where prettyAnnUnresolved = printLit
130+
instance PrettyAnnotated Nonterminal where prettyAnnUnresolved = printNonterminal
131+
instance PrettyAnnotated Pat where prettyAnnUnresolved = printPat
132+
instance PrettyAnnotated Path where prettyAnnUnresolved = flip printPath False
133+
instance PrettyAnnotated PolyTraitRef where prettyAnnUnresolved = printPolyTraitRef
134+
instance PrettyAnnotated Stmt where prettyAnnUnresolved = printStmt
135+
instance PrettyAnnotated StructField where prettyAnnUnresolved = printStructField
136+
instance PrettyAnnotated TraitItem where prettyAnnUnresolved = printTraitItem
137+
instance PrettyAnnotated TraitRef where prettyAnnUnresolved = printTraitRef
138+
instance PrettyAnnotated Ty where prettyAnnUnresolved = printType
139+
instance PrettyAnnotated TyParam where prettyAnnUnresolved = printTyParam
140+
instance PrettyAnnotated TyParamBound where prettyAnnUnresolved = printBound
141+
instance PrettyAnnotated Variant where prettyAnnUnresolved = printVariant
142+
instance PrettyAnnotated ViewPath where prettyAnnUnresolved = printViewPath
143+
instance PrettyAnnotated Visibility where prettyAnnUnresolved = printVis
144+
instance PrettyAnnotated WhereClause where prettyAnnUnresolved = printWhereClause True
145+
instance PrettyAnnotated WherePredicate where prettyAnnUnresolved = printWherePredicate
129146

0 commit comments

Comments
 (0)