/src/Editing/Tests.hs

http://github.com/Eelis/geordi · Haskell · 464 lines · 409 code · 23 blank · 32 comment · 17 complexity · 3e418083181f2f751a6c7f5277af3a7b MD5 · raw file

  1. {-# LANGUAGE UnicodeSyntax #-}
  2. module Main (main) where
  3. import qualified Editing.EditsPreparation
  4. import qualified Editing.Parse
  5. import qualified Editing.Execute
  6. import qualified Editing.Diff
  7. import qualified Cxx.Show
  8. import qualified Cxx.Parse
  9. import Parsers (eof, parseOrFailE)
  10. import Util (test_cmp, (<<), (.))
  11. import Request (EditableRequest(..), EditableRequestKind(..))
  12. import Prelude hiding ((.))
  13. import Data.SetOps
  14. basic_tests :: IO ()
  15. basic_tests = do
  16. f "" "make foo bar bas" "Unexpected end of command. Expected \"::\" or template-arguments."
  17. f "" "make " "Unexpected end of command. Expected \"declaration\", \"body\", production-name, \"all\", \"any\", \"every\", \"each\", ordinal, or declarator-id."
  18. f "" "make i pointer to" "Unexpected end of command. Expected type description."
  19. s "mutable int i;" "make i const" "const mutable int i;"
  20. s "int i;" "make i a const double" "double const i;"
  21. s "int const i;" "make i a double" "double const i;"
  22. s "void g(int); void f() { bind(&g)(3, 2); }" "make g a function taking two integers" "void g(int, int); void f() { bind(&g)(3, 2); }"
  23. -- "bind(&g)(3, 2);" is determined not to be declaration because it would be a reference initialized with two arguments.
  24. s "int i;" "make i a *&" "int *& i;"
  25. s "int * p = f();" "make p auto" "auto p = f();"
  26. s "inline void f();" "make f noninline" "void f();"
  27. s "int (* const i)(double);" "make i nonconst" "int (* i)(double);"
  28. s "int i;" "make i a pointer&" "int *& i;"
  29. f "int i;" "make j const" "Could not find free declaration of j."
  30. s "void f() { int i; i; i = 0; }" "make i a pointer" "void f() { int * i; i; i = 0; }"
  31. s "struct X { static void f(); }" "append semicolon and make f pure" "struct X { virtual void f()= 0 ; };"
  32. s "struct X { virtual void f() = 0; };" "make f static" "struct X { static void f() ; };"
  33. s "struct X { void f(); };" "make f virtual pure const inline explicit" "struct X { virtual inline explicit void f()const = 0 ; };"
  34. s "struct X { ~X(); };" "make ~ X virtual" "struct X { virtual ~X(); };"
  35. s "struct X { virtual inline explicit void f()const = 0 ; };" "make f impure nonvirtual nonexplicit noninline" "struct X { void f()const ; };"
  36. s "struct X { X(int i); };" "make i a reference to const and make constructor explicit" "struct X { explicit X(const int & i); };"
  37. s "int *p;" "make p a const*volatile" "const int *volatile p;"
  38. s "void N::f() {}" "make N::f inline" "inline void N::f() {}"
  39. s "struct X { void operator++(); };" "make operator++ a const function returning an X&" "struct X { X & operator++()const ; };"
  40. s "int x /*haha*/ ; // ok dan /* mja */" "make x const" "const int x /*haha*/ ; // ok dan /* mja */"
  41. s "T const ( &f() )[3] { T x = {v}; }" "make f inline" "inline T const ( &f() )[3] { T x = {v}; }"
  42. s "int *i; int * & j;" "make i a pointer to a pointer" "int ** i; int * & j;"
  43. s "struct Factorial { static int v = N; };" "make v const" "struct Factorial { const static int v = N; };"
  44. s "{ struct S {}; int (S:: * p) = 0; int (S:: * & r) = p; }" "make p and r const" "{ struct S {}; int (S:: * const p) = 0; int (S:: * const & r) = p; }"
  45. s "int i;" "make i an array" "int i[];"
  46. s "void f() { try { int long i; } catch(int long j) {} }" "make i and j long long" "void f() { try { long long int i; } catch(long long int j) {} }"
  47. s "void f() { try { long long i; } catch(long long j) {} }" "make i and j long" "void f() { try { long i; } catch(long j) {} }"
  48. s "int i;" "make i a const array" "const int i[];"
  49. s "int i;" "make i a const array of pointers" "int *const i[];"
  50. s "int i[];" "make i const" "const int i[];"
  51. s "struct X { ~X(); }" "append ; and make destructor virtual and show" "struct X { virtual ~X(); };"
  52. s "{ try{}catch(const int i){} }" "make i volatile" "{ try{}catch(volatile const int i){} }"
  53. s "void f(int i, double d){}" "make i and d long" "void f(long int i, long double d){}"
  54. s "void f(int i, int j, int k);" "make second parameter-declaration const and erase third parameter-declaration" "void f(int i, const int j);"
  55. s "void f(float, int, char, double);" "make second and third parameter-declaration const" "void f(float, const int, const char, double);"
  56. s "{ if(int i = 3) ; }" "make i const" "{ if(const int i = 3) ; }"
  57. s "int i;" "make i an array of const" "const int i[];"
  58. s "int i;" "make i a static const function" "static int i()const ;"
  59. s "int i;" "make i a pointer to a function" "int (* i)();"
  60. s "int i;" "make i a pointer to a function taking two doubles" "int (* i)(double, double);"
  61. s "int i;" "make i a function returning a const" "const int i();"
  62. s "int i;" "make i a function returning a const pointer and taking a bool" "int *const i(bool);"
  63. s "{ cout << 3, 3.2, 3ul, 3e+2, 0x3, 03, .3, 3., .3e1, 3.E0; int i; }" "make i const" "{ cout << 3, 3.2, 3ul, 3e+2, 0x3, 03, .3, 3., .3e1, 3.E0; const int i; }"
  64. s "void f(int i) { try {} catch(int j) {} }" "make f and i and j const" "void f(const int i) const { try {} catch(const int j) {} }"
  65. f "void f(int i) { try {} catch(int j) {} }" "make j mutable" "Invalid decl-specifier for type-specifier-seq: mutable"
  66. s "struct X { void f(int p); };" "make f static inline and make p a reference to long" "struct X { static inline void f(long int & p); };"
  67. s "struct X { operator ()(); };" "make operator() const" "struct X { operator ()()const ; };" -- Spaces don't matter when matching declarator-ids.
  68. s "<< 3, i; int i = 2;" "make i const" "<< 3, i; const int i = 2;"
  69. putStrLn "All make tests passed."
  70. t "erase all 2 and insert x before second 3 and prepend y" $ Right "y1 3 x3 4 5"
  71. t "erase everything before last 2 and replace everything after 4 with x" $ Right "2 3 4x"
  72. t "insert x after all 2 and append y" $ Right "1 2x 3 2x 3 4 5y"
  73. t "erase first 2 and replace second 2 with x and omit last " $ Right "1 3 x 3 45"
  74. t "erase first and last 2 and all 3 and 4 and everything before first 2 and everything after 4" $ Right " "
  75. t "erase third last space and kill everything after second last " $ Right "1 2 3 23 "
  76. t "insert x after 1 2 and before all 3 and erase 5 and prepend y" $ Right "y1 2x x3 2 x3 4 "
  77. t "erase everything before 4 and everything after 5" $ Right "4 5"
  78. t "insert x before 3 4 and 5" $ Right "1 2 3 2 x3 4 x5"
  79. t "insert x after 1 and all 3 and before 5 and erase 4" $ Right "1x 2 3x 2 3x x5"
  80. t "erase second space before 4" $ Right "1 2 3 23 4 5"
  81. t "erase first 2 3 and 3 2 and 4 5 and last " $ Right "1 3 "
  82. t "move 1 till second 3 to before 5" $ Right "3 4 1 2 3 2 5"
  83. t "move 1 till after second 3 to before 5" $ Right " 4 1 2 3 2 35"
  84. t "swap last 2 3 and last space before 4" $ Right "1 2 3 2 34 5"
  85. t "swap last 2 3 with last space before 4" $ Right "1 2 3 2 34 5"
  86. t "swap 1 and first 3 and second 3 and 5" $ Right "3 2 1 2 5 4 3"
  87. t "replace 2 after second space with x" $ Right "1 2 3 x 3 4 5"
  88. t "move everything till 4 to end and erase 4 " $ Right "51 2 3 2 3 "
  89. t "erase everything" $ Right ""
  90. t "insert x after second space before 4" $ Right "1 2 3 2 x3 4 5"
  91. t "add < and > around second 3" $ Right "1 2 3 2 <3> 4 5"
  92. t "add braces around everything" $ Right "{1 2 3 2 3 4 5}"
  93. t "move everything after second 3 to begin" $ Right " 4 51 2 3 2 3"
  94. t "move second 3 to end and 5 to begin" $ Right "51 2 3 2 4 3"
  95. t "erase first space until second space before 4" $ Right "1 3 4 5"
  96. t "erase spaces" $ return "1232345"
  97. t "erase second last space before 4" $ Right "1 2 3 23 4 5"
  98. t "erase after second 2" $ Right "1 2 3 2"
  99. t "erase after second 2 until before 5" $ Right "1 2 3 25"
  100. t "erase 1 and erase 1" $ Right " 2 3 2 3 4 5"
  101. t "erase before second last space" $ Right " 4 5"
  102. t "move 4 5 to before 1 and erase everything after second 2" $ Right "4 51 2 3 2"
  103. t "erase everything between last and first 2" $ Right "1 22 3 4 5"
  104. t "erase everything between second 2 and begin" $ Right "2 3 4 5"
  105. t "erase all space between second 2 and 4" $ Right "1 2 3 234 5"
  106. t "erase from first 3 until after everything" $ Right "1 2 "
  107. t "erase 2 after and before first 3" $ return "1 3 3 4 5"
  108. t "add + before and after 4" $ return "1 2 3 2 3 +4+ 5"
  109. t "move before second 3 until 4 to begin" $ Right "3 1 2 3 2 4 5"
  110. t "erase everything between begin and end" $ Right ""
  111. t "move everything between first 3 and 4 to begin" $ Right " 2 3 1 2 34 5"
  112. t "erase before second 3 until 4" $ Right "1 2 3 2 4 5"
  113. t "insert x before second 3 and at end" $ Right "1 2 3 2 x3 4 5x"
  114. t "erase until after second 3" $ Right " 4 5"
  115. t "erase from before second 3" $ Right "1 2 3 2 "
  116. t "replace all but first and second last space with x" $ Right "1 2x3x2x3 4x5"
  117. t "change all but first and second last space to x" $ Right "1 2x3x2x3 4x5"
  118. t "erase between second and fourth space and 1" $ Right " 2 3 4 5"
  119. t "erase between the first and third space and prepend x" $ Right "x1 2 3 4 5"
  120. t "add parentheses around every space between first 2 and 4 and around 5 and erase second last 3" $ Right "1 2( )( )2( )3( )4 (5)"
  121. t "move from first 3 until 4 to begin" $ Right "3 2 3 41 2 5"
  122. t "erase everything from before everything until the second 3" $ Right "3 4 5"
  123. t "add parentheses around first 2 and 5" $ Right "1 (2) 3 2 3 4 (5)"
  124. t "erase everything between first space and last space" $ Right "1 5"
  125. t "erase all 3 and all 2 between begin and end" $ Right "1 4 5"
  126. t "erase everything between second and first 2 " $ Right "1 2 2 3 4 5"
  127. t "erase from second 2 till last space" $ Right "1 2 3 5"
  128. t "erase from second 2 until after 3 and add x before 4" $ Right "1 2 3 x4 5"
  129. -- t "erase everything between 1 and the second 2 and everything between 4 and 5" $ Right "12 3 45"
  130. t "erase from before 4 until end" $ Right "1 2 3 2 3 "
  131. t "use 5x and y4" $ Right "1 2 3 2 3 y4 5x"
  132. t "erase everything from after 1 until second last space" $ Right "1 4 5"
  133. t "add parentheses around everything between 1 and second space before 4" $ Right "1( 2 3 2) 3 4 5"
  134. t "add + and - around all 3 and second 2 and prepend x" $ Right "x1 2 +3- +2- +3- 4 5"
  135. t "move 4 till end to front" $ Right "4 51 2 3 2 3 "
  136. t "erase all space after first 2" $ Right "1 232345"
  137. t "add x before first 3 after second 2" $ Right "1 2 3 2 x3 4 5"
  138. t "add x before second space after second 3" $ Right "1 2 3 2 3 4x 5"
  139. t "add x after all space before first 3" $ Right "1 x2 x3 2 3 4 5"
  140. t "erase all space before last 3" $ Right "12323 4 5"
  141. t "erase second 2 till end" $ Right "1 2 3 "
  142. t "append x before 5 and prepend y before all 2 between first 3 and 5" $ Right "1 2 3 y2 3 4 x5"
  143. t "move everything after second 3 to begin" $ Right " 4 51 2 3 2 3"
  144. t "replace first 2 with x and replace all 2 with x" $ Right "1 x 3 x 3 4 5"
  145. t "erase everything until 4 and 5" $ Right "4 "
  146. t "erase 3 2 till 5" $ Right "1 2 5"
  147. t "move second 2 to back and prepend x" $ Right "x1 2 3 3 4 52"
  148. t "cut everything before first 2 and first and second 3 and everything after 4 and prepend x" $ Right "x2 2 4"
  149. t "replace all 2 with 3 and erase all 3 and add x after second 2" $ Right "1 3 3x 4 5"
  150. t "insert spacer before 4 and insert a semicolon after 1 and erase last space" $ Right "1; 2 3 2 3 spacer45"
  151. t "erase first and second last " $ Right "12 3 2 34 5"
  152. t "replace 1 with x and all 2 with y and erase second 3" $ Right "x y 3 y 4 5"
  153. t "move everything after last 3 to front and erase 5" $ Right " 4 1 2 3 2 3"
  154. t "erase spaces around first 2" $ Right "123 2 3 4 5"
  155. t "erase spaces around 3 after second 2" $ Right "1 2 3 234 5"
  156. t "erase 1 and 2 around first space" $ Right " 3 2 3 4 5"
  157. t "erase all but first two spaces" $ Right "1 2 32345"
  158. t "add x after 4 and add y after 4" $ Right "1 2 3 2 3 4yx 5"
  159. t "erase 4 and add y before 4 and add x after 4" $ Right "1 2 3 2 3 yx 5"
  160. t "move 4 to end and insert x before 5" $ Right "1 2 3 2 3 x54"
  161. t "erase 4 and move 5 to begin" $ Right "51 2 3 2 3 "
  162. t "move 3 2 3 to front and insert x before second 2" $ Right "3 x2 31 2 4 5"
  163. t "append float x; int y;" $ Right "1 2 3 2 3 4 5float x; int y;"
  164. t "erase 5 and move everything after last 3 to front" $ Right " 4 1 2 3 2 3"
  165. t "move everything before 4 to end and move first 3 to front" $ Right "34 51 2 2 3 "
  166. t "move 3 4 5 to before 4" $ Left "Move destination lies in source range."
  167. t "move 1 and 4 to after first 3" $ Right " 2 314 2 3 5"
  168. -- Order-sensitive edits:
  169. t "add parentheses around everything and append x" $ Right "(1 2 3 2 3 4 5)x"
  170. t "add parentheses around all 3 and all 2 and erase 4" $ Right "1 (2) (3) (2) (3) 5"
  171. t "append x and add parentheses around everything" $ Right "(1 2 3 2 3 4 5x)"
  172. t "append x after everything before 4 and add y before 4" $ Right "1 2 3 2 3 xy4 5"
  173. t "insert y before 4 and insert z after second 3 " $ Right "1 2 3 2 3 zy4 5"
  174. t "prepend x and move 5 to begin and insert y before 1 and insert z before everything" $ Right "z5xy1 2 3 2 3 4 "
  175. t "add parentheses around everything and prepend x" $ Right "x(1 2 3 2 3 4 5)"
  176. t "prepend x and add parentheses around everything" $ Right "(x1 2 3 2 3 4 5)"
  177. t "prepend x before everything after 4 and add y after 4" $ Right "1 2 3 2 3 4yx 5"
  178. t "add y after 4 and prepend x before everything after 4" $ Right "1 2 3 2 3 4xy 5"
  179. -- Semantic edits:
  180. ct "a x;" "add b after first identifier" $ Right "ab x;"
  181. ct "struct X { operator bool() { return true; } };" "move declaration of operator bool to end" $ Right "struct X { };operator bool() { return true; } "
  182. ct "namespace N { void f(); } class C { void g() {} };" "swap body of N and body of C" $ Right "namespace N { void g() {} } class C { void f(); };"
  183. ct "void f() { int i; } void g() { int j; } void h() {}" "prepend BARK; in f and append BARK; in g and in h" $ Right "void f() { BARK;int i; } void g() { int j; BARK;} void h() {BARK;}"
  184. ct "class C { int f() {} };" "add int x; in C and add return x; in f" $ Right "class C { int f() {return x;} int x;};"
  185. ct "void f() { cout << 3; g(); }" "erase everything from after 3; until after body of f" $ Right "void f() { cout << 3;}"
  186. ct "int main() { cout << 3; }" "move << 3 to front and erase declaration of main" $ Right "<< 3"
  187. ct "{ cout << x; } enum E { x };" "add `cout, y;` in main and add ,y in E" $ Right "{ cout << x; cout, y;} enum E { x ,y};"
  188. ct "namespace N { void f(); void g(); void f(); } void h();" "add int x; after declaration of g in N" $ Right "namespace N { void f(); void g();int x; void f(); } void h();"
  189. ct "struct X { void f(); }; struct Y { void f(); };" "erase declaration of f in Y" $ Right "struct X { void f(); }; struct Y { };"
  190. ct "namespace N { void f(); void g(); void f(); } void h();" "move declaration of h to after declaration of g in N" $ Right "namespace N { void f(); void g(); void h();void f(); } "
  191. ct "void f() {} void g() {} namespace N { void f() {} } void f(int) {}" "add int x; in f in N and in g and append y" $ Right "void f() {} void g() {int x;} namespace N { void f() {int x;} } void f(int) {}y"
  192. ct "void f() { int x; } void g() { int x; } void h() { int x; }" "erase declaration of x in f and h" $ Right "void f() { } void g() { int x; } void h() { }"
  193. ct "namespace N { int x; } int x; void f() { int x; }" "use int y; in N and f" $ Right "namespace N { int y; } int x; void f() { int y; }"
  194. ct "void f() {} void f(int) {} void f(double) {} void f(char) {}" "add int x; in first f and in third and fourth body of f" $ Right "void f() {int x;} void f(int) {} void f(double) {int x;} void f(char) {int x;}"
  195. ct "namespace A { int x; namespace B { int x; namespace C { int x; namespace D { int x; } } } }" "erase declaration of x in D in C in B in A" $ Right "namespace A { int x; namespace B { int x; namespace C { int x; namespace D { } } } }"
  196. ct "struct X { X(int); };" "erase second declaration of X" $ Right "struct X { };"
  197. ct "template <typename> void f(); void f(int);" "erase second declaration of f" $ Right "template <typename> void f(); "
  198. ct "struct X { template <typename U> X(U); };" "erase second declaration of X" $ Right "struct X { };"
  199. ct "struct X { int x; X(); void f(); ~X(); struct Y {}; operator int(); X(int); };" "erase constructors and replace destructor with int y;" $ Right "struct X { int x; void f(); int y; struct Y {}; operator int(); };"
  200. ct "template <typename T> struct X { template <typename U> inline X(T, U); ~X(); }; template <typename T> template <typename U> X<T>::X(T, U) {} template<typename T> X<T>::~X() {}" "erase second constructor and second destructor" $ Right "template <typename T> struct X { template <typename U> inline X(T, U); ~X(); }; "
  201. ct "void f(int i);" "erase declaration of i" $ Right "void f();"
  202. ct "struct X { int i; };" "erase declaration of i" $ Right "struct X { };"
  203. ct "{ 3; 4; 5; }" "swap first and last statement" $ Right "{ 5; 4; 3; }"
  204. ct "{ 3; 4; 5; }" "swap statements around 4;" $ Right "{ 5; 4; 3; }"
  205. ct "{ 3; 4; 5; 6; }" "swap statements before 5 with last statement" $ Right "{ 6; 5; 3; 4; }"
  206. ct "void f(int,double,char);" "swap first two parameter-declarations" $ return "void f(double,int,char);"
  207. --todo: ct "{ if(b) 3; 4; 5; }" "add curlies around first two statements after if" $ Right "{ if(b) {3; 4;} 5; }"
  208. --todo: ct "{ 3; 4; 5; }" "add curlies around first and second statement" $ Right "{ {3; 4;} 5; }"
  209. ct "{ 3; 4; 5; }" "add curlies around first statement and around second statement" $ Right "{ {3;} {4;} 5; }"
  210. ct "<< max(3, 2, 1)" "add curlies around code between parens" $ return "<< max({3, 2, 1})"
  211. ct "{ 1;2;3;4;5; }" "swap first two statements with last two statements" $ Right "{ 4;5; 3;1;2;}"
  212. ct "{ 1;2;3; }" "swap first two statements" $ Right "{ 2;1;3; }"
  213. --ct "void f() { 1; } void g() { 1; 2; 3; 4; }" "replace first two and last statement in g with 0;" $ Right "void f() { 1; } void g() { 0;3; 0;}"
  214. ct "void f() { int x = 3; cout << x; } int i;" "replace everything after first statement in f with BARK;" $ Right "void f() { int x = 3; BARK;} int i;"
  215. ct "template <typename T, int i> struct S;" "erase second template-parameter" $ return "template <typename T> struct S;"
  216. ct "void g(string s); void f(int i, double d, char c, float, bool b);" "erase first and last two parameter-declarations in declaration of f and replace third parameter-declaration in declaration of f with wchar_t c" $ return "void g(string s); void f(double d, wchar_t c);"
  217. ct "int f();" "replace type-specifier with void" $ Right "void f();"
  218. ct "void g() { 0; struct X { void f() { 1;2;3;4; } }; 1; }" "erase statements around 2 in f" $ Right "void g() { 0; struct X { void f() { 2;} }; 1; }"
  219. ct "int a;in@@@t x;int y;int z;" "erase @@@ and erase int a; and erase second declaration" $ Right "int y;int z;"
  220. ct "@ int x;" "erase @ and replace declaration of x by bla" $ return " bla"
  221. ct "@@@@@ void f(){} int x;" "erase @@@@@ and erase first x after function-definition" $ Right " void f(){} int ;"
  222. ct "@@@@int x; int y; int z;" "erase @@@@ and erase from start until second declaration" $ Right "int z;"
  223. ct "@@@@int x; int y; int z;" "erase @@@@ and erase from second declaration until last space" $ Right "int x; z;"
  224. ct "class X extends Y { int i:2; };" "replace extends with : and replace literal after : with 3" $ Right "class X : Y { int i:3; };"
  225. ct "T f() { 0;x; } U y;" "erase everything after 0 in f" $ Right "T f() { 0} U y;"
  226. ct "T f() { 0;x; } U y;" "erase everything before x in f" $ Right "T f() { x; } U y;"
  227. ct "T f() { 0;1;2;3;4; } U y;" "erase everything between second and fourth statement in f" $ Right "T f() { 0;1;3;4; } U y;"
  228. ct "; void g() {} void f() { {1;} }" "erase first semicolon and erase curlies around 1;" $ return " void g() {} void f() { 1; }"
  229. -- Edit errors:
  230. ct "struct X { void f() { cout << 3; int x; cout << 3; } };" "erase second 3 after declaration of x in f in X" $ Left "String `3` does not occur twice after free declaration of x in f in X."
  231. t "erase second 4 after 1" $ Left "String `4` does not occur twice after 1."
  232. t "move second 2 to x" $ Left "Unexpected `x` after `second 2 to `. Expected \"beginning\", \"begin\", \"front\", \"start\", \"end\", \"back\", \"before\", or \"after\"."
  233. t "replace alligators with chickens" $ Left "String `alligators` does not occur."
  234. t "use banana" $ Left "No non-exact match for banana."
  235. t "use 5426" $ Left "No non-exact match for 5426."
  236. t "erase 2" $ Left "String `2` occurs multiple times."
  237. t "replace 1 and erase with 4" $ Left "String `erase` does not occur."
  238. t "replace tenth last 2 by x" $ Left "String `2` does not occur 10 times."
  239. t "erase second 9" $ Left "String `9` does not occur."
  240. t "replace all 2 with 3 and replace second 2 with x" $ Left "Overlapping edits: replace 2 with 3 and replace 2 with x."
  241. t "erase everything before first 3 and replace first 2 with x" $ Left "Overlapping edits: erase `1 2 ` and replace 2 with x."
  242. t "erase 5 between 1 and 4" $ Left "String `5` does not occur between 1 and 4."
  243. t "prepend x and replace 4 with a and replace 4 with b" $ Left "Overlapping edits: replace 4 with a and replace 4 with b."
  244. -- Syntax errors:
  245. t "isnert 3 before 4" $ Left "Unexpected `isnert` at start. Expected edit command."
  246. t "insert " $ Left "Unexpected end of command. Expected option, wrapping description, or verbatim string."
  247. t "insert kung fu" $ Left "Unexpected end of command. Expected \" and\", \" in\", \" at\", \" around\", \" before\", or \" after\"."
  248. t "move " $ Left "Unexpected end of command. Expected \"till\", \"until\", \"from\", \"everything\", \"code\", \"before\", \"between\", \"after\", \"declaration\", \"body\", production-name, verbatim string, \"all\", \"any\", \"every\", \"each\", or ordinal."
  249. t "move x " $ Left "Unexpected end of command. Expected \" till\", \" until\", \" around\", \" before\", \" after\", \" between\", \" in\", \" and\", or \" to\"."
  250. t "move x to "$ Left "Unexpected end of command. Expected \"beginning\", \"begin\", \"front\", \"start\", \"end\", \"back\", \"before\", or \"after\"."
  251. t "erase all 2 and " $ Left "Unexpected end of command. Expected verbatim string, \"till\", \"until\", \"from\", \"everything\", \"code\", \"before\", \"between\", \"after\", \"declaration\", \"body\", production-name, \"all\", \"any\", \"every\", \"each\", ordinal, wrapping description, option, or edit command."
  252. putStrLn "All basics tests passed."
  253. where
  254. ct :: String String Either String String IO ()
  255. ct x c o = test_cmp c o $ case parseOrFailE (Editing.Parse.commandsP << eof) c "command" of
  256. Left e Left e
  257. Right (cmds, _) editable_body . Editing.Execute.execute Nothing cmds (EditableRequest (Evaluate ()) x)
  258. s, f :: String String String IO ()
  259. s code cmdstring expectation = ct code cmdstring (Right expectation) -- test for success
  260. f code cmdstring expectation = ct code cmdstring (Left expectation) -- test for failure
  261. t = ct "1 2 3 2 3 4 5"
  262. diff_tests :: IO ()
  263. diff_tests = do
  264. dt' "foo; bar; monkey; chicken; bas;" "bar; monkey; chicken;" "Erased `foo;` and `bas;`." "Prepended `foo;` and appended `bas;`."
  265. dt' "{ fstream f(\"t.cpp\"); string s(istreambuf_iterator<char>(f), istreambuf_iterator<char>()); }"
  266. "{ fstream f(\"t.cpp\"); string s((istreambuf_iterator<char>(f)), istreambuf_iterator<char>()); }"
  267. "Inserted ( before `istreambuf_iterator<char>`, and inserted ) after `istreambuf_iterator<char>(f)`."
  268. "Erased ( before `istreambuf_iterator<char>` and ) after `istreambuf_iterator<char>(f)`."
  269. -- Todo: One day, the former should say "wrapped ...".
  270. dt' "int f(int & i) { i = 4; return i;} int g(int && i){return f(i);} int main() { cout << g(2); }"
  271. "int & f(int & i) { i = 4; return i;} int & g(int && i){return f(i);} int & g(int & i){return f(i);} int main() { cout << g(2); }"
  272. "Replaced `int f` with `int & f`, replaced `int g` with `int & g`, and inserted `int & g(int & i){return f(i);}` before `int main`."
  273. "Replaced `int & f` with `int f`, replaced `int & g` with `int g`, and erased `int & g(int & i){return f(i);}`."
  274. dt' "{string foo = \"kangaroo\"; auto m = foo.find_first_of('m'); cout << *m;}"
  275. "{string foo = \"kangaroo\"; size_t m = foo.find_first_of('m'); cout << foo[m];}"
  276. "Replaced `auto m` with `size_t m`, and replaced `<< *m` with `<< foo[m]`."
  277. "Replaced `size_t m` with `auto m`, and replaced `<< foo[m]` with `<< *m`."
  278. -- Todo: Group.
  279. dt "{int i=0,t=time(0);for(;i<5000000;i++)asm(\".org 0xffff\");cout << time(0)-t; }"
  280. "{int i=0,t=time(0);for(;i<5000;i++)int tmp=1*88+71/4000^66;cout << time(8)-t; }"
  281. "Replaced i<5000000 with i<5000, replaced `asm(\".org 0xffff\")` with `int tmp=1*88+71/4000^66`, and replaced 0 with 8."
  282. dt' "struct curr_func { string name; cf(string n):name(n){} }; \\ #define DEFUN(name) name try { throw curr_func(#name); } catch(curr_func& cfun) \\ DEFUN(void haha(int a)) { cout << cfun.name; } int main() { cout << haha; }"
  283. "struct curr_func { string name; curr_func(string n):name(n){} }; \\ #define DEFUN(name) name try { throw curr_func(#name); } catch(curr_func& cfun) \\ DEFUN(void haha(int a)) { cout << cfun.name << \": \" << a; } int main() { haha(42); }"
  284. "Replaced cf with curr_func, inserted `<< \": \" << a` after `<< cfun.name`, and replaced `cout << haha` with haha(42)."
  285. "Replaced curr_func with cf, erased `<< \": \" << a`, and replaced haha(42) with `cout << haha`."
  286. dt "{float i=0,t=time(0);for(;i<5000000;i++) { if(x == 3) f(reinterpret_cast<long>(x)); } }"
  287. "{int i=0,t=time(null);for(;i<5000000;++i) { if(x != 3) f(static_cast<long>(x)); } }"
  288. "Replaced `float i` with `int i`, replaced 0 with null, replaced i++ with ++i, replaced `x == 3` with `x != 3`, and replaced `reinterpret_cast<long>` with `static_cast<long>`."
  289. {-
  290. dt' "struct a { int b; a():b([]{ return 1 + 2 + 3; }){}}a_; int main() { cout << a_.b }"
  291. "struct a { int b; a({}):b([]{ return 1 + 2 + 3; }()){}}a_; int main() { cout << a_.b; }"
  292. "Replaced \"a():b([]{\" with \"a({}):b([]{\", replaced \")\" after \"return 1 + 2 + 3; }\" with \"())\", and inserted \";\" after \"cout << a_.b\"."
  293. "Replaced \"a({}):b([]{\" with \"a():b([]{\", replaced \"}()){}}a_\" with \"}){}}a_\", and erased \";\" after \"cout << a_.b\"."
  294. -}
  295. dt "struct curr_func { string name; cf(string n):name(n){} }; \\ #define DEFUN(name) name try { throw curr_func(#name); } catch(curr_func& cfun) \\ DEFUN(void haha(int a)) { cout << cfun.name; } int main() { cout << haha; }"
  296. "struct { string name; cf(string n){} }; \\ #define DEFUN(name) name try { } catch(curr_func& cfun) \\ DEFUN(void haha(int a) { cout << \"tortoise\"; } ) { cout << ETYPE(cfun.name); } int main() { do_something(complicated); cout << haha; }"
  297. "Replaced `struct curr_func` with struct, erased :name(n) and `throw curr_func(#name);`, inserted `{ cout << \"tortoise\"; }` before `) { cout`, replaced `<< cfun.name` with `<< ETYPE(cfun.name)`, and inserted `do_something(complicated);` before `cout << haha`."
  298. {-
  299. dt "{ char str[] = \"giraffe\"; char * pch; pch=(char*) memchr(str, 'y', (int)strlen(str)); if (pch!=NULL) { printf(\"'y' was found at position #%d\", pch-str+1); } }"
  300. "{ char * str = \"giraffe\"; char * pch; pch=(char*) memchr(str, 'v', (size_t)strlen(str)); if (pch!=NULL) { printf(\"'v' was found at position #%d\", pch-str-1); memset(str, '*', 6); puts(str); printf(\"%s\", str); } }"
  301. "Replaced `char str[]` with `char * str`, replaced 'y' with 'v', replaced int with size_t, replaced `\"'y' was` with `\"'v' was`, and replaced pch-str+1 with `pch-str-1); memset(str, '*', 6); puts(str); printf(\"%s\", str`."
  302. -}
  303. dt "geordi: { char y(34); stringstream i(\"geordi: { char y(34); stringstream i(!); string t; getline(i, t, '!'); cout << t << y << i.str() << y << i.rdbuf(); }\"); string t; getline(i, t, '!'); cout<< t << y << i.str() << y << i.rdbuf(); }"
  304. "geordi: { stringstream i(\"geordi: { stringstream i(!); string t; getline(i, t, '!'); cout << t << i.str() << i.rdbuf(); }\"); string t; getline(i, t, '!'); cout << t << i.str() << i.rdbuf(); }"
  305. "Erased `char y(34);` and `char y(34);` and `<< y` and `<< y` and `<< y` and `<< y`." -- Todo: "Erased all \"char y(34);\" and all \"<< y\"."
  306. dt "char *& f() { static char *p; cout << &p << endl; return p; } int main() { char *p = f(); cout << &p << endl; }"
  307. "char *& f() { static char *p; cout << &p << ' '; return p; } int main() { char *p = f(); cout << &p; }"
  308. "Replaced `<< endl` with `<< ' '`, and erased `<< endl`." -- Todo: say "first" and "last".
  309. putStrLn "All diff tests passed."
  310. where
  311. dt :: String String String IO ()
  312. dt x y r = test_cmp x r $ show $ Editing.Diff.diff x y
  313. dt' :: String → String → String → String → IO ()
  314. dt' x y xy yx = do
  315. test_cmp x xy $ show $ Editing.Diff.diff x y
  316. test_cmp y yx $ show $ Editing.Diff.diff y x
  317. dts :: String [(String, String)] IO ()
  318. dts _ [] = return ()
  319. dts s ((s', d) : r) = dt s s' d >> dts s' r
  320. make_type_tests :: IO ()
  321. make_type_tests = do
  322. t "void(pointer)" $ Right "void(T *)"
  323. t "pointer to const pointer to long double" $ Right "long double*const *"
  324. t "function taking an int and returning nothing" $ Right "void(int )"
  325. let q = "void(int (* const (** (* const volatile (X::* volatile* (* )(int) )(char*)) [2])(long) ) [3])" in t q $ Right q
  326. t "function returning nothing and taking a pointer to a function returning a bool and taking an int" $ Right "void (bool (*)(int))"
  327. t "function taking a pointer to a (function returning a bool and taking an int), returning nothing" $ Right "void(bool (*)(int))"
  328. t "reference to a pointer to a function returning nothing, and taking an int" $ Right "void(*&)(int)"
  329. t "function taking an int, a char, a double, and returning nothing" $ Right "void(int, char, double)"
  330. t "function returning nothing and taking an int, a char, and a double" $ Right "void (int, char, double)"
  331. t "function returning a B<C<T>>" $ Right "B<C<T>>()"
  332. t "vector<T*>" $ Right "vector<T*>"
  333. t "function returning a ::B<T, (3>>2)>::value_type and taking a vector<vector<int>>" $ Right "::B<T, (3>>2)>::value_type (vector<vector<int>>)"
  334. t "function taking no arguments, returning a reference to an array of three pointers to functions taking integers and returning nothing" $ Right "void(*(&())[3])(int )"
  335. t "pointer to a constant volatile pointer to an array of 3 ints" $ Right "int(*volatile const *)[3]"
  336. t "function returning nothing and taking a reference to an array of three pointers to void" $ Right "void (void*(&)[3])"
  337. t "pointer to void(void)" $ Right "void(*)(void)"
  338. t "reference to pointer to const array" $ Right "T const (*&)[]"
  339. t "function taking a const (pointer to int) and a volatile function" $ Right "T (int*const , T ()volatile )"
  340. t "function taking two integers, three doubles, and returning a boolean" $ Right "bool(int, int, double, double, double)"
  341. t "function taking two pointers to integers" $ Right "T (int*, int*)"
  342. t "rvalue reference to function" $ Right "T (&&)()"
  343. t "constant constant pointer to volatile volatile int" $ Right "volatile volatile int*const "
  344. --t "pointer to a function from string_bla to int" $ Right "int(*)(string_bla )"
  345. t "pointer to " $ Left "Unexpected end of type description. Expected type description."
  346. t "pointer to function taking pointer to function" $ Right "T (*)(T (*)())"
  347. --t "pointer to int and double" $ Left "Unexpected \"a\" after \"to int \". Expected type-specifier, abstract-declarator, or end of type description."
  348. t "function returning " $ Left "Unexpected end of type description. Expected type description."
  349. t "function taking a pointer and a reference and returning a reference to a constant array" $ Right "T const (&(T *, T &))[]"
  350. t "array of " $ Left "Unexpected end of type description. Expected type description or integer-literal."
  351. t "foo bar bas" $ Left "Unexpected `bas` after `foo bar `. Expected \"::\" or template-arguments."
  352. t "array of seven characters" $ Right "char[7]"
  353. t "pointer to (function taking constant integer)*" $ Right "T (**)(const int)"
  354. t "pointer to void()" $ Right "void(*)()"
  355. t "function taking a pointer to void() returning a reference to an int[3]" $ Right "int(&(void(*)() ))[3]"
  356. t "void(pointer to function)" $ Right "void(T (*)())"
  357. t "function*(const int)" $ Right "T (*(const int))()"
  358. t "constant pointer to a function" $ Right "T (*const )()"
  359. t "(function taking an int[3] )*" $ Right "T (*)(int[3] )"
  360. t "(function*[3])&()" $ Right "T (*(&())[3])()"
  361. t "int(::T::U::V::**)" $ Right "int(::T::U::V::**)"
  362. t "int(X::*)()const volatile" $ Right "int(X::*)()const volatile"
  363. t "int volatile X::* Y::* const Z::*" $ Right "int volatile X::* Y::* const Z::*"
  364. {-
  365. t "pointer to a member function" $ Right "void(T::*)()"
  366. t "pointer to member integer" $ Right "int T::*"
  367. t "pointer to member" $ Right "T T::*"
  368. t "pointer to member pointer to member pointer to member array" $ Right "T(T::* T::* T::*)[]"
  369. -}
  370. t "array*const" $ Right "T (*const)[]"
  371. t "function taking (pointer to function returning int taking int) returning int" $ Right "int(int (*)(int))"
  372. --t "function+" $ Left "Unexpected \"+\" after \"function\". Expected \"taking\", \"returning\", \"from\", abstract-declarator, or end of type description."
  373. t "void(register pointer to string)" $ Right "void(register string*)"
  374. t "array of three arrays of 2 arrays of 1 integer" $ Right "int[3][2][1]"
  375. putStrLn "All make-type tests passed."
  376. where
  377. t :: String Either String String IO ()
  378. t i o = test_cmp i o (either (Left . id) (Right . Cxx.Show.show_simple) $ Cxx.Parse.makeType i)
  379. precedence_tests :: IO ()
  380. precedence_tests = do
  381. s "x::y" "x::y"
  382. s "if (b) int *ptr = new int(3), a(2);" "if (b) {int *ptr = (new int(3));int a(2);}"
  383. s "if(b) if(c) foo; else bar;" "if(b) { if(c) { foo; } else { bar; } }"
  384. s "a=b<c?d=e:f=g" "a=((b<c)?(d=e):(f=g))" -- Example from TC++PL, section 6.2.
  385. s "x?y?z?a:b:c:d" "x?(y?(z?a:b):c):d"
  386. s "*i-40?(*i-x?S(1,*i):a)+r(i+1,e,x,a):'('+(i[1]-46?r(i+1,o-1,x,a):'.'+r(i+2,o-1,x+1,a))+')'+r(o,e,x,a)" "((*i)-40)?((((*i)-x)?(S(1,(*i))):a)+(r((i+1),e,x,a))):((('('+(((i[1])-46)?(r((i+1),(o-1),x,a)):('.'+(r((i+2),(o-1),(x+1),a)))))+')')+(r(o,e,x,a)))" -- Taken from the lambda calculus snippet.
  387. s "x->x->*x.x.*x" "((x->x)->*(x.x)).*x"
  388. s "x || x && x | x ^ x bitand x == x < x << x" "x || (x && (x | (x ^ (x bitand (x == (x < (x << x)))))))"
  389. s "*++vector<int>{2,5,4}.rbegin()" "*(++(((vector<int>{2,5,4}).rbegin)()))"
  390. s "x---------x" "((((x--)--)--)--)-x"
  391. s "z+operator+(x,y)" "z+(operator+(x,y))"
  392. s "x.operator()() * operator new[ ]()" "((x.operator())()) * (operator new[ ]())"
  393. s "throw 2 + 1, throw, 9" "((throw (2 + 1)), throw), 9"
  394. s "x + x *= x + x /= x + x" "(x + x) *= ((x + x) /= (x + x))"
  395. s "(x)y + x(y)" "((x)y) + (x(y))"
  396. f "(x+y)z" "Unexpected `z` after (x+y). Expected postfix operator, binary operator, ternary operator, or end of code."
  397. s "a+++a, b++ +b, c+ ++c, d+++ +d, e+ +++e" "(((((a++)+a), ((b++) +b)), (c+ (++c))), ((d++)+ (+d))), (e+ (++(+e)))"
  398. s "x += operatornew, b(), !c" "((x += operatornew), (b())), (!c)"
  399. s "sizeof u + sizeof(x) + sizeof(y*z)" "((sizeof u) + sizeof(x)) + (sizeof(y*z))"
  400. s "x.template a<int>()" "(x.template a<int>)()"
  401. s "const_cast<vector<vector<int>>>(x)" "const_cast<vector<vector<int>>>(x)" -- Tricky closing angle brackets.
  402. s "x.~y" "x.~y"
  403. s "f (x+3,y)-g(x+3)" "(f ((x+3),y))-(g(x+3))"
  404. s "::x + y::z + a::b::c::d::e" "(::x + y::z) + a::b::c::d::e"
  405. s "x[y + 'z']" "x[y + 'z']" -- No parens around x + z or around 'z'.
  406. f "x*" "Unexpected end of code. Expected pm-expression."
  407. f "x && throw 3" "Unexpected `throw` after `x && `. Expected inclusive-or-expression."
  408. f "&operator" "Unexpected end of code. Expected overloadable operator or conversion-type-id."
  409. f "x.*" "Unexpected end of code. Expected cast-expression."
  410. f "x--x" "Unexpected `x` after x--. Expected postfix operator, binary operator, ternary operator, or end of code."
  411. f "x." "Unexpected end of code. Expected id-expression, \"template\", or pseudo-destructor-name."
  412. f "x-" "Unexpected end of code. Expected multiplicative-expression."
  413. f "x( " "Unexpected end of code. Expected \")\" or expression-list."
  414. f "x(y" "Unexpected end of code. Expected \")\", \"(\", braced-init-list, \"::\", template-arguments, postfix operator, binary operator, ternary operator, or comma."
  415. f "x?y" "Unexpected end of code. Expected colon, \"(\", braced-init-list, \"::\", template-arguments, postfix operator, binary operator, or ternary operator."
  416. f "x[" "Unexpected end of code. Expected expression or braced-init-list."
  417. f "x.operator foo bar()" "Unexpected `(` after `foo bar`. Expected \"::\" or template-arguments."
  418. putStrLn "All precedence tests passed."
  419. where
  420. s :: String String IO () -- Test for success.
  421. s i o = test_cmp i (Right o) (Cxx.Parse.precedence i)
  422. f :: String String IO () -- Test for failure.
  423. f i o = test_cmp i (Left o) (Cxx.Parse.precedence i)
  424. parse_tests :: IO ()
  425. parse_tests = do
  426. t "struct A<int>;"
  427. t "void f(int, ...);"
  428. t "{ if(int i = 3); }"
  429. t "int (::x::y);"
  430. putStrLn "All parse tests passed."
  431. where
  432. t :: String IO ()
  433. t s = test_cmp s (Right s) $ fmap Cxx.Show.show_simple $ Cxx.Parse.parseRequest s
  434. main :: IO ()
  435. main = do
  436. basic_tests
  437. Editing.EditsPreparation.use_tests
  438. diff_tests
  439. make_type_tests
  440. precedence_tests
  441. parse_tests