Safe Haskell | None |
---|---|
Language | Haskell98 |
This module contains a collection of program analysis and transformation functions (the API) that work over the Type Decorated AST. Most of the functions defined in the module are taken directly from the API, but in some cases are modified to work with the type decorated AST.
In particular some new functions have been added to make type decorated AST traversals easier.
In HaRe, in order to preserve the comments and layout of refactored programs, a refactoring modifies not only the AST but also the token stream, and the program source after the refactoring is extracted from the token stream rather than the AST, for the comments and layout information is kept in the token steam instead of the AST. As a consequence, a program transformation function from this API modifies both the AST and the token stream (unless explicitly stated). So when you build your own program transformations, try to use the API to do the transformation, as this can liberate you from caring about the token stream.
This type decorated API is still in development. Any suggestions and comments are very much welcome.
- inScopeInfo :: InScopes -> [(String, NameSpace, ModuleName, Maybe ModuleName)]
- isInScopeAndUnqualified :: String -> InScopes -> Bool
- isInScopeAndUnqualifiedGhc :: String -> Maybe Name -> RefactGhc Bool
- inScopeNames :: String -> RefactGhc [Name]
- isExported :: Name -> RefactGhc Bool
- isExplicitlyExported :: NameMap -> Name -> ParsedSource -> Bool
- modIsExported :: ModuleName -> RenamedSource -> Bool
- equivalentNameInNewMod :: Name -> RefactGhc [Name]
- hsQualifier :: Name -> RefactGhc [ModuleName]
- isVarId :: String -> Bool
- isConId :: String -> Bool
- isOperator :: String -> Bool
- isTopLevelPN :: Name -> RefactGhc Bool
- isLocalPN :: Name -> Bool
- isNonLibraryName :: Name -> Bool
- isQualifiedPN :: Name -> RefactGhc Bool
- isFunOrPatName :: Data t => NameMap -> Name -> t -> Bool
- isTypeSig :: LSig a -> Bool
- isTypeSigDecl :: LHsDecl a -> Bool
- isFunBindP :: LHsDecl RdrName -> Bool
- isFunBindR :: LHsBind t -> Bool
- isPatBindP :: LHsDecl RdrName -> Bool
- isPatBindR :: LHsBind t -> Bool
- isSimplePatBind :: DataId t => LHsBind t -> Bool
- isSimplePatDecl :: LHsDecl RdrName -> Bool
- isComplexPatBind :: LHsBind name -> Bool
- isComplexPatDecl :: LHsDecl name -> Bool
- isFunOrPatBindP :: HsDeclP -> Bool
- isFunOrPatBindR :: LHsBind t -> Bool
- findEntity' :: (Data a, Data b) => a -> b -> Maybe (SimpPos, SimpPos)
- findIdForName :: Name -> RefactGhc (Maybe Id)
- getTypeForName :: Name -> RefactGhc (Maybe Type)
- definesTypeSigRdr :: NameMap -> Name -> Sig RdrName -> Bool
- sameBindRdr :: NameMap -> LHsDecl RdrName -> LHsDecl RdrName -> Bool
- class Data t => UsedByRhs t where
- isMainModule :: Module -> Bool
- getModule :: RefactGhc Module
- defineLoc :: Located Name -> SrcLoc
- useLoc :: Located Name -> SrcLoc
- locToExp :: (Data t, Typeable n) => SimpPos -> SimpPos -> t -> Maybe (LHsExpr n)
- locToRdrName :: Data t => SimpPos -> t -> Maybe (Located RdrName)
- getName :: Data t => String -> t -> Maybe Name
- addDecl :: (Data t, Typeable t) => t -> Maybe Name -> ([LHsDecl RdrName], Maybe Anns) -> RefactGhc t
- addItemsToImport :: ModuleName -> Maybe Name -> Either [RdrName] [LIE RdrName] -> ParsedSource -> RefactGhc ParsedSource
- addItemsToExport :: ParsedSource -> Maybe Name -> Bool -> Either [RdrName] [LIE RdrName] -> RefactGhc ParsedSource
- addHiding :: ModuleName -> ParsedSource -> [RdrName] -> RefactGhc ParsedSource
- addParamsToDecls :: [LHsDecl RdrName] -> Name -> [RdrName] -> RefactGhc [LHsDecl RdrName]
- addParamsToSigs :: [Name] -> LSig RdrName -> RefactGhc (LSig RdrName)
- addActualParamsToRhs :: Data t => Name -> [RdrName] -> t -> RefactGhc t
- addImportDecl :: ParsedSource -> ModuleName -> Maybe StringLiteral -> Bool -> Bool -> Bool -> Maybe String -> Bool -> [RdrName] -> RefactGhc ParsedSource
- duplicateDecl :: [LHsDecl RdrName] -> Name -> Name -> RefactGhc [LHsDecl RdrName]
- rmDecl :: Data t => Name -> Bool -> t -> RefactGhc (t, LHsDecl RdrName, Maybe (LSig RdrName))
- rmTypeSig :: Data t => Name -> t -> RefactGhc (t, Maybe (LSig RdrName))
- rmTypeSigs :: Data t => [Name] -> t -> RefactGhc (t, [LSig RdrName])
- rmQualifier :: Data t => [Name] -> t -> RefactGhc t
- qualifyToplevelName :: Name -> RefactGhc ()
- renamePN :: Data t => Name -> Name -> HowToQual -> t -> RefactGhc t
- data HowToQual
- autoRenameLocalVar :: Data t => Name -> t -> RefactGhc t
- expToNameRdr :: NameMap -> LHsExpr RdrName -> Maybe Name
- nameToString :: Name -> String
- patToNameRdr :: NameMap -> LPat RdrName -> Maybe Name
- pNtoPat :: name -> Pat name
- usedWithoutQualR :: Data t => Name -> t -> Bool
- divideDecls :: Data t => [t] -> Located Name -> RefactGhc ([t], [t], [t])
- mkRdrName :: String -> RdrName
- mkQualifiedRdrName :: ModuleName -> String -> RdrName
- mkNewGhcName :: Maybe Module -> String -> RefactGhc Name
- mkNewName :: String -> [String] -> Int -> String
- mkNewToplevelName :: Module -> String -> SrcSpan -> RefactGhc Name
- registerRdrName :: Located RdrName -> RefactGhc ()
- causeNameClashInExports :: NameMap -> Name -> Name -> ModuleName -> ParsedSource -> Bool
- declsSybTransform :: Typeable a => (forall b. HasDecls b => b -> RefactGhc b) -> a -> RefactGhc a
- rdrNameFromName :: Bool -> Name -> RefactGhc RdrName
Program Analysis
Imports and exports
:: InScopes | The inscope relation . |
-> [(String, NameSpace, ModuleName, Maybe ModuleName)] | The result |
Process the inscope relation returned from the parsing and module analysis pass, and return a list of four-element tuples. Each tuple contains an identifier name, the identifier's namespace info, the identifier's defining module name and its qualifier name.
The same identifier may have multiple entries in the result because it may have different qualifiers. This makes it easier to decide whether the identifier can be used unqualifiedly by just checking whether there is an entry for it with the qualifier field being Nothing.
isInScopeAndUnqualified Source #
Return True if the identifier is inscope and can be used without a qualifier.
isInScopeAndUnqualifiedGhc Source #
:: String | The identifier name. |
-> Maybe Name | Existing name, to be excluded from test, if known |
-> RefactGhc Bool | The result. |
Return True if the identifier is inscope and can be used without a qualifier. The identifier name string may have a qualifier already NOTE: may require qualification based on name clash with an existing identifier.
Return all Name
s that correspond to the given string, in the current
module.
isExported :: Name -> RefactGhc Bool Source #
Return True if an identifier is exported by the module currently being refactored.
:: NameMap | |
-> Name | The identifier |
-> ParsedSource | The AST of the module |
-> Bool | The result |
Return True if an identifier is explicitly exported by the module.
:: ModuleName | The module name |
-> RenamedSource | The AST of the module |
-> Bool | The result |
Return True if the current module is exported either by default or by specifying the module name in the export.
equivalentNameInNewMod :: Name -> RefactGhc [Name] Source #
Given a Name
defined in one module, find the equivalent one in the
currently loaded module. This is required otherwise name equality checking
based on nameUnique
will fail.
:: Name | The identifier. |
-> RefactGhc [ModuleName] | The result. |
Return all the possible qualifiers for the identifier. The identifier
is not inscope if the result is an empty list. NOTE: This is intended to be
used when processing a client module, so the Name
parameter is actually
from a different module.
Property checking
isOperator :: String -> Bool Source #
Return True if a string is a lexically valid operator name.
isNonLibraryName :: Name -> Bool Source #
Return True if the name has a GHC.SrcSpan
, i.e. is declared in
source we care about
isQualifiedPN :: Name -> RefactGhc Bool Source #
Return True if a PName is a qualified PName. AZ:NOTE: this tests the use instance, the underlying name may be qualified. e.g. used name is zip, GHC.List.zip NOTE2: not sure if this gives a meaningful result for a GHC.Name
isFunOrPatName :: Data t => NameMap -> Name -> t -> Bool Source #
Return True if a PName is a function/pattern name defined in t.
isTypeSigDecl :: LHsDecl a -> Bool Source #
Return True if a declaration is a type signature declaration.
isFunBindP :: LHsDecl RdrName -> Bool Source #
Return True if a declaration is a function definition.
isFunBindR :: LHsBind t -> Bool Source #
isPatBindR :: LHsBind t -> Bool Source #
isSimplePatBind :: DataId t => LHsBind t -> Bool Source #
Return True if a declaration is a pattern binding which only defines a variable value.
isSimplePatDecl :: LHsDecl RdrName -> Bool Source #
Return True if a declaration is a pattern binding which only defines a variable value.
isComplexPatBind :: LHsBind name -> Bool Source #
Return True if a LHsBin is a pattern binding but not a simple one.
isComplexPatDecl :: LHsDecl name -> Bool Source #
Return True if a declaration is a pattern binding but not a simple one.
isFunOrPatBindP :: HsDeclP -> Bool Source #
Return True if a declaration is a function/pattern definition.
isFunOrPatBindR :: LHsBind t -> Bool Source #
Return True if a declaration is a function/pattern definition.
Getting
findEntity' :: (Data a, Data b) => a -> b -> Maybe (SimpPos, SimpPos) Source #
Returns True is a syntax phrase, say a, is part of another syntax phrase, say b. Expects to be at least Parser output
definesTypeSigRdr :: NameMap -> Name -> Sig RdrName -> Bool Source #
Return True if the declaration defines the type signature of the specified identifier.
class Data t => UsedByRhs t where Source #
usedByRhsRdr :: NameMap -> t -> [Name] -> Bool Source #
Return True if any of the GHC.Name's appear in the given syntax element
Modules and files
isMainModule :: Module -> Bool Source #
Locations
defineLoc :: Located Name -> SrcLoc Source #
Return the identifier's defining location. defineLoc::PNT->SrcLoc
useLoc :: Located Name -> SrcLoc Source #
Return the identifier's source location. useLoc::PNT->SrcLoc
:: (Data t, Typeable n) | |
=> SimpPos | The start position. |
-> SimpPos | The end position. |
-> t | The syntax phrase. |
-> Maybe (LHsExpr n) | The result. |
Given the syntax phrase, find the largest-leftmost expression contained in the region specified by the start and end position, if found.
:: Data t | |
=> SimpPos | The row and column number |
-> t | The syntax phrase |
-> Maybe (Located RdrName) | The result |
Find the identifier(in GHC.RdrName format) whose start position is
(row,col) in the file specified by the fileName, and returns
Nothing
if such an identifier does not exist.
Find the identifier with the given name. This looks through the given syntax phrase for the first GHC.Name which matches. Because it is Renamed source, the GHC.Name will include its defining location. Returns Nothing if the name is not found.
Program transformation
Adding
:: (Data t, Typeable t) | |
=> t | The AST to be updated |
-> Maybe Name | If this is Just, then the declaration will be added right after this identifier's definition. |
-> ([LHsDecl RdrName], Maybe Anns) | The declaration with optional signatures to be added, together with optional Annotations. |
-> RefactGhc t |
Adding a declaration to the declaration list of the given syntax phrase. If the second argument is Nothing, then the declaration will be added to the beginning of the declaration list, but after the data type declarations is there is any.
:: ModuleName | The imported module name |
-> Maybe Name | The condition identifier. |
-> Either [RdrName] [LIE RdrName] | The items to be added |
-> ParsedSource | The current module |
-> RefactGhc ParsedSource | The result |
Add identifiers (given by the third argument) to the explicit entity list in the declaration importing the specified module name. This function does nothing if the import declaration does not have an explicit entity list.
:: ParsedSource | The module AST. |
-> Maybe Name | The condtion identifier. |
-> Bool | Create an explicit list or not |
-> Either [RdrName] [LIE RdrName] | The identifiers to add in either String or HsExportEntP format. |
-> RefactGhc ParsedSource | The result. |
Add identifiers to the export list of a module. If the second argument is like: Just p, then do the adding only if p occurs in the export list, and the new identifiers are added right after p in the export list. Otherwise the new identifiers are add to the beginning of the export list. In the case that the export list is empty, then if the third argument is True, then create an explict export list to contain only the new identifiers, otherwise do nothing. TODO:AZ: re-arrange params to line up with addItemsToExport
:: ModuleName | The imported module name |
-> ParsedSource | The current module |
-> [RdrName] | The items to be added |
-> RefactGhc ParsedSource | The result |
add items to the hiding list of an import declaration which imports the specified module.
:: ParsedSource | |
-> ModuleName | |
-> Maybe StringLiteral | qualifier |
-> Bool | |
-> Bool | |
-> Bool | |
-> Maybe String | alias |
-> Bool | |
-> [RdrName] | |
-> RefactGhc ParsedSource |
Add identifiers to the export list of a module. If the second argument is like: Just p, then do the adding only if p occurs in the export list, and the new identifiers are added right after p in the export list. Otherwise the new identifiers are add to the beginning of the export list. In the case that the export list is emport, then if the third argument is True, then create an explict export list to contain only the new identifiers, otherwise do nothing.
:: [LHsDecl RdrName] | decls to be updated, containing the original decl (and sig) |
-> Name | The identifier whose definition is to be duplicated |
-> Name | The new name (possibly qualified) |
-> RefactGhc [LHsDecl RdrName] | The result |
Duplicate a function/pattern binding declaration under a new name right after the original one.
Removing
:: Data t | |
=> Name | The identifier whose definition is to be removed. |
-> Bool | True means including the type signature. |
-> t | The AST fragment containting the declarations, originating from the ParsedSource |
-> RefactGhc (t, LHsDecl RdrName, Maybe (LSig RdrName)) | The result and the removed declaration and the possibly removed siganture |
Remove the declaration (and the type signature is the second parameter is True) that defines the given identifier from the declaration list.
:: Data t | |
=> Name | The identifier whose type signature is to be removed. |
-> t | The declarations |
-> RefactGhc (t, Maybe (LSig RdrName)) | The result and removed signature, if there was one |
Remove the type signature that defines the given identifier's type from the declaration list.
:: Data t | |
=> [Name] | The identifiers whose type signatures are to be removed. |
-> t | The declarations |
-> RefactGhc (t, [LSig RdrName]) | The result and removed signatures, if there were any |
Remove multiple type signatures
Updating
Remove the qualifier from the given identifiers in the given syntax phrase.
qualifyToplevelName :: Name -> RefactGhc () Source #
Replace all occurences of a top level GHC.Name with a qualified version.
:: Data t | |
=> Name | The identifier to be renamed. |
-> Name | The new name, including possible qualifier |
-> HowToQual | |
-> t | The syntax phrase |
-> RefactGhc t |
Rename each occurrences of the identifier in the given syntax phrase with the new name.
Check whether the specified identifier is declared in the given syntax phrase t, if so, rename the identifier by creating a new name automatically.
Identifiers, expressions, patterns and declarations
expToNameRdr :: NameMap -> LHsExpr RdrName -> Maybe Name Source #
If an expression consists of only one identifier then return this identifier in the GHC.Name format, otherwise return the default Name
nameToString :: Name -> String Source #
patToNameRdr :: NameMap -> LPat RdrName -> Maybe Name Source #
If a pattern consists of only one identifier then return this identifier, otherwise return Nothing
pNtoPat :: name -> Pat name Source #
Deprecated: Can't use Renamed in GHC 8
Compose a pattern from a pName.
usedWithoutQualR :: Data t => Name -> t -> Bool Source #
Return True if the identifier is unqualifiedly used in the given syntax phrase. Check in a way that the test can be done in a client module, i.e. not using the nameUnique usedWithoutQualR :: GHC.Name -> GHC.ParsedSource -> Bool
Others
divideDecls :: Data t => [t] -> Located Name -> RefactGhc ([t], [t], [t]) Source #
Divide a declaration list into three parts (before, parent, after)
according to the PNT, where parent
is the first decl containing
the PNT, before
are those decls before parent
and after
are
those decls after parent
.
mkQualifiedRdrName :: ModuleName -> String -> RdrName Source #
Make a qualified RdrName
mkNewGhcName :: Maybe Module -> String -> RefactGhc Name Source #
Make a new GHC.Name, using the Unique Int sequence stored in the RefactState.
:: String | The old name |
-> [String] | The set of names which the new name cannot take |
-> Int | The posfix value |
-> String | The result |
Create a new name base on the old name. Suppose the old name is f
, then
the new name would be like f_i
where i
is an integer.
causeNameClashInExports Source #
:: NameMap | |
-> Name | The original name |
-> Name | The new name |
-> ModuleName | The identity of the module |
-> ParsedSource | The AST of the module |
-> Bool | The result |
Check if the proposed new name will conflict with an existing export
declsSybTransform :: Typeable a => (forall b. HasDecls b => b -> RefactGhc b) -> a -> RefactGhc a Source #