haskell-tools-builtin-refactorings (empty) → 1.0.0.0
raw patch · 575 files changed
+9957/−0 lines, 575 filesdep +Cabaldep +basedep +containerssetup-changed
Dependencies added: Cabal, base, containers, directory, either, filepath, ghc, ghc-paths, haskell-tools-ast, haskell-tools-backend-ghc, haskell-tools-builtin-refactorings, haskell-tools-prettyprint, haskell-tools-refactor, haskell-tools-rewrite, mtl, old-time, polyparse, references, split, tasty, tasty-hunit, template-haskell, time, transformers, uniplate
This diff is very large; some files are shown as “too large to diff”. Download the raw patch for the complete diff.
Files
- LICENSE +29/−0
- Language/Haskell/Tools/Refactor/Builtin.hs +29/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers.hs +25/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/BangPatternsChecker.hs +28/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/DerivingsChecker.hs +275/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/FlexibleInstancesChecker.hs +182/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/LambdaCaseChecker.hs +34/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/MagicHashChecker.hs +81/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/PatternSynonymsChecker.hs +18/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/RecordWildCardsChecker.hs +17/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/TemplateHaskellChecker.hs +31/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/TupleSectionsChecker.hs +15/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/UnboxedTuplesChecker.hs +29/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/ViewPatternsChecker.hs +13/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/ExtMap.hs +20/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/ExtMonad.hs +92/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/TraverseAST.hs +592/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Utils/SupportedExtensions.hs +28/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Utils/TypeLookup.hs +82/−0
- Language/Haskell/Tools/Refactor/Builtin/ExtractBinding.hs +228/−0
- Language/Haskell/Tools/Refactor/Builtin/FloatOut.hs +73/−0
- Language/Haskell/Tools/Refactor/Builtin/GenerateExports.hs +40/−0
- Language/Haskell/Tools/Refactor/Builtin/GenerateTypeSignature.hs +176/−0
- Language/Haskell/Tools/Refactor/Builtin/InlineBinding.hs +243/−0
- Language/Haskell/Tools/Refactor/Builtin/OrganizeExtensions.hs +104/−0
- Language/Haskell/Tools/Refactor/Builtin/OrganizeImports.hs +229/−0
- Language/Haskell/Tools/Refactor/Builtin/RenameDefinition.hs +134/−0
- Setup.hs +2/−0
- examples/CPP/BetweenImports.hs +10/−0
- examples/CPP/BetweenImports_res.hs +10/−0
- examples/CPP/ConditionalCode.hs +8/−0
- examples/CPP/ConditionalImport.hs +10/−0
- examples/CPP/ConditionalImportBegin.hs +10/−0
- examples/CPP/ConditionalImportBegin_res.hs +9/−0
- examples/CPP/ConditionalImportEnd.hs +10/−0
- examples/CPP/ConditionalImportEnd_res.hs +9/−0
- examples/CPP/ConditionalImportHalfRemoved.hs +10/−0
- examples/CPP/ConditionalImportHalfRemoved_res.hs +10/−0
- examples/CPP/ConditionalImportMulti.hs +11/−0
- examples/CPP/ConditionalImportMulti_res.hs +11/−0
- examples/CPP/ConditionalImportOrder.hs +13/−0
- examples/CPP/ConditionalImportOrder_res.hs +13/−0
- examples/CPP/ConditionalImport_res.hs +10/−0
- examples/CPP/ConditionalSubImport.hs +10/−0
- examples/CPP/ConditionalSubImport_res.hs +11/−0
- examples/CPP/JustEnabled.hs +2/−0
- examples/CppHs/Language/Preprocessor/Cpphs.hs +34/−0
- examples/CppHs/Language/Preprocessor/Cpphs/CppIfdef.hs +416/−0
- examples/CppHs/Language/Preprocessor/Cpphs/HashDefine.hs +129/−0
- examples/CppHs/Language/Preprocessor/Cpphs/MacroPass.hs +184/−0
- examples/CppHs/Language/Preprocessor/Cpphs/Options.hs +156/−0
- examples/CppHs/Language/Preprocessor/Cpphs/Position.hs +106/−0
- examples/CppHs/Language/Preprocessor/Cpphs/ReadFirst.hs +55/−0
- examples/CppHs/Language/Preprocessor/Cpphs/RunCpphs.hs +82/−0
- examples/CppHs/Language/Preprocessor/Cpphs/SymTab.hs +92/−0
- examples/CppHs/Language/Preprocessor/Cpphs/Tokenise.hs +281/−0
- examples/CppHs/Language/Preprocessor/Unlit.hs +72/−0
- examples/Decl/AmbiguousFields.hs +9/−0
- examples/Decl/AnnPragma.hs +8/−0
- examples/Decl/ClassInfix.hs +10/−0
- examples/Decl/ClosedTypeFamily.hs +9/−0
- examples/Decl/CompletePragma.hs +16/−0
- examples/Decl/CtorOp.hs +10/−0
- examples/Decl/DataFamily.hs +6/−0
- examples/Decl/DataInstanceGADT.hs +6/−0
- examples/Decl/DataType.hs +5/−0
- examples/Decl/DataTypeDerivings.hs +5/−0
- examples/Decl/DefaultDecl.hs +3/−0
- examples/Decl/FunBind.hs +4/−0
- examples/Decl/FunFixity.hs +5/−0
- examples/Decl/FunGuards.hs +5/−0
- examples/Decl/FunctionalDeps.hs +6/−0
- examples/Decl/GADT.hs +9/−0
- examples/Decl/GadtConWithCtx.hs +5/−0
- examples/Decl/InfixAssertion.hs +9/−0
- examples/Decl/InfixInstances.hs +8/−0
- examples/Decl/InfixPatSyn.hs +10/−0
- examples/Decl/InjectiveTypeFamily.hs +6/−0
- examples/Decl/InlinePragma.hs +5/−0
- examples/Decl/InstanceFamily.hs +10/−0
- examples/Decl/InstanceOverlaps.hs +11/−0
- examples/Decl/InstanceSpec.hs +7/−0
- examples/Decl/LocalBindingInDo.hs +7/−0
- examples/Decl/LocalBindings.hs +9/−0
- examples/Decl/LocalFixity.hs +6/−0
- examples/Decl/MinimalPragma.hs +23/−0
- examples/Decl/MixedInstance.hs +11/−0
- examples/Decl/MultipleFixity.hs +12/−0
- examples/Decl/MultipleSigs.hs +6/−0
- examples/Decl/OperatorBind.hs +6/−0
- examples/Decl/OperatorDecl.hs +6/−0
- examples/Decl/ParamDataType.hs +5/−0
- examples/Decl/PatternBind.hs +3/−0
- examples/Decl/PatternSynonym.hs +28/−0
- examples/Decl/RecordPatternSynonyms.hs +8/−0
- examples/Decl/RecordType.hs +3/−0
- examples/Decl/RewriteRule.hs +3/−0
- examples/Decl/SpecializePragma.hs +5/−0
- examples/Decl/StandaloneDeriving.hs +6/−0
- examples/Decl/TypeClass.hs +13/−0
- examples/Decl/TypeClassMinimal.hs +8/−0
- examples/Decl/TypeFamily.hs +6/−0
- examples/Decl/TypeFamilyKindSig.hs +6/−0
- examples/Decl/TypeInstance.hs +14/−0
- examples/Decl/TypeRole.hs +5/−0
- examples/Decl/TypeSynonym.hs +3/−0
- examples/Decl/ValBind.hs +3/−0
- examples/Decl/ViewPatternSynonym.hs +8/−0
- examples/Expr/ArrowNotation.hs +10/−0
- examples/Expr/Case.hs +8/−0
- examples/Expr/DoNotation.hs +15/−0
- examples/Expr/EmptyCase.hs +8/−0
- examples/Expr/EmptyLet.hs +6/−0
- examples/Expr/FunSection.hs +6/−0
- examples/Expr/GeneralizedListComp.hs +31/−0
- examples/Expr/If.hs +4/−0
- examples/Expr/LambdaCase.hs +11/−0
- examples/Expr/ListComp.hs +3/−0
- examples/Expr/MultiwayIf.hs +7/−0
- examples/Expr/Negate.hs +4/−0
- examples/Expr/Operator.hs +5/−0
- examples/Expr/ParListComp.hs +4/−0
- examples/Expr/ParenName.hs +3/−0
- examples/Expr/PatternAndDo.hs +10/−0
- examples/Expr/RecordPuns.hs +6/−0
- examples/Expr/RecordWildcards.hs +6/−0
- examples/Expr/RecursiveDo.hs +9/−0
- examples/Expr/SccPragma.hs +4/−0
- examples/Expr/Sections.hs +4/−0
- examples/Expr/SemicolonDo.hs +7/−0
- examples/Expr/StaticPtr.hs +16/−0
- examples/Expr/TupleSections.hs +7/−0
- examples/Expr/UnboxedSum.hs +13/−0
- examples/Expr/UnicodeSyntax.hs +7/−0
- examples/InstanceControl/Control/Instances/Morph.hs +149/−0
- examples/InstanceControl/Control/Instances/ShortestPath.hs +69/−0
- examples/InstanceControl/Control/Instances/Test.hs +23/−0
- examples/InstanceControl/Control/Instances/TypeLevelPrelude.hs +88/−0
- examples/Module/DeprecatedPragma.hs +1/−0
- examples/Module/Export.hs +2/−0
- examples/Module/ExportModifiers.hs +4/−0
- examples/Module/ExportSubs.hs +3/−0
- examples/Module/GhcOptionsPragma.hs +2/−0
- examples/Module/Import.hs +11/−0
- examples/Module/ImportOp.hs +3/−0
- examples/Module/Imported.hs +6/−0
- examples/Module/LangPragmas.hs +4/−0
- examples/Module/NamespaceExport.hs +4/−0
- examples/Module/PatternImport.hs +4/−0
- examples/Module/Simple.hs +1/−0
- examples/Module/WarningPragma.hs +1/−0
- examples/Pattern/Backtick.hs +5/−0
- examples/Pattern/Constructor.hs +3/−0
- examples/Pattern/ImplicitParams.hs +9/−0
- examples/Pattern/Infix.hs +5/−0
- examples/Pattern/NPlusK.hs +6/−0
- examples/Pattern/NestedWildcard.hs +7/−0
- examples/Pattern/OperatorPattern.hs +3/−0
- examples/Pattern/Record.hs +11/−0
- examples/Pattern/UnboxedSum.hs +6/−0
- examples/Refactor/CommentHandling/BlockComments.hs +10/−0
- examples/Refactor/CommentHandling/CommentTypes.hs +10/−0
- examples/Refactor/CommentHandling/Crosslinking.hs +6/−0
- examples/Refactor/CommentHandling/FunctionArgs.hs +6/−0
- examples/Refactor/ExtractBinding/AddToExisting.hs +4/−0
- examples/Refactor/ExtractBinding/AddToExisting_res.hs +5/−0
- examples/Refactor/ExtractBinding/AssocOp.hs +3/−0
- examples/Refactor/ExtractBinding/AssocOpMiddle.hs +3/−0
- examples/Refactor/ExtractBinding/AssocOpMiddle_res.hs +4/−0
- examples/Refactor/ExtractBinding/AssocOpRightAssoc.hs +3/−0
- examples/Refactor/ExtractBinding/AssocOpRightAssoc_res.hs +4/−0
- examples/Refactor/ExtractBinding/AssocOp_res.hs +4/−0
- examples/Refactor/ExtractBinding/Case.hs +3/−0
- examples/Refactor/ExtractBinding/Case_res.hs +4/−0
- examples/Refactor/ExtractBinding/ClassInstance.hs +6/−0
- examples/Refactor/ExtractBinding/ClassInstance_res.hs +7/−0
- examples/Refactor/ExtractBinding/ExistingLocalDef.hs +4/−0
- examples/Refactor/ExtractBinding/ExistingLocalDef_res.hs +4/−0
- examples/Refactor/ExtractBinding/ExtractedFormatting.hs +5/−0
- examples/Refactor/ExtractBinding/ExtractedFormatting_res.hs +6/−0
- examples/Refactor/ExtractBinding/Indentation.hs +5/−0
- examples/Refactor/ExtractBinding/IndentationMultiLine.hs +7/−0
- examples/Refactor/ExtractBinding/IndentationMultiLine_res.hs +8/−0
- examples/Refactor/ExtractBinding/IndentationOperator.hs +5/−0
- examples/Refactor/ExtractBinding/IndentationOperator_res.hs +6/−0
- examples/Refactor/ExtractBinding/Indentation_res.hs +6/−0
- examples/Refactor/ExtractBinding/LeftSection.hs +3/−0
- examples/Refactor/ExtractBinding/LeftSection_res.hs +4/−0
- examples/Refactor/ExtractBinding/ListComprehension.hs +5/−0
- examples/Refactor/ExtractBinding/ListComprehension_res.hs +6/−0
- examples/Refactor/ExtractBinding/LocalDefinition.hs +4/−0
- examples/Refactor/ExtractBinding/LocalDefinition_res.hs +5/−0
- examples/Refactor/ExtractBinding/NameConflict.hs +4/−0
- examples/Refactor/ExtractBinding/Parentheses.hs +6/−0
- examples/Refactor/ExtractBinding/Parentheses_res.hs +7/−0
- examples/Refactor/ExtractBinding/RecordWildcards.hs +6/−0
- examples/Refactor/ExtractBinding/RecordWildcards_res.hs +7/−0
- examples/Refactor/ExtractBinding/Records.hs +5/−0
- examples/Refactor/ExtractBinding/Records_res.hs +6/−0
- examples/Refactor/ExtractBinding/RightSection.hs +3/−0
- examples/Refactor/ExtractBinding/RightSection_res.hs +4/−0
- examples/Refactor/ExtractBinding/SectionInfix.hs +3/−0
- examples/Refactor/ExtractBinding/SectionInfix_res.hs +4/−0
- examples/Refactor/ExtractBinding/SectionWithLocals.hs +6/−0
- examples/Refactor/ExtractBinding/SectionWithLocals_res.hs +7/−0
- examples/Refactor/ExtractBinding/SiblingDefs.hs +7/−0
- examples/Refactor/ExtractBinding/SiblingDefs_res.hs +8/−0
- examples/Refactor/ExtractBinding/Simple.hs +3/−0
- examples/Refactor/ExtractBinding/Simple_res.hs +4/−0
- examples/Refactor/ExtractBinding/TooSimple.hs +3/−0
- examples/Refactor/ExtractBinding/ViewPattern.hs +4/−0
- examples/Refactor/FloatOut/FloatLocals.hs +5/−0
- examples/Refactor/FloatOut/FloatLocals_res.hs +5/−0
- examples/Refactor/FloatOut/ImplicitLocal.hs +5/−0
- examples/Refactor/FloatOut/ImplicitParam.hs +4/−0
- examples/Refactor/FloatOut/MoveFixity.hs +5/−0
- examples/Refactor/FloatOut/MoveFixity_res.hs +5/−0
- examples/Refactor/FloatOut/MoveSignature.hs +5/−0
- examples/Refactor/FloatOut/MoveSignature_res.hs +5/−0
- examples/Refactor/FloatOut/NameCollosion.hs +6/−0
- examples/Refactor/FloatOut/NameCollosionWithImport.hs +4/−0
- examples/Refactor/FloatOut/NameCollosionWithLocal.hs +6/−0
- examples/Refactor/FloatOut/NoCollosion.hs +7/−0
- examples/Refactor/FloatOut/NoCollosion_res.hs +7/−0
- examples/Refactor/FloatOut/SharedSignature.hs +6/−0
- examples/Refactor/FloatOut/ToTopLevel.hs +4/−0
- examples/Refactor/FloatOut/ToTopLevel_res.hs +4/−0
- examples/Refactor/GenerateExports/Normal.hs +17/−0
- examples/Refactor/GenerateExports/Normal_res.hs +17/−0
- examples/Refactor/GenerateExports/Operators.hs +7/−0
- examples/Refactor/GenerateExports/Operators_res.hs +7/−0
- examples/Refactor/GenerateTypeSignature/BringToScope/A.hs +4/−0
- examples/Refactor/GenerateTypeSignature/BringToScope/AlreadyQualImport.hs +6/−0
- examples/Refactor/GenerateTypeSignature/BringToScope/AlreadyQualImport_res.hs +8/−0
- examples/Refactor/GenerateTypeSignature/BringToScope/B.hs +6/−0
- examples/Refactor/GenerateTypeSignature/CanCaptureVariable.hs +8/−0
- examples/Refactor/GenerateTypeSignature/CanCaptureVariableHasOtherDef.hs +11/−0
- examples/Refactor/GenerateTypeSignature/CanCaptureVariableHasOtherDef_res.hs +12/−0
- examples/Refactor/GenerateTypeSignature/CanCaptureVariable_res.hs +9/−0
- examples/Refactor/GenerateTypeSignature/CannotCaptureVariable.hs +7/−0
- examples/Refactor/GenerateTypeSignature/CannotCaptureVariableNoExt.hs +8/−0
- examples/Refactor/GenerateTypeSignature/Complex.hs +3/−0
- examples/Refactor/GenerateTypeSignature/ComplexLhs.hs +6/−0
- examples/Refactor/GenerateTypeSignature/Complex_res.hs +4/−0
- examples/Refactor/GenerateTypeSignature/Function.hs +3/−0
- examples/Refactor/GenerateTypeSignature/Function_res.hs +4/−0
- examples/Refactor/GenerateTypeSignature/HigherOrder.hs +3/−0
- examples/Refactor/GenerateTypeSignature/HigherOrder_res.hs +4/−0
- examples/Refactor/GenerateTypeSignature/Let.hs +4/−0
- examples/Refactor/GenerateTypeSignature/Let_res.hs +5/−0
- examples/Refactor/GenerateTypeSignature/Local.hs +4/−0
- examples/Refactor/GenerateTypeSignature/Local_res.hs +5/−0
- examples/Refactor/GenerateTypeSignature/Placement.hs +5/−0
- examples/Refactor/GenerateTypeSignature/Placement_res.hs +6/−0
- examples/Refactor/GenerateTypeSignature/Polymorph.hs +6/−0
- examples/Refactor/GenerateTypeSignature/PolymorphSub.hs +5/−0
- examples/Refactor/GenerateTypeSignature/PolymorphSubMulti.hs +5/−0
- examples/Refactor/GenerateTypeSignature/PolymorphSubMulti_res.hs +6/−0
- examples/Refactor/GenerateTypeSignature/PolymorphSub_res.hs +6/−0
- examples/Refactor/GenerateTypeSignature/Polymorph_res.hs +7/−0
- examples/Refactor/GenerateTypeSignature/Simple.hs +3/−0
- examples/Refactor/GenerateTypeSignature/Simple_res.hs +4/−0
- examples/Refactor/GenerateTypeSignature/Tuple.hs +3/−0
- examples/Refactor/GenerateTypeSignature/Tuple_res.hs +4/−0
- examples/Refactor/GenerateTypeSignature/TypeDefinedInModule.hs +6/−0
- examples/Refactor/GenerateTypeSignature/TypeDefinedInModule_res.hs +7/−0
- examples/Refactor/InlineBinding/AlreadyApplied.hs +4/−0
- examples/Refactor/InlineBinding/AlreadyApplied_res.hs +3/−0
- examples/Refactor/InlineBinding/AppearsInAnother/A.hs +3/−0
- examples/Refactor/InlineBinding/AppearsInAnother/B.hs +5/−0
- examples/Refactor/InlineBinding/AutoNaming.hs +5/−0
- examples/Refactor/InlineBinding/AutoNaming_res.hs +4/−0
- examples/Refactor/InlineBinding/FilterSignatures.hs +7/−0
- examples/Refactor/InlineBinding/FilterSignatures_res.hs +6/−0
- examples/Refactor/InlineBinding/InExportList.hs +4/−0
- examples/Refactor/InlineBinding/LetBind.hs +3/−0
- examples/Refactor/InlineBinding/LetBind_res.hs +3/−0
- examples/Refactor/InlineBinding/LetGuard.hs +5/−0
- examples/Refactor/InlineBinding/LetGuard_res.hs +4/−0
- examples/Refactor/InlineBinding/LetStmt.hs +4/−0
- examples/Refactor/InlineBinding/LetStmt_res.hs +3/−0
- examples/Refactor/InlineBinding/Local.hs +4/−0
- examples/Refactor/InlineBinding/LocalNested.hs +5/−0
- examples/Refactor/InlineBinding/LocalNested_res.hs +4/−0
- examples/Refactor/InlineBinding/Local_res.hs +3/−0
- examples/Refactor/InlineBinding/MultiApplied.hs +6/−0
- examples/Refactor/InlineBinding/MultiApplied_res.hs +5/−0
- examples/Refactor/InlineBinding/MultiMatch.hs +6/−0
- examples/Refactor/InlineBinding/MultiMatchGuarded.hs +6/−0
- examples/Refactor/InlineBinding/MultiMatchGuarded_res.hs +4/−0
- examples/Refactor/InlineBinding/MultiMatch_res.hs +5/−0
- examples/Refactor/InlineBinding/Nested.hs +4/−0
- examples/Refactor/InlineBinding/Nested_res.hs +3/−0
- examples/Refactor/InlineBinding/NotOccurring.hs +3/−0
- examples/Refactor/InlineBinding/Operator.hs +4/−0
- examples/Refactor/InlineBinding/Operator_res.hs +3/−0
- examples/Refactor/InlineBinding/PatternMatched.hs +4/−0
- examples/Refactor/InlineBinding/PatternMatched_res.hs +3/−0
- examples/Refactor/InlineBinding/Recursive.hs +4/−0
- examples/Refactor/InlineBinding/RemoveSignatures.hs +6/−0
- examples/Refactor/InlineBinding/RemoveSignatures_res.hs +3/−0
- examples/Refactor/InlineBinding/SimpleMultiMatch.hs +4/−0
- examples/Refactor/InlineBinding/SimpleMultiMatch_res.hs +3/−0
- examples/Refactor/InlineBinding/Simplest.hs +4/−0
- examples/Refactor/InlineBinding/Simplest_res.hs +3/−0
- examples/Refactor/InlineBinding/WithLocals.hs +6/−0
- examples/Refactor/InlineBinding/WithLocals_res.hs +4/−0
- examples/Refactor/OrganizeImports/Class.hs +6/−0
- examples/Refactor/OrganizeImports/Class_res.hs +6/−0
- examples/Refactor/OrganizeImports/Coerce.hs +11/−0
- examples/Refactor/OrganizeImports/Coerce_res.hs +11/−0
- examples/Refactor/OrganizeImports/Ctor.hs +5/−0
- examples/Refactor/OrganizeImports/Ctor_res.hs +5/−0
- examples/Refactor/OrganizeImports/Fields.hs +6/−0
- examples/Refactor/OrganizeImports/Fields_res.hs +6/−0
- examples/Refactor/OrganizeImports/InstanceCarry/DataType.hs +3/−0
- examples/Refactor/OrganizeImports/InstanceCarry/ImportNonOrphan.hs +3/−0
- examples/Refactor/OrganizeImports/InstanceCarry/ImportNonOrphan_res.hs +2/−0
- examples/Refactor/OrganizeImports/InstanceCarry/ImportOrphan.hs +3/−0
- examples/Refactor/OrganizeImports/InstanceCarry/ImportOrphan_res.hs +3/−0
- examples/Refactor/OrganizeImports/InstanceCarry/OrphanInstance.hs +7/−0
- examples/Refactor/OrganizeImports/InstanceCarry/TCWithInst.hs +9/−0
- examples/Refactor/OrganizeImports/InstanceCarry/TypeClass.hs +4/−0
- examples/Refactor/OrganizeImports/KeepCtorOfMarshalled.hs +5/−0
- examples/Refactor/OrganizeImports/KeepCtorOfMarshalled_res.hs +5/−0
- examples/Refactor/OrganizeImports/KeepExplicit.hs +5/−0
- examples/Refactor/OrganizeImports/KeepExplicit_res.hs +5/−0
- examples/Refactor/OrganizeImports/KeepHiding.hs +6/−0
- examples/Refactor/OrganizeImports/KeepHiding_res.hs +6/−0
- examples/Refactor/OrganizeImports/KeepPrelude.hs +3/−0
- examples/Refactor/OrganizeImports/KeepPrelude_res.hs +3/−0
- examples/Refactor/OrganizeImports/KeepReexported.hs +3/−0
- examples/Refactor/OrganizeImports/KeepReexported_res.hs +3/−0
- examples/Refactor/OrganizeImports/KeepRenamedReexported.hs +4/−0
- examples/Refactor/OrganizeImports/KeepRenamedReexported_res.hs +4/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ClassSource.hs +11/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ConSourceHiddenType.hs +3/−0
- examples/Refactor/OrganizeImports/MakeExplicit/FunSource.hs +3/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportClassFun.hs +7/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportClassFun_res.hs +7/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportCon.hs +5/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportCon_res.hs +5/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFour.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFour_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFunHiddenClass.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFunHiddenClass_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFunOutOfClass.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFunOutOfClass_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportOne.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportOne_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportRecordSel.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportRecordSel_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportThree.hs +5/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportThree_res.hs +5/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportUnited.hs +7/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportUnitedCount.hs +8/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportUnitedCount_res.hs +8/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportUnited_res.hs +7/−0
- examples/Refactor/OrganizeImports/MakeExplicit/Renamed.hs +5/−0
- examples/Refactor/OrganizeImports/MakeExplicit/Renamed_res.hs +5/−0
- examples/Refactor/OrganizeImports/MakeExplicit/Source.hs +15/−0
- examples/Refactor/OrganizeImports/Narrow.hs +5/−0
- examples/Refactor/OrganizeImports/NarrowQual.hs +6/−0
- examples/Refactor/OrganizeImports/NarrowQual_res.hs +6/−0
- examples/Refactor/OrganizeImports/NarrowSpec.hs +5/−0
- examples/Refactor/OrganizeImports/NarrowSpec_res.hs +5/−0
- examples/Refactor/OrganizeImports/NarrowType.hs +8/−0
- examples/Refactor/OrganizeImports/NarrowType_res.hs +8/−0
- examples/Refactor/OrganizeImports/Narrow_res.hs +5/−0
- examples/Refactor/OrganizeImports/Operator.hs +5/−0
- examples/Refactor/OrganizeImports/Operator_res.hs +5/−0
- examples/Refactor/OrganizeImports/Removed.hs +3/−0
- examples/Refactor/OrganizeImports/Removed_res.hs +2/−0
- examples/Refactor/OrganizeImports/Reorder.hs +7/−0
- examples/Refactor/OrganizeImports/ReorderComment.hs +12/−0
- examples/Refactor/OrganizeImports/ReorderComment_res.hs +12/−0
- examples/Refactor/OrganizeImports/ReorderGroups.hs +12/−0
- examples/Refactor/OrganizeImports/ReorderGroups_res.hs +12/−0
- examples/Refactor/OrganizeImports/Reorder_res.hs +7/−0
- examples/Refactor/OrganizeImports/SameName.hs +6/−0
- examples/Refactor/OrganizeImports/SameName_res.hs +6/−0
- examples/Refactor/OrganizeImports/StandaloneDeriving.hs +6/−0
- examples/Refactor/OrganizeImports/StandaloneDeriving_res.hs +6/−0
- examples/Refactor/OrganizeImports/TemplateHaskell.hs +5/−0
- examples/Refactor/OrganizeImports/TemplateHaskell_res.hs +5/−0
- examples/Refactor/RenameDefinition/AccentName.hs +6/−0
- examples/Refactor/RenameDefinition/AccentName_res.hs +6/−0
- examples/Refactor/RenameDefinition/AmbiguousFields.hs +11/−0
- examples/Refactor/RenameDefinition/AmbiguousFields_res.hs +11/−0
- examples/Refactor/RenameDefinition/Arg.hs +4/−0
- examples/Refactor/RenameDefinition/Arg_res.hs +4/−0
- examples/Refactor/RenameDefinition/BacktickName.hs +6/−0
- examples/Refactor/RenameDefinition/BacktickName_res.hs +6/−0
- examples/Refactor/RenameDefinition/ClassMember.hs +7/−0
- examples/Refactor/RenameDefinition/ClassMember_res.hs +7/−0
- examples/Refactor/RenameDefinition/ClassTypeVar.hs +4/−0
- examples/Refactor/RenameDefinition/ClassTypeVar_res.hs +4/−0
- examples/Refactor/RenameDefinition/Constructor.hs +6/−0
- examples/Refactor/RenameDefinition/Constructor_res.hs +6/−0
- examples/Refactor/RenameDefinition/CrossRename.hs +8/−0
- examples/Refactor/RenameDefinition/DefineSplices.hs too large to diff
- examples/Refactor/RenameDefinition/FormattingAware.hs too large to diff
- examples/Refactor/RenameDefinition/FormattingAware_res.hs too large to diff
- examples/Refactor/RenameDefinition/FunTypeVar.hs too large to diff
- examples/Refactor/RenameDefinition/FunTypeVarLocal.hs too large to diff
- examples/Refactor/RenameDefinition/FunTypeVarLocal_res.hs too large to diff
- examples/Refactor/RenameDefinition/FunTypeVar_res.hs too large to diff
- examples/Refactor/RenameDefinition/Function.hs too large to diff
- examples/Refactor/RenameDefinition/Function_res.hs too large to diff
- examples/Refactor/RenameDefinition/FunnyDo.hs too large to diff
- examples/Refactor/RenameDefinition/FunnyDo_res.hs too large to diff
- examples/Refactor/RenameDefinition/IllegalQualRename.hs too large to diff
- examples/Refactor/RenameDefinition/LayoutAware.hs too large to diff
- examples/Refactor/RenameDefinition/LayoutAware_res.hs too large to diff
- examples/Refactor/RenameDefinition/LibraryFunction.hs too large to diff
- examples/Refactor/RenameDefinition/LocalFunction.hs too large to diff
- examples/Refactor/RenameDefinition/LocalFunction_res.hs too large to diff
- examples/Refactor/RenameDefinition/MergeFields.hs too large to diff
- examples/Refactor/RenameDefinition/MergeFields_RenameY.hs too large to diff
- examples/Refactor/RenameDefinition/MergeFields_RenameY_res.hs too large to diff
- examples/Refactor/RenameDefinition/MergeFields_res.hs too large to diff
- examples/Refactor/RenameDefinition/MultiModule/A.hs too large to diff
- examples/Refactor/RenameDefinition/MultiModule/B.hs too large to diff
- examples/Refactor/RenameDefinition/MultiModule_res/A.hs too large to diff
- examples/Refactor/RenameDefinition/MultiModule_res/B.hs too large to diff
- examples/Refactor/RenameDefinition/NameClash.hs too large to diff
- examples/Refactor/RenameDefinition/NoPrelude.hs too large to diff
- examples/Refactor/RenameDefinition/NoPrelude_res.hs too large to diff
- examples/Refactor/RenameDefinition/ParenName.hs too large to diff
- examples/Refactor/RenameDefinition/ParenName_res.hs too large to diff
- examples/Refactor/RenameDefinition/PatternSynonym.hs too large to diff
- examples/Refactor/RenameDefinition/PatternSynonymTypeSig.hs too large to diff
- examples/Refactor/RenameDefinition/PatternSynonymTypeSig_res.hs too large to diff
- examples/Refactor/RenameDefinition/PatternSynonym_res.hs too large to diff
- examples/Refactor/RenameDefinition/QualImport.hs too large to diff
- examples/Refactor/RenameDefinition/QualImportAlso.hs too large to diff
- examples/Refactor/RenameDefinition/QualImport_res.hs too large to diff
- examples/Refactor/RenameDefinition/QualName.hs too large to diff
- examples/Refactor/RenameDefinition/QualName_res.hs too large to diff
- examples/Refactor/RenameDefinition/RecordField.hs too large to diff
- examples/Refactor/RenameDefinition/RecordField_res.hs too large to diff
- examples/Refactor/RenameDefinition/RecordPatternSynonyms.hs too large to diff
- examples/Refactor/RenameDefinition/RecordPatternSynonyms_res.hs too large to diff
- examples/Refactor/RenameDefinition/RecordWildcards.hs too large to diff
- examples/Refactor/RenameDefinition/RecordWildcards_res.hs too large to diff
- examples/Refactor/RenameDefinition/RenameModule/A.hs too large to diff
- examples/Refactor/RenameDefinition/RenameModule/B.hs too large to diff
- examples/Refactor/RenameDefinition/RenameModuleAlias.hs too large to diff
- examples/Refactor/RenameDefinition/RenameModuleAlias_res.hs too large to diff
- examples/Refactor/RenameDefinition/RenameModule_res/A.hs too large to diff
- examples/Refactor/RenameDefinition/RenameModule_res/C.hs too large to diff
- examples/Refactor/RenameDefinition/RoleAnnotation.hs too large to diff
- examples/Refactor/RenameDefinition/RoleAnnotation_res.hs too large to diff
- examples/Refactor/RenameDefinition/SameCtorAndType.hs too large to diff
- examples/Refactor/RenameDefinition/SameCtorAndType_res.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceDecls/Define.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceDecls/Use.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceDecls_res/Define.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceDecls_res/Use.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceExpr/Define.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceExpr/Use.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceExpr_res/Define.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceExpr_res/Use.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceType/Define.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceType/Use.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceType_res/Define.hs too large to diff
- examples/Refactor/RenameDefinition/SpliceType_res/Use.hs too large to diff
- examples/Refactor/RenameDefinition/Type.hs too large to diff
- examples/Refactor/RenameDefinition/TypeBracket.hs too large to diff
- examples/Refactor/RenameDefinition/TypeBracket_res.hs too large to diff
- examples/Refactor/RenameDefinition/TypeOperators.hs too large to diff
- examples/Refactor/RenameDefinition/TypeOperators_res.hs too large to diff
- examples/Refactor/RenameDefinition/Type_res.hs too large to diff
- examples/Refactor/RenameDefinition/UnusedDef.hs too large to diff
- examples/Refactor/RenameDefinition/UnusedDef_res.hs too large to diff
- examples/Refactor/RenameDefinition/ValBracket.hs too large to diff
- examples/Refactor/RenameDefinition/ValBracket_res.hs too large to diff
- examples/Refactor/RenameDefinition/WrongName.hs too large to diff
- examples/TH/Brackets.hs too large to diff
- examples/TH/ClassUse.hs too large to diff
- examples/TH/CrossDef.hs too large to diff
- examples/TH/DoubleSplice.hs too large to diff
- examples/TH/GADTFields.hs too large to diff
- examples/TH/LocalDefinition.hs too large to diff
- examples/TH/MultiImport.hs too large to diff
- examples/TH/NestedSplices.hs too large to diff
- examples/TH/QuasiQuote/Define.hs too large to diff
- examples/TH/QuasiQuote/Use.hs too large to diff
- examples/TH/Quoted.hs too large to diff
- examples/TH/Splice/Define.hs too large to diff
- examples/TH/Splice/Names.hs too large to diff
- examples/TH/Splice/Use.hs too large to diff
- examples/TH/Splice/UseImported.hs too large to diff
- examples/TH/Splice/UseQual.hs too large to diff
- examples/TH/Splice/UseQualMulti.hs too large to diff
- examples/TH/WithWildcards.hs too large to diff
- examples/Type/Bang.hs too large to diff
- examples/Type/Builtin.hs too large to diff
- examples/Type/Ctx.hs too large to diff
- examples/Type/ExplicitTypeApplication.hs too large to diff
- examples/Type/Forall.hs too large to diff
- examples/Type/Primitives.hs too large to diff
- examples/Type/TupleAssert.hs too large to diff
- examples/Type/TypeOperators.hs too large to diff
- examples/Type/Unpack.hs too large to diff
- examples/Type/Wildcard.hs too large to diff
- haskell-tools-builtin-refactorings.cabal too large to diff
- test/ExtensionOrganizerTest/AnnotationParser.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/Combined.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/InAlt.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/InExpr.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/InMatchLhs.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/InPatSynRhs.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/InPattern.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/InRhsGuard.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/InStmt.hs too large to diff
- test/ExtensionOrganizerTest/BangPatternsTest/InValueBind.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/DataDeriving.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/DataDerivingStrategies.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/Definitions.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/NewtypeDeriving.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/NewtypeDerivingStrategies.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneData.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneDataStrategies.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneDataSynonyms.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneDataSynonymsStrategies.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneNewtype.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneNewtypeAny.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneNewtypeStrategies.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneNewtypeSynonyms.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneNewtypeSynonymsAny.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/StandaloneNewtypeSynonymsStrategies.hs too large to diff
- test/ExtensionOrganizerTest/DerivingsTest/SynonymDefinitions.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/Combined.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/Definitions.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/NestedTypes.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/NestedUnitTyCon.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/NestedWiredInType.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/NoOccurenceOFF.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/NoOccurenceON.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/SameTyVars.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/TopLevelTyVar.hs too large to diff
- test/ExtensionOrganizerTest/FlexibleInstancesTest/TopLevelWiredInType.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/Definitions.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InCaseRhs.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InCompStmt.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InExpr.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InFieldUpdate.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InPattern.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InRhs.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InRhsGuard.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InStmt.hs too large to diff
- test/ExtensionOrganizerTest/LambdaCaseTest/InTupSecElem.hs too large to diff
- test/ExtensionOrganizerTest/Main.hs too large to diff
- test/ExtensionOrganizerTest/PatternSynonymsTest/BiDirectional.hs too large to diff
- test/ExtensionOrganizerTest/PatternSynonymsTest/UniDirectional.hs too large to diff
- test/ExtensionOrganizerTest/RecordWildCardsTest/Definitions.hs too large to diff
- test/ExtensionOrganizerTest/RecordWildCardsTest/InExpression.hs too large to diff
- test/ExtensionOrganizerTest/RecordWildCardsTest/InPattern.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/Definitions.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InCaseRhs.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InCompStmt.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InExpr.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InFieldUpdate.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InPattern.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InRhs.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InRhsGuard.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InStmt.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/InTupSecElem.hs too large to diff
- test/ExtensionOrganizerTest/TupleSectionsTest/NoTupleSections.hs too large to diff
- test/ExtensionOrganizerTest/ViewPatternsTest/InAlt.hs too large to diff
- test/ExtensionOrganizerTest/ViewPatternsTest/InExpr.hs too large to diff
- test/ExtensionOrganizerTest/ViewPatternsTest/InMatchLhs.hs too large to diff
- test/ExtensionOrganizerTest/ViewPatternsTest/InMatchLhsNested.hs too large to diff
- test/Main.hs too large to diff
@@ -0,0 +1,29 @@+Haskell-Tools is Copyright (c) Boldizsár Németh, 2016, all rights reserved, +and is distributed as free software under the following license. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions, and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions, and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- The names of the copyright holders may not be used to endorse or +promote products derived from this software without specific prior +written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,29 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} +module Language.Haskell.Tools.Refactor.Builtin ( builtinRefactorings ) where + +import Language.Haskell.Tools.Refactor (RefactoringChoice) +import Language.Haskell.Tools.Refactor.Builtin.ExtractBinding (ExtractBindingDomain, extractBindingRefactoring) +import Language.Haskell.Tools.Refactor.Builtin.FloatOut (floatOutRefactoring) +import Language.Haskell.Tools.Refactor.Builtin.GenerateExports (DomGenerateExports, generateExportsRefactoring) +import Language.Haskell.Tools.Refactor.Builtin.GenerateTypeSignature (GenerateSignatureDomain, generateTypeSignatureRefactoring) +import Language.Haskell.Tools.Refactor.Builtin.InlineBinding (inlineBindingRefactoring) +import Language.Haskell.Tools.Refactor.Builtin.OrganizeExtensions (OrganizeExtensionsDomain, organizeExtensionsRefactoring, projectOrganizeExtensionsRefactoring) +import Language.Haskell.Tools.Refactor.Builtin.OrganizeImports (OrganizeImportsDomain, organizeImportsRefactoring, projectOrganizeImportsRefactoring) +import Language.Haskell.Tools.Refactor.Builtin.RenameDefinition (DomainRenameDefinition, renameDefinitionRefactoring) + +builtinRefactorings :: ( DomGenerateExports dom, OrganizeImportsDomain dom + , DomainRenameDefinition dom, ExtractBindingDomain dom + , GenerateSignatureDomain dom, OrganizeExtensionsDomain dom + ) => [RefactoringChoice dom] +builtinRefactorings + = [ organizeImportsRefactoring + , projectOrganizeImportsRefactoring + , inlineBindingRefactoring + , generateTypeSignatureRefactoring + , renameDefinitionRefactoring + , generateExportsRefactoring + , floatOutRefactoring + , extractBindingRefactoring + , organizeExtensionsRefactoring + , projectOrganizeExtensionsRefactoring + ]
@@ -0,0 +1,25 @@+module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers + ( module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.RecordWildCardsChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleInstancesChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.DerivingsChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.BangPatternsChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.PatternSynonymsChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TemplateHaskellChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ViewPatternsChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.LambdaCaseChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TupleSectionsChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.UnboxedTuplesChecker + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.MagicHashChecker + ) where + +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.BangPatternsChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.DerivingsChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleInstancesChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.LambdaCaseChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.MagicHashChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.PatternSynonymsChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.RecordWildCardsChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TemplateHaskellChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TupleSectionsChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.UnboxedTuplesChecker +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ViewPatternsChecker
@@ -0,0 +1,28 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.BangPatternsChecker where + +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +-- NOTE: Here we implicitly constrained the type with ExtDomain. +-- but we don't really need any. + +chkBangPatterns :: CheckNode Pattern +chkBangPatterns = conditional chkBangPatterns' BangPatterns + +chkBangPatterns' :: CheckNode Pattern +chkBangPatterns' p@(BangPat _) = addOccurence BangPatterns p +chkBangPatterns' x = return x + +{- + RhsGuard DONE + MatchLhs DONE + ValueBind DONE + Expr DONE + Alt DONE + Stmt DONE + Pattern MORE TESTS + Bracket ASK + PatSynRhs DONE +-}
@@ -0,0 +1,275 @@+{-# LANGUAGE FlexibleContexts, MultiWayIf, RankNTypes, TypeFamilies, ViewPatterns #-} + +{- + NOTE: We need Decl level checking in order to gain extra information + from the newtype and data keywords. + NOTE: Here we implicitly constrained the type with ExtDomain. + but we only really need HasNameInfo. + + When a strategy is not explicitly given, every single extension + is analysied individually, so every occurence induces a separate + extension. However, when a strategy is specified, we only add + GND and DeriveAnyClass once, since no further examination is needed. + + For examples see the test files. + + SEE: https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DerivingStrategies#Thederivingstrategyresolutionalgorithm + + TODO: + - write tests for GADTs, data instances + - correct DerivingStrategies behaviour with StandaloneDeriving +-} + + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.DerivingsChecker where + +import Control.Reference ((^.), (!~), (&)) +import Language.Haskell.Tools.AST +import Language.Haskell.Tools.Refactor as Refact hiding (Enum) +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad as Ext +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.TypeLookup + +import Control.Monad.Trans.Maybe (MaybeT(..)) +import qualified Data.Map as Map (fromList, lookup) + +import qualified GHC (Name(..), isNewTyCon) +import qualified Name as GHC (Name) +import PrelNames +import THNames (liftClassName) + +-- can be derived +isStockClass = flip elem stockClasses +stockClasses = [ eqClassName + , ordClassName + , ixClassName + , showClassName + , readClassName + , enumClassName + , boundedClassName + , dataClassName + , typeableClassName + , genClassName + , gen1ClassName + , functorClassName + , foldableClassName + , traversableClassName + , liftClassName + ] + +-- can be derived for newtypes even without GND +gndNotNeeded :: GHC.Name -> Bool +gndNotNeeded = flip elem gndNotNeededClasses +gndNotNeededClasses = + [ eqClassName + , ordClassName + , ixClassName + , boundedClassName + ] + +-- can be derived for newtypes with GND +gndNeeded :: GHC.Name -> Bool +gndNeeded = flip elem gndNeededClasses +gndNeededClasses = + [ functorClassName + , foldableClassName + , enumClassName + ] + +-- never selected by default for newtypes (even with GND) +gndNotAllowed :: GHC.Name -> Bool +gndNotAllowed = flip elem gndNotAllowedClasses +gndNotAllowedClasses = + [ dataClassName + , typeableClassName + , showClassName + , readClassName + , traversableClassName + , genClassName + , gen1ClassName + , liftClassName + ] + +whichExtension :: GHC.Name -> Maybe Extension +whichExtension = flip Map.lookup nameExtensionMap + +nameExtensionMap = Map.fromList nameExtensions + where nameExtensions = [ (dataClassName, DeriveDataTypeable) + , (typeableClassName, DeriveDataTypeable) + , (genClassName, DeriveGeneric) + , (gen1ClassName, DeriveGeneric) + , (functorClassName, DeriveFunctor) + , (foldableClassName, DeriveFoldable) + , (traversableClassName, DeriveTraversable) + , (liftClassName, DeriveLift) + ] + +chkDerivings :: CheckNode Decl +chkDerivings = conditionalAny chkDerivings' derivingExts + >=> conditional chkStandaloneDeriving Ext.StandaloneDeriving + + where chkDerivings' = chkDataDecl + >=> chkGADTDataDecl + >=> chkDataInstance + + derivingExts = [ DeriveDataTypeable + , DeriveGeneric + , DeriveFunctor + , DeriveFoldable + , DeriveTraversable + , DeriveLift + , DeriveAnyClass + , GeneralizedNewtypeDeriving + , DerivingStrategies + ] + + +chkDataDecl :: CheckNode Decl +chkDataDecl d@(DataDecl keyw _ _ _ derivs) = do + annList !~ separateByKeyword keyw $ derivs + return d +chkDataDecl d = return d + +chkGADTDataDecl :: CheckNode Decl +chkGADTDataDecl d@(GADTDataDecl keyw _ _ _ _ derivs) = do + addOccurence_ GADTs d + annList !~ separateByKeyword keyw $ derivs + return d +chkGADTDataDecl d = return d + +chkDataInstance :: CheckNode Decl +chkDataInstance d@(DataInstance keyw _ _ derivs) = do + addOccurence_ TypeFamilies d + annList !~ separateByKeyword keyw $ derivs + return d +chkDataInstance d = return d + + +separateByKeyword :: DataOrNewtypeKeyword dom -> CheckNode Deriving +separateByKeyword keyw derivs + | isNewtypeDecl keyw = chkByStrat chkClassForNewtype derivs + | otherwise = chkByStrat chkClassForData derivs + where isNewtypeDecl keyw = case keyw ^. element of + UNewtypeKeyword -> True + _ -> False + + +getStrategy :: Deriving dom -> Maybe (DeriveStrategy dom) +getStrategy d = d ^. (deriveStrategy & annMaybe) + +addExtension :: (MonadState ExtMap m, HasRange node) => + GHC.Name -> node -> m node +addExtension sname + | Just ext <- whichExtension sname = addOccurence ext + | otherwise = return + +addStockExtension :: CheckNode InstanceHead +addStockExtension x + | Just sname <- nameFromStock x = addExtension sname x + | otherwise = return x + +chkByStrat :: CheckNode' InstanceHead dom -> CheckNode' Deriving dom +chkByStrat checker d + | Just strat <- getStrategy d = do + addOccurence DerivingStrategies d + chkDerivingClause (chkStrat strat) d + | otherwise = + chkDerivingClause checker d + +chkStrat :: DeriveStrategy dom -> CheckNode' InstanceHead dom +chkStrat (_element -> UStockStrategy) = addStockExtension +chkStrat (_element -> UNewtypeStrategy) = addOccurence GeneralizedNewtypeDeriving +chkStrat (_element -> UAnyClassStrategy) = addOccurence DeriveAnyClass + +chkDerivingClause :: CheckNode' InstanceHead dom -> CheckNode' Deriving dom +chkDerivingClause checker d@(DerivingOne x) = checker x >> return d +chkDerivingClause checker d@(DerivingMulti xs) = (annList !~ checker) xs >> return d + +-- checks whether the class is stock, and if it is, returns its name +nameFromStock :: HasNameInfo dom => InstanceHead dom -> Maybe GHC.Name +nameFromStock x + | InstanceHead name <- skipParens x, + Just sname <- getSemName name, + isStockClass sname + = Just sname + | otherwise = Nothing + +chkClassForData :: CheckNode InstanceHead +chkClassForData x + | Just sname <- nameFromStock x = addExtension sname x + | otherwise = addOccurence DeriveAnyClass x + +-- performs check in case no explicit strategy is given +chkClassForNewtype :: CheckNode InstanceHead +chkClassForNewtype x + | Just sname <- nameFromStock x + = if | gndNotNeeded sname -> return x + | gndNeeded sname -> addOccurence GeneralizedNewtypeDeriving x + | gndNotAllowed sname -> addExtension sname x + | otherwise = do + gndOn <- isTurnedOn GeneralizedNewtypeDeriving + deriveAnyOn <- isTurnedOn DeriveAnyClass + if | gndOn && deriveAnyOn -> addOccurence_ DeriveAnyClass x + | deriveAnyOn -> addOccurence_ DeriveAnyClass x + | gndOn -> addOccurence_ GeneralizedNewtypeDeriving x + | otherwise -> return () + return x + +skipParens :: InstanceHead dom -> InstanceHead dom +skipParens (ParenInstanceHead x) = skipParens x +skipParens x = x + +chkStandaloneDeriving :: CheckNode Decl +chkStandaloneDeriving d@(Refact.StandaloneDeriving strat _ (decompRule -> (cls,ty))) + | Just strat' <- strat = do + addOccurence_ Ext.DerivingStrategies d + addOccurence_ Ext.StandaloneDeriving d + chkSynonym ty + chkStrat strat' cls + return d + | otherwise = do + addOccurence_ Ext.StandaloneDeriving d + itIsNewType <- isNewtype ty + itIsSynNewType <- isSynNewType ty + if itIsNewType || itIsSynNewType + then chkClassForNewtype cls + else chkClassForData cls + return d +chkStandaloneDeriving d = return d + +decompRule :: InstanceRule dom -> (InstanceHead dom, Type dom) +decompRule instRule = (cls, ty) + where ihead = instRule ^. irHead + cls = getClassCon ihead + ty = rightmostType ihead + +getClassCon :: InstanceHead dom -> InstanceHead dom +getClassCon (AppInstanceHead f _) = getClassCon f +getClassCon (ParenInstanceHead x) = getClassCon x +getClassCon x = x + +rightmostType :: InstanceHead dom -> Type dom +rightmostType ihead + | AppInstanceHead _ tyvar <- skipParens ihead = tyvar + +{- + NOTE: Returns false if the type is certainly not a type synonym. + Returns true if it is a synonym for a newtype or it could not have been looked up. + NOTE: It always has the following side-effects: + - If the input is a type synonym, then adds TypeSynonymInstances + (regardless of it being a newtype or not) + + This behaviour will produce false positives. + This is desirable since the underlying type might be a newtype + in which case GeneralizedNewtypeDeriving might be necessary. +-} +isSynNewType :: HasNameInfo dom => Type dom -> ExtMonad Bool +isSynNewType t = do + mtycon <- runMaybeT . lookupType $ t + case mtycon of + Nothing -> return True + Just tycon -> isSynNewType' tycon + where isSynNewType' x = case lookupSynDef x of + Nothing -> return False + Just def -> do + addOccurence_ TypeSynonymInstances t + return (GHC.isNewTyCon def)
@@ -0,0 +1,182 @@+{-# LANGUAGE FlexibleContexts, MultiWayIf, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleInstancesChecker where + +import Control.Reference ((^.), (!~), biplateRef) +import Language.Haskell.Tools.Refactor as Refact +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.TypeLookup (lookupSynDefM) + + +import Control.Monad.Trans.Maybe (MaybeT(..)) +import Data.Data (Data(..)) +import Data.List (nub) + +import Name as GHC (isTyVarName, isTyConName, isWiredInName) + +{-# ANN module "HLint: ignore Redundant bracket" #-} + +-- TODO: write "deriving instance ..." tests (should work) +-- TODO: should expand type synonyms !!! + +-- NOTE: Here we implicitly constrained the type with ExtDomain. +-- but we only really need HasNameInfo. + +-- NOTE: We need Decl level checking, in order to distinguish +-- class instances from data and type family instances. + +chkFlexibleInstances :: CheckNode Decl +chkFlexibleInstances = conditional chkFlexibleInstances' FlexibleInstances + +chkFlexibleInstances' :: CheckNode Decl +chkFlexibleInstances' d@(Refact.StandaloneDeriving _ _ rule) = checkedReturn rule d +chkFlexibleInstances' d@(InstanceDecl rule _) = checkedReturn rule d +chkFlexibleInstances' d = return d + +checkedReturn :: ExtDomain dom => InstanceRule dom -> a -> ExtMonad a +checkedReturn rule x = chkInstanceRule rule >> return x + +-- this check DOES transform the AST for its internal computations +-- but returns the original one in the end +-- NOTE: There are two traversals: +-- First one on the class level, and the second one one on the type level. +-- Since biplateRef is lazy, it won't go down to the type level in the first traversal +chkInstanceRule :: CheckNode InstanceRule +chkInstanceRule r@(InstanceRule _ _ ihead) = do + chkInstanceHead ihead + return $! r +chkInstanceRule r = return r + +refact :: + (Data.Data.Data (node dom stage), Data.Data.Data (inner dom stage), + Monad m) => + (inner dom stage -> m (inner dom stage)) + -> node dom stage -> m (node dom stage) +refact op = biplateRef !~ op + + +-- one IHApp will only check its own tyvars (their structure and uniqueness) +-- thus with MultiParamTypeclasses each param will be checked independently +-- (so the same type variable can appear in multiple params) +chkInstanceHead :: CheckNode InstanceHead +chkInstanceHead x@(InfixInstanceHead tyvars _) = do + tyvars' <- refact rmTypeMisc tyvars + chkTyVars tyvars' + addOccurence_ MultiParamTypeClasses x + addOccurence_ TypeOperators x + return x +chkInstanceHead app@(AppInstanceHead f tyvars) = do + tyvars' <- refact rmTypeMisc tyvars + chkTyVars tyvars' + case f of + AppInstanceHead _ _ -> addOccurence_ MultiParamTypeClasses app + _ -> return () + chkInstanceHead f + return app +chkInstanceHead x@(ParenInstanceHead h) = do + chkInstanceHead h + return x +chkInstanceHead app = return app + +-- TODO: skip other unnecessary parts of the AST (eg.: UType ctors) +-- where can UTyPromoted appear? +-- can i write forall in instance heads? +-- unboxed tuple (has different kind, can't use in ihead), par array? +-- TH ctors +-- other misc ... +-- synonym expansion (runMaybeT . lookupSynDefM $ vars) (now: if synonym, keep FC) +chkTyVars :: CheckNode Type +chkTyVars vars = do + msyn <- runMaybeT . lookupSynDefM $ vars + maybe (performCheck vars) (const $ addOccurence FlexibleInstances vars) msyn + + where performCheck vars = do + (isOk, (_, vs)) <- runStateT (runMaybeT (chkAll vars)) ([],[]) + case isOk of + Just isOk -> + unless (isOk && length vs == (length . nub $ vs)) --tyvars are different + (addOccurence_ FlexibleInstances vars) + Nothing -> error "chkTyVars: Couldn't look up something" + return vars + + chkAll x = + ifM (chkTopLevel x) $ + chkOnlyApp x + + chkTopLevel x = -- NOTE: this resembles a monadic bind ... (Cont?) + ifM (chkListType x) . + ifM (chkTupleType x) . + ifM (chkUnitTyCon x) $ + return False + + ifM cond f = do b <- cond; if b then (return b) else f + + chkUnitTyCon (VarType x) = do + sname <- tyVarSemNameM x + -- standalone top-level type variables are not accepted + -- NOTE: -XHaskell98 operator type variables?? + -- NOTE VarType is either TyCon or TyVar + -- if it is a TyCon, it cannot be wired in (Int, Char, etc) + if | isTyVarName sname -> addTyVarM x >> return False + | isWiredInName sname -> addTyConM x >> return False + | isTyConName sname -> addTyConM x >> return True + | otherwise -> return True -- NEVER + chkUnitTyCon _ = return False + + + chkSingleTyVar (VarType x) = do + sname <- tyVarSemNameM x + if (isTyVarName sname) + then addTyVarM x >> return True + else addTyConM x >> return False + chkSingleTyVar _ = return False + + + chkTupleType (TupleType args) = do + let xs = args ^. annListElems + bs <- mapM chkSingleTyVar xs + return $! and bs + chkTupleType _ = return False + + chkListType (ListType v) = chkSingleTyVar v + chkListType _ = return False + + chkOnlyApp :: (MonadState ([Name dom],[Name dom]) (m1 m2), + MonadTrans m1, + MonadState ExtMap m2, + ExtDomain dom) => + Type dom -> MaybeT (m1 m2) Bool + chkOnlyApp (TypeApp f v@(VarType _)) = do + isTyVar <- chkSingleTyVar v + if isTyVar + then case f of + (VarType c) -> addTyConM c >> return True + _ -> chkOnlyApp f + else return False + chkOnlyApp x@(InfixTypeApp lhs op rhs) = do + lift . lift $ addOccurence_ TypeOperators x + addTyConM . mkNormalName $ (op ^. operatorName) + lOK <- chkSingleTyVar lhs + rOK <- chkSingleTyVar rhs + return $! lOK && rOK + chkOnlyApp _ = return False + + addTyCon n (ctors, vars) = (n:ctors, vars) + addTyVar n (ctors, vars) = (ctors, n:vars) + addTyConM n = modify $ addTyCon n + addTyVarM n = modify $ addTyVar n + + tyVarSemNameM x = MaybeT . return . semanticsName $ x ^. simpleName + +rmTypeMisc :: Type dom -> ExtMonad (Type dom) +rmTypeMisc = rmTParens >=> rmTKinded + +rmTKinded :: Type dom -> ExtMonad (Type dom) +rmTKinded kt@(KindedType t _) = addOccurence_ KindSignatures kt >> return t +rmTKinded x = return x + +-- removes Parentheses from the AST +-- the structure is reserved +rmTParens :: Type dom -> ExtMonad (Type dom) +rmTParens (ParenType x) = return x +rmTParens x = return x
@@ -0,0 +1,34 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.LambdaCaseChecker where + +import Language.Haskell.Tools.Refactor as Refact +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad as Ext + +chkLambdaCase :: CheckNode Expr +chkLambdaCase = conditional chkLambdaCase' Ext.LambdaCase + +chkLambdaCase' :: CheckNode Expr +chkLambdaCase' e@(Refact.LambdaCase _) = addOccurence Ext.LambdaCase e +chkLambdaCase' e = return e + + +{- + TopLevelPragma, + Rule, + + Splice, + Bracket, + + Cmd, + + Rhs DONE + RhsGuard DONE + Expr DONE + FieldUpdate DONE + TupSecElem DONE + CaseRhs DONE + Stmt DONE + CompStmt DONE + Pattern DONE +-}
@@ -0,0 +1,81 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.MagicHashChecker where + +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +{-# ANN module "HLint: ignore Redundant bracket" #-} + +chkMagicHashLiteral :: CheckNode Literal +chkMagicHashLiteral = conditional chkMagicHashLiteral' MagicHash + +chkMagicHashNamePart :: CheckNode NamePart +chkMagicHashNamePart = conditional chkMagicHashNamePart' MagicHash + +chkMagicHashKind :: CheckNode Kind +chkMagicHashKind = conditional chkMagicHashKind' MagicHash + + + + +chkMagicHashLiteral' :: CheckNode Literal +chkMagicHashLiteral' l@(PrimIntLit _) = addOccurence MagicHash l +chkMagicHashLiteral' l@(PrimWordLit _) = addOccurence MagicHash l +chkMagicHashLiteral' l@(PrimFloatLit _) = addOccurence MagicHash l +chkMagicHashLiteral' l@(PrimDoubleLit _) = addOccurence MagicHash l +chkMagicHashLiteral' l@(PrimCharLit _) = addOccurence MagicHash l +chkMagicHashLiteral' l@(PrimStringLit _) = addOccurence MagicHash l +chkMagicHashLiteral' l = return l + + +chkMagicHashNamePart' :: CheckNode NamePart +chkMagicHashNamePart' n@(NamePart name) = + if (last name == '#') then addOccurence MagicHash n + else return n + +-- NOTE: is this really needed? +chkMagicHashKind' :: CheckNode Kind +chkMagicHashKind' k@UnboxKind = addOccurence MagicHash k +chkMagicHashKind' k = return k + +{- Name can be reached from: + UIESpec + USubSpec + UInjectivityAnn + URuleVar + UTopLevelPragma + UAnnotationSubject + UMinimalFormula + + UDecl DONE + UClassElement DONE + UDeclHead DONE + UGadtConDecl DONE + UPatSynLhs DONE + UPatternTypeSignature DONE + UFunDep DONE + UConDecl DONE + UFieldDecl DONE + UInstanceHead DONE + UTypeSignature DONE + UMatchLhs DONE + UTyVar DONE + UType DONE + UKind DONE + UAssertion DONE + UExpr DONE + UFieldUpdate DONE + UPattern DONE + UPatternField DONE + USplice + UQuasiQuote + + UPromoted t +-} + +{- QualifiedName can be reached from: + UDecl DONE + UOperator DONE + UName (obviously) DONE +-}
@@ -0,0 +1,18 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.PatternSynonymsChecker where + +import Language.Haskell.Tools.Refactor (PatternSignature, PatternSynonym) +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +-- NOTE: Here we implicitly constrained the type with ExtDomain. +-- but we don't really need any. + +chkPatternSynonymsSyn :: CheckNode PatternSynonym +chkPatternSynonymsSyn = conditional chkPatternSynonymsSyn' PatternSynonyms + +chkPatternSynonymsSyn' :: CheckNode PatternSynonym +chkPatternSynonymsSyn' = addOccurence PatternSynonyms + +chkPatternSynonymsTypeSig :: CheckNode PatternSignature +chkPatternSynonymsTypeSig = conditional (addOccurence PatternSynonyms) PatternSynonyms
@@ -0,0 +1,17 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.RecordWildCardsChecker where + +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +-- NOTE: Here we implicitly constrained the type with ExtDomain. +-- but we don't really need any contraint. + +chkRecordWildCardsPatField :: CheckNode PatternField +chkRecordWildCardsPatField p@(FieldWildcardPattern {}) = addOccurence RecordWildCards p +chkRecordWildCardsPatField p = return p + +chkRecordWildCardsFieldUpdate :: CheckNode FieldUpdate +chkRecordWildCardsFieldUpdate e@(FieldWildcard {}) = addOccurence RecordWildCards e +chkRecordWildCardsFieldUpdate e = return e
@@ -0,0 +1,31 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TemplateHaskellChecker where + +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +-- NOTE: Here we implicitly constrained the type with ExtDomain. +-- but we don't really need any. + +-- can be reached from: Decl, Type, Expr, Pattern +chkTemplateHaskellSplice :: CheckNode Splice +chkTemplateHaskellSplice = addOccurence TemplateHaskell + +-- can be reached from: Type, Expr, Pattern +chkTemplateHaskellQuasiQuote :: CheckNode QuasiQuote +chkTemplateHaskellQuasiQuote = addOccurence QuasiQuotes + +-- can be reached from: Expr +chkTemplateHaskellBracket :: CheckNode Bracket +chkTemplateHaskellBracket = addOccurence TemplateHaskellQuotes + +chkTemplateHaskellhNamePart :: CheckNode NamePart +chkTemplateHaskellhNamePart = conditional chkTemplateHaskellNamePart' TemplateHaskellQuotes + + +-- should be THQuotes OR DataKinds +chkTemplateHaskellNamePart' :: CheckNode NamePart +chkTemplateHaskellNamePart' n@(NamePart name) = + if (head name == '\'') then addOccurence TemplateHaskellQuotes n + else return n
@@ -0,0 +1,15 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TupleSectionsChecker where + +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +chkTupleSections :: CheckNode Expr +chkTupleSections = conditional chkTupleSections' TupleSections + +chkTupleSections' :: CheckNode Expr +chkTupleSections' e@(TupleSection _) = addOccurence TupleSections e +chkTupleSections' e@(UnboxedTupleSection _) = addOccurence TupleSections e + >> addOccurence UnboxedTuples e +chkTupleSections' e = return e
@@ -0,0 +1,29 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.UnboxedTuplesChecker where + +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +chkUnboxedTuplesExpr :: CheckNode Expr +chkUnboxedTuplesExpr = conditional chkUnboxedTuplesExpr' UnboxedTuples + +chkUnboxedTuplesPat :: CheckNode Pattern +chkUnboxedTuplesPat = conditional chkUnboxedTuplesPat' UnboxedTuples + +chkUnboxedTuplesType :: CheckNode Type +chkUnboxedTuplesType = conditional chkUnboxedTuplesType' UnboxedTuples + + +chkUnboxedTuplesExpr' :: CheckNode Expr +chkUnboxedTuplesExpr' e@(UnboxedTuple _) = addOccurence UnboxedTuples e +chkUnboxedTuplesExpr' e@(UnboxedTupleSection _) = addOccurence UnboxedTuples e +chkUnboxedTuplesExpr' e = return e + +chkUnboxedTuplesPat' :: CheckNode Pattern +chkUnboxedTuplesPat' p@(UnboxTuplePat _) = addOccurence UnboxedTuples p +chkUnboxedTuplesPat' p = return p + +chkUnboxedTuplesType' :: CheckNode Type +chkUnboxedTuplesType' t@(UnboxedTupleType _) = addOccurence UnboxedTuples t +chkUnboxedTuplesType' t = return t
@@ -0,0 +1,13 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ViewPatternsChecker where + +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +chkViewPatterns :: CheckNode Pattern +chkViewPatterns = conditional chkViewPatterns' ViewPatterns + +chkViewPatterns' :: CheckNode Pattern +chkViewPatterns' p@(ViewPat _ _) = addOccurence ViewPatterns p +chkViewPatterns' p = return p
@@ -0,0 +1,20 @@+{-# LANGUAGE DeriveFunctor #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMap where + +import Language.Haskell.TH.LanguageExtensions (Extension) +import SrcLoc (SrcSpan) + +import qualified Data.Map.Strict as SMap (Map) + + +infix 6 :||: +infix 7 :&&: + +data LogicalRelation a = LVar a + | Not (LogicalRelation a) + | LogicalRelation a :&&: LogicalRelation a + | LogicalRelation a :||: LogicalRelation a + deriving (Eq, Show, Functor, Ord) + +type ExtMap = SMap.Map (LogicalRelation Extension) [SrcSpan]
@@ -0,0 +1,92 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, RankNTypes, StandaloneDeriving, TypeFamilies, TypeSynonymInstances #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + ( module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMap + , module Language.Haskell.TH.LanguageExtensions + , module Control.Monad.State + , module Control.Monad.Reader + ) where + +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMap + +import GHC (SrcSpan(..), Ghc(..), runGhc) +import GHC.Paths ( libdir ) +import Language.Haskell.TH.LanguageExtensions +import SrcLoc (SrcSpan) + +import Control.Monad.Reader +import Control.Monad.State +import qualified Data.Map.Strict as SMap (Map(..), empty, insertWith) + + +{-# ANN module "HLint: ignore Use mappend" #-} +{-# ANN module "HLint: ignore Use import/export shortcut" #-} + +deriving instance Ord Extension +deriving instance Read Extension + + +-- how could I hide the tyvar a? +-- type Asd a = forall m . (MonadReader [Extension] m, MonadState ExtMap m, GhcMonad m) => m a + + +type ExtMonad = ReaderT [Extension] (StateT ExtMap Ghc) +type ExtDomain dom = (HasNameInfo dom) + +type CheckNode elem = forall dom . CheckNode' elem dom +type CheckNode' elem dom = ExtDomain dom => elem dom -> ExtMonad (elem dom) + +type CheckUNode uelem = forall dom . CheckUNode' uelem dom +type CheckUNode' uelem dom = ExtDomain dom => Ann uelem dom SrcTemplateStage -> ExtMonad (Ann uelem dom SrcTemplateStage) + +addOccurence' :: (Ord k, HasRange a) => + k -> a -> SMap.Map k [SrcSpan] -> SMap.Map k [SrcSpan] +addOccurence' key node = SMap.insertWith (++) key [getRange node] + +-- TODO: add isTurnedOn check +addOccurence_ :: (MonadState ExtMap m, HasRange node) => + Extension -> node -> m () +addOccurence_ extension element = modify $ addOccurence' (LVar extension) element + +addOccurence :: (MonadState ExtMap m, HasRange node) => + Extension -> node -> m node +addOccurence ext node = addOccurence_ ext node >> return node + +isTurnedOn :: Extension -> ExtMonad Bool +isTurnedOn ext = do + defaults <- ask + return $! ext `elem` defaults + +conditional :: (node -> ExtMonad node) -> + Extension -> + node -> + ExtMonad node +conditional checker ext = conditionalAny checker [ext] + +conditionalNot :: (node -> ExtMonad node) -> + Extension -> + node -> + ExtMonad node +conditionalNot checker ext node = do + b <-isTurnedOn ext + if b then return node else checker node + +conditionalAny :: (node -> ExtMonad node) -> + [Extension] -> + node -> + ExtMonad node +conditionalAny checker exts node = do + bs <- mapM isTurnedOn exts + if or bs then checker node else return node + +conditionalAdd :: HasRange node => Extension -> node -> ExtMonad node +conditionalAdd ext = conditional (addOccurence ext) ext + + +runExtMonadIO :: ExtMonad a -> IO a +runExtMonadIO = runGhc (Just libdir) . runExtMonadGHC + +runExtMonadGHC :: ExtMonad a -> Ghc a +runExtMonadGHC = liftM fst . flip runStateT SMap.empty . flip runReaderT []
@@ -0,0 +1,592 @@+{-# LANGUAGE FlexibleContexts, RankNTypes, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.TraverseAST + ( module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.TraverseAST + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + ) where + +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +import Language.Haskell.Tools.AST +import Language.Haskell.Tools.Refactor as Refact + +import Control.Reference ((!~), (&), (&+&)) + +{- + NOTE: We need Decl level checking for deriving clausese + in order to gain extra information from the newtype and data keywords. + + We need Decl level checking for instance heads, in order to distinguish + class instances from data and type family instances. +-} +chkDecl :: CheckNode Decl +chkDecl = chkFlexibleInstances >=> chkDerivings + +chkPattern :: CheckNode Pattern +chkPattern = chkBangPatterns + >=> chkViewPatterns + >=> chkUnboxedTuplesPat + +chkExpr :: CheckNode Expr +chkExpr = chkTupleSections + >=> chkUnboxedTuplesExpr + >=> chkLambdaCase + +chkType :: CheckNode Type +chkType = chkUnboxedTuplesType + +chkPatternField :: CheckNode PatternField +chkPatternField = chkRecordWildCardsPatField + +chkFieldUpdate :: CheckNode FieldUpdate +chkFieldUpdate = chkRecordWildCardsFieldUpdate + +chkPatternSynonym :: CheckNode PatternSynonym +chkPatternSynonym = chkPatternSynonymsSyn + +chkPatternSignature :: CheckNode PatternSignature +chkPatternSignature = chkPatternSynonymsTypeSig + +chkLiteral :: CheckNode Literal +chkLiteral = chkMagicHashLiteral + +chkNamePart :: CheckNode NamePart +chkNamePart = chkMagicHashNamePart + >=> chkTemplateHaskellhNamePart + +chkKind :: CheckNode Kind +chkKind = chkMagicHashKind + + +traverseModule :: CheckNode UnnamedModule +traverseModule = (modDecl & annList !~ traverseDecl) + >=> (modHead & annJust !~ traverseModuleHead) + -- more + +traverseModuleHead :: CheckNode ModuleHead +traverseModuleHead = mhExports & annJust !~ traverseExportSpecs + -- more + +traverseExportSpecs :: CheckNode ExportSpecs +traverseExportSpecs = espExports & annList !~ traverseExportSpec + +traverseExportSpec :: CheckNode ExportSpec +traverseExportSpec = exportDecl !~ traverseIESpec + +traverseIESpec :: CheckNode IESpec +traverseIESpec = (ieName !~ traverseName) + >=> (ieSubspec & annJust !~ traverseSubSpec) + +traverseSubSpec :: CheckNode SubSpec +traverseSubSpec = essList & annList !~ traverseName + +traverseDecl :: CheckNode Decl +traverseDecl = chkDecl + >=> (declValBind !~ traverseValueBind) + >=> (declBody & annJust !~ traverseClassBody) + >=> (declSplice !~ traverseSplice) + >=> (innerType !~ traverseType) + >=> (declTypeSig !~ traverseTypeSignature) + >=> (declTypeFamily !~ traverseTypeFamily) -- + >=> (declSpec & annJust !~ traverseTypeFamilySpec) + >=> (declSafety & annJust !~ traverseSafety) + >=> (declRoles & annList !~ traverseRole) + >=> (declPragma !~ traverseTopLevelPragma) + >=> (declPatTypeSig !~ traversePatternSignature) + >=> (declPatSyn !~ traversePatternSynonym) + >=> (declOverlap & annJust !~ traverseOverlapPragma) + >=> (declKind & annJust !~ traverseKindContraint) + >=> (innerInstanceRule !~ traverseInstanceRule) + >=> (declInstDecl & annJust !~ traverseInstBody) + >=> (declHead !~ traverseDeclHead) + >=> (declGadt & annList !~ traverseGadtConDecl) + >=> (declFunDeps & annJust !~ traverseFunDeps) + >=> (declForeignType !~ traverseType) + >=> (declFixity !~ traverseFixitySignature) + >=> (declDeriving & annList !~ traverseDeriving) + >=> (declDecl & annList !~ traverseTypeEqn) + >=> (declCtx & annJust !~ traverseContext) + >=> (declCons & annList !~ traverseConDecl) + >=> (declCallConv !~ traverseCallConv) + >=> (declName !~ traverseName) + >=> (declRoleType !~ traverseQualifiedName) + + where innerType = (declTypes & annList) + &+& declType + &+& declAssignedType + + innerInstanceRule = declInstance &+& declInstRule + +traverseTypeFamily :: CheckNode TypeFamily +traverseTypeFamily = (tfHead !~ traverseDeclHead) + >=> (tfSpec & annJust !~ traverseTypeFamilySpec) + >=> (tfKind & annJust !~ traverseKindContraint) + +-- tfTypeVar is from 0.9 +traverseTypeFamilySpec :: CheckNode TypeFamilySpec +traverseTypeFamilySpec = (tfSpecKind !~ traverseKindContraint) + -- >=> (tfTypeVar !~ traverseTyVar) + >=> (tfInjectivity !~ traverseInjectivityAnn) + +traverseInjectivityAnn :: CheckNode InjectivityAnn +traverseInjectivityAnn = (injAnnRes !~ traverseTyVar) + >=> (injAnnDeps & annList !~ traverseName) + +-- DONE +traverseSafety :: CheckNode Safety +traverseSafety = return + +-- DONE +traverseRole :: CheckNode Role +traverseRole = return + +traverseTopLevelPragma :: CheckNode TopLevelPragma +traverseTopLevelPragma = (pragmaRule & annList !~ traverseRule) + >=> (pragmaObjects & annList !~ traverseName) + >=> (annotationSubject !~ traverseAnnotationSubject) + >=> (pragmaInline !~ traverseInlinePragma) + >=> (specializePragma !~ traverseSpecializePragma) + +-- no references for this +traverseSpecializePragma :: CheckUNode USpecializePragma +traverseSpecializePragma = return {- (specializeDef !~ traverseName) + >=> (specializeType & annList !~ traverseType) -} + +traverseAnnotationSubject :: CheckNode AnnotationSubject +traverseAnnotationSubject = annotateName !~ traverseName + +traverseRule :: CheckNode Rule +traverseRule = (ruleBounded & annList !~ traverseRuleVar) + >=> (innerExpr !~ traverseExpr) + -- some more + + where innerExpr = ruleLhs &+& ruleRhs + +traverseRuleVar :: CheckNode RuleVar +traverseRuleVar = (ruleVarName !~ traverseName) + >=> (ruleVarType !~ traverseType) + +traversePatternSignature :: CheckNode PatternSignature +traversePatternSignature = chkPatternSignature + >=> (patSigName & annList !~ traverseName) + >=> (patSigType !~ traverseType) + +-- DONE +traverseOverlapPragma :: CheckNode OverlapPragma +traverseOverlapPragma = return + +-- weird structure of nodes (Maybe (Ann AnnListG dom stage)) +traverseInstanceRule :: CheckNode InstanceRule +traverseInstanceRule = (irVars & annJust & element & annList !~ traverseTyVar) + >=> (irCtx & annJust !~ traverseContext) + >=> (irHead !~ traverseInstanceHead) + +traverseInstanceHead :: CheckNode InstanceHead +traverseInstanceHead = (ihConName !~ traverseName) + >=> (ihOperator !~ traverseOperator) + >=> (innerType !~ traverseType) + >=> (innerIHead !~ traverseInstanceHead) + + where innerType = ihLeftOp &+& ihType + innerIHead = ihHead &+& ihFun + +traverseDeclHead :: CheckNode DeclHead +traverseDeclHead = (dhName !~ traverseName) + >=> (dhOperator !~ traverseOperator) + >=> (innerDHead !~ traverseDeclHead) + >=> (innerTyVar !~ traverseTyVar) + + where innerDHead = dhBody &+& dhAppFun + innerTyVar = dhAppOperand &+& dhLeft &+& dhRight + +traverseGadtConDecl :: CheckNode GadtConDecl +traverseGadtConDecl = (gadtConNames & annList !~ traverseName) + >=> (gadtConTypeArgs & annList !~ traverseTyVar) + >=> (gadtConTypeCtx & annJust !~ traverseContext) + >=> (gadtConType !~ traverseGadtConType) + +traverseGadtConType :: CheckNode GadtConType +traverseGadtConType = (innerType !~ traverseType) + >=> (gadtConRecordFields & annList !~ traverseFieldDecl) + + where innerType = gadtConNormalType &+& gadtConResultType + +traverseFieldDecl :: CheckNode FieldDecl +traverseFieldDecl = (fieldNames & annList !~ traverseName) + >=> (fieldType !~ traverseType) + +traverseFunDeps :: CheckNode FunDeps +traverseFunDeps = funDeps & annList !~ traverseFunDep + +traverseFunDep :: CheckNode FunDep +traverseFunDep = innerName !~ traverseName + where innerName = (funDepLhs & annList) &+& (funDepRhs & annList) + +traverseDeriving :: CheckNode Deriving +traverseDeriving = innerIHead !~ traverseInstanceHead + where innerIHead = oneDerived &+& (allDerived & annList) + +traverseConDecl :: CheckNode ConDecl +traverseConDecl = (conTypeArgs & annList !~ traverseTyVar) + >=> (conTypeCtx & annJust !~ traverseContext) + >=> (conDeclName !~ traverseName) + >=> (innerType !~ traverseType) + >=> (conDeclFields & annList !~ traverseFieldDecl) + + where innerType = (conDeclArgs & annList) + &+& conDeclLhs + &+& conDeclRhs + +-- DONE +traverseCallConv :: CheckNode CallConv +traverseCallConv = return + +traverseMinimalFormula :: CheckNode MinimalFormula +traverseMinimalFormula = (minimalName !~ traverseName) + >=> (innerFormula !~ traverseMinimalFormula) + + where innerFormula = minimalInner + &+& (minimalOrs & annList) + &+& (minimalAnds & annList) + +-- there is no wrapper type for InlinePragma +-- no references generated +traverseInlinePragma :: CheckUNode UInlinePragma +traverseInlinePragma = return {- nnerName !~ traverseName + where innerName = inlineDef &+& noInlineDef &+& inlinableDef -} + + + + +traversePatternSynonym :: CheckNode PatternSynonym +traversePatternSynonym = chkPatternSynonym + >=> (patRhs !~ traverseInnerRhs) + >=> (patLhs !~ traverseInnerLhs) + + where traverseInnerRhs = (patRhsPat !~ traversePattern) + >=> (patRhsOpposite & annJust & patOpposite & annList !~ traverseMatch) + + traverseInnerLhs = (innerName !~ traverseName) + >=> (patSynOp !~ traverseOperator) + + innerName = patName &+& (patArgs & annList) &+& patSynLhs &+& patSynRhs + + + +traverseMatch :: CheckNode Match +traverseMatch = (matchLhs !~ traverseMatchLhs) + >=> (matchRhs !~ traverseRhs) + >=> (matchBinds & annJust !~ traverseLocalBinds) + +traverseMatchLhs :: CheckNode MatchLhs +traverseMatchLhs = (matchLhsName !~ traverseName) + >=> (matchLhsOperator !~ traverseOperator) + >=> (innerPattern !~ traversePattern) + + where innerPattern = matchLhsArgs & annList + &+& matchLhsLhs + &+& matchLhsRhs + +traverseRhs :: CheckNode Rhs +traverseRhs = (rhsExpr !~ traverseExpr) + >=> (rhsGuards & annList !~ traverseGuardedRhs) + +traverseGuardedRhs :: CheckNode GuardedRhs +traverseGuardedRhs = (guardStmts & annList !~ traverseRhsGuard) + >=> (guardExpr !~ traverseExpr) + +traverseRhsGuard :: CheckNode RhsGuard +traverseRhsGuard = (guardPat !~ traversePattern) + >=> (guardRhs &+& guardCheck !~ traverseExpr) + >=> (guardBinds & annList !~ traverseLocalBind) + +traverseLocalBinds :: CheckNode LocalBinds +traverseLocalBinds = localBinds & annList !~ traverseLocalBind + +traverseLocalBind :: CheckNode LocalBind +traverseLocalBind = (localVal !~ traverseValueBind) + >=> (localSig !~ traverseTypeSignature) + >=> (localFixity !~ traverseFixitySignature) + -- >=> (localInline !~ ...) + + +traverseInstBody :: CheckNode InstBody +traverseInstBody = instBodyDecls & annList !~ traverseInstBodyDecl + +traverseInstBodyDecl :: CheckNode InstBodyDecl +traverseInstBodyDecl = (instBodyDeclFunbind !~ traverseValueBind) + >=> (instBodyTypeSig !~ traverseTypeSignature) + >=> (instBodyTypeEqn !~ traverseTypeEqn) + >=> (specializeInstanceType !~ traverseType) + -- and many more ... + +traverseTypeEqn :: CheckNode TypeEqn +traverseTypeEqn = teLhs &+& teRhs !~ traverseType + +traverseClassBody :: CheckNode ClassBody +traverseClassBody = cbElements & annList !~ traverseClassElem + +traverseClassElem :: CheckNode ClassElement +traverseClassElem = (ceTypeSig !~ traverseTypeSignature) + >=> (clsFixity !~ traverseFixitySignature) + >=> (ceBind !~ traverseValueBind) + >=> (ceName !~ traverseName) + >=> (ceKind &+& ceType !~ traverseType) + + -- some more, but are not important + + +traverseValueBind :: CheckNode ValueBind +traverseValueBind = (valBindPat !~ traversePattern) + >=> (valBindRhs !~ traverseRhs) + >=> (valBindLocals & annJust !~ traverseLocalBinds) + >=> (funBindMatches & annList !~ traverseMatch) + + +traversePattern :: CheckNode Pattern +traversePattern = chkPattern + >=> (innerPattern !~ traversePattern) + >=> (innerLiteral !~ traverseLiteral) + >=> (patternOperator !~ traverseOperator) + >=> (patternFields & annList !~ traversePatternField) + >=> (patternName !~ traverseName) + >=> (patternExpr !~ traverseExpr) + >=> (patternType !~ traverseType) + >=> (patternSplice !~ traverseSplice) + >=> (patQQ !~ traverseQuasiQuote) + + where + innerPattern = patternLhs + &+& patternRhs + &+& patternInner + &+& (patternElems & annList) + &+& (patternArgs & annList) + + innerLiteral = patternLiteral &+& patternLit + +traversePatternField :: CheckNode PatternField +traversePatternField = chkPatternField + >=> (fieldPatternName !~ traverseName) + >=> (fieldPattern !~ traversePattern) + +-- TODO: TemplateHaskell? +traverseExpr :: CheckNode Expr +traverseExpr = chkExpr + >=> (innerExpressions !~ traverseExpr) + >=> (innerPatterns !~ traversePattern) + >=> (exprFunBind & annList !~ traverseLocalBind) + >=> (exprIfAlts & annList !~ traverseGuardedCaseRhs traverseExpr) + >=> (exprAlts & annList !~ traverseAlt traverseExpr) + >=> (exprOperator !~ traverseOperator) + >=> (exprLit !~ traverseLiteral) + >=> (innerNames !~ traverseName) + >=> (exprStmts & annList !~ traverseStmt traverseExpr) + >=> (tupleSectionElems & annList !~ traverseTupSecElem) + >=> (exprRecFields & annList !~ traverseFieldUpdate) + >=> (compBody & annList !~ traverseListCompBody) + >=> (innerTypes !~ traverseType) + >=> (exprSplice !~ traverseSplice) + >=> (exprBracket !~ traverseBracket) + >=> (exprQQ !~ traverseQuasiQuote) + + where innerExpressions = (tupleElems & annList) + &+& (listElems & annList) + &+& innerExpr + &+& exprCond + &+& exprThen + &+& exprElse + &+& exprRhs + &+& exprLhs + &+& exprInner + &+& exprFun + &+& exprCase + &+& exprArg + &+& enumToFix + &+& (enumTo & annJust) + &+& (enumThen & annJust) + &+& Refact.enumFrom + &+& compExpr + + innerPatterns = (exprBindings & annList) &+& procPattern + innerNames = exprName &+& exprRecName &+& quotedName + innerTypes = exprSig &+& exprType + +-- These types are needed to generalize AST traversal for polymorphic nodes. +-- These nodes are polymorphic in their inner nodes, which can be any "UNodes" +-- (UType. UExpr, UDecl etc ...) +type AltG uexpr dom = Ann (UAlt' uexpr) dom SrcTemplateStage +type StmtG uexpr dom = Ann (UStmt' uexpr) dom SrcTemplateStage +type CaseRhsG uexpr dom = Ann (UCaseRhs' uexpr) dom SrcTemplateStage +type GuardedCaseRhsG uexpr dom = Ann (UGuardedCaseRhs' uexpr) dom SrcTemplateStage + +type PromotedG t dom = Ann (UPromoted t) dom SrcTemplateStage + +traverseAlt :: CheckUNode uexpr -> CheckNode (AltG uexpr) +traverseAlt f = (altPattern !~ traversePattern) + >=> (altRhs !~ traverseCaseRhs f) + >=> (altBinds & annJust !~ traverseLocalBinds) + +traverseCaseRhs :: CheckUNode uexpr -> CheckNode (CaseRhsG uexpr) +traverseCaseRhs f = (rhsCaseExpr !~ f) + >=> (rhsCaseGuards & annList !~ traverseGuardedCaseRhs f) + +traverseGuardedCaseRhs :: CheckUNode uexpr -> CheckNode (GuardedCaseRhsG uexpr) +traverseGuardedCaseRhs f = (caseGuardStmts & annList !~ traverseRhsGuard) + >=> (caseGuardExpr !~ f) + +traverseStmt :: CheckUNode uexpr -> CheckNode (StmtG uexpr) +traverseStmt f = (stmtPattern !~ traversePattern) + >=> (stmtExpr !~ f) + >=> (stmtBinds & annList !~ traverseLocalBind) + >=> (cmdStmtBinds & annList !~ traverseStmt f) + +traversePromoted :: CheckUNode t -> CheckNode (PromotedG t) +traversePromoted f = (promotedConName !~ traverseName) + >=> (promotedElements & annList !~ f) + +traverseTupSecElem :: CheckNode TupSecElem +traverseTupSecElem = tupSecExpr !~ traverseExpr + +traverseFieldUpdate :: CheckNode FieldUpdate +traverseFieldUpdate = chkFieldUpdate + >=> (fieldName &+& fieldUpdateName !~ traverseName) + >=> (fieldValue !~ traverseExpr) + +traverseListCompBody :: CheckNode ListCompBody +traverseListCompBody = compStmts & annList !~ traverseCompStmt + +traverseCompStmt :: CheckNode CompStmt +traverseCompStmt = (compStmt !~ traverseStmt traverseExpr) + >=> (innerExpressions !~ traverseExpr) + + where innerExpressions = thenExpr + &+& (byExpr & annJust) + &+& (usingExpr & annJust) + +traverseCmd :: CheckNode Cmd +traverseCmd = return +{- + +References are not generated for UCmd + +traverseCmd = (innerExpressions !~ traverseExpr) + >=> (innerCmds !~ traverseCmd) + >=> (cmdStmtBinds & annList !~ traversePattern) + >=> (cmdBinds & annList !~ traverseLocalBind) + >=> (cmdAlts & annList !~ traverseAlt traverseCmd) + >=> (cmdStmts & annList !~ traverseStmt traverseCmd) + where innerExpressions = cmdLhs &+& cmdRhs &+& cmdExpr &+& cmdApplied + + innerCmds = (cmdInnerCmds & annList) + &+& cmdInnerCmd + &+& cmdLeftCmd + &+& cmdRightCmd + &+& cmdInner + &+& cmdThen + &+& cmdElse +-} + +traverseSplice :: CheckNode Splice +traverseSplice = chkTemplateHaskellSplice + >=> (spliceId !~ traverseName) + >=> (spliceExpr !~ traverseExpr) + +traverseBracket :: CheckNode Bracket +traverseBracket = chkTemplateHaskellBracket + >=> (bracketExpr !~ traverseExpr) + >=> (bracketPattern !~ traversePattern) + >=> (bracketType !~ traverseType) + >=> (bracketDecl & annList !~ traverseDecl) + +traverseQuasiQuote :: CheckNode QuasiQuote +traverseQuasiQuote = chkTemplateHaskellQuasiQuote + >=> (qqExprName !~ traverseName) + +traverseType :: CheckNode Type +traverseType = chkType + >=> (typeBounded & annList !~ traverseTyVar) + >=> (innerType !~ traverseType) + >=> (innerName !~ traverseName) + >=> (typeCtx !~ traverseContext) + >=> (typeOperator !~ traverseOperator) + >=> (typeKind !~ traverseKind) + >=> (tpPromoted !~ traversePromoted traverseType) + >=> (tsSplice !~ traverseSplice) + >=> (typeQQ !~ traverseQuasiQuote) + + where innerType = typeType + &+& typeParam + &+& typeResult + &+& (typeElements & annList) + &+& typeElement + &+& typeCon + &+& typeArg + &+& typeInner + &+& typeLeft + &+& typeRight + + innerName = typeName &+& typeWildcardName + +traverseTyVar :: CheckNode TyVar +traverseTyVar = (tyVarName !~ traverseName) + >=> (tyVarKind & annJust !~ traverseKindContraint) + +traverseKindContraint :: CheckNode KindConstraint +traverseKindContraint = kindConstr !~ traverseKind + +traverseKind :: CheckNode Kind +traverseKind = chkKind + >=> (innerKind !~ traverseKind) + >=> (kindVar !~ traverseName) + >=> (kindAppOp !~ traverseOperator) + >=> (kindPromoted !~ traversePromoted traverseKind) + + where innerKind = kindLeft + &+& kindRight + &+& kindParen + &+& kindAppFun + &+& kindAppArg + &+& kindLhs + &+& kindRhs + &+& kindElem + &+& (kindElems & annList) + +traverseContext :: CheckNode Context +traverseContext = contextAssertion !~ traverseAssertion + +traverseAssertion :: CheckNode Assertion +traverseAssertion = (innerType !~ traverseType) + >=> (innerName !~ traverseName) + >=> (assertOp !~ traverseOperator) + >=> (innerAsserts & annList !~ traverseAssertion) + + where innerType = (assertTypes & annList) + &+& assertLhs + &+& assertRhs + &+& assertImplType + + innerName = assertClsName &+& assertImplVar + +traverseName :: CheckNode Name +traverseName = simpleName !~ traverseQualifiedName + +traverseQualifiedName :: CheckNode QualifiedName +traverseQualifiedName = unqualifiedName !~ traverseNamePart + >=> qualifiers & annList !~ traverseNamePart + +traverseNamePart :: CheckNode NamePart +traverseNamePart = chkNamePart + +traverseLiteral :: CheckNode Literal +traverseLiteral = chkLiteral + +traverseOperator :: CheckNode Operator +traverseOperator = operatorName !~ traverseQualifiedName + +traverseTypeSignature :: CheckNode TypeSignature +traverseTypeSignature = (tsName & annList !~ traverseName) + >=> (tsType !~ traverseType) + +traverseFixitySignature :: CheckNode FixitySignature +traverseFixitySignature = fixityOperators & annList !~ traverseOperator
@@ -0,0 +1,28 @@+module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.SupportedExtensions where + +import Language.Haskell.TH.LanguageExtensions (Extension(..)) + +unregularExts :: String -> String +unregularExts "CPP" = "Cpp" +unregularExts "NamedFieldPuns" = "RecordPuns" +unregularExts "GeneralisedNewtypeDeriving" = "GeneralizedNewtypeDeriving" +unregularExts e = e + +isSupported :: Extension -> Bool +isSupported = flip elem fullyHandledExtensions + +fullyHandledExtensions :: [Extension] +fullyHandledExtensions = syntacticExtensions + ++ derivingExtensions + -- ++ [FlexibleInstances] + +syntacticExtensions :: [Extension] +syntacticExtensions = [ RecordWildCards, TemplateHaskell, BangPatterns + , PatternSynonyms, TupleSections, LambdaCase, QuasiQuotes + , ViewPatterns, MagicHash, UnboxedTuples] + +derivingExtensions :: [Extension] +derivingExtensions = [ DeriveDataTypeable, DeriveGeneric, DeriveFunctor + , DeriveFoldable, DeriveTraversable, DeriveLift + , DeriveAnyClass, GeneralizedNewtypeDeriving + , StandaloneDeriving, DerivingStrategies ]
@@ -0,0 +1,82 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-} + +module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.TypeLookup where + + +import Language.Haskell.Tools.AST (HasNameInfo'(..), HasNameInfo(..), simpleName) +import Language.Haskell.Tools.Refactor +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + +import Control.Monad.Trans.Maybe (MaybeT(..)) +import Control.Reference ((^.)) + +import qualified GHC +import qualified TyCoRep as GHC (Type(..), TyThing(..)) + + +chkSynonym :: CheckNode Type +chkSynonym t = do + mtycon <- runMaybeT . lookupType $ t + case mtycon of + Nothing -> return t + Just tycon -> chkSynonym' tycon + where chkSynonym' x = case lookupSynDef x of + Nothing -> return t + Just _ -> addOccurence TypeSynonymInstances t + +lookupSynDefM :: HasNameInfo dom => Type dom -> MaybeT ExtMonad GHC.TyCon +lookupSynDefM t = do + tything <- lookupType t + liftMaybe $ lookupSynDef tything + where liftMaybe = MaybeT . return + +-- NOTE: Returns Nothing if it is not a type synonym +-- (or has some weird structure I didn't think of) +lookupSynDef :: GHC.TyThing -> Maybe GHC.TyCon +lookupSynDef syn = do + tycon <- tyconFromTyThing syn + rhs <- GHC.synTyConRhs_maybe tycon + tyconFromGHCType rhs + +tyconFromTyThing :: GHC.TyThing -> Maybe GHC.TyCon +tyconFromTyThing (GHC.ATyCon tycon) = Just tycon +tyconFromTyThing _ = Nothing + +-- won't bother +tyconFromGHCType :: GHC.Type -> Maybe GHC.TyCon +tyconFromGHCType (GHC.AppTy t1 _) = tyconFromGHCType t1 +tyconFromGHCType (GHC.TyConApp tycon _) = Just tycon +tyconFromGHCType _ = Nothing + + +-- NOTE: Return false if the type is certainly not a newtype +-- Returns true if it is a newtype or it could not have been looked up +isNewtype :: HasNameInfo dom => Type dom -> ExtMonad Bool +isNewtype t = do + tycon <- runMaybeT . lookupType $ t + return $! maybe True isNewtypeTyCon tycon + + + +lookupType :: HasNameInfo dom => Type dom -> MaybeT ExtMonad GHC.TyThing +lookupType t = do + name <- liftMaybe . nameFromType $ t + sname <- liftMaybe . getSemName $ name + MaybeT . GHC.lookupName $ sname + where liftMaybe = MaybeT . return + +-- NOTE: gives just name if the type being scrutinised can be newtype +-- else it gives nothing +nameFromType :: Type dom -> Maybe (Name dom) +nameFromType (TypeApp f _) = nameFromType f +nameFromType (ParenType x) = nameFromType x +nameFromType (KindedType t _) = nameFromType t +nameFromType (VarType x) = Just x +nameFromType _ = Nothing + +isNewtypeTyCon :: GHC.TyThing -> Bool +isNewtypeTyCon (GHC.ATyCon tycon) = GHC.isNewTyCon tycon +isNewtypeTyCon _ = False + +getSemName :: HasNameInfo dom => Name dom -> Maybe GHC.Name +getSemName x = semanticsName (x ^. simpleName)
@@ -0,0 +1,228 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, MultiWayIf, RankNTypes, ScopedTypeVariables, TypeApplications, TypeFamilies, ViewPatterns #-} +module Language.Haskell.Tools.Refactor.Builtin.ExtractBinding + (extractBinding', ExtractBindingDomain, tryItOut, extractBindingRefactoring) where + +import qualified GHC +import Name (nameModule_maybe) +import qualified OccName as GHC (occNameString) +import OccName (HasOccName(..)) +import PrelNames +import RdrName (isOrig_maybe) +import SrcLoc + +import Control.Monad.State +import Control.Reference +import Data.Generics.Uniplate.Data () +import Data.List (find, intersperse) +import Data.Maybe + +import Language.Haskell.Tools.Refactor + + +extractBindingRefactoring :: (ExtractBindingDomain dom, HasModuleInfo dom) => RefactoringChoice dom +extractBindingRefactoring = NamingRefactoring "ExtractBinding" (\loc s -> localRefactoring (extractBinding' loc s)) + +-- | We need name information to identify bindings, and scope information to check which +-- entities must be directly passed as parameters. +type ExtractBindingDomain dom = ( HasNameInfo dom, HasDefiningInfo dom, HasScopeInfo dom ) + +tryItOut :: String -> String -> String -> IO () +tryItOut mod sp name = tryRefactor (localRefactoring . flip extractBinding' name) mod sp + +extractBinding' :: ExtractBindingDomain dom => RealSrcSpan -> String -> LocalRefactoring dom +extractBinding' sp name mod + = if isNothing (isValidBindingName name) + then extractBinding sp (nodesContaining sp) (nodesContaining sp) name mod + else refactError $ "The given name is not a valid for the extracted binding: " ++ fromJust (isValidBindingName name) + +-- | Safely performs the transformation to introduce the local binding and replace the expression with the call. +-- Checks if the introduction of the name causes a name conflict. +extractBinding :: forall dom . ExtractBindingDomain dom + => RealSrcSpan -> Simple Traversal (Module dom) (ValueBind dom) + -> Simple Traversal (ValueBind dom) (Expr dom) + -> String -> LocalRefactoring dom +extractBinding sp selectDecl selectExpr name mod + = let conflicting = filter (isConflicting name) ((take 1 $ reverse $ mod ^? selectDecl) ^? biplateRef :: [QualifiedName dom]) + exprRanges = map getRange (mod ^? selectDecl & selectExpr) + decl = last (mod ^? selectDecl) + declPats = decl ^? valBindPat &+& funBindMatches & annList & matchLhs + & (matchLhsArgs & annList &+& matchLhsLhs &+& matchLhsRhs &+& matchLhsArgs & annList) + in case exprRanges of + (reverse -> exprRange:_) -> + if | not (null conflicting) + -> refactError $ "The given name causes name conflict with the definition(s) at: " ++ concat (intersperse "," (map (shortShowSpanWithFile . getRange) conflicting)) + | any (`containsRange` exprRange) $ map getRange declPats + -> refactError "Extract binding cannot be applied to view pattern expressions." + | otherwise + -> case decl ^? actualContainingExpr exprRange of + expr:_ -> do (res, st) <- runStateT (selectDecl&selectExpr !~ extractThatBind sp name expr $ mod) Nothing + case st of Just def -> return $ evalState (selectDecl !~ addLocalBinding exprRange def $ res) False + Nothing -> refactError "There is no applicable expression to extract." + [] -> refactError $ "There is no applicable expression to extract." + [] -> refactError "There is no applicable expression to extract." + where RealSrcSpan sp1 `containsRange` RealSrcSpan sp2 = sp1 `containsSpan` sp2 + _ `containsRange` _ = False + +-- | Decides if a new name defined to be the given string will conflict with the given AST element +isConflicting :: ExtractBindingDomain dom => String -> QualifiedName dom -> Bool +isConflicting name used + = semanticsDefining used + && (GHC.occNameString . GHC.getOccName <$> semanticsName used) == Just name + +-- Replaces the selected expression with a call and generates the called binding. +extractThatBind :: ExtractBindingDomain dom + => RealSrcSpan -> String -> Expr dom -> Expr dom -> StateT (Maybe (ValueBind dom)) (LocalRefactor dom) (Expr dom) +extractThatBind sp name cont e + = do ret <- get -- being in a state monad to only apply the + if (isJust ret) then return e + else case e of + -- only the expression inside the parameters should be extracted + Paren {} | hasParameter -> exprInner !~ doExtract name cont $ e + | otherwise -> doExtract name cont (fromJust $ e ^? exprInner) + -- a single variable cannot be extracted (would lead to precedence problems) + Var {} -> lift $ refactError "The selected expression is too simple to be extracted." + -- extract operator sections + InfixApp lhs op rhs + | (lhs `outside` sp) && (sp `encloses` op) && (sp `encloses` rhs) + -> do let params = getExternalBinds cont rhs ++ opName op + put (Just (generateBind name (map mkVarPat params) (mkRightSection op (parenIfInfix rhs)))) + return (mkApp (generateCall name params) (parenIfInfix lhs)) + | (sp `encloses` lhs) && (sp `encloses` op) && (rhs `outside` sp) + -> do let params = getExternalBinds cont lhs ++ opName op + put (Just (generateBind name (map mkVarPat params) (mkLeftSection (parenIfInfix lhs) op))) + return (mkApp (generateCall name params) (parenIfInfix rhs)) + where parenIfInfix e@(InfixApp {}) = mkParen e + parenIfInfix e = e + -- extract parts of known associative infix operators + InfixApp (InfixApp lhs lop mid) rop rhs -- correction for left-associative operators + | (Just lName, Just rName) <- (semanticsName (lop ^. operatorName), semanticsName (rop ^. operatorName)) + , (lop `outside` sp) && (sp `encloses` mid) && (sp `encloses` rhs) + && lName == rName && isKnownCommutativeOp lName + -> do let params = getExternalBinds cont mid ++ opName rop ++ getExternalBinds cont rhs + put (Just (generateBind name (map mkVarPat params) (mkInfixApp mid rop rhs))) + return (mkInfixApp lhs lop (generateCall name params)) + InfixApp lhs lop (InfixApp mid rop rhs) -- correction for right-associative operators + | (Just lName, Just rName) <- (semanticsName (lop ^. operatorName), semanticsName (rop ^. operatorName)) + , (sp `encloses` lhs) && (sp `encloses` mid) && (rop `outside` sp) + && lName == rName && isKnownCommutativeOp lName + -> do let params = getExternalBinds cont lhs ++ opName lop ++ getExternalBinds cont mid + put (Just (generateBind name (map mkVarPat params) (mkInfixApp lhs lop mid))) + return (mkInfixApp (generateCall name params) rop rhs) + -- normal case + el | isParenLikeExpr el && hasParameter -> mkParen <$> doExtract name cont e + | otherwise -> doExtract name cont e + where hasParameter = not (null (getExternalBinds cont e)) + -- True if the elem is completely inside the given source range + sp `encloses` elem = case getRange elem of RealSrcSpan enc -> sp `containsSpan` enc + _ -> False + -- True if the elem is completely outside the given range (no overlapping) + elem `outside` sp = case getRange elem of RealSrcSpan out -> realSrcSpanStart sp > realSrcSpanEnd out + || realSrcSpanEnd sp < realSrcSpanStart out + _ -> False + opName op = case semanticsName (op ^. operatorName) of + Nothing -> [] + Just n -> [mkUnqualName' n | not $ n `inScope` semanticsScope cont] + isKnownCommutativeOp :: GHC.Name -> Bool + isKnownCommutativeOp n = isJust $ find (maybe False (\(mn, occ) -> (nameModule_maybe n) == Just mn && occName n == occ) . isOrig_maybe) ops + where ops = [plus_RDR, times_RDR, append_RDR, and_RDR, {- or_RDR, -} compose_RDR] -- somehow or is missing... WHY? + +-- | Adds a local binding to the where clause of the enclosing binding +addLocalBinding :: SrcSpan -> ValueBind dom -> ValueBind dom -> State Bool (ValueBind dom) +-- this uses the state monad to only add the local binding to the first selected element +addLocalBinding exprRange local bind + = do done <- get + if not done then do put True + return $ indentBody $ doAddBinding exprRange local bind + else return bind + where + doAddBinding _ local sb@(SimpleBind {}) = valBindLocals .- insertLocalBind local $ sb + doAddBinding (RealSrcSpan rng) local fb@(FunctionBind {}) + = funBindMatches & annList & filtered (isInside rng) & matchBinds + .- insertLocalBind local $ fb + doAddBinding _ _ _ = error "doAddBinding: invalid expression range" + + indentBody = (valBindRhs .- updIndent) . (funBindMatches & annList & matchLhs .- updIndent) . (funBindMatches & annList & matchRhs .- updIndent) + + updIndent :: SourceInfoTraversal elem => elem dom SrcTemplateStage -> elem dom SrcTemplateStage + updIndent = setMinimalIndent 4 + +-- | Puts a value definition into a list of local binds +insertLocalBind :: ValueBind dom -> MaybeLocalBinds dom -> MaybeLocalBinds dom +insertLocalBind toInsert locals + | isAnnNothing locals = mkLocalBinds [mkLocalValBind toInsert] + | otherwise = annJust & localBinds .- insertWhere True (mkLocalValBind toInsert) (const True) isNothing $ locals + +-- | All expressions that are bound stronger than function application. +isParenLikeExpr :: Expr dom -> Bool +isParenLikeExpr (If {}) = True +isParenLikeExpr (Paren {}) = True +isParenLikeExpr (List {}) = True +isParenLikeExpr (ParArray {}) = True +isParenLikeExpr (LeftSection {}) = True +isParenLikeExpr (RightSection {}) = True +isParenLikeExpr (RecCon {}) = True +isParenLikeExpr (RecUpdate {}) = True +isParenLikeExpr (Enum {}) = True +isParenLikeExpr (ParArrayEnum {}) = True +isParenLikeExpr (ListComp {}) = True +isParenLikeExpr (ParArrayComp {}) = True +isParenLikeExpr (BracketExpr {}) = True +isParenLikeExpr (SpliceExpr {}) = True +isParenLikeExpr (QuasiQuoteExpr {}) = True +isParenLikeExpr _ = False + +-- | Replaces the expression with the call and stores the binding of the call in its state +doExtract :: ExtractBindingDomain dom + => String -> Expr dom -> Expr dom -> StateT (Maybe (ValueBind dom)) (LocalRefactor dom) (Expr dom) +doExtract name cont e@(Lambda (AnnList bindings) inner) + = do let params = getExternalBinds cont e + put (Just (generateBind name (map mkVarPat params ++ bindings) inner)) + return (generateCall name params) +doExtract name cont e + = do let params = getExternalBinds cont e + put (Just (generateBind name (map mkVarPat params) e)) + return (generateCall name params) + +-- | Gets the values that have to be passed to the extracted definition +getExternalBinds :: ExtractBindingDomain dom => Expr dom -> Expr dom -> [Name dom] +getExternalBinds cont expr = map exprToName $ keepFirsts $ filter isApplicableName (expr ^? uniplateRef) + where isApplicableName (getExprNameInfo -> Just nm) = inScopeForOriginal nm && notInScopeForExtracted nm + isApplicableName _ = False + + getExprNameInfo :: ExtractBindingDomain dom => Expr dom -> Maybe GHC.Name + getExprNameInfo expr = semanticsName =<< (listToMaybe $ expr ^? (exprName&simpleName &+& exprOperator&operatorName)) + + -- | Creates the parameter value to pass the name (operators are passed in parentheses) + exprToName :: Expr dom -> Name dom + exprToName e | Just n <- e ^? exprName = n + | Just op <- e ^? exprOperator & operatorName = mkParenName op + | otherwise = error "exprToName: name not found" + + notInScopeForExtracted :: GHC.Name -> Bool + notInScopeForExtracted n = not $ n `inScope` semanticsScope cont + + inScopeForOriginal :: GHC.Name -> Bool + inScopeForOriginal n = n `inScope` semanticsScope expr + + keepFirsts (e:rest) = e : keepFirsts (filter (/= e) rest) + keepFirsts [] = [] + +actualContainingExpr :: SrcSpan -> Simple Traversal (ValueBind dom) (Expr dom) +actualContainingExpr (RealSrcSpan rng) = accessRhs & accessExpr + where accessRhs :: Simple Traversal (ValueBind dom) (Rhs dom) + accessRhs = valBindRhs &+& funBindMatches & annList & filtered (rng `isInside`) & matchRhs + accessExpr :: Simple Traversal (Rhs dom) (Expr dom) + accessExpr = rhsExpr &+& rhsGuards & annList & filtered (rng `isInside`) & guardExpr +actualContainingExpr _ = error "actualContainingExpr: not a real range" + +-- | Generates the expression that calls the local binding +generateCall :: String -> [Name dom] -> Expr dom +generateCall name args = foldl (\e a -> mkApp e (mkVar a)) (mkVar $ mkNormalName $ mkSimpleName name) args + +-- | Generates the local binding for the selected expression +generateBind :: String -> [Pattern dom] -> Expr dom -> ValueBind dom +generateBind name [] e = mkSimpleBind (mkVarPat $ mkNormalName $ mkSimpleName name) (mkUnguardedRhs e) Nothing +generateBind name args e = mkFunctionBind [mkMatch (mkMatchLhs (mkNormalName $ mkSimpleName name) args) (mkUnguardedRhs e) Nothing] + +isValidBindingName :: String -> Maybe String +isValidBindingName = nameValid Variable
@@ -0,0 +1,73 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, LambdaCase, ScopedTypeVariables, TypeApplications, TypeFamilies #-} +module Language.Haskell.Tools.Refactor.Builtin.FloatOut + (floatOut, FloatOutDefinition, floatOutRefactoring) where + +import Control.Monad.State +import Control.Reference +import Data.List +import Data.Maybe (Maybe(..), catMaybes) + +import Language.Haskell.Tools.Refactor + +import Name as GHC (Name, NamedThing(..), occNameString) +import SrcLoc (RealSrcSpan) + +floatOutRefactoring :: (FloatOutDefinition dom, HasModuleInfo dom) => RefactoringChoice dom +floatOutRefactoring = SelectionRefactoring "FloatOut" (localRefactoring . floatOut) + +type FloatOutDefinition dom = (HasNameInfo dom, HasScopeInfo dom) + +floatOut :: FloatOutDefinition dom => RealSrcSpan -> LocalRefactoring dom +floatOut sp mod + = do (mod', st) <- runStateT (nodesContaining sp !~ extractAndInsert sp $ mod) NotEncountered + case st of NotEncountered -> refactError "No definition is selected. The selection range must be inside the definition." + Extracted bnds -> -- insert it to the global definition list + return $ modDecl & annListElems .- (++ map toTopLevel bnds) $ removeEmpties mod' + Inserted -> -- already inserted to a local scope + return (removeEmpties mod') + where toTopLevel :: LocalBind dom -> Decl dom + toTopLevel (LocalValBind vb) = mkValueBinding vb + toTopLevel (LocalTypeSig sg) = mkTypeSigDecl sg + toTopLevel (LocalFixity fx) = mkFixityDecl fx + + removeEmpties = removeEmptyBnds (nodesContaining sp) (nodesContaining sp) + +data FloatState dom = NotEncountered | Extracted [LocalBind dom] | Inserted + +extractAndInsert :: FloatOutDefinition dom => RealSrcSpan -> LocalBindList dom -> StateT (FloatState dom) (LocalRefactor dom) (LocalBindList dom) +extractAndInsert sp locs + | hasSharedSig = refactError "Cannot float out a definition, since it has a signature shared with other bindings that stay in the scope." + | not (null nameConflicts) = refactError $ "Cannot float out a definition, since it would cause a name conflicts in the target scope: " + ++ concat (intersperse ", " nameConflicts) + | not (null implicitConflicts) = refactError $ "Cannot float out a definition, since it uses the implicit parameters: " + ++ concat (intersperse ", " implicitConflicts) + | otherwise = get >>= \case NotEncountered -> put (Extracted floated) >> return filteredLocs + Extracted binds -> put Inserted >> (return $ annListElems .- (++ binds) $ locs) + Inserted -> return locs + where selected = locs ^? annList & filtered (isInside sp) + floated = normalizeElements $ selected ++ (locs ^? annList & filtered (nameIsSelected . (^? elementName))) + where nameIsSelected [n] = n `elem` concatMap (^? elementName) selected + nameIsSelected _ = False + + filteredLocs = filterList (\e -> not (getRange e `elem` floatedElemRanges)) locs + where floatedElemRanges = map getRange floated + hasSharedSig = any (\e -> not $ null ((filteredLocs ^? annList & elementName) `intersect` (e ^? elementName))) selected + conflicts = map checkConflict selected + + nameConflicts = concat $ map fst conflicts + implicitConflicts = concat $ map snd conflicts + +checkConflict :: forall dom . FloatOutDefinition dom => LocalBind dom -> ([String], [String]) +checkConflict bnd = (concatMap @[] getConflict bndNames, implicits) + where bndNames = bnd ^? elementName + getConflict bndName = filter ((== nameStr) . Just) $ map (occNameString . getOccName) outerScope + where outerScope = map (^. _1) $ concat $ take 1 $ drop 2 $ semanticsScope bndName + nameStr = fmap (occNameString . getOccName) $ semanticsName bndName + implicits = map (occNameString . getOccName) + (concatMap getPossibleImplicits bndNames `intersect` getQNames (bnd ^? biplateRef)) + + getQNames :: [QualifiedName dom] -> [GHC.Name] + getQNames = catMaybes . map semanticsName + + getPossibleImplicits :: QualifiedName dom -> [GHC.Name] + getPossibleImplicits qn = concat (map (map (^. _1)) $ take 2 $ semanticsScope qn) \\ catMaybes (map semanticsName bndNames)
@@ -0,0 +1,40 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, LambdaCase, TupleSections, TypeFamilies #-} +module Language.Haskell.Tools.Refactor.Builtin.GenerateExports + (generateExports, DomGenerateExports, generateExportsRefactoring) where + +import Control.Reference ((^?), (.=), (&)) +import Language.Haskell.Tools.Refactor + +import qualified GHC (NamedThing(..), Name) + +import Control.Applicative ((<|>)) +import Data.Maybe (Maybe(..), catMaybes) + +generateExportsRefactoring :: (DomGenerateExports dom, HasModuleInfo dom) => RefactoringChoice dom +generateExportsRefactoring = ModuleRefactoring "GenerateExports" (localRefactoring generateExports) + +-- | We need name information to generate exports +type DomGenerateExports dom = (Domain dom, HasNameInfo dom) + +-- | Creates an export list that imports standalone top-level definitions with all of their contained definitions +generateExports :: DomGenerateExports dom => LocalRefactoring dom +generateExports mod = return (modHead & annJust & mhExports & annMaybe + .= Just (createExports (getTopLevels mod)) $ mod) + +-- | Get all the top-level definitions with flags that mark if they can contain other top-level definitions +-- (classes and data declarations). +getTopLevels :: DomGenerateExports dom => Module dom -> [(GHC.Name, Bool)] +getTopLevels mod = catMaybes $ map (\d -> fmap (,exportContainOthers d) + (foldl (<|>) Nothing $ map semanticsName $ d ^? elementName)) + (filter (\case TypeSigDecl{} -> False; _ -> True) + $ mod ^? modDecl & annList) + where exportContainOthers :: Decl dom -> Bool + exportContainOthers (DataDecl {}) = True + exportContainOthers (ClassDecl {}) = True + exportContainOthers _ = False + +-- | Create the export for a give name. +createExports :: [(GHC.Name, Bool)] -> ExportSpecs dom +createExports elems = mkExportSpecs $ map (mkExportSpec . createExport) elems + where createExport (n, False) = mkIESpec (mkUnqualName' (GHC.getName n)) Nothing + createExport (n, True) = mkIESpec (mkUnqualName' (GHC.getName n)) (Just mkSubAll)
@@ -0,0 +1,176 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, RankNTypes, ScopedTypeVariables, TupleSections, TypeApplications, TypeFamilies, ViewPatterns #-} +module Language.Haskell.Tools.Refactor.Builtin.GenerateTypeSignature + ( generateTypeSignature, generateTypeSignature', GenerateSignatureDomain, tryItOut + , generateTypeSignatureRefactoring) where + +import GHC hiding (Module) +import Id as GHC +import OccName as GHC (isSymOcc) +import Outputable as GHC (Outputable(..), showSDocUnsafe) +import TyCon as GHC (TyCon(..), isTupleTyCon) +import Type as GHC +import TysWiredIn as GHC (listTyCon, charTyCon) + +import Control.Monad +import Control.Monad.State +import Control.Reference +import Data.Generics.Uniplate.Data (universeBi) +import Data.List +import Data.Maybe (Maybe(..), catMaybes) + +import Language.Haskell.Tools.Refactor as AST + +type GenerateSignatureDomain dom = ( HasModuleInfo dom, HasIdInfo dom, HasImportInfo dom, HasScopeInfo dom ) + +generateTypeSignatureRefactoring :: GenerateSignatureDomain dom => RefactoringChoice dom +generateTypeSignatureRefactoring = SelectionRefactoring "GenerateSignature" (localRefactoring . generateTypeSignature') + +tryItOut :: String -> String -> IO () +tryItOut = tryRefactor (localRefactoring . generateTypeSignature') + +generateTypeSignature' :: GenerateSignatureDomain dom => RealSrcSpan -> LocalRefactoring dom +generateTypeSignature' sp = generateTypeSignature (nodesContaining sp) (nodesContaining sp) (getValBindInList sp) + +-- | Perform the refactoring on either local or top-level definition +generateTypeSignature :: GenerateSignatureDomain dom => Simple Traversal (Module dom) (DeclList dom) + -- ^ Access for a top-level definition if it is the selected definition + -> Simple Traversal (Module dom) (LocalBindList dom) + -- ^ Access for a definition list if it contains the selected definition + -> (forall d . (BindingElem d) => AnnList d dom -> Maybe (ValueBind dom)) + -- ^ Selector for either local or top-level declaration in the definition list + -> LocalRefactoring dom +generateTypeSignature topLevelRef localRef vbAccess mod + = let typeSigs = universeBi mod + bindings = universeBi mod + findTypeSigFor id = find (\ts -> any (id ==) $ map semanticsId (ts ^? tsName & annList & simpleName)) + bindsWithSigs = catMaybes $ concatMap (\b -> map (\n -> let id = semanticsId n in fmap (id,,b) (findTypeSigFor id typeSigs)) (b ^? bindingName)) bindings + scopedSigs = hasScopedTypeSignatures mod + in do (mod', done) <- flip runStateT False . + (topLevelRef !~ genTypeSig scopedSigs bindsWithSigs vbAccess + <=< localRef !~ genTypeSig scopedSigs bindsWithSigs vbAccess) $ mod + if done + then return mod' + else refactError "No binding without type signature is found at the selection." + + +hasScopedTypeSignatures :: Module dom -> Bool +hasScopedTypeSignatures mod = "ScopedTypeVariables" `elem` (mod ^? filePragmas & annList & lpPragmas & annList & langExt :: [String]) + +genTypeSig :: forall dom d . (GenerateSignatureDomain dom, BindingElem d) => Bool -> [(GHC.Var, TypeSignature dom, ValueBind dom)] -> (AnnList d dom -> Maybe (ValueBind dom)) + -> AnnList d dom -> StateT Bool (LocalRefactor dom) (AnnList d dom) +genTypeSig scopedSigs sigBinds vbAccess ls + | Just vb <- vbAccess ls + , not (typeSignatureAlreadyExist ls vb) + = if isSimpleBinding vb + then + do let id = getBindingName vb + isTheBind (Just decl) + = isBinding decl && map semanticsId (decl ^? elementName) == map semanticsId (vb ^? bindingName) + isTheBind _ = False + + alreadyGenerated <- get + if alreadyGenerated + then return ls + else do put True + -- checking for possible situations when we cannot generate signature because of + -- an implicitly passed value + let dangerousTypeVars = dangerousTVs scopedSigs sigBinds + myTvs = concatMap @[] (getExternalTVs . idType . semanticsId) (vb ^? bindingName) + if not $ null @[] $ myTvs `intersect` dangerousTypeVars + then refactError $ "Could not generate type signature: the type variable(s) " + ++ concat (intersperse ", " $ map (showSDocUnsafe . ppr) (myTvs `intersect` dangerousTypeVars)) + ++ " cannot be captured. (Use ScopedTypeVariables and forall-ed type signatures)" + else do + typeSig <- lift $ generateTSFor (getName id) (idType id) + return $ insertWhere True (createTypeSig typeSig) (const True) isTheBind ls + else refactError "Signature can only be generated for simple value bindings." + | otherwise = return ls + where isSimpleBinding vb = case vb of SimpleBind (AST.VarPat {}) _ _ -> True + SimpleBind _ _ _ -> False + _ -> True + dangerousTVs scopedSigs sigBinds + = let dangerousDecls = if scopedSigs then filter (\(_,ts,_) -> not $ isForalledTS ts) sigBinds else sigBinds + dangerousNames = map (\(_,_,bn) -> bn ^? (valBindPats & biplateRef &+& bindingName)) dangerousDecls + in concatMap (concatMap @[] (getExternalTVs . idType . semanticsId @(QualifiedName dom))) dangerousNames + +generateTSFor :: GenerateSignatureDomain dom => GHC.Name -> GHC.Type -> LocalRefactor dom (TypeSignature dom) +generateTSFor n t = mkTypeSignature (mkUnqualName' n) <$> generateTypeFor (-1) (dropForAlls t) + +-- | Generates the source-level type for a GHC internal type +generateTypeFor :: GenerateSignatureDomain dom => Int -> GHC.Type -> LocalRefactor dom (AST.Type dom) +generateTypeFor prec t + -- context + | (break (not . isPredTy) -> (preds, other), rt) <- splitFunTys t + , not (null preds) + = do ctx <- case preds of [pred] -> mkContext <$> generateAssertionFor pred + _ -> mkContext <$> (mkTupleAssertion <$> mapM generateAssertionFor preds) + wrapParen 0 <$> (mkCtxType ctx <$> generateTypeFor 0 (mkFunTys other rt)) + -- function + | Just (at, rt) <- splitFunTy_maybe t + = wrapParen 0 <$> (mkFunctionType <$> generateTypeFor 10 at <*> generateTypeFor 0 rt) + -- type operator (we don't know the precedences, so always use parentheses) + | (op, [at,rt]) <- splitAppTys t + , Just tc <- tyConAppTyCon_maybe op + , isSymOcc (getOccName (getName tc)) + = wrapParen 0 <$> (mkInfixTypeApp <$> generateTypeFor 10 at <*> referenceOperator (idName $ getTCId tc) <*> generateTypeFor 10 rt) + -- tuple types + | Just (tc, tas) <- splitTyConApp_maybe t + , isTupleTyCon tc + = mkTupleType <$> mapM (generateTypeFor (-1)) tas + -- string type + | Just (ls, [et]) <- splitTyConApp_maybe t + , Just ch <- tyConAppTyCon_maybe et + , listTyCon == ls + , charTyCon == ch + = return $ mkVarType (mkNormalName $ mkSimpleName "String") + -- list types + | Just (tc, [et]) <- splitTyConApp_maybe t + , listTyCon == tc + = mkListType <$> generateTypeFor (-1) et + -- type application + | Just (tf, ta) <- splitAppTy_maybe t + = wrapParen 10 <$> (mkTypeApp <$> generateTypeFor 10 tf <*> generateTypeFor 11 ta) + -- type constructor + | Just tc <- tyConAppTyCon_maybe t + = mkVarType <$> referenceName (idName $ getTCId tc) + -- type variable + | Just tv <- getTyVar_maybe t + = mkVarType <$> referenceName (idName tv) + -- forall type + | (tvs@(_:_), t') <- splitForAllTys t + = wrapParen (-1) <$> (mkForallType (map (mkTypeVar' . getName) tvs) <$> generateTypeFor 0 t') + | otherwise = error ("Cannot represent type: " ++ showSDocUnsafe (ppr t)) + where wrapParen :: Int -> AST.Type dom -> AST.Type dom + wrapParen prec' node = if prec' < prec then mkParenType node else node + + getTCId :: GHC.TyCon -> GHC.Id + getTCId tc = GHC.mkVanillaGlobal (GHC.tyConName tc) (tyConKind tc) + + generateAssertionFor :: GenerateSignatureDomain dom => GHC.Type -> LocalRefactor dom (Assertion dom) + generateAssertionFor t + | Just (tc, types) <- splitTyConApp_maybe t + = mkClassAssert <$> referenceName (idName $ getTCId tc) <*> mapM (generateTypeFor 0) types + | otherwise = error "generateAssertionFor: type not supported yet." + +-- | Check whether the definition already has a type signature +typeSignatureAlreadyExist :: (GenerateSignatureDomain dom, BindingElem d) => AnnList d dom -> ValueBind dom -> Bool +typeSignatureAlreadyExist ls vb = + getBindingName vb `elem` (map semanticsId $ concatMap (^? elementName) (filter isTypeSig $ ls ^? annList)) + +getBindingName :: GenerateSignatureDomain dom => ValueBind dom -> GHC.Id +getBindingName vb = case nub $ map semanticsId $ vb ^? bindingName of + [n] -> n + [] -> error "Trying to generate a signature for a binding with no name" + _ -> error "Trying to generate a signature for a binding with multiple names" + +-- * Checking for type variable constraints + +getExternalTVs :: GHC.Type -> [GHC.Var] +getExternalTVs t + | Just tv <- getTyVar_maybe t = [tv] + | Just (op, arg) <- splitAppTy_maybe t = getExternalTVs op `union` getExternalTVs arg + | Just (tv, t') <- splitForAllTy_maybe t = delete tv $ getExternalTVs t' + | otherwise = [] + +isForalledTS :: TypeSignature dom -> Bool +isForalledTS ts = not $ null @[] $ ts ^? tsType & typeBounded & annList
@@ -0,0 +1,243 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, LambdaCase, MultiWayIf, RankNTypes, ScopedTypeVariables, TypeApplications, TypeFamilies #-} +-- | Defines the inline binding refactoring that removes a value binding and replaces all occurences +-- with an expression equivalent to the body of the binding. +module Language.Haskell.Tools.Refactor.Builtin.InlineBinding + (inlineBinding, InlineBindingDomain, tryItOut, inlineBindingRefactoring) where + +import Control.Monad.State +import Control.Reference +import Data.Generics.Uniplate.Data () +import Data.Generics.Uniplate.Operations (Uniplate(..), Biplate(..)) +import Data.List (nub) +import Data.Maybe (Maybe(..), catMaybes) + +import Name as GHC (NamedThing(..), Name, occNameString) +import SrcLoc as GHC (SrcSpan(..), RealSrcSpan) + +import Language.Haskell.Tools.Refactor as AST + +inlineBindingRefactoring :: InlineBindingDomain dom => RefactoringChoice dom +inlineBindingRefactoring = SelectionRefactoring "InlineBinding" inlineBinding + +tryItOut :: String -> String -> IO () +tryItOut = tryRefactor inlineBinding + +type InlineBindingDomain dom = ( HasNameInfo dom, HasDefiningInfo dom, HasScopeInfo dom, HasModuleInfo dom ) + +inlineBinding :: forall dom . InlineBindingDomain dom => RealSrcSpan -> Refactoring dom +inlineBinding span namedMod@(_,mod) mods + = let topLevel :: Simple Traversal (Module dom) (DeclList dom) + topLevel = nodesContaining span + local :: Simple Traversal (Module dom) (LocalBindList dom) + local = nodesContaining span + exprs :: Simple Traversal (Module dom) (Expr dom) + exprs = nodesContaining span + elemAccess :: (BindingElem d) => AnnList d dom -> Maybe (ValueBind dom) + elemAccess = getValBindInList span + removed = catMaybes $ map elemAccess (mod ^? topLevel) ++ map elemAccess (mod ^? local) + in case reverse removed of + [] -> refactError "No binding is selected." + removedBinding:_ -> + let [removedBindingName] = nub $ catMaybes $ map semanticsName (removedBinding ^? bindingName) + in if | any (containInlined removedBindingName) mods + -> refactError "Cannot inline the definition, it is used in other modules." + | _:_ <- mod ^? modHead & annJust & mhExports & annJust & biplateRef + & filtered (\n -> semanticsName (n :: QualifiedName dom) == Just removedBindingName) + -> refactError "Cannot inline the definition, it is present in the export list." + | otherwise -> localRefactoring (inlineBinding' topLevel local exprs removedBinding removedBindingName) namedMod mods + +-- | Performs the inline binding on a single module. +inlineBinding' :: InlineBindingDomain dom + => Simple Traversal (Module dom) (DeclList dom) + -> Simple Traversal (Module dom) (LocalBindList dom) + -> Simple Traversal (Module dom) (Expr dom) + -> ValueBind dom -> GHC.Name + -> LocalRefactoring dom +inlineBinding' topLevelRef localRef exprRef removedBinding removedBindingName mod + = do replacement <- createReplacement removedBinding + let RealSrcSpan bindingSpan = getRange removedBinding + mod' <- removeBindingAndSig topLevelRef localRef exprRef removedBindingName mod + (mod'', used) <- runStateT (descendBiM (replaceInvocations bindingSpan removedBindingName replacement) mod') False + if not used + then refactError "The selected definition is not used, it can be safely deleted." + else return mod'' + +-- | True if the given module contains the name of the inlined definition. +containInlined :: forall dom . InlineBindingDomain dom => GHC.Name -> ModuleDom dom -> Bool +containInlined name (_,mod) + = any (\qn -> semanticsName qn == Just name) $ (mod ^? biplateRef :: [QualifiedName dom]) + +-- | Removes the inlined binding and the accompanying type and fixity signatures. +removeBindingAndSig :: InlineBindingDomain dom + => Simple Traversal (Module dom) (DeclList dom) + -> Simple Traversal (Module dom) (LocalBindList dom) + -> Simple Traversal (Module dom) (Expr dom) + -> GHC.Name + -> LocalRefactoring dom +removeBindingAndSig topLevelRef localRef exprRef name + = (return . removeEmptyBnds (topLevelRef & annList & declValBind &+& localRef & annList & localVal) exprRef) + <=< (topLevelRef !~ removeBindingAndSig' name) + <=< (localRef !~ removeBindingAndSig' name) + +removeBindingAndSig' :: (SourceInfoTraversal d, InlineBindingDomain dom, BindingElem d) + => GHC.Name -> AnnList d dom -> LocalRefactor dom (AnnList d dom) +removeBindingAndSig' name ls = do + bnds <- mapM notThatBindOrSig (ls ^? annList) + return $ (annList .- removeNameFromSigBind) (filterListIndexed (\i _ -> bnds !! i) ls) + where notThatBindOrSig e + | Just sb <- e ^? sigBind = return $ nub (map semanticsName (sb ^? tsName & annList & simpleName)) /= [Just name] + | Just vb <- e ^? valBind = do + let isThat = nub (map semanticsName (vb ^? bindingName)) == [Just name] + when isThat (void $ accessRhs !| checkForRecursion name $ vb) + return $ not isThat + | Just fs <- e ^? fixitySig = return $ nub (map semanticsName (fs ^? fixityOperators & annList & operatorName)) /= [Just name] + | otherwise = return True + + removeNameFromSigBind + = (sigBind & tsName .- filterList (\n -> semanticsName (n ^. simpleName) /= Just name)) + . (fixitySig & fixityOperators .- filterList (\n -> semanticsName (n ^. operatorName) /= Just name)) + + accessRhs = valBindRhs + &+& valBindLocals & accessLocalRhs + &+& funBindMatches & annList & matchRhs + &+& funBindMatches & annList & (matchRhs &+& matchBinds & accessLocalRhs) + accessLocalRhs = annJust & localBinds & annList & localVal & accessRhs + +-- | Check the extracted bindings right-hand-side for possible recursion +checkForRecursion :: InlineBindingDomain dom + => GHC.Name -> Rhs dom -> LocalRefactor dom () +checkForRecursion n = void . (biplateRef !| checkNameForRecursion n) + +checkNameForRecursion :: InlineBindingDomain dom + => GHC.Name -> AST.Name dom -> LocalRefactor dom () +checkNameForRecursion name n + | semanticsName (n ^. simpleName) == Just name + = refactError $ "Cannot inline definitions containing direct recursion. Recursive call at: " + ++ shortShowSpanWithFile (getRange n) + | otherwise = return () + +-- | As a top-down transformation, replaces the occurrences of the binding with generated expressions. This method passes +-- the captured arguments of the function call to generate simpler results. +replaceInvocations :: InlineBindingDomain dom + => RealSrcSpan -> GHC.Name -> ([[GHC.Name]] -> [Expr dom] -> Expr dom) -> Expr dom -> StateT Bool (LocalRefactor dom) (Expr dom) +replaceInvocations bindingRange name replacement expr + | (Var n, args) <- splitApps expr + , semanticsName (n ^. simpleName) == Just name + = do put True + replacement (map (map (^. _1)) $ semanticsScope expr) + <$> mapM (descendM (replaceInvocations bindingRange name replacement)) args + | otherwise + = descendM (replaceInvocations bindingRange name replacement) expr + +-- | Splits an application into function and arguments. Works also for operators. +splitApps :: Expr dom -> (Expr dom, [Expr dom]) +splitApps (App f a) = case splitApps f of (fun, args) -> (fun, args ++ [a]) +splitApps (InfixApp l (NormalOp qn) r) = (mkVar (mkParenName qn), [l,r]) +splitApps (InfixApp l (BacktickOp qn) r) = (mkVar (mkNormalName qn), [l,r]) +splitApps (Paren expr) = splitApps expr +splitApps expr = (expr, []) + +-- | Rejoins the function and the arguments as an expression. +joinApps :: Expr dom -> [Expr dom] -> Expr dom +joinApps f [] = f +joinApps f args = parenIfNeeded (foldl mkApp f args) + +-- | Create an expression that is equivalent to calling the given bind. +createReplacement :: InlineBindingDomain dom => ValueBind dom -> LocalRefactor dom ([[GHC.Name]] -> [Expr dom] -> Expr dom) +createReplacement (SimpleBind (VarPat _) (UnguardedRhs e) locals) + = return $ \_ args -> joinApps (parenIfNeeded $ wrapLocals locals e) args +createReplacement (SimpleBind _ _ _) + = refactError "Cannot inline, illegal simple bind. Only variable left-hand sides and unguarded right-hand sides are accepted." +createReplacement (FunctionBind (AnnList [Match lhs (UnguardedRhs expr) locals])) + = return $ \_ args -> let (argReplacement, matchedPats, appliedArgs) = matchArguments (getArgsOf lhs) args + in joinApps (parenIfNeeded (createLambda matchedPats (wrapLocals locals (replaceExprs argReplacement expr)))) appliedArgs + where getArgsOf (MatchLhs _ (AnnList args)) = args + getArgsOf (InfixLhs lhs _ rhs (AnnList more)) = lhs:rhs:more +createReplacement (FunctionBind matches) + -- function bind has at least one match + = return $ \sc args -> let numArgs = getArgNum (head (matches ^? annList & matchLhs)) - length args + newArgs = take numArgs $ map mkName $ filter notInScope $ map (("x" ++ ) . show @Int) [1..] + notInScope str = not $ any (any ((== str) . occNameString . getOccName)) sc + in parenIfNeeded $ createLambda (map mkVarPat newArgs) + $ mkCase (mkTuple $ map mkVar newArgs ++ args) + $ map replaceMatch (matches ^? annList) + where getArgNum (MatchLhs _ (AnnList args)) = length args + getArgNum (InfixLhs _ _ _ (AnnList more)) = length more + 2 + +-- | Replaces names with expressions according to a mapping. +replaceExprs :: InlineBindingDomain dom => [(GHC.Name, Expr dom)] -> Expr dom -> Expr dom +replaceExprs [] = id +replaceExprs replaces = (uniplateRef .-) $ \case + Var n | Just name <- semanticsName (n ^. simpleName) + , Just replace <- lookup name replaces + -> replace + e -> e + +-- | Matches a pattern list with an expression list and generates bindings. Matches until an argument cannot be matched. +matchArguments :: InlineBindingDomain dom => [Pattern dom] -> [Expr dom] -> ([(GHC.Name, Expr dom)], [Pattern dom], [Expr dom]) +matchArguments (ParenPat p : pats) exprs = matchArguments (p:pats) exprs +matchArguments (p:pats) (e:exprs) + | Just replacement <- staticPatternMatch p e + = case matchArguments pats exprs of (replacements, patterns, expressions) -> (replacement ++ replacements, patterns, expressions) + | otherwise + = ([], p:pats, e:exprs) +matchArguments pats [] = ([], pats, []) +matchArguments [] exprs = ([], [], exprs) + +-- | Matches a pattern with an expression. Generates a mapping of names to expressions. +staticPatternMatch :: InlineBindingDomain dom => Pattern dom -> Expr dom -> Maybe [(GHC.Name, Expr dom)] +staticPatternMatch (VarPat n) e + | Just name <- semanticsName $ n ^. simpleName + = Just [(name, e)] +staticPatternMatch (AppPat n (AnnList args)) e + | (Var n', exprs) <- splitApps e + , length args == length exprs + && semanticsName (n ^. simpleName) == semanticsName (n' ^. simpleName) + , Just subs <- sequence $ zipWith staticPatternMatch args exprs + = Just $ concat subs +staticPatternMatch (TuplePat (AnnList pats)) (Tuple (AnnList args)) + | length pats == length args + , Just subs <- sequence $ zipWith staticPatternMatch pats args + = Just $ concat subs +staticPatternMatch _ _ = Nothing + +replaceMatch :: Match dom -> Alt dom +replaceMatch (Match lhs rhs locals) = mkAlt (toPattern lhs) (toAltRhs rhs) (locals ^? annJust) + where toPattern (MatchLhs _ (AnnList pats)) = mkTuplePat pats + toPattern (InfixLhs lhs _ rhs (AnnList more)) = mkTuplePat (lhs:rhs:more) + + toAltRhs (UnguardedRhs expr) = mkCaseRhs expr + toAltRhs (GuardedRhss (AnnList rhss)) = mkGuardedCaseRhss (map toAltGuardedRhs rhss) + + toAltGuardedRhs (GuardedRhs (AnnList guards) expr) = mkGuardedCaseRhs guards expr + +wrapLocals :: MaybeLocalBinds dom -> Expr dom -> Expr dom +wrapLocals bnds = case bnds ^? annJust & localBinds & annList of + [] -> id + localBinds -> mkLet localBinds + +-- | True for patterns that need to be parenthesized if in a lambda +compositePat :: Pattern dom -> Bool +compositePat (AppPat {}) = True +compositePat (InfixAppPat {}) = True +compositePat (TypeSigPat {}) = True +compositePat (ViewPat {}) = True +compositePat _ = False + +parenIfNeeded :: Expr dom -> Expr dom +parenIfNeeded e = if compositeExprs e then mkParen e else e + +-- | True for expresssions that need to be parenthesized if in application +compositeExprs :: Expr dom -> Bool +compositeExprs (App {}) = True +compositeExprs (InfixApp {}) = True +compositeExprs (Lambda {}) = True +compositeExprs (Let {}) = True +compositeExprs (If {}) = True +compositeExprs (Case {}) = True +compositeExprs (Do {}) = True +compositeExprs _ = False + +createLambda :: [Pattern dom] -> Expr dom -> Expr dom +createLambda [] = id +createLambda pats = mkLambda (map (\p -> if compositePat p then mkParenPat p else p) pats)
@@ -0,0 +1,104 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, RankNTypes, TupleSections, TypeFamilies, LambdaCase #-} + +module Language.Haskell.Tools.Refactor.Builtin.OrganizeExtensions + ( module Language.Haskell.Tools.Refactor.Builtin.OrganizeExtensions + , module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad + ) where + +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.TraverseAST +import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.SupportedExtensions (unregularExts, isSupported, fullyHandledExtensions) + +import Language.Haskell.Tools.Refactor hiding (LambdaCase) +import Language.Haskell.Tools.Refactor.Utils.Extensions (expandExtension) + +import GHC (Ghc(..)) + +import Control.Reference +import Data.Char (isAlpha) +import Data.Function (on) +import Data.List +import qualified Data.Map.Strict as SMap (keys, empty) + +-- NOTE: When working on the entire AST, we should build a monad, +-- that will will avoid unnecessary checks. +-- For example if it already found a record wildcard, it won't check again + +-- Pretty easy now. Chcek wheter it is already in the ExtMap. + +type OrganizeExtensionsDomain dom = (HasModuleInfo dom, ExtDomain dom) + +organizeExtensionsRefactoring :: OrganizeExtensionsDomain dom => RefactoringChoice dom +organizeExtensionsRefactoring = ModuleRefactoring "OrganizeExtensions" (localRefactoring organizeExtensions) + +projectOrganizeExtensionsRefactoring :: OrganizeExtensionsDomain dom => RefactoringChoice dom +projectOrganizeExtensionsRefactoring = ProjectRefactoring "ProjectOrganizeExtensions" projectOrganizeExtensions + +projectOrganizeExtensions :: forall dom . OrganizeExtensionsDomain dom => ProjectRefactoring dom +projectOrganizeExtensions = + mapM (\(k, m) -> ContentChanged . (k,) <$> localRefactoringRes id m (organizeExtensions m)) + +tryOut :: String -> String -> IO () +tryOut = tryRefactor (localRefactoring . const organizeExtensions) + +organizeExtensions :: ExtDomain dom => LocalRefactoring dom +organizeExtensions moduleAST = do + exts <- liftGhc $ reduceExtensions moduleAST + let isRedundant e = extName `notElem` foundExts && extName `elem` handledExts + where extName = unregularExts (e ^. langExt) + handledExts = map show fullyHandledExtensions + foundExts = map show exts + + -- remove unused extensions (only those that are fully handled) + filePragmas & annList & lpPragmas !~ filterListSt (not . isRedundant) + -- remove empty {-# LANGUAGE #-} pragmas + >=> filePragmas !~ filterListSt (\case LanguagePragma (AnnList []) -> False; _ -> True) + $ moduleAST + +-- | Reduces default extension list (keeps unsupported extensions) +reduceExtensions :: ExtDomain dom => UnnamedModule dom -> Ghc [Extension] +reduceExtensions = \moduleAST -> do + let expanded = expandDefaults moduleAST + (xs, ys) = partition isSupported expanded + xs' <- flip execStateT SMap.empty . flip runReaderT xs . traverseModule $ moduleAST + return . sortBy (compare `on` show) . mergeInduced . nub $ (calcExts xs' ++ ys) + + where isLVar (LVar _) = True + isLVar _ = False + + calcExts :: ExtMap -> [Extension] + calcExts logRels + | ks <- SMap.keys logRels + , all isLVar ks + = map (\(LVar x) -> x) . SMap.keys $ logRels + | otherwise = [] + + rmInduced :: Extension -> [Extension] -> [Extension] + rmInduced e = flip (\\) induced + where induced = delete e $ expandExtension e + + mergeInduced :: [Extension] -> [Extension] + mergeInduced exts = foldl (flip rmInduced) exts exts + + +-- | Collects extensions induced by the source code (with location info) +collectExtensions :: ExtDomain dom => UnnamedModule dom -> Ghc ExtMap +collectExtensions moduleAST = do + let expanded = expandDefaults moduleAST + flip execStateT SMap.empty . flip runReaderT expanded . traverseModule $ moduleAST + +-- | Collects default extension list, and expands each extension +expandDefaults :: UnnamedModule dom -> [Extension] +expandDefaults = nub . concatMap expandExtension . collectDefaultExtensions + +-- | Collects extensions enabled by default +collectDefaultExtensions :: UnnamedModule dom -> [Extension] +collectDefaultExtensions = map toExt . getExtensions + where + getExtensions :: UnnamedModule dom -> [String] + getExtensions = flip (^?) (filePragmas & annList & lpPragmas & annList & langExt) + +toExt :: String -> Extension +toExt str = case map fst . reads . unregularExts . takeWhile isAlpha $ str of + e:_ -> e + [] -> error $ "Extension '" ++ takeWhile isAlpha str ++ "' is not known."
@@ -0,0 +1,229 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, LambdaCase, ScopedTypeVariables, TupleSections, TypeApplications, TypeFamilies #-} +module Language.Haskell.Tools.Refactor.Builtin.OrganizeImports + ( organizeImports, OrganizeImportsDomain, projectOrganizeImports + , organizeImportsRefactoring, projectOrganizeImportsRefactoring + ) where + +import ConLike (ConLike(..)) +import DataCon (dataConTyCon) +import DynFlags (xopt) +import FamInstEnv (FamInst(..)) +import GHC (TyThing(..), lookupName) +import qualified GHC +import Id +import IdInfo (RecSelParent(..)) +import InstEnv (ClsInst(..)) +import Language.Haskell.TH.LanguageExtensions as GHC (Extension(..)) +import Name (NamedThing(..)) +import OccName (HasOccName(..), isSymOcc) +import qualified PrelNames as GHC (fromStringName, coerceKey) +import SrcLoc (SrcSpan(..), noSrcSpan) +import TyCon (TyCon(..), tyConFamInst_maybe) +import Unique (getUnique) + +import Control.Applicative ((<$>), Alternative(..)) +import Control.Monad +import Control.Reference hiding (element) +import Data.Function hiding ((&)) +import Data.Generics.Uniplate.Data (universeBi) +import Data.List +import Data.Maybe (Maybe(..), maybe, catMaybes) + +import Language.Haskell.Tools.Refactor as AST + +organizeImportsRefactoring :: OrganizeImportsDomain dom => RefactoringChoice dom +organizeImportsRefactoring = ModuleRefactoring "OrganizeImports" (localRefactoring organizeImports) + +projectOrganizeImportsRefactoring :: OrganizeImportsDomain dom => RefactoringChoice dom +projectOrganizeImportsRefactoring = ProjectRefactoring "ProjectOrganizeImports" projectOrganizeImports + +type OrganizeImportsDomain dom = ( HasNameInfo dom, HasImportInfo dom, HasModuleInfo dom, HasImplicitFieldsInfo dom ) + +projectOrganizeImports :: forall dom . OrganizeImportsDomain dom => ProjectRefactoring dom +projectOrganizeImports mods + = mapM (\(k, m) -> ContentChanged . (k,) <$> localRefactoringRes id m (organizeImports m)) mods + +organizeImports :: forall dom . OrganizeImportsDomain dom => LocalRefactoring dom +organizeImports mod + = do usedTyThings <- catMaybes <$> mapM lookupName usedNames + let dfs = semanticsDynFlags mod + noNarrowingImports + = xopt TemplateHaskell dfs -- no narrowing if TH is present (we don't know what will be used) + || xopt QuasiQuotes dfs -- no narrowing if TH quotes are present (we don't know what will be used) + || (xopt FlexibleInstances dfs && noNarrowingSubspecs) -- arbitrary ctors might be needed when using imported data families + || hasCoerce -- the presence of coerce implicitely requires the constructors to be present + noNarrowingSubspecs + = -- both standalone deriving and FFI marshalling can cause constructors to be used in the generated code + xopt GHC.StandaloneDeriving dfs || hasMarshalling + -- while pattern synonyms are not handled correctly, we disable subspec narrowing to be safe + || patternSynonymAreUsed usedTyThings + if noNarrowingImports + then -- we don't know what definitions the generated code will use + return $ modImports .- sortImports $ mod + else modImports !~ narrowImports noNarrowingSubspecs exportedModules (addFromString dfs usedNames) exportedNames prelInstances prelFamInsts . sortImports $ mod + where prelInstances = semanticsPrelOrphanInsts mod + prelFamInsts = semanticsPrelFamInsts mod + addFromString dfs = if xopt OverloadedStrings dfs then (GHC.fromStringName :) else id + usedNames = map getName $ (catMaybes $ map semanticsName + -- obviously we don't want the names in the imports to be considered, but both from + -- the declarations (used), both from the module head (re-exported) will count as usage + (universeBi (mod ^. modHead) ++ universeBi (mod ^. modDecl) :: [QualifiedName dom])) + ++ concatMap (map fst . semanticsImplicitFlds) (universeBi (mod ^. modDecl) :: [FieldWildcard dom]) + -- Prelude is not actually exported, but we don't want to remove it if it is explicitly there + -- otherwise, we might add new imported elements that cause conflicts. + exportedModules = "Prelude" : (mod ^? modHead & annJust & mhExports & annJust + & espExports & annList & exportModuleName & moduleNameString) + + -- Exported definitions must be kept imported + exports = mod ^? modHead & annJust & mhExports & annJust & espExports & annList & exportDecl + exportedNames = catMaybes $ map getExported exports + getExported e = fmap (,hasChild) name + where name = semanticsName (e ^. ieName & simpleName) + hasChild = (case e ^? ieSubspec & annJust of Just SubAll -> True; _ -> False) + || not (null @[] (e ^? ieSubspec & annJust & essList & annList)) + + -- Checks if the module uses foreign import/export that requires marshalling. In this case no + -- subspecifiers could be narrowed because constructors might be needed. + hasMarshalling = not $ null @[] (mod ^? modDecl & annList & declForeignType) + hasCoerce = GHC.coerceKey `elem` map getUnique usedNames + + -- Can this name be part of the source code? + -- isSourceName n = ':' `notElem` occNameString (occName n) + patternSynonymAreUsed tts = any (\case AConLike (PatSynCon _) -> True; _ -> False) tts + +-- | Sorts the imports in alphabetical order +sortImports :: forall dom . ImportDeclList dom -> ImportDeclList dom +sortImports ls = srcInfo & srcTmpSeparators .= filter (not . null . fst) (concatMap (\(sep,elems) -> sep : map fst elems) reordered) + $ annListElems .= concatMap (map snd . snd) reordered + $ ls + where reordered :: [(([SourceTemplateTextElem], SrcSpan), [(([SourceTemplateTextElem], SrcSpan), ImportDecl dom)])] + reordered = map (_2 .- sortBy (compare `on` (^. _2 & importModule & AST.moduleNameString))) parts + + parts = map (_2 .- reverse) $ reverse $ breakApart [] imports + + -- break up the list of imports to import groups + breakApart :: [(([SourceTemplateTextElem], SrcSpan), [(([SourceTemplateTextElem], SrcSpan), ImportDecl dom)])] + -> [(([SourceTemplateTextElem], SrcSpan), ImportDecl dom)] + -> [(([SourceTemplateTextElem], SrcSpan), [(([SourceTemplateTextElem], SrcSpan), ImportDecl dom)])] + breakApart res [] = res + breakApart res ((sep, e) : rest) | length (filter ('\n' ==) (sep ^? _1 & traversal & sourceTemplateText & traversal)) > 1 + || "\n#" `isInfixOf` (sep ^? _1 & traversal & sourceTemplateText & traversal) + = breakApart ((sep, [(([], noSrcSpan),e)]) : res) rest + breakApart ((lastSep, lastRes) : res) (elem : rest) + = breakApart ((lastSep, elem : lastRes) : res) rest + breakApart [] ((sep, e) : rest) + = breakApart [(sep, [(([], noSrcSpan),e)])] rest + + imports = zipWithSeparators ls + +-- | Modify an import to only import names that are used. +narrowImports :: forall dom . OrganizeImportsDomain dom + => Bool -> [String] -> [GHC.Name] -> [(GHC.Name, Bool)] -> [ClsInst] -> [FamInst] -> ImportDeclList dom -> LocalRefactor dom (ImportDeclList dom) +narrowImports noNarrowSubspecs exportedModules usedNames exportedNames prelInsts prelFamInsts imps + = (annListElems & traversal !~ narrowImport noNarrowSubspecs exportedModules usedNames exportedNames) + =<< filterListIndexedSt (\i _ -> impsNeeded !! i) imps + where impsNeeded = neededImports exportedModules (usedNames ++ map fst exportedNames) prelInsts prelFamInsts (imps ^. annListElems) + +-- | Reduces the number of definitions used from an import +narrowImport :: OrganizeImportsDomain dom + => Bool -> [String] -> [GHC.Name] -> [(GHC.Name, Bool)] -> ImportDecl dom -> LocalRefactor dom (ImportDecl dom) +narrowImport noNarrowSubspecs exportedModules usedNames exportedNames imp + | (imp ^. importModule & moduleNameString) `elem` exportedModules + || maybe False (`elem` exportedModules) (imp ^? importAs & annJust & importRename & moduleNameString) + = return imp -- dont change an import if it is exported as-is (module export) + | importIsExact imp + = importSpec&annJust&importSpecList !~ narrowImportSpecs noNarrowSubspecs usedNames exportedNames $ imp + | importIsHiding imp + = return imp -- a hiding import is not changed, because the wildcard importing of class and datatype + -- members could bring into scope the exact definition that was hidden + | otherwise + = do namedThings <- mapM lookupName actuallyImported + let -- to explicitly import pattern synonyms or type operators we need to enable an extension, and the user might not expect this + hasRiskyDef = any isRiskyDef namedThings + groups = groupThings noNarrowSubspecs (semanticsImported imp) + (filter ((`elem` semanticsImported imp) . fst) exportedNames) (catMaybes namedThings) + return $ if not hasRiskyDef && length groups < 4 + then importSpec .- replaceWithJust (createImportSpec groups) $ imp + else imp + where actuallyImported = semanticsImported imp `intersect` usedNames + isRiskyDef (Just (AConLike (PatSynCon _))) = True + isRiskyDef (Just (ATyCon tc)) = isSymOcc (occName (tyConName tc)) + isRiskyDef _ = False + +-- | Group things as importable definitions. The second member of the pair will be true, when there is a sub-name +-- that should be imported apart from the name of the importable definition. +groupThings :: Bool -> [GHC.Name] -> [(GHC.Name, Bool)] -> [TyThing] -> [(GHC.Name, Bool)] +groupThings noNarrowSubspecs importable exported + = map last . groupBy ((==) `on` fst) . sort . (exported ++) . map createImportFromTyThing + where createImportFromTyThing :: TyThing -> (GHC.Name, Bool) + createImportFromTyThing tt | Just (td, isDataType) <- getTopDef tt + = if (td `elem` importable || isDataType) then (td, True) + else (getName tt, False) + createImportFromTyThing tt@(ATyCon {}) = (getName tt, noNarrowSubspecs) + createImportFromTyThing tt = (getName tt, False) + +-- | Gets the importable definition for a (looked up) name. The bool flag tells if it is from +-- a data type. +getTopDef :: TyThing -> Maybe (GHC.Name, Bool) +getTopDef (AnId id) | isRecordSelector id + = case recordSelectorTyCon id of RecSelData tc -> Just (getName tc, True) + RecSelPatSyn ps -> Just (getName ps, False) +getTopDef (AnId id) + | Just n <- fmap (getName . dataConTyCon) (isDataConWorkId_maybe id <|> isDataConId_maybe id) + = Just (n, True) +getTopDef (AnId id) = fmap ((,False) . getName) (isClassOpId_maybe id) +getTopDef (AConLike (RealDataCon dc)) + = case tyConFamInst_maybe (dataConTyCon dc) of + Just (dataFam, _) -> Just (getName dataFam, True) + _ -> Just (getName $ dataConTyCon dc, True) +getTopDef (AConLike (PatSynCon _)) = error "getTopDef: should not be called with pattern synonyms" +getTopDef (ATyCon _) = Nothing + +createImportSpec :: [(GHC.Name, Bool)] -> ImportSpec dom +createImportSpec elems = mkImportSpecList $ map createIESpec elems + where createIESpec (n, False) = mkIESpec (mkUnqualName' (GHC.getName n)) Nothing + createIESpec (n, True) = mkIESpec (mkUnqualName' (GHC.getName n)) (Just mkSubAll) + +-- | Check each import if it is actually needed +neededImports :: OrganizeImportsDomain dom + => [String] -> [GHC.Name] -> [ClsInst] -> [FamInst] -> [ImportDecl dom] -> [Bool] +neededImports exportedModules usedNames prelInsts prelFamInsts imps = neededImports' usedNames [] imps + where neededImports' _ _ [] = [] + -- keep the import if any definition is needed from it + neededImports' usedNames kept (imp : rest) + | not (null actuallyImported) + || (imp ^. importModule & moduleNameString) `elem` exportedModules + || maybe False (`elem` exportedModules) (imp ^? importAs & annJust & importRename & moduleNameString) + = True : neededImports' usedNames (imp : kept) rest + where actuallyImported = semanticsImported imp `intersect` usedNames + neededImports' usedNames kept (imp : rest) + = needed : neededImports' usedNames (if needed then imp : kept else kept) rest + where needed = any (`notElem` otherClsInstances) (map is_dfun $ semanticsOrphanInsts imp) + || any (`notElem` otherFamInstances) (map fi_axiom $ semanticsFamInsts imp) + otherClsInstances = map is_dfun (concatMap semanticsOrphanInsts kept ++ prelInsts) + otherFamInstances = map fi_axiom (concatMap semanticsFamInsts kept ++ prelFamInsts) + +-- | Narrows the import specification (explicitly imported elements) +narrowImportSpecs :: forall dom . OrganizeImportsDomain dom + => Bool -> [GHC.Name] -> [(GHC.Name, Bool)] -> IESpecList dom -> LocalRefactor dom (IESpecList dom) +narrowImportSpecs noNarrowSubspecs usedNames exportedNames + = (if noNarrowSubspecs then return else annList !~ narrowImportSubspecs neededNames exportedNames) + >=> filterListSt isNeededSpec + where neededNames = usedNames ++ map fst exportedNames + + isNeededSpec :: IESpec dom -> Bool + isNeededSpec ie = + (semanticsName (ie ^. ieName&simpleName)) `elem` map Just neededNames + -- if the name is not used, but some of its constructors are used, it is needed + || ((ie ^? ieSubspec&annJust&essList&annList) /= []) + -- its a bit hard to decide if there is an element inside (for example bundled pattern synonyms) + || (case ie ^? ieSubspec&annJust of Just SubAll -> True; _ -> False) + +-- | Reduces the number of definitions imported from a sub-specifier. +narrowImportSubspecs :: OrganizeImportsDomain dom => [GHC.Name] -> [(GHC.Name, Bool)] -> IESpec dom -> LocalRefactor dom (IESpec dom) +narrowImportSubspecs neededNames exportedNames ss | noNarrowingForThis = return ss + | otherwise + = ieSubspec & annJust & essList !~ filterListSt (\n -> (semanticsName (n ^. simpleName)) `elem` map Just neededNames) $ ss + where noNarrowingForThis = case semanticsName (ss ^. ieName&simpleName) of + Just name -> lookup name exportedNames == Just True + _ -> False
@@ -0,0 +1,134 @@+{-# LANGUAGE ConstraintKinds, FlexibleContexts, MultiWayIf, ScopedTypeVariables, TupleSections, TypeApplications, TypeFamilies, ViewPatterns #-} +module Language.Haskell.Tools.Refactor.Builtin.RenameDefinition + (renameDefinition, renameDefinition', DomainRenameDefinition, renameDefinitionRefactoring) where + +import DataCon (dataConFieldLabels, FieldLbl(..), dataConFieldType) +import qualified GHC +import Id +import IdInfo (RecSelParent(..)) +import Name (OccName(..), NamedThing(..), occNameString) +import SrcLoc (RealSrcSpan) +import TyCon (tyConDataCons) +import Type (funResultTy, eqType) + +import Control.Monad.State +import Control.Reference as Ref +import Data.Generics.Uniplate.Data () +import Data.List +import Data.List.Split (splitOn) +import Data.Maybe +import Language.Haskell.Tools.Refactor + +renameDefinitionRefactoring :: DomainRenameDefinition dom => RefactoringChoice dom +renameDefinitionRefactoring = NamingRefactoring "RenameDefinition" renameDefinition' + +type DomainRenameDefinition dom = ( HasNameInfo dom, HasScopeInfo dom, HasDefiningInfo dom + , HasImplicitFieldsInfo dom, HasModuleInfo dom ) + +renameDefinition' :: forall dom . DomainRenameDefinition dom => RealSrcSpan -> String -> Refactoring dom +renameDefinition' sp str mod mods + = case (getNodeContaining sp (snd mod) :: Maybe (QualifiedName dom)) >>= (fmap getName . semanticsName) of + Just name -> do let sameNames = bindsWithSameName name (snd mod ^? biplateRef) + renameDefinition name sameNames str mod mods + where bindsWithSameName :: GHC.Name -> [FieldWildcard dom] -> [GHC.Name] + bindsWithSameName name wcs = catMaybes $ map ((lookup name) . semanticsImplicitFlds) wcs + Nothing -> case getNodeContaining sp (snd mod) of + Just modName -> renameModule (any @[] (sp `isInside`) ((snd mod) ^? modImports&annList&importAs)) + (modName ^. moduleNameString) str mod mods + Nothing -> refactError "No name is selected" + +renameModule :: forall dom . DomainRenameDefinition dom => Bool -> String -> String -> Refactoring dom +renameModule isAlias from to m mods + | any (nameConflict to) (map snd $ m:mods) = refactError "Name conflict when renaming module" + | isJust (validModuleName to) = refactError $ "The given name is not a valid module name: " ++ fromJust (validModuleName to) + | otherwise = -- here it is important that the delete is the last, because rename + -- can still use the info about the deleted module + (if isAlias then id else (fmap (\ls -> map (alterChange from to) ls ++ [ModuleRemoved from]))) + $ mapM (\(name,mod) -> ContentChanged . (name,) <$> localRefactoringRes id mod (replaceModuleNames =<< alterNormalNames mod)) (m:mods) + where alterChange from to (ContentChanged (mod,res)) + | (mod ^. sfkModuleName) == from + = ModuleCreated to res mod + alterChange _ _ c = c + + replaceModuleNames :: LocalRefactoring dom + replaceModuleNames = modNames & filtered (\e -> (e ^. moduleNameString) == from) != mkModuleName to + where modNames = modHead & annJust & (mhName &+& mhExports & annJust & espExports & annList & exportModuleName) + &+& modImports & annList & ( importModule + &+& importAs & annJust & importRename ) + + alterNormalNames :: LocalRefactoring dom + alterNormalNames mod = + biplateRef @_ @(QualifiedName dom) & filtered (\e -> concat (intersperse "." (e ^? qualifiers&annList&simpleNameStr)) == from) + !- (\e -> mkQualifiedName (splitOn "." to) (e ^. unqualifiedName&simpleNameStr)) $ mod + + nameConflict :: String -> Module dom -> Bool + nameConflict to mod + = let modName = mod ^? modHead&annJust&mhName&moduleNameString + imports = mod ^? modImports&annList + importNames = map (\imp -> fromMaybe (imp ^. importModule) (imp ^? importAs&annJust&importRename) ^. moduleNameString) imports + in modName == Just to || to `elem` importNames + +renameDefinition :: DomainRenameDefinition dom => GHC.Name -> [GHC.Name] -> String -> Refactoring dom +renameDefinition toChangeOrig toChangeWith newName mod mods + = do nameCls <- classifyName toChangeOrig + (changedModules,defFound) <- runStateT (catMaybes <$> mapM (renameInAModule toChangeOrig toChangeWith newName) (mod:mods)) False + if | isJust (nameValid nameCls newName) -> refactError $ "The new name is not valid: " ++ fromJust (nameValid nameCls newName) + | not defFound -> refactError "The definition to rename was not found. Maybe it is in another package." + | otherwise -> return $ map ContentChanged changedModules + where + renameInAModule :: DomainRenameDefinition dom => GHC.Name -> [GHC.Name] -> String -> ModuleDom dom -> StateT Bool Refactor (Maybe (ModuleDom dom)) + renameInAModule toChangeOrig toChangeWith newName (name, mod) + = mapStateT (localRefactoringRes (\f (a,s) -> (fmap (\(n,r) -> (n, f r)) a,s)) mod) $ + do origTT <- GHC.lookupName toChangeOrig + let origId = case origTT of + Just (GHC.AnId id) -> Just id + _ -> Nothing + (res, isChanged) <- runStateT (biplateRef !~ changeName toChangeOrig origId toChangeWith newName $ mod) False + if isChanged then return $ Just (name, res) + else return Nothing + + changeName :: DomainRenameDefinition dom => GHC.Name -> Maybe Id -> [GHC.Name] -> String -> QualifiedName dom + -> StateT Bool (StateT Bool (LocalRefactor dom)) (QualifiedName dom) + changeName toChangeOrig origId toChangeWith str name + | maybe False (`elem` toChange) actualName + && semanticsDefining name == False + && any @[] (\n -> str == occNameString (getOccName (n ^. _1)) && not (mergeableFields origId (n ^. _1)) + && notQualified (n ^. _2)) + (scopeUpToDef (semanticsScope name) ^? traversal & traversal & filtered (sameNamespace toChangeOrig . (^. _1))) + = refactError $ "The definition clashes with an existing one at: " ++ shortShowSpanWithFile (getRange name) -- name clash with an external definition + | maybe False (`elem` toChange) actualName + = do put True -- state that something is changed in the local state + when (actualName == Just toChangeOrig) + $ lift $ modify (|| semanticsDefining name) -- state that the definition is renamed in the global state + return $ unqualifiedName .= mkNamePart str $ name -- found the changed name (or a name that have to be changed too) + | let namesInScope = map (map (^. _1)) $ semanticsScope name + in case semanticsName name of + Just (getName -> exprName) -> str == occNameString (getOccName exprName) + && sameNamespace toChangeOrig exprName + && conflicts toChangeOrig exprName namesInScope + && not (mergeableFields origId exprName) + Nothing -> False -- ambiguous names + = refactError $ "The definition clashes with an existing one: " ++ shortShowSpanWithFile (getRange name) -- local name clash + | otherwise = return name -- not the changed name, leave as before + where toChange = toChangeOrig : toChangeWith + actualName = fmap getName (semanticsName name) + scopeUpToDef sc = let (inside, outside) = span (null . (toChange `intersect`) . map (^. _1)) sc + in inside ++ take 1 outside + mergeableFields (Just orig) conflict + | isRecordSelector orig + , RecSelData tc <- recordSelectorTyCon orig + = let selectorsWithTypes = concatMap (\dc -> map (\fld -> (flSelector fld, dataConFieldType dc (flLabel fld))) (dataConFieldLabels dc)) + (filter (\dc -> toChangeOrig `notElem` map flSelector (dataConFieldLabels dc)) (tyConDataCons tc)) + in maybe False (`eqType` funResultTy (idType orig)) (lookup conflict selectorsWithTypes) + mergeableFields _ _ = False + notQualified usage = isNothing usage || any @[] (not . usageQualified) (usage ^? just & traversal) + +conflicts :: GHC.Name -> GHC.Name -> [[GHC.Name]] -> Bool +conflicts overwrites overwritten (scopeBlock : scope) + | overwritten `elem` scopeBlock && overwrites `notElem` scopeBlock = False + | overwrites `elem` scopeBlock = True + | otherwise = conflicts overwrites overwritten scope +conflicts _ _ [] = False + +sameNamespace :: GHC.Name -> GHC.Name -> Bool +sameNamespace n1 n2 = occNameSpace (getOccName n1) == occNameSpace (getOccName n2)
@@ -0,0 +1,2 @@+import Distribution.Simple +main = defaultMain
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleContexts #-} +module CPP.BetweenImports where + +import Data.List +#if !(MIN_VERSION_text(1,2,1)) +#endif +import Data.Maybe + +x = Just
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleContexts #-} +module CPP.BetweenImports where + +import Data.Maybe (Maybe(..)) +#if !(MIN_VERSION_text(1,2,1)) +#endif + + +x = Just
@@ -0,0 +1,8 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalCode where + +#if __GLASGOW_HASKELL__ >= 800 +version = "GHC 8" +#else +version = "not GHC 8" +#endif
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImport where + +import Data.List +#ifndef USE_DATA_LIST +import Control.Monad (Monad(..)) +#endif +import Data.List + +a = Nothing >> Nothing
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportBegin where + +#ifndef USE_DATA_LIST +import Control.Monad ((>>)) +#endif +import Data.List +import Data.List + +a = Nothing >> Nothing
@@ -0,0 +1,9 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportBegin where + +#ifndef USE_DATA_LIST +import Control.Monad ((>>)) +#endif + + +a = Nothing >> Nothing
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportEnd where + +import Data.List +import Data.List +#ifndef USE_DATA_LIST +import Control.Monad ((>>)) +#endif + +a = Nothing >> Nothing
@@ -0,0 +1,9 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportEnd where + + +#ifndef USE_DATA_LIST +import Control.Monad ((>>)) +#endif + +a = Nothing >> Nothing
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportHalfRemoved where + +import Data.List +#ifndef USE_DATA_LIST +import Control.Monad ((>>)) +#endif +import Control.Applicative ((<$>)) + +a = id <$> (Nothing >> Nothing)
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportHalfRemoved where + + +#ifndef USE_DATA_LIST +import Control.Monad ((>>)) +#endif +import Control.Applicative ((<$>)) + +a = id <$> (Nothing >> Nothing)
@@ -0,0 +1,11 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportMulti where + +import Data.List +#ifndef USE_DATA_LIST +import Control.Applicative ((<$>)) +import Control.Monad ((>>)) +#endif +import Data.List + +a = id <$> (Nothing >> Nothing)
@@ -0,0 +1,11 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportMulti where + + +#ifndef USE_DATA_LIST +import Control.Applicative ((<$>)) +import Control.Monad ((>>)) +#endif + + +a = id <$> (Nothing >> Nothing)
@@ -0,0 +1,13 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportOrder where + +import Data.List (intersperse) +#ifndef USE_DATA_LIST +import Control.Monad (Monad(..)) +#endif +import Control.Applicative ((<$>)) + +a = Nothing >> Nothing + +b = id <$> Nothing +c = intersperse "," ["a","b"]
@@ -0,0 +1,13 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImportOrder where + +import Data.List (intersperse) +#ifndef USE_DATA_LIST +import Control.Monad (Monad(..)) +#endif +import Control.Applicative ((<$>)) + +a = Nothing >> Nothing + +b = id <$> Nothing +c = intersperse "," ["a","b"]
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalImport where + + +#ifndef USE_DATA_LIST +import Control.Monad (Monad(..)) +#endif + + +a = Nothing >> Nothing
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalSubImport where + +import Data.List(findIndex,intersperse,nub,sort,sortBy +#if __GLASGOW_HASKELL__ >= 710 + , sortOn +#endif + ) + +a = sortOn fst [("a","x")]
@@ -0,0 +1,11 @@+{-# LANGUAGE CPP #-} +module CPP.ConditionalSubImport where + +import Data.List( +#if __GLASGOW_HASKELL__ >= 710 + + sortOn +#endif + ) + +a = sortOn fst [("a","x")]
@@ -0,0 +1,2 @@+{-# LANGUAGE CPP #-} +module CPP.JustEnabled where
@@ -0,0 +1,34 @@+----------------------------------------------------------------------------- +-- | +-- Module : Language.Preprocessor.Cpphs +-- Copyright : 2000-2006 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : experimental +-- Portability : All +-- +-- Include the interface that is exported +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs + ( runCpphs, runCpphsPass1, runCpphsPass2, runCpphsReturningSymTab + , cppIfdef, tokenise, WordStyle(..) + , macroPass, macroPassReturningSymTab + , CpphsOptions(..), BoolOptions(..) + , parseOptions, defaultCpphsOptions, defaultBoolOptions + , module Language.Preprocessor.Cpphs.Position + ) where + +import Language.Preprocessor.Cpphs.CppIfdef(cppIfdef) +import Language.Preprocessor.Cpphs.MacroPass(macroPass + ,macroPassReturningSymTab) +import Language.Preprocessor.Cpphs.RunCpphs(runCpphs + ,runCpphsPass1 + ,runCpphsPass2 + ,runCpphsReturningSymTab) +import Language.Preprocessor.Cpphs.Options + (CpphsOptions(..), BoolOptions(..), parseOptions + ,defaultCpphsOptions,defaultBoolOptions) +import Language.Preprocessor.Cpphs.Position +import Language.Preprocessor.Cpphs.Tokenise
@@ -0,0 +1,416 @@+----------------------------------------------------------------------------- +-- | +-- Module : CppIfdef +-- Copyright : 1999-2004 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : experimental +-- Portability : All + +-- Perform a cpp.first-pass, gathering \#define's and evaluating \#ifdef's. +-- and \#include's. +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs.CppIfdef + ( cppIfdef -- :: FilePath -> [(String,String)] -> [String] -> Options + -- -> String -> IO [(Posn,String)] + ) where + + +import Text.Parse +import Language.Preprocessor.Cpphs.SymTab +import Language.Preprocessor.Cpphs.Position (Posn,newfile,newline,newlines + ,cppline,cpp2hask,newpos) +import Language.Preprocessor.Cpphs.ReadFirst (readFirst) +import Language.Preprocessor.Cpphs.Tokenise (linesCpp,reslash) +import Language.Preprocessor.Cpphs.Options (BoolOptions(..)) +import Language.Preprocessor.Cpphs.HashDefine(HashDefine(..),parseHashDefine + ,expandMacro) +import Language.Preprocessor.Cpphs.MacroPass (preDefine,defineMacro) +import Data.Char (isDigit,isSpace,isAlphaNum) +import Data.List (intercalate,isPrefixOf) +import Numeric (readHex,readOct,readDec) +import System.IO.Unsafe (unsafeInterleaveIO) +import System.IO (hPutStrLn,stderr) +import Control.Monad (when) + +-- | Run a first pass of cpp, evaluating \#ifdef's and processing \#include's, +-- whilst taking account of \#define's and \#undef's as we encounter them. +cppIfdef :: FilePath -- ^ File for error reports + -> [(String,String)] -- ^ Pre-defined symbols and their values + -> [String] -- ^ Search path for \#includes + -> BoolOptions -- ^ Options controlling output style + -> String -- ^ The input file content + -> IO [(Posn,String)] -- ^ The file after processing (in lines) +cppIfdef fp syms search options = + cpp posn defs search options (Keep []) . initial . linesCpp + where + posn = newfile fp + defs = preDefine options syms + initial = if literate options then id else (cppline posn:) +-- Previous versions had a very simple symbol table mapping strings +-- to strings. Now the #ifdef pass uses a more elaborate table, in +-- particular to deal with parameterised macros in conditionals. + + +-- | Internal state for whether lines are being kept or dropped. +-- In @Drop n b ps@, @n@ is the depth of nesting, @b@ is whether +-- we have already succeeded in keeping some lines in a chain of +-- @elif@'s, and @ps@ is the stack of positions of open @#if@ contexts, +-- used for error messages in case EOF is reached too soon. +data KeepState = Keep [Posn] | Drop Int Bool [Posn] + +-- | Return just the list of lines that the real cpp would decide to keep. +cpp :: Posn -> SymTab HashDefine -> [String] -> BoolOptions -> KeepState + -> [String] -> IO [(Posn,String)] + +cpp _ _ _ _ (Keep ps) [] | not (null ps) = do + hPutStrLn stderr $ "Unmatched #if: positions of open context are:\n"++ + unlines (map show ps) + return [] +cpp _ _ _ _ _ [] = return [] + +cpp p syms path options (Keep ps) (l@('#':x):xs) = + let ws = words x + cmd = if null ws then "" else head ws + line = tail ws + sym = head (tail ws) + rest = tail (tail ws) + def = defineMacro options (sym++" "++ maybe "1" id (un rest)) + un v = if null v then Nothing else Just (unwords v) + keepIf b = if b then Keep (p:ps) else Drop 1 False (p:ps) + skipn syms' retain ud xs' = + let n = 1 + length (filter (=='\n') l) in + (if macros options && retain then emitOne (p,reslash l) + else emitMany (replicate n (p,""))) $ + cpp (newlines n p) syms' path options ud xs' + in case cmd of + "define" -> skipn (insertST def syms) True (Keep ps) xs + "undef" -> skipn (deleteST sym syms) True (Keep ps) xs + "ifndef" -> skipn syms False (keepIf (not (definedST sym syms))) xs + "ifdef" -> skipn syms False (keepIf (definedST sym syms)) xs + "if" -> do b <- gatherDefined p syms (unwords line) + skipn syms False (keepIf b) xs + "else" -> skipn syms False (Drop 1 False ps) xs + "elif" -> skipn syms False (Drop 1 True ps) xs + "endif" | null ps -> + do hPutStrLn stderr $ "Unmatched #endif at "++show p + return [] + "endif" -> skipn syms False (Keep (tail ps)) xs + "pragma" -> skipn syms True (Keep ps) xs + ('!':_) -> skipn syms False (Keep ps) xs -- \#!runhs scripts + "include"-> do (inc,content) <- readFirst (file syms (unwords line)) + p path + (warnings options) + cpp p syms path options (Keep ps) + (("#line 1 "++show inc): linesCpp content + ++ cppline (newline p): xs) + "warning"-> if warnings options then + do hPutStrLn stderr (l++"\nin "++show p) + skipn syms False (Keep ps) xs + else skipn syms False (Keep ps) xs + "error" -> error (l++"\nin "++show p) + "line" | all isDigit sym + -> (if locations options && hashline options then emitOne (p,l) + else if locations options then emitOne (p,cpp2hask l) + else id) $ + cpp (newpos (read sym) (un rest) p) + syms path options (Keep ps) xs + n | all isDigit n && not (null n) + -> (if locations options && hashline options then emitOne (p,l) + else if locations options then emitOne (p,cpp2hask l) + else id) $ + cpp (newpos (read n) (un (tail ws)) p) + syms path options (Keep ps) xs + | otherwise + -> do when (warnings options) $ + hPutStrLn stderr ("Warning: unknown directive #"++n + ++"\nin "++show p) + emitOne (p,l) $ + cpp (newline p) syms path options (Keep ps) xs + +cpp p syms path options (Drop n b ps) (('#':x):xs) = + let ws = words x + cmd = if null ws then "" else head ws + delse | n==1 && b = Drop 1 b ps + | n==1 = Keep ps + | otherwise = Drop n b ps + dend | n==1 = Keep (tail ps) + | otherwise = Drop (n-1) b (tail ps) + delif v | n==1 && not b && v + = Keep ps + | otherwise = Drop n b ps + skipn ud xs' = + let n' = 1 + length (filter (=='\n') x) in + emitMany (replicate n' (p,"")) $ + cpp (newlines n' p) syms path options ud xs' + in + if cmd == "ifndef" || + cmd == "if" || + cmd == "ifdef" then skipn (Drop (n+1) b (p:ps)) xs + else if cmd == "elif" then do v <- gatherDefined p syms (unwords (tail ws)) + skipn (delif v) xs + else if cmd == "else" then skipn delse xs + else if cmd == "endif" then + if null ps then do hPutStrLn stderr $ "Unmatched #endif at "++show p + return [] + else skipn dend xs + else skipn (Drop n b ps) xs + -- define, undef, include, error, warning, pragma, line + +cpp p syms path options (Keep ps) (x:xs) = + let p' = newline p in seq p' $ + emitOne (p,x) $ cpp p' syms path options (Keep ps) xs +cpp p syms path options d@(Drop _ _ _) (_:xs) = + let p' = newline p in seq p' $ + emitOne (p,"") $ cpp p' syms path options d xs + + +-- | Auxiliary IO functions +emitOne :: a -> IO [a] -> IO [a] +emitMany :: [a] -> IO [a] -> IO [a] +emitOne x io = do ys <- unsafeInterleaveIO io + return (x:ys) +emitMany xs io = do ys <- unsafeInterleaveIO io + return (xs++ys) + + +---- +gatherDefined :: Posn -> SymTab HashDefine -> String -> IO Bool +gatherDefined p st inp = + case runParser (preExpand st) inp of + (Left msg, _) -> error ("Cannot expand #if directive in file "++show p + ++":\n "++msg) + (Right s, xs) -> do +-- hPutStrLn stderr $ "Expanded #if at "++show p++" is:\n "++s + when (any (not . isSpace) xs) $ + hPutStrLn stderr ("Warning: trailing characters after #if" + ++" macro expansion in file "++show p++": "++xs) + + case runParser parseBoolExp s of + (Left msg, _) -> error ("Cannot parse #if directive in file "++show p + ++":\n "++msg) + (Right b, xs) -> do when (any (not . isSpace) xs && notComment xs) $ + hPutStrLn stderr + ("Warning: trailing characters after #if" + ++" directive in file "++show p++": "++xs) + return b + +notComment = not . ("//"`isPrefixOf`) . dropWhile isSpace + + +-- | The preprocessor must expand all macros (recursively) before evaluating +-- the conditional. +preExpand :: SymTab HashDefine -> TextParser String +preExpand st = + do eof + return "" + <|> + do a <- many1 (satisfy notIdent) + commit $ pure (a++) `apply` preExpand st + <|> + do b <- expandSymOrCall st + commit $ pure (b++) `apply` preExpand st + +-- | Expansion of symbols. +expandSymOrCall :: SymTab HashDefine -> TextParser String +expandSymOrCall st = + do sym <- parseSym + if sym=="defined" then do arg <- skip parseSym; convert sym [arg] + <|> + do arg <- skip $ parenthesis (do x <- skip parseSym; + skip (return x)) + convert sym [arg] + <|> convert sym [] + else + ( do args <- parenthesis (commit $ fragment `sepBy` skip (isWord ",")) + args' <- flip mapM args $ \arg-> + case runParser (preExpand st) arg of + (Left msg, _) -> fail msg + (Right s, _) -> return s + convert sym args' + <|> convert sym [] + ) + where + fragment = many1 (satisfy (`notElem`",)")) + convert "defined" [arg] = + case lookupST arg st of + Nothing | all isDigit arg -> return arg + Nothing -> return "0" + Just (a@AntiDefined{}) -> return "0" + Just (a@SymbolReplacement{}) -> return "1" + Just (a@MacroExpansion{}) -> return "1" + convert sym args = + case lookupST sym st of + Nothing -> if null args then return sym + else return "0" + -- else fail (disp sym args++" is not a defined macro") + Just (a@SymbolReplacement{}) -> do reparse (replacement a) + return "" + Just (a@MacroExpansion{}) -> do reparse (expandMacro a args False) + return "" + Just (a@AntiDefined{}) -> + if null args then return sym + else return "0" + -- else fail (disp sym args++" explicitly undefined with -U") + disp sym args = let len = length args + chars = map (:[]) ['a'..'z'] + in sym ++ if null args then "" + else "("++intercalate "," (take len chars)++")" + +parseBoolExp :: TextParser Bool +parseBoolExp = + do a <- parseExp1 + bs <- many (do skip (isWord "||") + commit $ skip parseBoolExp) + return $ foldr (||) a bs + +parseExp1 :: TextParser Bool +parseExp1 = + do a <- parseExp0 + bs <- many (do skip (isWord "&&") + commit $ skip parseExp1) + return $ foldr (&&) a bs + +parseExp0 :: TextParser Bool +parseExp0 = + do skip (isWord "!") + a <- commit $ parseExp0 + return (not a) + <|> + do val1 <- parseArithExp1 + op <- parseCmpOp + val2 <- parseArithExp1 + return (val1 `op` val2) + <|> + do sym <- parseArithExp1 + case sym of + 0 -> return False + _ -> return True + <|> + do parenthesis (commit parseBoolExp) + +parseArithExp1 :: TextParser Integer +parseArithExp1 = + do val1 <- parseArithExp0 + ( do op <- parseArithOp1 + val2 <- parseArithExp1 + return (val1 `op` val2) + <|> return val1 ) + <|> + do parenthesis parseArithExp1 + +parseArithExp0 :: TextParser Integer +parseArithExp0 = + do val1 <- parseNumber + ( do op <- parseArithOp0 + val2 <- parseArithExp0 + return (val1 `op` val2) + <|> return val1 ) + <|> + do parenthesis parseArithExp0 + +parseNumber :: TextParser Integer +parseNumber = fmap safeRead $ skip parseSym + where + safeRead s = + case s of + '0':'x':s' -> number readHex s' + '0':'o':s' -> number readOct s' + _ -> number readDec s + number rd s = + case rd s of + [] -> 0 :: Integer + ((n,_):_) -> n :: Integer + +parseCmpOp :: TextParser (Integer -> Integer -> Bool) +parseCmpOp = + do skip (isWord ">=") + return (>=) + <|> + do skip (isWord ">") + return (>) + <|> + do skip (isWord "<=") + return (<=) + <|> + do skip (isWord "<") + return (<) + <|> + do skip (isWord "==") + return (==) + <|> + do skip (isWord "!=") + return (/=) + +parseArithOp1 :: TextParser (Integer -> Integer -> Integer) +parseArithOp1 = + do skip (isWord "+") + return (+) + <|> + do skip (isWord "-") + return (-) + +parseArithOp0 :: TextParser (Integer -> Integer -> Integer) +parseArithOp0 = + do skip (isWord "*") + return (*) + <|> + do skip (isWord "/") + return (div) + <|> + do skip (isWord "%") + return (rem) + +-- | Return the expansion of the symbol (if there is one). +parseSymOrCall :: SymTab HashDefine -> TextParser String +parseSymOrCall st = + do sym <- skip parseSym + args <- parenthesis (commit $ parseSymOrCall st `sepBy` skip (isWord ",")) + return $ convert sym args + <|> + do sym <- skip parseSym + return $ convert sym [] + where + convert sym args = + case lookupST sym st of + Nothing -> sym + Just (a@SymbolReplacement{}) -> recursivelyExpand st (replacement a) + Just (a@MacroExpansion{}) -> recursivelyExpand st (expandMacro a args False) + Just (a@AntiDefined{}) -> name a + +recursivelyExpand :: SymTab HashDefine -> String -> String +recursivelyExpand st inp = + case runParser (parseSymOrCall st) inp of + (Left msg, _) -> inp + (Right s, _) -> s + +parseSym :: TextParser String +parseSym = many1 (satisfy (\c-> isAlphaNum c || c`elem`"'`_")) + `onFail` + do xs <- allAsString + fail $ "Expected an identifier, got \""++xs++"\"" + +notIdent :: Char -> Bool +notIdent c = not (isAlphaNum c || c`elem`"'`_") + +skip :: TextParser a -> TextParser a +skip p = many (satisfy isSpace) >> p + +-- | The standard "parens" parser does not work for us here. Define our own. +parenthesis :: TextParser a -> TextParser a +parenthesis p = do isWord "(" + x <- p + isWord ")" + return x + +-- | Determine filename in \#include +file :: SymTab HashDefine -> String -> String +file st name = + case name of + ('"':ns) -> init ns + ('<':ns) -> init ns + _ -> let ex = recursivelyExpand st name in + if ex == name then name else file st ex +
@@ -0,0 +1,129 @@+----------------------------------------------------------------------------- +-- | +-- Module : HashDefine +-- Copyright : 2004 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : experimental +-- Portability : All +-- +-- What structures are declared in a \#define. +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs.HashDefine + ( HashDefine(..) + , ArgOrText(..) + , expandMacro + , parseHashDefine + , simplifyHashDefines + ) where + +import Data.Char (isSpace) +import Data.List (intercalate) + +data HashDefine + = LineDrop + { name :: String } + | Pragma + { name :: String } + | AntiDefined + { name :: String + , linebreaks :: Int + } + | SymbolReplacement + { name :: String + , replacement :: String + , linebreaks :: Int + } + | MacroExpansion + { name :: String + , arguments :: [String] + , expansion :: [(ArgOrText,String)] + , linebreaks :: Int + } + deriving (Eq,Show) + +-- | 'smart' constructor to avoid warnings from ghc (undefined fields) +symbolReplacement :: HashDefine +symbolReplacement = + SymbolReplacement + { name=undefined, replacement=undefined, linebreaks=undefined } + +-- | Macro expansion text is divided into sections, each of which is classified +-- as one of three kinds: a formal argument (Arg), plain text (Text), +-- or a stringised formal argument (Str). +data ArgOrText = Arg | Text | Str deriving (Eq,Show) + +-- | Expand an instance of a macro. +-- Precondition: got a match on the macro name. +expandMacro :: HashDefine -> [String] -> Bool -> String +expandMacro macro parameters layout = + let env = zip (arguments macro) parameters + replace (Arg,s) = maybe ("") id (lookup s env) + replace (Str,s) = maybe (str "") str (lookup s env) + replace (Text,s) = if layout then s else filter (/='\n') s + str s = '"':s++"\"" + checkArity | length (arguments macro) == 1 && length parameters <= 1 + || length (arguments macro) == length parameters = id + | otherwise = error ("macro "++name macro++" expected "++ + show (length (arguments macro))++ + " arguments, but was given "++ + show (length parameters)) + in + checkArity $ concatMap replace (expansion macro) + +-- | Parse a \#define, or \#undef, ignoring other \# directives +parseHashDefine :: Bool -> [String] -> Maybe HashDefine +parseHashDefine ansi def = (command . skip) def + where + skip xss@(x:xs) | all isSpace x = skip xs + | otherwise = xss + skip [] = [] + command ("line":xs) = Just (LineDrop ("#line"++concat xs)) + command ("pragma":xs) = Just (Pragma ("#pragma"++concat xs)) + command ("define":xs) = Just (((define . skip) xs) { linebreaks=count def }) + command ("undef":xs) = Just (((undef . skip) xs)) + command _ = Nothing + undef (sym:_) = AntiDefined { name=sym, linebreaks=0 } + define (sym:xs) = case {-skip-} xs of + ("(":ys) -> (macroHead sym [] . skip) ys + ys -> symbolReplacement + { name=sym + , replacement = concatMap snd + (classifyRhs [] (chop (skip ys))) } + macroHead sym args (",":xs) = (macroHead sym args . skip) xs + macroHead sym args (")":xs) = MacroExpansion + { name =sym , arguments = reverse args + , expansion = classifyRhs args (skip xs) + , linebreaks = undefined } + macroHead sym args (var:xs) = (macroHead sym (var:args) . skip) xs + macroHead sym args [] = error ("incomplete macro definition:\n" + ++" #define "++sym++"(" + ++intercalate "," args) + classifyRhs args ("#":x:xs) + | ansi && + x `elem` args = (Str,x): classifyRhs args xs + classifyRhs args ("##":xs) + | ansi = classifyRhs args xs + classifyRhs args (s:"##":s':xs) + | ansi && all isSpace s && all isSpace s' + = classifyRhs args xs + classifyRhs args (word:xs) + | word `elem` args = (Arg,word): classifyRhs args xs + | otherwise = (Text,word): classifyRhs args xs + classifyRhs _ [] = [] + count = length . filter (=='\n') . concat + chop = reverse . dropWhile (all isSpace) . reverse + +-- | Pretty-print hash defines to a simpler format, as key-value pairs. +simplifyHashDefines :: [HashDefine] -> [(String,String)] +simplifyHashDefines = concatMap simp + where + simp hd@LineDrop{} = [] + simp hd@Pragma{} = [] + simp hd@AntiDefined{} = [] + simp hd@SymbolReplacement{} = [(name hd, replacement hd)] + simp hd@MacroExpansion{} = [(name hd++"("++intercalate "," (arguments hd) + ++")" + ,concatMap snd (expansion hd))]
@@ -0,0 +1,184 @@+----------------------------------------------------------------------------- +-- | +-- Module : MacroPass +-- Copyright : 2004 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : experimental +-- Portability : All +-- +-- Perform a cpp.second-pass, accumulating \#define's and \#undef's, +-- whilst doing symbol replacement and macro expansion. +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs.MacroPass + ( macroPass + , preDefine + , defineMacro + , macroPassReturningSymTab + ) where + +import Language.Preprocessor.Cpphs.HashDefine (HashDefine(..), expandMacro + , simplifyHashDefines) +import Language.Preprocessor.Cpphs.Tokenise (tokenise, WordStyle(..) + , parseMacroCall) +import Language.Preprocessor.Cpphs.SymTab (SymTab, lookupST, insertST + , emptyST, flattenST) +import Language.Preprocessor.Cpphs.Position (Posn, newfile, filename, lineno) +import Language.Preprocessor.Cpphs.Options (BoolOptions(..)) +import System.IO.Unsafe (unsafeInterleaveIO) +import Control.Monad ((=<<)) +import System.Time (getClockTime, toCalendarTime, formatCalendarTime) +import System.Locale (defaultTimeLocale) + +noPos :: Posn +noPos = newfile "preDefined" + +-- | Walk through the document, replacing calls of macros with the expanded RHS. +macroPass :: [(String,String)] -- ^ Pre-defined symbols and their values + -> BoolOptions -- ^ Options that alter processing style + -> [(Posn,String)] -- ^ The input file content + -> IO String -- ^ The file after processing +macroPass syms options = + fmap (safetail -- to remove extra "\n" inserted below + . concat + . onlyRights) + . macroProcess (pragma options) (layout options) (lang options) + (preDefine options syms) + . tokenise (stripEol options) (stripC89 options) + (ansi options) (lang options) + . ((noPos,""):) -- ensure recognition of "\n#" at start of file + where + safetail [] = [] + safetail (_:xs) = xs + +-- | auxiliary +onlyRights :: [Either a b] -> [b] +onlyRights = concatMap (\x->case x of Right t-> [t]; Left _-> [];) + +-- | Walk through the document, replacing calls of macros with the expanded RHS. +-- Additionally returns the active symbol table after processing. +macroPassReturningSymTab + :: [(String,String)] -- ^ Pre-defined symbols and their values + -> BoolOptions -- ^ Options that alter processing style + -> [(Posn,String)] -- ^ The input file content + -> IO (String,[(String,String)]) + -- ^ The file and symbol table after processing +macroPassReturningSymTab syms options = + fmap (mapFst (safetail -- to remove extra "\n" inserted below + . concat) + . walk) + . macroProcess (pragma options) (layout options) (lang options) + (preDefine options syms) + . tokenise (stripEol options) (stripC89 options) + (ansi options) (lang options) + . ((noPos,""):) -- ensure recognition of "\n#" at start of file + where + safetail [] = [] + safetail (_:xs) = xs + walk (Right x: rest) = let (xs, foo) = walk rest + in (x:xs, foo) + walk (Left x: []) = ( [] , simplifyHashDefines (flattenST x) ) + walk (Left x: rest) = walk rest + mapFst f (a,b) = (f a, b) + + +-- | Turn command-line definitions (from @-D@) into 'HashDefine's. +preDefine :: BoolOptions -> [(String,String)] -> SymTab HashDefine +preDefine options defines = + foldr (insertST . defineMacro options . (\ (s,d)-> s++" "++d)) + emptyST defines + +-- | Turn a string representing a macro definition into a 'HashDefine'. +defineMacro :: BoolOptions -> String -> (String,HashDefine) +defineMacro opts s = + let (Cmd (Just hd):_) = tokenise True True (ansi opts) (lang opts) + [(noPos,"\n#define "++s++"\n")] + in (name hd, hd) + + +-- | Trundle through the document, one word at a time, using the WordStyle +-- classification introduced by 'tokenise' to decide whether to expand a +-- word or macro. Encountering a \#define or \#undef causes that symbol to +-- be overwritten in the symbol table. Any other remaining cpp directives +-- are discarded and replaced with blanks, except for \#line markers. +-- All valid identifiers are checked for the presence of a definition +-- of that name in the symbol table, and if so, expanded appropriately. +-- (Bool arguments are: keep pragmas? retain layout? haskell language?) +-- The result lazily intersperses output text with symbol tables. Lines +-- are emitted as they are encountered. A symbol table is emitted after +-- each change to the defined symbols, and always at the end of processing. +macroProcess :: Bool -> Bool -> Bool -> SymTab HashDefine -> [WordStyle] + -> IO [Either (SymTab HashDefine) String] +macroProcess _ _ _ st [] = return [Left st] +macroProcess p y l st (Other x: ws) = emit x $ macroProcess p y l st ws +macroProcess p y l st (Cmd Nothing: ws) = emit "\n" $ macroProcess p y l st ws +macroProcess p y l st (Cmd (Just (LineDrop x)): ws) + = emit "\n" $ + emit x $ macroProcess p y l st ws +macroProcess pragma y l st (Cmd (Just (Pragma x)): ws) + | pragma = emit "\n" $ emit x $ macroProcess pragma y l st ws + | otherwise = emit "\n" $ macroProcess pragma y l st ws +macroProcess p layout lang st (Cmd (Just hd): ws) = + let n = 1 + linebreaks hd + newST = insertST (name hd, hd) st + in + emit (replicate n '\n') $ + emitSymTab newST $ + macroProcess p layout lang newST ws +macroProcess pr layout lang st (Ident p x: ws) = + case x of + "__FILE__" -> emit (show (filename p))$ macroProcess pr layout lang st ws + "__LINE__" -> emit (show (lineno p)) $ macroProcess pr layout lang st ws + "__DATE__" -> do w <- return . + formatCalendarTime defaultTimeLocale "\"%d %b %Y\"" + =<< toCalendarTime =<< getClockTime + emit w $ macroProcess pr layout lang st ws + "__TIME__" -> do w <- return . + formatCalendarTime defaultTimeLocale "\"%H:%M:%S\"" + =<< toCalendarTime =<< getClockTime + emit w $ macroProcess pr layout lang st ws + _ -> + case lookupST x st of + Nothing -> emit x $ macroProcess pr layout lang st ws + Just hd -> + case hd of + AntiDefined {name=n} -> emit n $ + macroProcess pr layout lang st ws + SymbolReplacement {replacement=r} -> + let r' = if layout then r else filter (/='\n') r in + -- one-level expansion only: + -- emit r' $ macroProcess layout st ws + -- multi-level expansion: + macroProcess pr layout lang st + (tokenise True True False lang [(p,r')] + ++ ws) + MacroExpansion {} -> + case parseMacroCall p ws of + Nothing -> emit x $ + macroProcess pr layout lang st ws + Just (args,ws') -> + if length args /= length (arguments hd) then + emit x $ macroProcess pr layout lang st ws + else do args' <- mapM (fmap (concat.onlyRights) + . macroProcess pr layout + lang st) + args + -- one-level expansion only: + -- emit (expandMacro hd args' layout) $ + -- macroProcess layout st ws' + -- multi-level expansion: + macroProcess pr layout lang st + (tokenise True True False lang + [(p,expandMacro hd args' layout)] + ++ ws') + +-- | Useful helper function. +emit :: a -> IO [Either b a] -> IO [Either b a] +emit x io = do xs <- unsafeInterleaveIO io + return (Right x:xs) +-- | Useful helper function. +emitSymTab :: b -> IO [Either b a] -> IO [Either b a] +emitSymTab x io = do xs <- unsafeInterleaveIO io + return (Left x:xs)
@@ -0,0 +1,156 @@+----------------------------------------------------------------------------- +-- | +-- Module : Options +-- Copyright : 2006 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : experimental +-- Portability : All +-- +-- This module deals with Cpphs options and parsing them +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs.Options + ( CpphsOptions(..) + , BoolOptions(..) + , parseOptions + , defaultCpphsOptions + , defaultBoolOptions + , trailing + ) where + +import Data.Maybe +import Data.List (isPrefixOf) + +-- | Cpphs options structure. +data CpphsOptions = CpphsOptions + { infiles :: [FilePath] + , outfiles :: [FilePath] + , defines :: [(String,String)] + , includes :: [String] + , preInclude:: [FilePath] -- ^ Files to \#include before anything else + , boolopts :: BoolOptions + } deriving (Show) + +-- | Default options. +defaultCpphsOptions :: CpphsOptions +defaultCpphsOptions = CpphsOptions { infiles = [], outfiles = [] + , defines = [], includes = [] + , preInclude = [] + , boolopts = defaultBoolOptions } + +-- | Options representable as Booleans. +data BoolOptions = BoolOptions + { macros :: Bool -- ^ Leave \#define and \#undef in output of ifdef? + , locations :: Bool -- ^ Place \#line droppings in output? + , hashline :: Bool -- ^ Write \#line or {-\# LINE \#-} ? + , pragma :: Bool -- ^ Keep \#pragma in final output? + , stripEol :: Bool -- ^ Remove C eol (\/\/) comments everywhere? + , stripC89 :: Bool -- ^ Remove C inline (\/**\/) comments everywhere? + , lang :: Bool -- ^ Lex input as Haskell code? + , ansi :: Bool -- ^ Permit stringise \# and catenate \#\# operators? + , layout :: Bool -- ^ Retain newlines in macro expansions? + , literate :: Bool -- ^ Remove literate markup? + , warnings :: Bool -- ^ Issue warnings? + } deriving (Show) + +-- | Default settings of boolean options. +defaultBoolOptions :: BoolOptions +defaultBoolOptions = BoolOptions { macros = True, locations = True + , hashline = True, pragma = False + , stripEol = False, stripC89 = False + , lang = True, ansi = False + , layout = False, literate = False + , warnings = True } + +-- | Raw command-line options. This is an internal intermediate data +-- structure, used during option parsing only. +data RawOption + = NoMacro + | NoLine + | LinePragma + | Pragma + | Text + | Strip + | StripEol + | Ansi + | Layout + | Unlit + | SuppressWarnings + | Macro (String,String) + | Path String + | PreInclude FilePath + | IgnoredForCompatibility + deriving (Eq, Show) + +flags :: [(String, RawOption)] +flags = [ ("--nomacro", NoMacro) + , ("--noline", NoLine) + , ("--linepragma", LinePragma) + , ("--pragma", Pragma) + , ("--text", Text) + , ("--strip", Strip) + , ("--strip-eol", StripEol) + , ("--hashes", Ansi) + , ("--layout", Layout) + , ("--unlit", Unlit) + , ("--nowarn", SuppressWarnings) + ] + +-- | Parse a single raw command-line option. Parse failure is indicated by +-- result Nothing. +rawOption :: String -> Maybe RawOption +rawOption x | isJust a = a + where a = lookup x flags +rawOption ('-':'D':xs) = Just $ Macro (s, if null d then "1" else tail d) + where (s,d) = break (=='=') xs +rawOption ('-':'U':xs) = Just $ IgnoredForCompatibility +rawOption ('-':'I':xs) = Just $ Path $ trailing "/\\" xs +rawOption xs | "--include="`isPrefixOf`xs + = Just $ PreInclude (drop 10 xs) +rawOption _ = Nothing + +-- | Trim trailing elements of the second list that match any from +-- the first list. Typically used to remove trailing forward\/back +-- slashes from a directory path. +trailing :: (Eq a) => [a] -> [a] -> [a] +trailing xs = reverse . dropWhile (`elem`xs) . reverse + +-- | Convert a list of RawOption to a BoolOptions structure. +boolOpts :: [RawOption] -> BoolOptions +boolOpts opts = + BoolOptions + { macros = not (NoMacro `elem` opts) + , locations = not (NoLine `elem` opts) + , hashline = not (LinePragma `elem` opts) + , pragma = Pragma `elem` opts + , stripEol = StripEol`elem` opts + , stripC89 = StripEol`elem` opts || Strip `elem` opts + , lang = not (Text `elem` opts) + , ansi = Ansi `elem` opts + , layout = Layout `elem` opts + , literate = Unlit `elem` opts + , warnings = not (SuppressWarnings `elem` opts) + } + +-- | Parse all command-line options. +parseOptions :: [String] -> Either String CpphsOptions +parseOptions xs = f ([], [], []) xs + where + f (opts, ins, outs) (('-':'O':x):xs) = f (opts, ins, x:outs) xs + f (opts, ins, outs) (x@('-':_):xs) = case rawOption x of + Nothing -> Left x + Just a -> f (a:opts, ins, outs) xs + f (opts, ins, outs) (x:xs) = f (opts, normalise x:ins, outs) xs + f (opts, ins, outs) [] = + Right CpphsOptions { infiles = reverse ins + , outfiles = reverse outs + , defines = [ x | Macro x <- reverse opts ] + , includes = [ x | Path x <- reverse opts ] + , preInclude=[ x | PreInclude x <- reverse opts ] + , boolopts = boolOpts opts + } + normalise ('/':'/':filepath) = normalise ('/':filepath) + normalise (x:filepath) = x:normalise filepath + normalise [] = []
@@ -0,0 +1,106 @@+----------------------------------------------------------------------------- +-- | +-- Module : Position +-- Copyright : 2000-2004 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : experimental +-- Portability : All +-- +-- Simple file position information, with recursive inclusion points. +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs.Position + ( Posn(..) + , newfile + , addcol, newline, tab, newlines, newpos + , cppline, haskline, cpp2hask + , filename, lineno, directory + , cleanPath + ) where + +import Data.List (isPrefixOf) + +-- | Source positions contain a filename, line, column, and an +-- inclusion point, which is itself another source position, +-- recursively. +data Posn = Pn String !Int !Int (Maybe Posn) + deriving (Eq) + +instance Show Posn where + showsPrec _ (Pn f l c i) = showString f . + showString " at line " . shows l . + showString " col " . shows c . + ( case i of + Nothing -> id + Just p -> showString "\n used by " . + shows p ) + +-- | Constructor. Argument is filename. +newfile :: String -> Posn +newfile name = Pn (cleanPath name) 1 1 Nothing + +-- | Increment column number by given quantity. +addcol :: Int -> Posn -> Posn +addcol n (Pn f r c i) = Pn f r (c+n) i + +-- | Increment row number, reset column to 1. +newline :: Posn -> Posn +--newline (Pn f r _ i) = Pn f (r+1) 1 i +newline (Pn f r _ i) = let r' = r+1 in r' `seq` Pn f r' 1 i + +-- | Increment column number, tab stops are every 8 chars. +tab :: Posn -> Posn +tab (Pn f r c i) = Pn f r (((c`div`8)+1)*8) i + +-- | Increment row number by given quantity. +newlines :: Int -> Posn -> Posn +newlines n (Pn f r _ i) = Pn f (r+n) 1 i + +-- | Update position with a new row, and possible filename. +newpos :: Int -> Maybe String -> Posn -> Posn +newpos r Nothing (Pn f _ c i) = Pn f r c i +newpos r (Just ('"':f)) (Pn _ _ c i) = Pn (init f) r c i +newpos r (Just f) (Pn _ _ c i) = Pn f r c i + +-- | Project the line number. +lineno :: Posn -> Int +-- | Project the filename. +filename :: Posn -> String +-- | Project the directory of the filename. +directory :: Posn -> FilePath + +lineno (Pn _ r _ _) = r +filename (Pn f _ _ _) = f +directory (Pn f _ _ _) = dirname f + + +-- | cpp-style printing of file position +cppline :: Posn -> String +cppline (Pn f r _ _) = "#line "++show r++" "++show f + +-- | haskell-style printing of file position +haskline :: Posn -> String +haskline (Pn f r _ _) = "{-# LINE "++show r++" "++show f++" #-}" + +-- | Conversion from a cpp-style "#line" to haskell-style pragma. +cpp2hask :: String -> String +cpp2hask line | "#line" `isPrefixOf` line = "{-# LINE " + ++unwords (tail (words line)) + ++" #-}" + | otherwise = line + +-- | Strip non-directory suffix from file name (analogous to the shell +-- command of the same name). +dirname :: String -> String +dirname = reverse . safetail . dropWhile (not.(`elem`"\\/")) . reverse + where safetail [] = [] + safetail (_:x) = x + +-- | Sigh. Mixing Windows filepaths with unix is bad. Make sure there is a +-- canonical path separator. +cleanPath :: FilePath -> FilePath +cleanPath [] = [] +cleanPath ('\\':cs) = '/': cleanPath cs +cleanPath (c:cs) = c: cleanPath cs
@@ -0,0 +1,55 @@+----------------------------------------------------------------------------- +-- | +-- Module : ReadFirst +-- Copyright : 2004 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : experimental +-- Portability : All +-- +-- Read the first file that matches in a list of search paths. +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs.ReadFirst + ( readFirst + ) where + +import System.IO (hPutStrLn, stderr) +import System.Directory (doesFileExist) +import Data.List (intersperse) +import Control.Monad (when) +import Language.Preprocessor.Cpphs.Position (Posn,directory,cleanPath) + +-- | Attempt to read the given file from any location within the search path. +-- The first location found is returned, together with the file content. +-- (The directory of the calling file is always searched first, then +-- the current directory, finally any specified search path.) +readFirst :: String -- ^ filename + -> Posn -- ^ inclusion point + -> [String] -- ^ search path + -> Bool -- ^ report warnings? + -> IO ( FilePath + , String + ) -- ^ discovered filepath, and file contents + +readFirst name demand path warn = + case name of + '/':nm -> try nm [""] + _ -> try name (cons dd (".":path)) + where + dd = directory demand + cons x xs = if null x then xs else x:xs + try name [] = do + when warn $ + hPutStrLn stderr ("Warning: Can't find file \""++name + ++"\" in directories\n\t" + ++concat (intersperse "\n\t" (cons dd (".":path))) + ++"\n Asked for by: "++show demand) + return ("missing file: "++name,"") + try name (p:ps) = do + let file = cleanPath p++'/':cleanPath name + ok <- doesFileExist file + if not ok then try name ps + else do content <- readFile file + return (file,content)
@@ -0,0 +1,82 @@+{- +-- The main program for cpphs, a simple C pre-processor written in Haskell. + +-- Copyright (c) 2004 Malcolm Wallace +-- This file is LGPL (relicensed from the GPL by Malcolm Wallace, October 2011). +-} +module Language.Preprocessor.Cpphs.RunCpphs ( runCpphs + , runCpphsPass1 + , runCpphsPass2 + , runCpphsReturningSymTab + ) where + +import Language.Preprocessor.Cpphs.CppIfdef (cppIfdef) +import Language.Preprocessor.Cpphs.MacroPass(macroPass,macroPassReturningSymTab) +import Language.Preprocessor.Cpphs.Options (CpphsOptions(..), BoolOptions(..) + ,trailing) +import Language.Preprocessor.Cpphs.Tokenise (deWordStyle, tokenise) +import Language.Preprocessor.Cpphs.Position (cleanPath, Posn) +import Language.Preprocessor.Unlit as Unlit (unlit) + + +runCpphs :: CpphsOptions -> FilePath -> String -> IO String +runCpphs options filename input = do + pass1 <- runCpphsPass1 options filename input + runCpphsPass2 (boolopts options) (defines options) filename pass1 + +runCpphsPass1 :: CpphsOptions -> FilePath -> String -> IO [(Posn,String)] +runCpphsPass1 options' filename input = do + let options= options'{ includes= map (trailing "\\/") (includes options') } + let bools = boolopts options + preInc = case preInclude options of + [] -> "" + is -> concatMap (\f->"#include \""++f++"\"\n") is + ++ "#line 1 \""++cleanPath filename++"\"\n" + + pass1 <- cppIfdef filename (defines options) (includes options) bools + (preInc++input) + return pass1 + +runCpphsPass2 :: BoolOptions -> [(String,String)] -> FilePath -> [(Posn,String)] -> IO String +runCpphsPass2 bools defines filename pass1 = do + pass2 <- macroPass defines bools pass1 + let result= if not (macros bools) + then if stripC89 bools || stripEol bools + then concatMap deWordStyle $ + tokenise (stripEol bools) (stripC89 bools) + (ansi bools) (lang bools) pass1 + else unlines (map snd pass1) + else pass2 + pass3 = if literate bools then Unlit.unlit filename else id + return (pass3 result) + +runCpphsReturningSymTab :: CpphsOptions -> FilePath -> String + -> IO (String,[(String,String)]) +runCpphsReturningSymTab options' filename input = do + let options= options'{ includes= map (trailing "\\/") (includes options') } + let bools = boolopts options + preInc = case preInclude options of + [] -> "" + is -> concatMap (\f->"#include \""++f++"\"\n") is + ++ "#line 1 \""++cleanPath filename++"\"\n" + (pass2,syms) <- + if macros bools then do + pass1 <- cppIfdef filename (defines options) (includes options) + bools (preInc++input) + macroPassReturningSymTab (defines options) bools pass1 + else do + pass1 <- cppIfdef filename (defines options) (includes options) + bools{macros=True} (preInc++input) + (_,syms) <- macroPassReturningSymTab (defines options) bools pass1 + pass1 <- cppIfdef filename (defines options) (includes options) + bools (preInc++input) + let result = if stripC89 bools || stripEol bools + then concatMap deWordStyle $ + tokenise (stripEol bools) (stripC89 bools) + (ansi bools) (lang bools) pass1 + else init $ unlines (map snd pass1) + return (result,syms) + + let pass3 = if literate bools then Unlit.unlit filename else id + return (pass3 pass2, syms) +
@@ -0,0 +1,92 @@+----------------------------------------------------------------------------- +-- | +-- Module : SymTab +-- Copyright : 2000-2004 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : Stable +-- Portability : All +-- +-- Symbol Table, based on index trees using a hash on the key. +-- Keys are always Strings. Stored values can be any type. +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs.SymTab + ( SymTab + , emptyST + , insertST + , deleteST + , lookupST + , definedST + , flattenST + , IndTree + ) where + +-- | Symbol Table. Stored values are polymorphic, but the keys are +-- always strings. +type SymTab v = IndTree [(String,v)] + +emptyST :: SymTab v +insertST :: (String,v) -> SymTab v -> SymTab v +deleteST :: String -> SymTab v -> SymTab v +lookupST :: String -> SymTab v -> Maybe v +definedST :: String -> SymTab v -> Bool +flattenST :: SymTab v -> [v] + +emptyST = itgen maxHash [] +insertST (s,v) ss = itiap (hash s) ((s,v):) ss id +deleteST s ss = itiap (hash s) (filter ((/=s).fst)) ss id +lookupST s ss = let vs = filter ((==s).fst) ((itind (hash s)) ss) + in if null vs then Nothing + else (Just . snd . head) vs +definedST s ss = let vs = filter ((==s).fst) ((itind (hash s)) ss) + in (not . null) vs +flattenST ss = itfold (map snd) (++) ss + + +---- +-- | Index Trees (storing indexes at nodes). + +data IndTree t = Leaf t | Fork Int (IndTree t) (IndTree t) + deriving Show + +itgen :: Int -> a -> IndTree a +itgen 1 x = Leaf x +itgen n x = + let n' = n `div` 2 + in Fork n' (itgen n' x) (itgen (n-n') x) + +itiap :: --Eval a => + Int -> (a->a) -> IndTree a -> (IndTree a -> b) -> b +itiap _ f (Leaf x) k = let fx = f x in {-seq fx-} (k (Leaf fx)) +itiap i f (Fork n lt rt) k = + if i<n then + itiap i f lt $ \lt' -> k (Fork n lt' rt) + else itiap (i-n) f rt $ \rt' -> k (Fork n lt rt') + +itind :: Int -> IndTree a -> a +itind _ (Leaf x) = x +itind i (Fork n lt rt) = if i<n then itind i lt else itind (i-n) rt + +itfold :: (a->b) -> (b->b->b) -> IndTree a -> b +itfold leaf _fork (Leaf x) = leaf x +itfold leaf fork (Fork _ l r) = fork (itfold leaf fork l) (itfold leaf fork r) + +---- +-- Hash values + +maxHash :: Int -- should be prime +maxHash = 101 + +class Hashable a where + hashWithMax :: Int -> a -> Int + hash :: a -> Int + hash = hashWithMax maxHash + +instance Enum a => Hashable [a] where + hashWithMax m = h 0 + where h a [] = a + h a (c:cs) = h ((17*(fromEnum c)+19*a)`rem`m) cs + +----
@@ -0,0 +1,281 @@+----------------------------------------------------------------------------- +-- | +-- Module : Tokenise +-- Copyright : 2004 Malcolm Wallace +-- Licence : LGPL +-- +-- Maintainer : Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk> +-- Stability : experimental +-- Portability : All +-- +-- The purpose of this module is to lex a source file (language +-- unspecified) into tokens such that cpp can recognise a replaceable +-- symbol or macro-use, and do the right thing. +----------------------------------------------------------------------------- + +module Language.Preprocessor.Cpphs.Tokenise + ( linesCpp + , reslash + , tokenise + , WordStyle(..) + , deWordStyle + , parseMacroCall + ) where + +import Data.Char +import Language.Preprocessor.Cpphs.HashDefine +import Language.Preprocessor.Cpphs.Position + +-- | A Mode value describes whether to tokenise a la Haskell, or a la Cpp. +-- The main difference is that in Cpp mode we should recognise line +-- continuation characters. +data Mode = Haskell | Cpp + +-- | linesCpp is, broadly speaking, Prelude.lines, except that +-- on a line beginning with a \#, line continuation characters are +-- recognised. In a line continuation, the newline character is +-- preserved, but the backslash is not. +linesCpp :: String -> [String] +linesCpp [] = [] +linesCpp (x:xs) | x=='#' = tok Cpp ['#'] xs + | otherwise = tok Haskell [] (x:xs) + where + tok Cpp acc ('\\':'\n':ys) = tok Cpp ('\n':acc) ys + tok _ acc ('\n':'#':ys) = reverse acc: tok Cpp ['#'] ys + tok _ acc ('\n':ys) = reverse acc: tok Haskell [] ys + tok _ acc [] = reverse acc: [] + tok mode acc (y:ys) = tok mode (y:acc) ys + +-- | Put back the line-continuation characters. +reslash :: String -> String +reslash ('\n':xs) = '\\':'\n':reslash xs +reslash (x:xs) = x: reslash xs +reslash [] = [] + +---- +-- | Submodes are required to deal correctly with nesting of lexical +-- structures. +data SubMode = Any | Pred (Char->Bool) (Posn->String->WordStyle) + | String Char | LineComment | NestComment Int + | CComment | CLineComment + +-- | Each token is classified as one of Ident, Other, or Cmd: +-- * Ident is a word that could potentially match a macro name. +-- * Cmd is a complete cpp directive (\#define etc). +-- * Other is anything else. +data WordStyle = Ident Posn String | Other String | Cmd (Maybe HashDefine) + deriving (Eq,Show) +other :: Posn -> String -> WordStyle +other _ s = Other s + +deWordStyle :: WordStyle -> String +deWordStyle (Ident _ i) = i +deWordStyle (Other i) = i +deWordStyle (Cmd _) = "\n" + +-- | tokenise is, broadly-speaking, Prelude.words, except that: +-- * the input is already divided into lines +-- * each word-like "token" is categorised as one of {Ident,Other,Cmd} +-- * \#define's are parsed and returned out-of-band using the Cmd variant +-- * All whitespace is preserved intact as tokens. +-- * C-comments are converted to white-space (depending on first param) +-- * Parens and commas are tokens in their own right. +-- * Any cpp line continuations are respected. +-- No errors can be raised. +-- The inverse of tokenise is (concatMap deWordStyle). +tokenise :: Bool -> Bool -> Bool -> Bool -> [(Posn,String)] -> [WordStyle] +tokenise _ _ _ _ [] = [] +tokenise stripEol stripComments ansi lang ((pos,str):pos_strs) = + (if lang then haskell else plaintext) Any [] pos pos_strs str + where + -- rules to lex Haskell + haskell :: SubMode -> String -> Posn -> [(Posn,String)] + -> String -> [WordStyle] + haskell Any acc p ls ('\n':'#':xs) = emit acc $ -- emit "\n" $ + cpp Any haskell [] [] p ls xs + -- warning: non-maximal munch on comment + haskell Any acc p ls ('-':'-':xs) = emit acc $ + haskell LineComment "--" p ls xs + haskell Any acc p ls ('{':'-':xs) = emit acc $ + haskell (NestComment 0) "-{" p ls xs + haskell Any acc p ls ('/':'*':xs) + | stripComments = emit acc $ + haskell CComment " " p ls xs + haskell Any acc p ls ('/':'/':xs) + | stripEol = emit acc $ + haskell CLineComment " " p ls xs + haskell Any acc p ls ('"':xs) = emit acc $ + haskell (String '"') ['"'] p ls xs + haskell Any acc p ls ('\'':'\'':xs) = emit acc $ -- TH type quote + haskell Any "''" p ls xs + haskell Any acc p ls ('\'':xs@('\\':_)) = emit acc $ -- escaped char literal + haskell (String '\'') "'" p ls xs + haskell Any acc p ls ('\'':x:'\'':xs) = emit acc $ -- character literal + emit ['\'', x, '\''] $ + haskell Any [] p ls xs + haskell Any acc p ls ('\'':xs) = emit acc $ -- TH name quote + haskell Any "'" p ls xs + haskell Any acc p ls (x:xs) | single x = emit acc $ emit [x] $ + haskell Any [] p ls xs + haskell Any acc p ls (x:xs) | space x = emit acc $ + haskell (Pred space other) [x] + p ls xs + haskell Any acc p ls (x:xs) | symbol x = emit acc $ + haskell (Pred symbol other) [x] + p ls xs + -- haskell Any [] p ls (x:xs) | ident0 x = id $ + haskell Any acc p ls (x:xs) | ident0 x = emit acc $ + haskell (Pred ident1 Ident) [x] + p ls xs + haskell Any acc p ls (x:xs) = haskell Any (x:acc) p ls xs + + haskell pre@(Pred pred ws) acc p ls (x:xs) + | pred x = haskell pre (x:acc) p ls xs + haskell (Pred _ ws) acc p ls xs = ws p (reverse acc): + haskell Any [] p ls xs + haskell (String c) acc p ls ('\\':x:xs) + | x=='\\' = haskell (String c) ('\\':'\\':acc) p ls xs + | x==c = haskell (String c) (c:'\\':acc) p ls xs + haskell (String c) acc p ls (x:xs) + | x==c = emit (c:acc) $ haskell Any [] p ls xs + | otherwise = haskell (String c) (x:acc) p ls xs + haskell LineComment acc p ls xs@('\n':_) = emit acc $ haskell Any [] p ls xs + haskell LineComment acc p ls (x:xs) = haskell LineComment (x:acc) p ls xs + haskell (NestComment n) acc p ls ('{':'-':xs) + = haskell (NestComment (n+1)) + ("-{"++acc) p ls xs + haskell (NestComment 0) acc p ls ('-':'}':xs) + = emit ("}-"++acc) $ haskell Any [] p ls xs + haskell (NestComment n) acc p ls ('-':'}':xs) + = haskell (NestComment (n-1)) + ("}-"++acc) p ls xs + haskell (NestComment n) acc p ls (x:xs) = haskell (NestComment n) (x:acc) + p ls xs + haskell CComment acc p ls ('*':'/':xs) = emit (" "++acc) $ + haskell Any [] p ls xs + haskell CComment acc p ls (x:xs) = haskell CComment (white x:acc) p ls xs + haskell CLineComment acc p ls xs@('\n':_)= emit acc $ haskell Any [] p ls xs + haskell CLineComment acc p ls (_:xs) = haskell CLineComment (' ':acc) + p ls xs + haskell mode acc _ ((p,l):ls) [] = haskell mode acc p ls ('\n':l) + haskell _ acc _ [] [] = emit acc $ [] + + -- rules to lex Cpp + cpp :: SubMode -> (SubMode -> String -> Posn -> [(Posn,String)] + -> String -> [WordStyle]) + -> String -> [String] -> Posn -> [(Posn,String)] + -> String -> [WordStyle] + cpp mode next word line pos remaining input = + lexcpp mode word line remaining input + where + lexcpp Any w l ls ('/':'*':xs) = lexcpp (NestComment 0) "" (w*/*l) ls xs + lexcpp Any w l ls ('/':'/':xs) = lexcpp LineComment " " (w*/*l) ls xs + lexcpp Any w l ((p,l'):ls) ('\\':[]) = cpp Any next [] ("\n":w*/*l) p ls l' + lexcpp Any w l ls ('\\':'\n':xs) = lexcpp Any [] ("\n":w*/*l) ls xs + lexcpp Any w l ls xs@('\n':_) = Cmd (parseHashDefine ansi + (reverse (w*/*l))): + next Any [] pos ls xs + -- lexcpp Any w l ls ('"':xs) = lexcpp (String '"') ['"'] (w*/*l) ls xs + -- lexcpp Any w l ls ('\'':xs) = lexcpp (String '\'') "'" (w*/*l) ls xs + lexcpp Any w l ls ('"':xs) = lexcpp Any [] ("\"":(w*/*l)) ls xs + lexcpp Any w l ls ('\'':xs) = lexcpp Any [] ("'": (w*/*l)) ls xs + lexcpp Any [] l ls (x:xs) + | ident0 x = lexcpp (Pred ident1 Ident) [x] l ls xs + -- lexcpp Any w l ls (x:xs) | ident0 x = lexcpp (Pred ident1 Ident) [x] (w*/*l) ls xs + lexcpp Any w l ls (x:xs) + | single x = lexcpp Any [] ([x]:w*/*l) ls xs + | space x = lexcpp (Pred space other) [x] (w*/*l) ls xs + | symbol x = lexcpp (Pred symbol other) [x] (w*/*l) ls xs + | otherwise = lexcpp Any (x:w) l ls xs + lexcpp pre@(Pred pred _) w l ls (x:xs) + | pred x = lexcpp pre (x:w) l ls xs + lexcpp (Pred _ _) w l ls xs = lexcpp Any [] (w*/*l) ls xs + lexcpp (String c) w l ls ('\\':x:xs) + | x=='\\' = lexcpp (String c) ('\\':'\\':w) l ls xs + | x==c = lexcpp (String c) (c:'\\':w) l ls xs + lexcpp (String c) w l ls (x:xs) + | x==c = lexcpp Any [] ((c:w)*/*l) ls xs + | otherwise = lexcpp (String c) (x:w) l ls xs + lexcpp LineComment w l ((p,l'):ls) ('\\':[]) + = cpp LineComment next [] (('\n':w)*/*l) pos ls l' + lexcpp LineComment w l ls ('\\':'\n':xs) + = lexcpp LineComment [] (('\n':w)*/*l) ls xs + lexcpp LineComment w l ls xs@('\n':_) = lexcpp Any w l ls xs + lexcpp LineComment w l ls (_:xs) = lexcpp LineComment (' ':w) l ls xs + lexcpp (NestComment _) w l ls ('*':'/':xs) + = lexcpp Any [] (w*/*l) ls xs + lexcpp (NestComment n) w l ls (x:xs) = lexcpp (NestComment n) (white x:w) l + ls xs + lexcpp mode w l ((p,l'):ls) [] = cpp mode next w l p ls ('\n':l') + lexcpp _ _ _ [] [] = [] + + -- rules to lex non-Haskell, non-cpp text + plaintext :: SubMode -> String -> Posn -> [(Posn,String)] + -> String -> [WordStyle] + plaintext Any acc p ls ('\n':'#':xs) = emit acc $ -- emit "\n" $ + cpp Any plaintext [] [] p ls xs + plaintext Any acc p ls ('/':'*':xs) + | stripComments = emit acc $ + plaintext CComment " " p ls xs + plaintext Any acc p ls ('/':'/':xs) + | stripEol = emit acc $ + plaintext CLineComment " " p ls xs + plaintext Any acc p ls (x:xs) | single x = emit acc $ emit [x] $ + plaintext Any [] p ls xs + plaintext Any acc p ls (x:xs) | space x = emit acc $ + plaintext (Pred space other) [x] + p ls xs + plaintext Any acc p ls (x:xs) | ident0 x = emit acc $ + plaintext (Pred ident1 Ident) [x] + p ls xs + plaintext Any acc p ls (x:xs) = plaintext Any (x:acc) p ls xs + plaintext pre@(Pred pred ws) acc p ls (x:xs) + | pred x = plaintext pre (x:acc) p ls xs + plaintext (Pred _ ws) acc p ls xs = ws p (reverse acc): + plaintext Any [] p ls xs + plaintext CComment acc p ls ('*':'/':xs) = emit (" "++acc) $ + plaintext Any [] p ls xs + plaintext CComment acc p ls (x:xs) = plaintext CComment (white x:acc) p ls xs + plaintext CLineComment acc p ls xs@('\n':_) + = emit acc $ plaintext Any [] p ls xs + plaintext CLineComment acc p ls (_:xs)= plaintext CLineComment (' ':acc) + p ls xs + plaintext mode acc _ ((p,l):ls) [] = plaintext mode acc p ls ('\n':l) + plaintext _ acc _ [] [] = emit acc $ [] + + -- predicates for lexing Haskell. + ident0 x = isAlpha x || x `elem` "_`" + ident1 x = isAlphaNum x || x `elem` "'_`" + symbol x = x `elem` ":!#$%&*+./<=>?@\\^|-~" + single x = x `elem` "(),[];{}" + space x = x `elem` " \t" + -- conversion of comment text to whitespace + white '\n' = '\n' + white '\r' = '\r' + white _ = ' ' + -- emit a token (if there is one) from the accumulator + emit "" = id + emit xs = (Other (reverse xs):) + -- add a reversed word to the accumulator + "" */* l = l + w */* l = reverse w : l + -- help out broken Haskell compilers which need balanced numbers of C + -- comments in order to do import chasing :-) -----> */* + + +-- | Parse a possible macro call, returning argument list and remaining input +parseMacroCall :: Posn -> [WordStyle] -> Maybe ([[WordStyle]],[WordStyle]) +parseMacroCall p = call . skip + where + skip (Other x:xs) | all isSpace x = skip xs + skip xss = xss + call (Other "(":xs) = (args (0::Int) [] [] . skip) xs + call _ = Nothing + args 0 w acc ( Other ")" :xs) = Just (reverse (addone w acc), xs) + args 0 w acc ( Other "," :xs) = args 0 [] (addone w acc) (skip xs) + args n w acc (x@(Other "("):xs) = args (n+1) (x:w) acc xs + args n w acc (x@(Other ")"):xs) = args (n-1) (x:w) acc xs + args n w acc ( Ident _ v :xs) = args n (Ident p v:w) acc xs + args n w acc (x@(Other _) :xs) = args n (x:w) acc xs + args _ _ _ _ = Nothing + addone w acc = reverse (skip w): acc
@@ -0,0 +1,72 @@+-- | Part of this code is from "Report on the Programming Language Haskell", +-- version 1.2, appendix C. +module Language.Preprocessor.Unlit (unlit) where + +import Data.Char +import Data.List (isPrefixOf) + +data Classified = Program String | Blank | Comment + | Include Int String | Pre String + +classify :: [String] -> [Classified] +classify [] = [] +classify (('\\':x):xs) | x == "begin{code}" = Blank : allProg xs + where allProg [] = [] -- Should give an error message, + -- but I have no good position information. + allProg (('\\':x):xs) | "end{code}"`isPrefixOf`x = Blank : classify xs + allProg (x:xs) = Program x:allProg xs +classify (('>':x):xs) = Program (' ':x) : classify xs +classify (('#':x):xs) = (case words x of + (line:rest) | all isDigit line + -> Include (read line) (unwords rest) + _ -> Pre x + ) : classify xs +--classify (x:xs) | "{-# LINE" `isPrefixOf` x = Program x: classify xs +classify (x:xs) | all isSpace x = Blank:classify xs +classify (x:xs) = Comment:classify xs + +unclassify :: Classified -> String +unclassify (Program s) = s +unclassify (Pre s) = '#':s +unclassify (Include i f) = '#':' ':show i ++ ' ':f +unclassify Blank = "" +unclassify Comment = "" + +-- | 'unlit' takes a filename (for error reports), and transforms the +-- given string, to eliminate the literate comments from the program text. +unlit :: FilePath -> String -> String +unlit file lhs = (unlines + . map unclassify + . adjacent file (0::Int) Blank + . classify) (inlines lhs) + +adjacent :: FilePath -> Int -> Classified -> [Classified] -> [Classified] +adjacent file 0 _ (x :xs) = x : adjacent file 1 x xs -- force evaluation of line number +adjacent file n y@(Program _) (x@Comment :xs) = error (message file n "program" "comment") +adjacent file n y@(Program _) (x@(Include i f):xs) = x: adjacent f i y xs +adjacent file n y@(Program _) (x@(Pre _) :xs) = x: adjacent file (n+1) y xs +adjacent file n y@Comment (x@(Program _) :xs) = error (message file n "comment" "program") +adjacent file n y@Comment (x@(Include i f):xs) = x: adjacent f i y xs +adjacent file n y@Comment (x@(Pre _) :xs) = x: adjacent file (n+1) y xs +adjacent file n y@Blank (x@(Include i f):xs) = x: adjacent f i y xs +adjacent file n y@Blank (x@(Pre _) :xs) = x: adjacent file (n+1) y xs +adjacent file n _ (x@next :xs) = x: adjacent file (n+1) x xs +adjacent file n _ [] = [] + +message :: String -> Int -> String -> String -> String +message "\"\"" n p c = "Line "++show n++": "++p++ " line before "++c++" line.\n" +message [] n p c = "Line "++show n++": "++p++ " line before "++c++" line.\n" +message file n p c = "In file " ++ file ++ " at line "++show n++": "++p++ " line before "++c++" line.\n" + + +-- Re-implementation of 'lines', for better efficiency (but decreased laziness). +-- Also, importantly, accepts non-standard DOS and Mac line ending characters. +inlines :: String -> [String] +inlines s = lines' s id + where + lines' [] acc = [acc []] + lines' ('\^M':'\n':s) acc = acc [] : lines' s id -- DOS + lines' ('\^M':s) acc = acc [] : lines' s id -- MacOS + lines' ('\n':s) acc = acc [] : lines' s id -- Unix + lines' (c:s) acc = lines' s (acc . (c:)) +
@@ -0,0 +1,9 @@+{-# LANGUAGE DuplicateRecordFields #-} +module Decl.AmbiguousFields where + +data A = A { x, y :: Int } +data B = B { x, y :: Int } + +f :: A -> Int +f = x +
@@ -0,0 +1,8 @@+module Decl.AnnPragma where +{-# ANN module (Just "Hello") #-} +{-# ANN f (Just "Hello") #-} +f :: Int -> Int +f a = a + 1 + +{-# ANN type A (Just "Hello") #-} +data A = A
@@ -0,0 +1,10 @@+module Decl.ClassInfix where + +import Control.Applicative + +class Applicative f => MonoidApplicative f where + infixl 4 +<*> + (+<*>) :: f (a -> a) -> f a -> f a + + infixl 5 >< + (><) :: Monoid a => f a -> f a -> f a
@@ -0,0 +1,9 @@+{-# LANGUAGE TypeFamilies #-} +module Decl.ClosedTypeFamily where + +type family F a where + F Int = Bool + F Bool = Char + F a = Bool + +type family ClosedEmpty t where
@@ -0,0 +1,16 @@+{-# LANGUAGE PatternSynonyms #-} +module Decl.CompletePragma where + +data Choice a = Choice Bool a + +pattern LeftChoice :: a -> Choice a +pattern LeftChoice a = Choice False a + +pattern RightChoice :: a -> Choice a +pattern RightChoice a = Choice True a + +{-# COMPLETE LeftChoice, RightChoice #-} + +foo :: Choice Int -> Int +foo (LeftChoice n) = n * 2 +foo (RightChoice n) = n - 2
@@ -0,0 +1,10 @@+{-# LANGUAGE TypeOperators #-} +module Decl.CtorOp where + +data a :+: b = a :+: b + +data (a :!: b) c = a c :!: b c + +data ((:-:) a) b = a :-: b + +data (:*:) a b = a :*: b
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeFamilies #-} +module Decl.DataFamily where + +data family Array :: * -> * + +data instance Array () = UnitArray Int deriving Show
@@ -0,0 +1,6 @@+{-# LANGUAGE GADTs, KindSignatures, TypeFamilies #-} +module Decl.DataInstanceGADT where + +data family GadtFam (a :: *) (b :: *) +data instance GadtFam c d where + MkGadtFam1 :: x -> y -> GadtFam y x
@@ -0,0 +1,5 @@+module Decl.DataType where + +data EmptyData + +data A = B Int | C
@@ -0,0 +1,5 @@+module Decl.DataTypeDerivings where + +data A = A deriving (Eq, Show) +data B = B deriving (Eq) +data C = C deriving Eq
@@ -0,0 +1,3 @@+module Decl.DefaultDecl where + +default ()
@@ -0,0 +1,4 @@+module Decl.FunBind where + +f 0 = 1 +f x = x
@@ -0,0 +1,5 @@+module Decl.FunFixity where + +infixl `snoc` +snoc :: [a] -> a -> [a] +snoc xs x = xs ++ [x]
@@ -0,0 +1,5 @@+module Decl.FunGuards where + +f 0 = 1 +f x | even x = 0 + | otherwise = 2
@@ -0,0 +1,6 @@+{-# LANGUAGE FunctionalDependencies, MultiParamTypeClasses #-} +module Decl.FunctionalDeps where + +class C a b | a -> b, b -> a where + trf :: a -> b +
@@ -0,0 +1,9 @@+{-# LANGUAGE GADTs, KindSignatures, DeriveDataTypeable #-} +module Decl.GADT where + +import Data.Typeable + +data DMap k f where + Tip :: DMap k f + Bin :: !Int -> !(k v) -> f v -> !(DMap k f) -> !(DMap k f) -> DMap k f + deriving Typeable
@@ -0,0 +1,5 @@+{-# LANGUAGE GADTs #-} +module Decl.GadtConWithCtx where + +data Concurrently m a where + Concurrently :: Monad m => { runConcurrently :: m a } -> Concurrently m a
@@ -0,0 +1,9 @@+{-# LANGUAGE DataKinds, TypeOperators, KindSignatures, TypeFamilies #-} +module Decl.InfixAssertion where + +import GHC.TypeLits + +data Proxy (n :: Nat) = Proxy + +divSNat :: (1 <= b) => Proxy b -> Proxy b +divSNat n = n
@@ -0,0 +1,8 @@+{-# LANGUAGE TypeOperators, TypeFamilies #-} +module Decl.InfixInstances where + +data Zipper h i a = Zipper +data (:@) a i +infixl 8 :> +type family (:>) h p +type instance h :> (a :@ i) = Zipper h i a
@@ -0,0 +1,10 @@+{-# LANGUAGE PatternSynonyms, ViewPatterns #-} +module Decl.InfixPatSyn where + +pattern x :. xs <- (uncons -> Just (x,xs)) where + x:.xs = cons x xs +infixr 5 :. + +cons x xs = x:xs +uncons (x:xs) = Just (x,xs) +uncons [] = Nothing
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeFamilies, TypeFamilyDependencies #-} +module Decl.InjectiveTypeFamily where + +type family Array a = r | r -> a + +type instance Array () = Int
@@ -0,0 +1,5 @@+module Decl.InlinePragma where + +comp :: (b -> c) -> (a -> b) -> a -> c +{-# INLINE CONLIKE [~1] comp #-} +comp f g = \x -> f (g x)
@@ -0,0 +1,10 @@+{-# LANGUAGE TypeOperators, TypeFamilies #-} +module Decl.InstanceFamily where + +import GHC.Generics + +class HasTrie a where + data (:->:) a :: * -> * + +instance (HasTrie (f x)) => HasTrie (M1 i t f x) where + data (M1 i t f x :->: b) = M1Trie (f x :->: b)
@@ -0,0 +1,11 @@+{-# LANGUAGE FlexibleInstances #-} +module Decl.InstanceOverlaps where + +data A a = A a + +instance {-# OVERLAPPING #-} Show (A String) where + show (A a) = a +instance {-# OVERLAPS #-} Show a => Show (A [a]) where + show (A a) = show a +instance {-# OVERLAPPABLE #-} Show (A a) where + show (A _) = "A"
@@ -0,0 +1,7 @@+module Decl.InstanceSpec where + +data Foo a = Foo a + +instance (Eq a) => Eq (Foo a) where + {-# SPECIALIZE instance Eq (Foo Char) #-} + Foo a == Foo b = a == b
@@ -0,0 +1,7 @@+module Decl.LocalBindingInDo where + +x :: Maybe () +x = do let y = f a + where a = () + return y + where f = id
@@ -0,0 +1,9 @@+module Decl.LocalBindings where + +f x = g x + where g :: Int -> Int + g = id + +f' x | even x = g x + where g :: Int -> Int + g = id
@@ -0,0 +1,6 @@+module Decl.LocalFixity where + +x = 1 `f` 2 + where f :: Int -> Int -> Int + f a b = a + b + infixl 6 `f`
@@ -0,0 +1,23 @@+module Decl.MinimalPragma where + +class A x where + f, g :: x -> () + {-# MINIMAL f,g #-} + +class B x where + fb, gb :: x -> () + fb = gb + gb = fb + {-# MINIMAL fb | gb #-} + +class C x where + fc, gc, hc :: x -> x + gc = fc + hc = fc + fc = gc . hc + {-# MINIMAL fc | (gc, hc) #-} + +class D x where + fd :: x -> x + fd = id + {-# MINIMAL #-}
@@ -0,0 +1,11 @@+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-} +module Decl.MixedInstance where + +data Canvas = Canvas +data V2 = V2 + +class Backend c v e where + data Options c v e :: * + +instance Backend Canvas V2 Double where + data Options Canvas V2 Double = CanvasOptions
@@ -0,0 +1,12 @@+module Decl.MultipleFixity where + +f :: Int -> Int -> Int +f a b = a + b + +g = f + +infixl 6 `f`, `g` + +h = f + +infixl 5 `h`
@@ -0,0 +1,6 @@+module Decl.MultipleSigs where + +f, g :: Int -> Int -> Int +f a b = a + b + +g = f
@@ -0,0 +1,6 @@+module Decl.OperatorBind where + +a >< b = a ++ b + +(<+>) :: Int -> Int -> Int -> Int +(a <+> b) c = a + b + c
@@ -0,0 +1,6 @@+module Decl.OperatorDecl where + +(-!-) :: Int -> Int -> Int +(-!-) a b = a + b + +test = (-!-) (1 -!- 2) 3
@@ -0,0 +1,5 @@+module Decl.ParamDataType where + +data A a = B Int | C a + +data X a = X a
@@ -0,0 +1,3 @@+module Decl.PatternBind where + +(x,y) | 1 == 1 = (1,2)
@@ -0,0 +1,28 @@+{-# LANGUAGE PatternSynonyms, ViewPatterns #-} +module Decl.PatternSynonym where + +data Type = App String [Type] + +pattern Arrow :: Type -> Type -> Type +pattern Arrow t1 t2 = App "->" [t1, t2] + + +pattern Int <- App "Int" [] + +pattern Maybe t <- App "Maybe" [t] + where Maybe (App "()" []) = App "Bool" [] + Maybe t = App "Maybe" [t] + +pattern (:<) :: [a] -> a -> [a] +pattern (:<) xs x <- ((\ys -> (init ys,last ys)) -> (xs,x)) + where + (:<) xs x = xs ++ [x] + +------ this is not supported yet +-- class ListLike a where +-- pattern Head :: e -> a e0 +-- pattern Tail :: a e -> a e + +-- instance ListLike [] where +-- pattern Head h = h:_ +-- pattern Tail t = _:t
@@ -0,0 +1,8 @@+{-# LANGUAGE PatternSynonyms #-} +module Decl.RecordPatternSynonyms where + +pattern XPoint {xp} <- (xp, 0) where XPoint xp = (xp, 0) + +pattern Point {x, y} = (x, y) + +r = (0, 0) { x = 1 }
@@ -0,0 +1,3 @@+module Decl.RecordType where + +data A = B { valB, extra :: Int, qq :: Double } | C
@@ -0,0 +1,3 @@+module Decl.RewriteRule where + +{-# RULES "map/map" forall f g xs . map f (map g xs) = map (f . g) xs #-}
@@ -0,0 +1,5 @@+module Decl.SpecializePragma where + +hammeredLookup :: Ord key => [(key, value)] -> key -> value +{-# SPECIALIZE hammeredLookup :: [(String, value)] -> String -> value, [(Char, value)] -> Char -> value #-} +hammeredLookup = undefined
@@ -0,0 +1,6 @@+{-# LANGUAGE StandaloneDeriving #-} +module Decl.StandaloneDeriving where + +data WrapStr = WrapStr String + +deriving instance Eq WrapStr
@@ -0,0 +1,13 @@+{-# LANGUAGE TypeFamilies #-} +module Decl.TypeClass where + +class EmptyClass a + +class Show a => C a where + type X a :: * + type X a = Int + data Q a :: * + + f :: a -> String + f = show +
@@ -0,0 +1,8 @@+module Decl.TypeClassMinimal where + +class Eq' a where + (=.=) :: a -> a -> Bool + (/.=) :: a -> a -> Bool + x =.= y = not (x /.= y) + x /.= y = not (x =.= y) + {-# MINIMAL (=.=) | (/.=) #-}
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeFamilies #-} +module Decl.TypeFamily where + +type family Array a :: * + +type instance Array () = Int
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeFamilies #-} +module Decl.TypeFamilyKindSig where + +type family Array (a :: *) :: * + +type instance Array () = Int
@@ -0,0 +1,14 @@+{-# LANGUAGE TypeFamilies, InstanceSigs #-} +module Decl.TypeInstance where + +import Decl.TypeClass + +data A = A deriving Show + +instance C A where + type X A = Int + data Q A = Bool + + f :: A -> String + f A = "XXX" +
@@ -0,0 +1,5 @@+{-# LANGUAGE RoleAnnotations #-} +module Decl.TypeRole where + +type role Foo representational representational +data Foo a b = Foo Int
@@ -0,0 +1,3 @@+module Decl.TypeSynonym where + +type List = Int
@@ -0,0 +1,3 @@+module Decl.ValBind where + +x = 1
@@ -0,0 +1,8 @@+{-# LANGUAGE PatternSynonyms, ViewPatterns #-} +module Decl.ViewPatternSynonym where + +data Uncert a = Un a a + +pattern x :+/- dx <- Un x (sqrt->dx) + where + x :+/- dx = Un x (dx*dx)
@@ -0,0 +1,10 @@+{-# LANGUAGE Arrows #-} +module Expr.ArrowNotation where + +import Control.Arrow + +addA :: Arrow a => a b Int -> a b Int -> a b Int +addA f g = proc x -> do + y <- f -< x + z <- g -< x + returnA -< y + z
@@ -0,0 +1,8 @@+module Expr.Case where + +x = 12 + +a = case x of 1 -> 0 + _ -> 1 + +b = case x of { 1 -> 0; _ -> 1 }
@@ -0,0 +1,15 @@+module Expr.DoNotation where + +import Control.Monad.Identity + +x1 :: Identity () +x1 = return () + +x2 :: Identity () +x2 = do return () + +x3 :: Identity () +x3 = do { return () } + +x4 :: Identity Int +x4 = do { one <- Identity 1; return (one + 1) }
@@ -0,0 +1,8 @@+{-# LANGUAGE EmptyCase #-} +module Expr.EmptyCase where + +x = 12 + +a = case x of + +b = case x of {}
@@ -0,0 +1,6 @@+module Expr.EmptyLet where + +a = let in () + +m = do let + putStrLn "hello"
@@ -0,0 +1,6 @@+module Expr.FunSection where + +data Rule = Rule { + rulePath :: String -> Bool } + +f r = filter (`rulePath` r)
@@ -0,0 +1,31 @@+{-# LANGUAGE ParallelListComp, + TransformListComp, + MonadComprehensions, + RecordWildCards #-} +module Expr.GeneralizedListComp where + +import GHC.Exts +import qualified Data.Map as M +import Data.Ord (comparing) + +data Character = Character + { firstName :: String + , lastName :: String + , birthYear :: Int + } deriving (Show, Eq) + +friends :: [Character] +friends = [ Character "Phoebe" "Buffay" 1963 + , Character "Chandler" "Bing" 1969 + , Character "Rachel" "Green" 1969 + , Character "Joey" "Tribbiani" 1967 + , Character "Monica" "Geller" 1964 + , Character "Ross" "Geller" 1966 + ] + +oldest :: Int -> [Character] -> [String] +oldest k tbl = [ firstName ++ " " ++ lastName + | Character{..} <- tbl + , then sortWith by birthYear + , then take k + ]
@@ -0,0 +1,4 @@+module Expr.If where + +b = 12 +a = if b > 3 then 1 else 0
@@ -0,0 +1,11 @@+{-# LANGUAGE LambdaCase, EmptyCase #-} +module Expr.LambdaCase where + +a = \case 1 -> 0 + _ -> 1 + +b = \case { 1 -> 0; _ -> 1 } + +c = \case {} + +d = \case
@@ -0,0 +1,3 @@+module Expr.ListComp where + +ls = [ x+y | x <- [1..5], y <- [1..5]]
@@ -0,0 +1,7 @@+{-# LANGUAGE MultiWayIf #-} +module Expr.MultiwayIf where + +b = 12 +a = if | b > 3 -> 1 + | b < -5 -> 2 + | otherwise -> 3
@@ -0,0 +1,4 @@+module Expr.Negate where + +y = 1 +x = -y
@@ -0,0 +1,5 @@+module Expr.Operator where + +x = 1 + 2 +y = (+) 1 2 +z = 1 `mod` 2
@@ -0,0 +1,4 @@+{-# LANGUAGE ParallelListComp #-} +module Expr.ParListComp where + +ls = [ x+y | x <- [1..5] | y <- [1..5]]
@@ -0,0 +1,3 @@+module Expr.ParenName where + +a x y = (mod) x y
@@ -0,0 +1,10 @@+{-# LANGUAGE RecordWildCards #-} +module Expr.PatternAndDo where + +import Control.Monad +import Control.Monad.Identity + +data A = A { x :: Int } + +a = forM_ [] $ \A {..} -> do + Identity "Hello"
@@ -0,0 +1,6 @@+{-# LANGUAGE NamedFieldPuns #-} +module Expr.RecordPuns where + +data Point = Point { x :: Int, y :: Int } + +f (Point {y}) = y
@@ -0,0 +1,6 @@+{-# LANGUAGE RecordWildCards #-} +module Expr.RecordWildcards where + +data Point = Point { x :: Int, y :: Int } + +p1 = let x = 3; y = 4 in Point { x = 1, .. }
@@ -0,0 +1,9 @@+{-# LANGUAGE RecursiveDo #-} +module Expr.RecursiveDo where + +justOnes = mdo xs <- Just (1:xs) + return (map negate xs) + +justOnes' = do rec xs <- Just (1:xs) + return (map negate xs) + return xs
@@ -0,0 +1,4 @@+module Expr.SccPragma where + +f x = {-# SCC "drawComponent" #-} + case x of () -> ()
@@ -0,0 +1,4 @@+module Expr.Sections where + +x = (1+) +y = (+1)
@@ -0,0 +1,7 @@+module Expr.SemicolonDo where + +import Control.Monad.Identity + +a = do { n <- Identity () + ; return () + }
@@ -0,0 +1,16 @@+{-# LANGUAGE StaticPointers #-} +module Expr.StaticPtr where + +import GHC.StaticPtr + +inc :: Int -> Int +inc x = x + 1 + +ref1, ref3, ref4 :: StaticPtr Int +ref2 :: StaticPtr (Int -> Int) +ref5 :: Int -> StaticPtr Int +ref1 = static 1 +ref2 = static inc +ref3 = static (inc 1) +ref4 = static ((\x -> x + 1) (1 :: Int)) +ref5 y = static (let x = 1 in x)
@@ -0,0 +1,7 @@+{-# LANGUAGE TupleSections #-} +module Expr.TupleSections where + +f1 = (1,,) +f2 = (,1) + +x = (,("x", []))
@@ -0,0 +1,13 @@+{-# LANGUAGE UnboxedSums #-} +module Expr.UnboxedSum where + +f = () + where + expr :: (# Int | Bool #) + expr = (# | True #) + + expr2 :: (# Int | Bool #) + expr2 = (# 3 | #) + + expr3 :: (# Int | String | Bool #) + expr3 = (# | "aaa" | #)
@@ -0,0 +1,7 @@+{-# LANGUAGE UnicodeSyntax #-} +module Expr.UnicodeSyntax where + +import Data.List.Unicode ((∪)) + +main ∷ IO () +main = print $ [1, 2, 3] ∪ [1, 3, 5]
@@ -0,0 +1,149 @@+{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, MultiParamTypeClasses, FlexibleInstances, PolyKinds, UndecidableInstances, AllowAmbiguousTypes, RankNTypes, ScopedTypeVariables, FlexibleContexts #-} + +module Control.Instances.Morph (GenMorph(..), Morph(..)) where + +import Control.Instances.ShortestPath + +import Control.Monad.Identity +import Control.Monad.Trans.Maybe +import Control.Monad.Trans.List +import Control.Monad.State +import Data.Maybe +import Data.Proxy +import GHC.TypeLits +import Control.Instances.TypeLevelPrelude + +-- | States that 'm1' can be represented with 'm2'. +-- That is because 'm2' contains more infromation than 'm1'. +-- +-- The 'MMorph' relation defines a natural transformation from 'm1' to 'm2' +-- that keeps the following laws: +-- +-- > morph (return x) = return x +-- > morph (m >>= f) = morph m >>= morph . f +-- +-- It is a reflexive and transitive relation. +-- +class Morph (m1 :: * -> *) (m2 :: * -> *) where + -- | Lifts the first monad into the second. + morph :: m1 a -> m2 a + +instance GenMorph DB m1 m2 => Morph m1 m2 where + morph = genMorph db + +-- | A generalized version of 'Morph'. Can work on different +-- rulesets, so this should be used if the ruleset is to be extended. +class GenMorph db (m1 :: * -> *) (m2 :: * -> *) where + -- | Lifts the first monad into the second. + genMorph :: db -> m1 a -> m2 a + +instance ( fl ~ (TransformPath (PathFromList (ShortestPath (ToMorphRepo DB) x y))) + , CorrectPath x y fl + , GeneratableMorph DB fl + , Morph' fl x y + ) => GenMorph DB x y where + genMorph db = repr (generateMorph db :: fl) + +class Morph' fl x y where + repr :: fl -> x a -> y a + +instance Morph' r y z => Morph' (ConnectMorph x y :+: r) x z where + repr (ConnectMorph m :+: r) = repr r . m + +instance (Morph' r m x, Monad m) => Morph' (IdentityMorph m :+: r) Identity x where + repr (IdentityMorph :+: r) = (repr r :: forall a . m a -> x a) . return . runIdentity + +instance Morph' (MUMorph m :+: r) m Proxy where + repr (MUMorph :+: _) = const Proxy + +instance Morph' NoMorph x x where + repr fl = id + +infixr 6 :+: +data a :+: r = a :+: r + +data NoMorph = NoMorph + +type family ToMorphRepo db where + ToMorphRepo (cm :+: r) = TranslateConn cm ': ToMorphRepo r + ToMorphRepo NoMorph = '[] + +type DB = ConnectMorph_2m Maybe MaybeT + :+: ConnectMorph_mt MaybeT + :+: ConnectMorph Maybe [] + :+: ConnectMorph_2m [] ListT + :+: ConnectMorph (MaybeT IO) (ListT IO) + :+: NoMorph + +db :: DB +db = ConnectMorph_2m (MaybeT . return) + :+: ConnectMorph_mt (MaybeT . liftM Just) + :+: ConnectMorph (maybeToList) + :+: ConnectMorph_2m (ListT . return) + :+: ConnectMorph (ListT . liftM maybeToList . runMaybeT) + :+: NoMorph + +-- | This class provides a way to construct the value-level transformations +-- from the type-level path and a rulebase. +class GeneratableMorph db ch where + generateMorph :: db -> ch + +instance GeneratableMorph db NoMorph where + generateMorph _ = NoMorph + +instance GeneratableMorph db r + => GeneratableMorph db ((IdentityMorph m) :+: r) where + generateMorph db = IdentityMorph :+: generateMorph db + +instance GeneratableMorph db r + => GeneratableMorph db (MUMorph m :+: r) where + generateMorph db = MUMorph :+: generateMorph db + +instance (HasMorph db (ConnectMorph a b), GeneratableMorph db r) + => GeneratableMorph db (ConnectMorph a b :+: r) where + generateMorph db = getMorph db :+: generateMorph db + +-- | This class extracts a given morph from the set of rules +class HasMorph r m where + getMorph :: r -> m +instance {-# OVERLAPPING #-} Monad k => HasMorph (ConnectMorph_2m a b :+: r) (ConnectMorph a (b k)) where + getMorph (ConnectMorph_2m f :+: r) = ConnectMorph f +instance {-# OVERLAPPING #-} Monad k => HasMorph (ConnectMorph_mt t :+: r) (ConnectMorph k (t k)) where + getMorph (ConnectMorph_mt f :+: r) = ConnectMorph f +instance {-# OVERLAPS #-} HasMorph r m => HasMorph (c :+: r) m where + getMorph (c :+: r) = getMorph r +instance {-# OVERLAPPABLE #-} HasMorph (m :+: r) m where + getMorph (c :+: r) = c + +-- | Checks if the path is found to provide usable error messages +class CorrectPath from to path + +instance CorrectPath from to (a :+: b) +instance CorrectPath from to NoMorph + +data ConnectMorph m1 m2 = ConnectMorph { fromConnectMorph :: forall a . m1 a -> m2 a } +data ConnectMorph_2m m1 m2 = ConnectMorph_2m { fromConnectMorph_2m :: forall a k . Monad k => m1 a -> m2 k a } +data ConnectMorph_mt mt = ConnectMorph_mt { fromConnectMorph_mt :: forall a k . Monad k => k a -> mt k a } +data IdentityMorph (m :: * -> *) = IdentityMorph +data MUMorph m = MUMorph + +-- | Transforms a path element from the generic format to the specific one +type family TranslateConn m where + TranslateConn (ConnectMorph m1 m2) = Connect m1 m2 + TranslateConn (ConnectMorph_2m m1 m2) = Connect_2m m1 m2 + TranslateConn (ConnectMorph_mt mt) = Connect_mt mt + +-- | Transforms the path from the generic format to the specific one +type family TransformPath m where + TransformPath (Connect m1 m2 :+: r) = ConnectMorph m1 m2 :+: TransformPath r + TransformPath (Connect_id m :+: r) = IdentityMorph m :+: TransformPath r + TransformPath (Connect_MU m :+: r) = MUMorph m :+: TransformPath r + TransformPath NoMorph = NoMorph + TransformPath NoPathFound = NoPathFound + +type family PathFromList ls where + PathFromList '[] = NoMorph + PathFromList '[ NoPathFound ] = NoPathFound + PathFromList (c ': ls) = c :+: PathFromList ls + +
@@ -0,0 +1,69 @@+{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, MultiParamTypeClasses, FlexibleInstances, PolyKinds, UndecidableInstances, AllowAmbiguousTypes, RankNTypes, ScopedTypeVariables, FlexibleContexts #-} + +module Control.Instances.ShortestPath where + +import Control.Monad.Identity +import Control.Monad.Trans.Maybe +import Control.Monad.Trans.List +import Control.Monad.State +import Data.Maybe +import Data.Proxy +import GHC.TypeLits +import Control.Instances.TypeLevelPrelude + +-- * Generic datatypes to store connections + +data Connect m1 m2 +data Connect_2m m1 m2 +data Connect_mt mt +data Connect_id m +data Connect_MU m + +-- | Marks that there is no legal path between the two types according +-- to the rulebase. +data NoPathFound + +type family ShortestPath (e :: [*]) (s :: * -> *) (t :: * -> *) :: [*] where + ShortestPath e t t = '[] + ShortestPath e Identity t = '[ Connect_id t ] + ShortestPath e s Proxy = '[ Connect_MU s ] + ShortestPath e s t = ShortestPath' e s (InitCurrent e t) + +type family ShortestPath' (e :: [*]) (s :: * -> *) (c :: [[*]]) :: [*] where + ShortestPath' e s '[] = '[ NoPathFound ] + ShortestPath' e s c = FromMaybe (ShortestPath' e s (ApplyEdges e c c)) + (GetFinished s c) + + +type family GetFinished s c where + GetFinished s ((Connect s b ': p) ': lls) + = Just (Connect s b ': p) + GetFinished s (p ': lls) = GetFinished s lls + GetFinished s '[] = Nothing + +type family InitCurrent (e :: [*]) (t :: * -> *) :: [[*]] where + InitCurrent '[] t = '[] + InitCurrent (e ': es) t = IfJust (ApplyEdge e t) + ('[ MonomorphEnd e t ] ': InitCurrent es t) + (InitCurrent es t) + +type family ApplyEdges (e :: [*]) (co :: [[*]]) (c :: [[*]]) :: [[*]] where + ApplyEdges (e ': es) co ((Connect s b ': p) ': cs) + = AppendJust (IfThenJust (IsJust (ApplyEdge e s)) + (MonomorphEnd e s ': Connect s b ': p)) + (ApplyEdges (e ': es) co cs) + ApplyEdges (e ': es) co '[] = ApplyEdges es co co + ApplyEdges '[] co cr = '[] + +type family ApplyEdge e t :: Maybe (* -> *) where + ApplyEdge (Connect ms mr) mr = Just ms + ApplyEdge (Connect_2m ms mt) (mt m) = Just ms + ApplyEdge (Connect_mt mt) (mt m) = Just m + ApplyEdge e t = Nothing + +type family MonomorphEnd c v :: * where + MonomorphEnd (Connect_2m m m') v = Connect m v + MonomorphEnd (Connect_mt t) (t m) = Connect m (t m) + MonomorphEnd c v = c + +
@@ -0,0 +1,23 @@+module Control.Instances.Test where + +import Control.Instances.Morph + +import Control.Monad.Identity +import Control.Monad.Trans.Maybe +import Control.Monad.Trans.List +import Control.Monad.State + +test1 :: Identity a -> IO a +test1 = morph + +test2 :: Maybe a -> [a] +test2 = morph + +test3 :: Maybe a -> ListT IO a +test3 = morph + +test4 :: Maybe a -> MaybeT IO a +test4 = morph + +test5 :: Monad m => Maybe a -> ListT (StateT s m) a +test5 = morph
@@ -0,0 +1,88 @@+{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, MultiParamTypeClasses, FlexibleInstances, PolyKinds, UndecidableInstances, AllowAmbiguousTypes, RankNTypes, ScopedTypeVariables, FlexibleContexts #-} + +module Control.Instances.TypeLevelPrelude where + +import GHC.TypeLits + +type family Const a b where + Const a b = a + +type family Seq a b where + Seq a b = b + +type family LazyIfThenElse p a b where + LazyIfThenElse True a b = a + LazyIfThenElse False a b = b + +type family Iterate a where + Iterate a = a ': Iterate a + +type family l1 :++: l2 where + '[] :++: l2 = l2 + (e ': r1) :++: l2 = e ': (r1 :++: l2) + +type family Elem e ls where + Elem e '[] = False + Elem e (e ': ls) = True + Elem e (x ': ls) = Elem e ls + +type family IfThenElse (b :: Bool) (th :: x) (el :: x) :: x where + IfThenElse True th el = th + IfThenElse False th el = el + +type family Length ls :: Nat where + Length '[] = 0 + Length (e ': ls) = 1 + Length ls + +type family Head (ls :: [k]) :: k where + Head (e ': ls) = e + +type family HeadMaybe (ls :: [k]) :: Maybe k where + HeadMaybe (e ': ls) = Just e + HeadMaybe '[] = Nothing + +type family FromMaybe d m where + FromMaybe d (Just x) = x + FromMaybe d Nothing = d + +type family Same a b where + Same a a = True + Same a b = False + +type family Null (ls :: [k]) :: Bool where + Null '[] = True + Null ls = False + +type family MapAppend e lls where + MapAppend e (ls ': lls) = (e ': ls) ': MapAppend e lls + MapAppend e '[] = '[] + +type family AppendJust m ls where + AppendJust (Just x) ls = x ': ls + AppendJust Nothing ls = ls + +type family Revert ls where + Revert '[] = '[] + Revert (e ': ls) = Revert ls :++: '[ e ] + +type family IfThenJust (p :: Bool) (v :: k) :: Maybe k where + IfThenJust True v = Just v + IfThenJust False v = Nothing + +type family IfJust (p :: Maybe k) (t :: kr) (e :: kr) :: kr where + IfJust (Just x) t e = t + IfJust Nothing t e = e + +type family IsJust (p :: Maybe k) :: Bool where + IsJust (Just x) = True + IsJust Nothing = False + +type family FromJust (p :: Maybe k) :: k where + FromJust (Just x) = x + +type family Cat (f2 :: k2 -> k3) (f1 :: k1 -> k2) (a :: k1) :: k3 where + Cat f2 f1 a = f2 (f1 a) + + + +
@@ -0,0 +1,1 @@+module Module.DeprecatedPragma {-# DEPRECATED "this module is deprecated" #-} where
@@ -0,0 +1,2 @@+module Module.Export (maybe, Maybe(..), Either(Left)) where +-- this module reexports Maybe from Prelude
@@ -0,0 +1,4 @@+{-# LANGUAGE ExplicitNamespaces, PatternSynonyms #-} +module Module.ExportModifiers (type Maybe, pattern Maybe) where + +pattern Maybe = 42
@@ -0,0 +1,3 @@+module Module.ExportSubs (T(Cons, name)) where + +data T = Cons { name :: String }
@@ -0,0 +1,2 @@+{-# OPTIONS_GHC -Wno-name-shadowing #-} +module Module.GhcOptionsPragma where
@@ -0,0 +1,11 @@+{-# LANGUAGE PackageImports, Safe #-} +module Module.Import where + +import Data.List +import "base" Data.List +import {-# SOURCE #-} Data.List +import qualified Data.List +import Data.List as List +import Data.List(map,(++)) +import Data.Function hiding ((&)) +import safe Control.Monad.Writer hiding (Alt, Writer())
@@ -0,0 +1,3 @@+module Module.ImportOp where + +import Module.Imported ((:-)(..))
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeOperators #-} +module Module.Imported where + +infixr 8 :- +-- | A stack datatype. Just a better looking tuple. +data a :- b = a :- b deriving (Eq, Show)
@@ -0,0 +1,4 @@+{-# LANGUAGE LambdaCase #-} +{-#LANGUAGE LambdaCase #-} +{-# LANGUAGE LambdaCase#-} +module Module.LangPragmas where
@@ -0,0 +1,4 @@+{-# LANGUAGE TypeOperators #-} +module Module.NamespaceExport (type (++)) where + +data a ++ b = Ctor
@@ -0,0 +1,4 @@+{-# LANGUAGE PatternSynonyms #-} +module Module.PatternImport where + +import Decl.PatternSynonym (pattern Arrow)
@@ -0,0 +1,1 @@+module Module.Simple where
@@ -0,0 +1,1 @@+module Module.WarningPragma {-# WARNING "this module is dangerous" #-} where
@@ -0,0 +1,5 @@+module Pattern.Backtick where + +data Point = Point { x :: Prelude.Int, y :: Int } + +f (x `Point` y) = 0
@@ -0,0 +1,3 @@+module Pattern.Constructor where + +Just x = Just 1
@@ -0,0 +1,9 @@+{-# LANGUAGE ImplicitParams #-} +module Pattern.ImplicitParams where + +import Data.List (sortBy) + +sort :: (?cmp :: a -> a -> Ordering) => [a] -> [a] +sort = sortBy ?cmp + +main = let ?cmp = compare in putStrLn (show (sort [3,1,2]))
@@ -0,0 +1,5 @@+module Pattern.Infix where + +--(a:b:c:d) = ["1","2","3","4"] + +Nothing:_ = undefined
@@ -0,0 +1,6 @@+{-# LANGUAGE NPlusKPatterns #-} +module Pattern.NPlusK where + +factorial :: Integer -> Integer +factorial 0 = 1 +factorial (n+1) = (*) (n+1) (factorial n)
@@ -0,0 +1,7 @@+{-# LANGUAGE NamedFieldPuns, RecordWildCards #-} +module Pattern.NestedWildcard where + +data A = A { b :: B, ai :: Int } +data B = B { bi :: Int } + +h A { b = B {..}, .. } = bi + ai
@@ -0,0 +1,3 @@+module Pattern.OperatorPattern where + +child r (_:ps) = r ps
@@ -0,0 +1,11 @@+{-# LANGUAGE NamedFieldPuns, RecordWildCards #-} +module Pattern.Record where + +data Point = Point { x :: Int, y :: Int } + +f Point { x = 3, y = 1 } = 0 +f Point {} = 1 + +g Point { x } = x + +h Point { x = 1, .. } = y
@@ -0,0 +1,6 @@+{-# LANGUAGE UnboxedSums #-} +module Pattern.UnboxedSum where + +f :: (# Int | Bool #) -> () +f (# i | #) = () +f (# | b #) = ()
@@ -0,0 +1,10 @@+module Refactor.CommentHandling.BlockComments where + +{-| 1 -} +{- 2 -} +import Control.Monad {- 3 -} +{-^ 4 -} +{-| 5 -} +{- 6 -} +import Control.Monad as Monad {- 7 -} +{-^ 8 -}
@@ -0,0 +1,10 @@+module Refactor.CommentHandling.CommentTypes where + +-- | 1 +-- 2 +import Control.Monad -- 3 +-- ^ 4 +-- | 5 +-- 6 +import Control.Monad as Monad -- 7 +-- ^ 8
@@ -0,0 +1,6 @@+module Refactor.CommentHandling.Crosslinking where + +import Control.Monad +-- | forward +-- ^ back +import Control.Monad as Monad
@@ -0,0 +1,6 @@+module Refactor.CommentHandling.FunctionArgs where + +f :: Int -- something + -> {-| result -} Int + -> Int -- ^ other thing +f = undefined
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.AddToExisting where + +x = a ++ [] + where a = []
@@ -0,0 +1,5 @@+module Refactor.ExtractBinding.AddToExisting where + +x = a ++ b + where a = [] + b = []
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.AssocOp where + +a = 1 + 2 + 3
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.AssocOpMiddle where + +a = 1 * 2 * 3 * 4
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.AssocOpMiddle where + +a = 1 * b * 4 + where b = 2 * 3
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.AssocOpRightAssoc where + +f = id . id . id
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.AssocOpRightAssoc where + +f = g . id + where g = id . id
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.AssocOp where + +a = 1 + b + where b = 2 + 3
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.Case where + +f a = case a of (x,y) -> x + y
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.Case where + +f a = case a of (x,y) -> g x y + where g x y = x + y
@@ -0,0 +1,6 @@+module Refactor.ExtractBinding.ClassInstance where + +data Better a = Better a + +instance Functor Better where + fmap f (Better a) = Better (f a)
@@ -0,0 +1,7 @@+module Refactor.ExtractBinding.ClassInstance where + +data Better a = Better a + +instance Functor Better where + fmap f (Better a) = Better g + where g = f a
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.ExistingLocalDef where + +f = 1 + 2 + 3 + where
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.ExistingLocalDef where + +f = a + 3 + where a = 1 + 2
@@ -0,0 +1,5 @@+module Refactor.ExtractBinding.ExtractedFormatting where + +stms + = id + . id
@@ -0,0 +1,6 @@+module Refactor.ExtractBinding.ExtractedFormatting where + +stms + = extracted + where extracted = id + . id
@@ -0,0 +1,5 @@+module Refactor.ExtractBinding.Indentation where + +f a = case Just a of + Nothing -> 0 + Just x -> x
@@ -0,0 +1,7 @@+module Refactor.ExtractBinding.IndentationMultiLine where + +f a = case Just a of + Nothing + -> 0 + Just x + -> x
@@ -0,0 +1,8 @@+module Refactor.ExtractBinding.IndentationMultiLine where + +f a = case extracted of + Nothing + -> 0 + Just x + -> x + where extracted = Just a
@@ -0,0 +1,5 @@+module Refactor.ExtractBinding.IndentationOperator where + +f aaa bbb = id . id $ + aaa + ++ bbb
@@ -0,0 +1,6 @@+module Refactor.ExtractBinding.IndentationOperator where + +f aaa bbb = extracted $ + aaa + ++ bbb + where extracted = id . id
@@ -0,0 +1,6 @@+module Refactor.ExtractBinding.Indentation where + +f a = case extracted of + Nothing -> 0 + Just x -> x + where extracted = Just a
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.LeftSection where + +a = 1 + 2
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.LeftSection where + +a = f 2 + where f = (1 +)
@@ -0,0 +1,5 @@+module Refactor.ExtractBinding.ListComprehension where + +filterPrime (p:xs) = + p : filterPrime [ x | x <- xs + , x `mod` p /= 0 ]
@@ -0,0 +1,6 @@+module Refactor.ExtractBinding.ListComprehension where + +filterPrime (p:xs) = + p : filterPrime [ x | x <- xs + , notDivisible x ] + where notDivisible x = x `mod` p /= 0
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.LocalDefinition where + +stms = x + where x = "s"
@@ -0,0 +1,5 @@+module Refactor.ExtractBinding.LocalDefinition where + +stms = x + where x = y + where y = "s"
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.NameConflict where + +stms = map (\s -> s ++ bang) ["a", "b"] + where bang = "!"
@@ -0,0 +1,6 @@+module Refactor.ExtractBinding.Parentheses where + +distance p1 p2 = sqrt ((x p1 - x p2) ^ 2 + (y p1 - y p2) ^ 2) + +-- try to rename the type, the constructor or the fields +data Point = Point { x :: Double, y :: Double }
@@ -0,0 +1,7 @@+module Refactor.ExtractBinding.Parentheses where + +distance p1 p2 = sqrt sqDistance + where sqDistance = (x p1 - x p2) ^ 2 + (y p1 - y p2) ^ 2 + +-- try to rename the type, the constructor or the fields +data Point = Point { x :: Double, y :: Double }
@@ -0,0 +1,6 @@+{-# LANGUAGE RecordWildCards #-} +module Refactor.ExtractBinding.RecordWildcards where + +data Point = Point { x :: Double, y :: Double } + +d = (\(Point {..}) -> x + y) (Point 1 2)
@@ -0,0 +1,7 @@+{-# LANGUAGE RecordWildCards #-} +module Refactor.ExtractBinding.RecordWildcards where + +data Point = Point { x :: Double, y :: Double } + +d = plus (Point 1 2) + where plus (Point {..}) = x + y
@@ -0,0 +1,5 @@+module Refactor.ExtractBinding.Records where + +data Point = Point { x :: Double, y :: Double } + +d = (\(Point {x = x, y = y}) -> x + y) (Point 1 2)
@@ -0,0 +1,6 @@+module Refactor.ExtractBinding.Records where + +data Point = Point { x :: Double, y :: Double } + +d = plus (Point 1 2) + where plus (Point {x = x, y = y}) = x + y
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.RightSection where + +a = 1 + 2
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.RightSection where + +a = f 1 + where f = (+ 2)
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.SectionInfix where + +a = 1 + 2 + 3
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.SectionInfix where + +a = f 3 + where f = ((1 + 2) +)
@@ -0,0 +1,6 @@+module Refactor.ExtractBinding.SectionWithLocals where + +a x = let y = 2 + z = 3 + (<->) = (-) + in x <-> (y + z)
@@ -0,0 +1,7 @@+module Refactor.ExtractBinding.SectionWithLocals where + +a x = let y = 2 + z = 3 + (<->) = (-) + in f y z (<->) x + where f y z (<->) = (<-> (y + z))
@@ -0,0 +1,7 @@+module Refactor.ExtractBinding.SiblingDefs where + +f = 1 + where + g = a + where a = 1 + h = 2
@@ -0,0 +1,8 @@+module Refactor.ExtractBinding.SiblingDefs where + +f = 1 + where + g = a + where a = 1 + h = a + where a = 2
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.Simple where + +stms = map (\s -> s ++ "!") ["a", "b"]
@@ -0,0 +1,4 @@+module Refactor.ExtractBinding.Simple where + +stms = map (\s -> exaggerate s) ["a", "b"] + where exaggerate s = s ++ "!"
@@ -0,0 +1,3 @@+module Refactor.ExtractBinding.TooSimple where + +stms = map (\s -> s ++ "!") ["a", "b"]
@@ -0,0 +1,4 @@+{-# LANGUAGE ViewPatterns #-} +module Refactor.ExtractBinding.ViewPattern where + +f (id . id -> x) = x
@@ -0,0 +1,5 @@+module Refactor.FloatOut.FloatLocals where + +f = g + where g = h + where h = id
@@ -0,0 +1,5 @@+module Refactor.FloatOut.FloatLocals where + +f = g + where g = h + h = id
@@ -0,0 +1,5 @@+module Refactor.FloatOut.ImplicitLocal where + +f = g + where g = h + h = ()
@@ -0,0 +1,4 @@+module Refactor.FloatOut.ImplicitParam where + +f a = g + where g = a
@@ -0,0 +1,5 @@+module Refactor.FloatOut.MoveFixity where + +f = 3 <+> 4 + where infixl 6 <+> + a <+> b = a + b
@@ -0,0 +1,5 @@+module Refactor.FloatOut.MoveFixity where + +f = 3 <+> 4 +infixl 6 <+> +a <+> b = a + b
@@ -0,0 +1,5 @@+module Refactor.FloatOut.MoveSignature where + +f = g + where g :: a -> a + g = id
@@ -0,0 +1,5 @@+module Refactor.FloatOut.MoveSignature where + +f = g +g :: a -> a +g = id
@@ -0,0 +1,6 @@+module Refactor.FloatOut.NameCollosion where + +f = g + where g = id + +g = ()
@@ -0,0 +1,4 @@+module Refactor.FloatOut.NameCollosionWithImport where + +f = id + where id = ()
@@ -0,0 +1,6 @@+module Refactor.FloatOut.NameCollosionWithLocal where + +f = g + where g = h + where h = id + h = ()
@@ -0,0 +1,7 @@+module Refactor.FloatOut.NoCollosion where + +f = g + where g = h + where h = id + +h = ()
@@ -0,0 +1,7 @@+module Refactor.FloatOut.NoCollosion where + +f = g + where g = h + h = id + +h = ()
@@ -0,0 +1,6 @@+module Refactor.FloatOut.SharedSignature where + +f = g + where g, h :: a -> a + g = id + h = id
@@ -0,0 +1,4 @@+module Refactor.FloatOut.ToTopLevel where + +f = g + where g = id
@@ -0,0 +1,4 @@+module Refactor.FloatOut.ToTopLevel where + +f = g +g = id
@@ -0,0 +1,17 @@+{-# LANGUAGE TypeFamilies #-} +module Refactor.GenerateExports.Normal where + +function :: Int -> Int +function a = a + +data TypeCtor = DataCtor { recordName :: Int } + +class TypeClass a where + classFunction :: a -> a + +type family TypeFamily a :: * + +data family DataFamily a :: * + +foreign import ccall "exp" c_exp :: Double -> Double +
@@ -0,0 +1,17 @@+{-# LANGUAGE TypeFamilies #-} +module Refactor.GenerateExports.Normal (function, TypeCtor(..), TypeClass(..), TypeFamily, DataFamily, c_exp) where + +function :: Int -> Int +function a = a + +data TypeCtor = DataCtor { recordName :: Int } + +class TypeClass a where + classFunction :: a -> a + +type family TypeFamily a :: * + +data family DataFamily a :: * + +foreign import ccall "exp" c_exp :: Double -> Double +
@@ -0,0 +1,7 @@+{-# LANGUAGE TypeOperators #-} +module Refactor.GenerateExports.Operators where + +(|=>|) :: Int -> Int -> Int +a |=>| b = a + b + +data a :+: b = a :+: b
@@ -0,0 +1,7 @@+{-# LANGUAGE TypeOperators #-} +module Refactor.GenerateExports.Operators ((|=>|), (:+:)(..)) where + +(|=>|) :: Int -> Int -> Int +a |=>| b = a + b + +data a :+: b = a :+: b
@@ -0,0 +1,4 @@+module Refactor.GenerateTypeSignature.BringToScope.A where + +data T = T +data S = S
@@ -0,0 +1,6 @@+module Refactor.GenerateTypeSignature.BringToScope.AlreadyQualImport where + +import Refactor.GenerateTypeSignature.BringToScope.B +import qualified Refactor.GenerateTypeSignature.BringToScope.A as AAA (S) + +g = f
@@ -0,0 +1,8 @@+module Refactor.GenerateTypeSignature.BringToScope.AlreadyQualImport where + +import Refactor.GenerateTypeSignature.BringToScope.B +import qualified Refactor.GenerateTypeSignature.BringToScope.A as AAA (S) +import qualified Refactor.GenerateTypeSignature.BringToScope.A(T) + +g :: Refactor.GenerateTypeSignature.BringToScope.A.T -> AAA.S +g = f
@@ -0,0 +1,6 @@+module Refactor.GenerateTypeSignature.BringToScope.B where + +import Refactor.GenerateTypeSignature.BringToScope.A + +f :: T -> S +f = const S
@@ -0,0 +1,8 @@+{-# LANGUAGE ScopedTypeVariables #-} +module Refactor.GenerateTypeSignature.CanCaptureVariable where + +import qualified Data.Map as Map + +insertMany :: forall k v . (Ord k) => (v -> v -> v) -> [(k,v)] -> Map.Map k v -> Map.Map k v +insertMany accf vs m = foldr f1 m vs + where f1 (k,v) m = Map.insertWith accf k v m
@@ -0,0 +1,11 @@+{-# LANGUAGE ScopedTypeVariables #-} +module Refactor.GenerateTypeSignature.CanCaptureVariableHasOtherDef where + +import qualified Data.Map as Map + +insertMany :: forall k v . (Ord k) => (v -> v -> v) -> [(k,v)] -> Map.Map k v -> Map.Map k v +insertMany accf vs m = foldr f1 m vs + where f1 (k,v) m = Map.insertWith accf k v m + +someOtherFun :: (k,v) -> (k,v) +someOtherFun = id
@@ -0,0 +1,12 @@+{-# LANGUAGE ScopedTypeVariables #-} +module Refactor.GenerateTypeSignature.CanCaptureVariableHasOtherDef where + +import qualified Data.Map as Map + +insertMany :: forall k v . (Ord k) => (v -> v -> v) -> [(k,v)] -> Map.Map k v -> Map.Map k v +insertMany accf vs m = foldr f1 m vs + where f1 :: Ord k => (k, v) -> Map.Map k v -> Map.Map k v + f1 (k,v) m = Map.insertWith accf k v m + +someOtherFun :: (k,v) -> (k,v) +someOtherFun = id
@@ -0,0 +1,9 @@+{-# LANGUAGE ScopedTypeVariables #-} +module Refactor.GenerateTypeSignature.CanCaptureVariable where + +import qualified Data.Map as Map + +insertMany :: forall k v . (Ord k) => (v -> v -> v) -> [(k,v)] -> Map.Map k v -> Map.Map k v +insertMany accf vs m = foldr f1 m vs + where f1 :: Ord k => (k, v) -> Map.Map k v -> Map.Map k v + f1 (k,v) m = Map.insertWith accf k v m
@@ -0,0 +1,7 @@+module Refactor.GenerateTypeSignature.CannotCaptureVariable where + +import qualified Data.Map as Map + +insertMany :: (Ord k) => (v -> v -> v) -> [(k,v)] -> Map.Map k v -> Map.Map k v +insertMany accf vs m = foldr f1 m vs + where f1 (k,v) m = Map.insertWith accf k v m
@@ -0,0 +1,8 @@+{-# LANGUAGE RankNTypes #-} +module Refactor.GenerateTypeSignature.CannotCaptureVariableNoExt where + +import qualified Data.Map as Map + +insertMany :: forall k v . (Ord k) => (v -> v -> v) -> [(k,v)] -> Map.Map k v -> Map.Map k v +insertMany accf vs m = foldr f1 m vs + where f1 (k,v) m = Map.insertWith accf k v m
@@ -0,0 +1,3 @@+module Refactor.GenerateTypeSignature.Complex where + +app f x = f (Just x)
@@ -0,0 +1,6 @@+module Refactor.GenerateTypeSignature.ComplexLhs where + +(x) = 3 +Just y = Just 4 +(a,b) = (1,2) +[c,d,e] = [1,2,3]
@@ -0,0 +1,4 @@+module Refactor.GenerateTypeSignature.Complex where + +app :: (Maybe a -> t) -> a -> t +app f x = f (Just x)
@@ -0,0 +1,3 @@+module Refactor.GenerateTypeSignature.Function where + +identity x = x
@@ -0,0 +1,4 @@+module Refactor.GenerateTypeSignature.Function where + +identity :: p -> p +identity x = x
@@ -0,0 +1,3 @@+module Refactor.GenerateTypeSignature.HigherOrder where + +app f x = f x
@@ -0,0 +1,4 @@+module Refactor.GenerateTypeSignature.HigherOrder where + +app :: (t1 -> t2) -> t1 -> t2 +app f x = f x
@@ -0,0 +1,4 @@+module Refactor.GenerateTypeSignature.Let where + +x = let unit = () + in ()
@@ -0,0 +1,5 @@+module Refactor.GenerateTypeSignature.Let where + +x = let unit :: () + unit = () + in ()
@@ -0,0 +1,4 @@+module Refactor.GenerateTypeSignature.Local where + +x = () where + unit = ()
@@ -0,0 +1,5 @@+module Refactor.GenerateTypeSignature.Local where + +x = () where + unit :: () + unit = ()
@@ -0,0 +1,5 @@+module Refactor.GenerateTypeSignature.Placement where + +otherThing = () +unit = () +anotherThing = ()
@@ -0,0 +1,6 @@+module Refactor.GenerateTypeSignature.Placement where + +otherThing = () +unit :: () +unit = () +anotherThing = ()
@@ -0,0 +1,6 @@+module Refactor.GenerateTypeSignature.Polymorph where + +three = 3 + +four :: Int +four = three + 1
@@ -0,0 +1,5 @@+module Refactor.GenerateTypeSignature.PolymorphSub where + +f :: Num a => a -> a +f a = g a where + g a = a + 1
@@ -0,0 +1,5 @@+module Refactor.GenerateTypeSignature.PolymorphSubMulti where + +f :: (Num a, Ord a) => a -> a +f a = g a where + g a = if a > 0 then a + 1 else a
@@ -0,0 +1,6 @@+module Refactor.GenerateTypeSignature.PolymorphSubMulti where + +f :: (Num a, Ord a) => a -> a +f a = g a where + g :: (Num p, Ord p) => p -> p + g a = if a > 0 then a + 1 else a
@@ -0,0 +1,6 @@+module Refactor.GenerateTypeSignature.PolymorphSub where + +f :: Num a => a -> a +f a = g a where + g :: Num a => a -> a + g a = a + 1
@@ -0,0 +1,7 @@+module Refactor.GenerateTypeSignature.Polymorph where + +three :: Int +three = 3 + +four :: Int +four = three + 1
@@ -0,0 +1,3 @@+module Refactor.GenerateTypeSignature.Simple where + +unit = ()
@@ -0,0 +1,4 @@+module Refactor.GenerateTypeSignature.Simple where + +unit :: () +unit = ()
@@ -0,0 +1,3 @@+module Refactor.GenerateTypeSignature.Tuple where + +tuple x y = (x,y)
@@ -0,0 +1,4 @@+module Refactor.GenerateTypeSignature.Tuple where + +tuple :: a -> b -> (a, b) +tuple x y = (x,y)
@@ -0,0 +1,6 @@+module Refactor.GenerateTypeSignature.TypeDefinedInModule where + +distance p1 p2 = sqrt ((x p1 - x p2) ^ 2 + (y p1 - y p2) ^ 2) + +data Point = Point { x :: Double, y :: Double } +
@@ -0,0 +1,7 @@+module Refactor.GenerateTypeSignature.TypeDefinedInModule where + +distance :: Point -> Point -> Double +distance p1 p2 = sqrt ((x p1 - x p2) ^ 2 + (y p1 - y p2) ^ 2) + +data Point = Point { x :: Double, y :: Double } +
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.AlreadyApplied where + +b u v = a u v +a x y = x ++ y
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.AlreadyApplied where + +b u v = (u ++ v)
@@ -0,0 +1,3 @@+module A where + +a = ()
@@ -0,0 +1,5 @@+module B where + +import A + +b = a
@@ -0,0 +1,5 @@+module Refactor.InlineBinding.Simplest where + +b = a +a x = x +x1 = ()
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.Simplest where + +b = (\x2 -> x2) +x1 = ()
@@ -0,0 +1,7 @@+module Refactor.InlineBinding.FilterSignatures where + +b u v = u <++> v +(<++>), (<**>) :: String -> String -> String +x <++> y = x ++ y +x <**> y = y ++ x +infixl 7 <++>, <**>
@@ -0,0 +1,6 @@+module Refactor.InlineBinding.FilterSignatures where + +b u v = (u ++ v) +(<**>) :: String -> String -> String +x <**> y = y ++ x +infixl 7 <**>
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.InExportList (a) where + +b = a +a = ()
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.LetBind where + +a = let x = () in x
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.LetBind where + +a = ()
@@ -0,0 +1,5 @@+module Refactor.InlineBinding.LetGuard where + +a | let x = 3 + , x == 3 + = ()
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.LetGuard where + +a | 3 == 3 + = ()
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.LetStmt where + +a = do let x = () + putStrLn (show x)
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.LetStmt where + +a = do putStrLn (show ())
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.Local where + +b = a + where a = ()
@@ -0,0 +1,5 @@+module Refactor.InlineBinding.LocalNested where + +a = b + where b = c + where c = ()
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.LocalNested where + +a = b + where b = ()
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.Local where + +b = ()
@@ -0,0 +1,6 @@+module Refactor.InlineBinding.MultiApplied where + +b u v = a u v +a x "a" = x +a "a" y = y +a x y = x ++ y
@@ -0,0 +1,5 @@+module Refactor.InlineBinding.MultiApplied where + +b u v = (case (u, v) of (x, "a") -> x + ("a", y) -> y + (x, y) -> x ++ y)
@@ -0,0 +1,6 @@+module Refactor.InlineBinding.MultiMatch where + +b = a +a x "a" = x +a "a" y = y +a x y = x ++ y
@@ -0,0 +1,6 @@+module Refactor.InlineBinding.MultiMatchGuarded where + +b u v = a u v +a x y | x == y + = x +a x y = x ++ y
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.MultiMatchGuarded where + +b u v = (case (u, v) of (x, y) | x == y -> x + (x, y) -> x ++ y)
@@ -0,0 +1,5 @@+module Refactor.InlineBinding.MultiMatch where + +b = (\x1 x2 -> case (x1, x2) of (x, "a") -> x + ("a", y) -> y + (x, y) -> x ++ y)
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.Nested where + +b = f (f ()) +f a = a
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.Nested where + +b = (())
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.NotOccurring where + +a = ()
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.Operator where + +b u v = u <++> v +x <++> y = x ++ y
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.Operator where + +b u v = (u ++ v)
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.PatternMatched where + +b u v = a (Just u) v +a (Just x) (Just y) = x ++ y
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.PatternMatched where + +b u v = ((\(Just y) -> u ++ y) v)
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.Recursive where + +b = f () +f a = f a
@@ -0,0 +1,6 @@+module Refactor.InlineBinding.RemoveSignatures where + +b u v = u <++> v +(<++>) :: String -> String -> String +x <++> y = x ++ y +infixl 7 <++>
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.RemoveSignatures where + +b u v = (u ++ v)
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.SimpleMultiMatch where + +b = a +a x y = x ++ y
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.SimpleMultiMatch where + +b = (\x y -> x ++ y)
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.Simplest where + +b = a +a = ()
@@ -0,0 +1,3 @@+module Refactor.InlineBinding.Simplest where + +b = ()
@@ -0,0 +1,6 @@+module Refactor.InlineBinding.WithLocals where + +b = a +a = x y + where x = id + y = ()
@@ -0,0 +1,4 @@+module Refactor.InlineBinding.WithLocals where + +b = (let x = id + y = () in x y)
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.Class where + +import Decl.TypeClass (C(f)) +import Decl.TypeInstance + +test = f A
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.Class where + +import Decl.TypeClass (C(f)) +import Decl.TypeInstance (A(..)) + +test = f A
@@ -0,0 +1,11 @@+module Refactor.OrganizeImports.Coerce where + +import Prelude () +import Data.Maybe (Maybe(Just, Nothing)) +import Data.List +import Data.Coerce (coerce) + +newtype Mayb' a = Mayb' (Maybe a) + +a :: Mayb' a -> Maybe a +a = coerce
@@ -0,0 +1,11 @@+module Refactor.OrganizeImports.Coerce where + +import Data.Coerce (coerce) +import Data.List +import Data.Maybe (Maybe(Just, Nothing)) +import Prelude () + +newtype Mayb' a = Mayb' (Maybe a) + +a :: Mayb' a -> Maybe a +a = coerce
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.Ctor where + +import Data.Maybe (Maybe(Nothing, Just)) + +test = Just 3
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.Ctor where + +import Data.Maybe (Maybe(Just)) + +test = Just 3
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.Fields where + +import Control.Monad.Trans (MonadTrans(..)) +import Control.Monad.State (Monad(..), StateT(runStateT)) + +x = runStateT (lift putStrLn >> return ()) ()
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.Fields where + +import Control.Monad.State (Monad(..), StateT(runStateT)) +import Control.Monad.Trans (MonadTrans(..)) + +x = runStateT (lift putStrLn >> return ()) ()
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.InstanceCarry.DataType where + +data A = A
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.InstanceCarry.ImportNonOrphan where + +import Refactor.OrganizeImports.InstanceCarry.TCWithInst ()
@@ -0,0 +1,2 @@+module Refactor.OrganizeImports.InstanceCarry.ImportNonOrphan where +
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.InstanceCarry.ImportOrphan where + +import Refactor.OrganizeImports.InstanceCarry.OrphanInstance ()
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.InstanceCarry.ImportOrphan where + +import Refactor.OrganizeImports.InstanceCarry.OrphanInstance ()
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.InstanceCarry.OrphanInstance where + +import Refactor.OrganizeImports.InstanceCarry.DataType +import Refactor.OrganizeImports.InstanceCarry.TypeClass + +instance C A where + f = id
@@ -0,0 +1,9 @@+module Refactor.OrganizeImports.InstanceCarry.TCWithInst where + +import Refactor.OrganizeImports.InstanceCarry.DataType + +class D t where + g :: t -> t + +instance D A where + g = id
@@ -0,0 +1,4 @@+module Refactor.OrganizeImports.InstanceCarry.TypeClass where + +class C t where + f :: t -> t
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.KeepCtorOfMarshalled where + +import Foreign.C.String + +foreign import ccall unsafe "abc" abc :: CString -> IO ()
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.KeepCtorOfMarshalled where + +import Foreign.C.String (CString(..)) + +foreign import ccall unsafe "abc" abc :: CString -> IO ()
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.KeepExplicit where + +import Data.Functor.Identity (Identity (runIdentity)) + +x = runIdentity
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.KeepExplicit where + +import Data.Functor.Identity (Identity (runIdentity)) + +x = runIdentity
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.KeepHiding where + +import Data.Map hiding (map) + +m :: Map Int String +m = empty
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.KeepHiding where + +import Data.Map hiding (map) + +m :: Map Int String +m = empty
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.KeepPrelude where + +import Prelude ()
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.KeepPrelude where + +import Prelude ()
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.KeepReexported (module Control.Monad) where + +import Control.Monad
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.KeepReexported (module Control.Monad) where + +import Control.Monad
@@ -0,0 +1,4 @@+module Refactor.OrganizeImports.KeepRenamedReexported (module X) where + +import Control.Monad as X +import Data.Maybe as X
@@ -0,0 +1,4 @@+module Refactor.OrganizeImports.KeepRenamedReexported (module X) where + +import Control.Monad as X +import Data.Maybe as X
@@ -0,0 +1,11 @@+module Refactor.OrganizeImports.MakeExplicit.ClassSource where + +class D a where + f :: a + +instance D () where + f = () + +g :: D a => a +g = f +
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.MakeExplicit.ConSourceHiddenType (A(B)) where + +import Refactor.OrganizeImports.MakeExplicit.Source
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.MakeExplicit.FunSource (f) where + +import Refactor.OrganizeImports.MakeExplicit.ClassSource
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.MakeExplicit.ImportClassFun where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x :: () +x = f +
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.MakeExplicit.ImportClassFun where + +import Refactor.OrganizeImports.MakeExplicit.Source (D(..)) + +x :: () +x = f +
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.MakeExplicit.ImportCon where + +import Refactor.OrganizeImports.MakeExplicit.ConSourceHiddenType + +x = B
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.MakeExplicit.ImportCon where + +import Refactor.OrganizeImports.MakeExplicit.ConSourceHiddenType (A(..)) + +x = B
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFour where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = (a,b,e,g) +
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFour where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = (a,b,e,g) +
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFunHiddenClass where + +import Refactor.OrganizeImports.MakeExplicit.FunSource + +h :: () +h = f
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFunHiddenClass where + +import Refactor.OrganizeImports.MakeExplicit.FunSource (f) + +h :: () +h = f
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFunOutOfClass where + +import Refactor.OrganizeImports.MakeExplicit.ClassSource + +h :: () +h = g
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFunOutOfClass where + +import Refactor.OrganizeImports.MakeExplicit.ClassSource (g) + +h :: () +h = g
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportOne where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = a +
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportOne where + +import Refactor.OrganizeImports.MakeExplicit.Source (a) + +x = a +
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportRecordSel where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = b +
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportRecordSel where + +import Refactor.OrganizeImports.MakeExplicit.Source (A(..)) + +x = b +
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.MakeExplicit.ImportThree where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = (a,e,g)
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.MakeExplicit.ImportThree where + +import Refactor.OrganizeImports.MakeExplicit.Source (g, e, a) + +x = (a,e,g)
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.MakeExplicit.ImportUnited where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = B () +y = b x +
@@ -0,0 +1,8 @@+module Refactor.OrganizeImports.MakeExplicit.ImportUnitedCount where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = B () +y = b x +z = a +w = e
@@ -0,0 +1,8 @@+module Refactor.OrganizeImports.MakeExplicit.ImportUnitedCount where + +import Refactor.OrganizeImports.MakeExplicit.Source (A(..), e, a) + +x = B () +y = b x +z = a +w = e
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.MakeExplicit.ImportUnited where + +import Refactor.OrganizeImports.MakeExplicit.Source (A(..)) + +x = B () +y = b x +
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.MakeExplicit.Renamed where + +import Refactor.OrganizeImports.MakeExplicit.Source as Src + +x = B
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.MakeExplicit.Renamed where + +import Refactor.OrganizeImports.MakeExplicit.Source as Src (A(..)) + +x = B
@@ -0,0 +1,15 @@+module Refactor.OrganizeImports.MakeExplicit.Source where + +a = () +e = () +g = () + +data A = B { b :: () } + | C + +class D a where + f :: a + +instance D () where + f = () +
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.Narrow where + +import Data.List (map, null) + +test = map (+1) [1..10]
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.NarrowQual where + +import Data.List +import Data.List as L + +test = intersperse 0 $ L.map (+1) [1..10]
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.NarrowQual where + +import Data.List (map, intersperse) +import Data.List as L (map, intersperse) + +test = intersperse 0 $ L.map (+1) [1..10]
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.NarrowSpec where + +import Control.Monad.State (State(..)) + +type St = State ()
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.NarrowSpec where + +import Control.Monad.State (State(..)) + +type St = State ()
@@ -0,0 +1,8 @@+module Refactor.OrganizeImports.NarrowType where + +import Control.Monad.State + +type St = State () +type StT = StateT () IO + +f = runStateT
@@ -0,0 +1,8 @@+module Refactor.OrganizeImports.NarrowType where + +import Control.Monad.State (StateT(..), State) + +type St = State () +type StT = StateT () IO + +f = runStateT
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.Narrow where + +import Data.List (map) + +test = map (+1) [1..10]
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.Operator where + +import Data.List ((\\), intersect) + +test = [1,2,3] \\ [1,2]
@@ -0,0 +1,5 @@+module Refactor.OrganizeImports.Operator where + +import Data.List ((\\)) + +test = [1,2,3] \\ [1,2]
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.Removed where + +import Control.Monad ()
@@ -0,0 +1,2 @@+module Refactor.OrganizeImports.Removed where +
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.Reorder where + +import Data.List (intersperse) +import Control.Monad ((>>=)) + +x = intersperse '-' "abc" +y = Just () >>= \_ -> Nothing
@@ -0,0 +1,12 @@+module Refactor.OrganizeImports.ReorderComment where + +import Data.List (intersperse) +import Control.Monad ((>>=)) +-- some comment +import Data.Tuple (swap) +import Data.Maybe (catMaybes) + +a = intersperse '-' "abc" +b = Just () >>= \_ -> Nothing +c = catMaybes [Just ()] +d = swap ("a","b")
@@ -0,0 +1,12 @@+module Refactor.OrganizeImports.ReorderComment where + +import Control.Monad ((>>=)) +import Data.List (intersperse) +import Data.Maybe (catMaybes) +-- some comment +import Data.Tuple (swap) + +a = intersperse '-' "abc" +b = Just () >>= \_ -> Nothing +c = catMaybes [Just ()] +d = swap ("a","b")
@@ -0,0 +1,12 @@+module Refactor.OrganizeImports.ReorderGroups where + +import Data.List (intersperse) +import Control.Monad ((>>=)) + +import Data.Tuple (swap) +import Data.Maybe (catMaybes) + +a = intersperse '-' "abc" +b = Just () >>= \_ -> Nothing +c = catMaybes [Just ()] +d = swap ("a","b")
@@ -0,0 +1,12 @@+module Refactor.OrganizeImports.ReorderGroups where + +import Control.Monad ((>>=)) +import Data.List (intersperse) + +import Data.Maybe (catMaybes) +import Data.Tuple (swap) + +a = intersperse '-' "abc" +b = Just () >>= \_ -> Nothing +c = catMaybes [Just ()] +d = swap ("a","b")
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.Reorder where + +import Control.Monad ((>>=)) +import Data.List (intersperse) + +x = intersperse '-' "abc" +y = Just () >>= \_ -> Nothing
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.SameName where + +import Data.List (map, null) + +test = map (+1) [1..null] + where null = 10
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.SameName where + +import Data.List (map) + +test = map (+1) [1..null] + where null = 10
@@ -0,0 +1,6 @@+{-# LANGUAGE StandaloneDeriving #-} +module Refactor.OrganizeImports.StandaloneDeriving where + +import Control.Monad.State (State(..), StateT) + +type St = State ()
@@ -0,0 +1,6 @@+{-# LANGUAGE StandaloneDeriving #-} +module Refactor.OrganizeImports.StandaloneDeriving where + +import Control.Monad.State (State(..)) + +type St = State ()
@@ -0,0 +1,5 @@+{-# LANGUAGE TemplateHaskell #-} +module Refactor.OrganizeImports.TemplateHaskell where + +import Control.Monad.Writer +import Control.Monad.State (State(..))
@@ -0,0 +1,5 @@+{-# LANGUAGE TemplateHaskell #-} +module Refactor.OrganizeImports.TemplateHaskell where + +import Control.Monad.State (State(..)) +import Control.Monad.Writer
@@ -0,0 +1,6 @@+module Refactor.RenameDefinition.AccentName where + +f :: Int -> Int +f x = x + +g = f
@@ -0,0 +1,6 @@+module Refactor.RenameDefinition.AccentName where + +á :: Int -> Int +á x = x + +g = á
@@ -0,0 +1,11 @@+{-# LANGUAGE DuplicateRecordFields #-} +module Refactor.RenameDefinition.AmbiguousFields where + +data A = A { x, y :: Int } +data B = B { x, y :: Int } + +f :: A -> Int +f = x + +g :: B -> Int +g = x
@@ -0,0 +1,11 @@+{-# LANGUAGE DuplicateRecordFields #-} +module Refactor.RenameDefinition.AmbiguousFields where + +data A = A { xx, y :: Int } +data B = B { x, y :: Int } + +f :: A -> Int +f = xx + +g :: B -> Int +g = x
@@ -0,0 +1,4 @@+module Refactor.RenameDefinition.Arg where + +f :: Int -> Int +f x = x
@@ -0,0 +1,4 @@+module Refactor.RenameDefinition.Arg where + +f :: Int -> Int +f y = y
@@ -0,0 +1,6 @@+module Refactor.RenameDefinition.BacktickName where + +f :: Int -> Int -> Int +f = (+) + +x = 3 `f` 4
@@ -0,0 +1,6 @@+module Refactor.RenameDefinition.BacktickName where + +g :: Int -> Int -> Int +g = (+) + +x = 3 `g` 4
@@ -0,0 +1,7 @@+module Refactor.RenameDefinition.ClassMember where + +class C t where + f :: t -> t + +instance C Int where + f i = i
@@ -0,0 +1,7 @@+module Refactor.RenameDefinition.ClassMember where + +class C t where + q :: t -> t + +instance C Int where + q i = i
@@ -0,0 +1,4 @@+module Refactor.RenameDefinition.ClassTypeVar where + +class C t where + f :: t -> t
@@ -0,0 +1,4 @@+module Refactor.RenameDefinition.ClassTypeVar where + +class C f where + f :: f -> f
@@ -0,0 +1,6 @@+module Refactor.RenameDefinition.Constructor where + +data Point = Point Double Double + +distance :: Point -> Point -> Double +distance (Point x1 y1) (Point x2 y2) = sqrt ((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
@@ -0,0 +1,6 @@+module Refactor.RenameDefinition.Constructor where + +data Point = Point2D Double Double + +distance :: Point -> Point -> Double +distance (Point2D x1 y1) (Point2D x2 y2) = sqrt ((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
@@ -0,0 +1,8 @@+module Refactor.RenameDefinition.CrossRename where + +-- Renaming f to g should fail +f x = x + +ff x = g + where + g = f 'g'
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff
file too large to diff