content: {-# language DataKinds #-}
  {-# language FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses #-}
  
  {-|
  Module      : Language.Python.Optics.Indents
  Copyright   : (C) CSIRO 2017-2019
  License     : BSD3
  Maintainer  : Isaac Elliott <isaace71295@gmail.com>
  Stability   : experimental
  Portability : non-portable
  -}
  
  module Language.Python.Optics.Indents where
  
  import Control.Lens.Traversal (Traversal')
  
  import Language.Python.Syntax
  import Language.Python.Internal.Token
  
  -- | 'Traversal'' targeting the indent-chunks in a structure
  --
  -- e.g.
  --
  -- This is one indent chunk:
  --
  -- @
  -- def a():
  --     pass
  --     if b:
  --         pass
  -- ^^^^
  -- @
  --
  -- and this is another
  --
  -- @
  -- def a():
  --     pass
  --     if b:
  --         pass
  --     ^^^^
  -- @
  _Indent :: HasIndents s a => Traversal' s [Whitespace]
  _Indent = _Indents.indentsValue.traverse.indentWhitespaces
  
  class HasIndents s a | s -> a where
    -- | 'Traversal'' targeting the indentation inside a structure
    --
    -- Note: whitespace inside \'enclosed forms\' (such as lists or tuples) is not
    -- considered indentation.
    --
    -- e.g.
    --
    -- In the following code, there is only one chunk of indentation:
    --
    -- @
    -- def a():
    --     [ b
    --     , c
    --     , d
    --     ]
    -- @
    --
    -- it's here:
    --
    -- @
    -- def a():
    --     [ b
    -- ^^^^
    --     , c
    --     , d
    --     ]
    -- @
    --
    -- The rest is whitespace that is internal to the list.
    _Indents :: Traversal' s (Indents a)
  
  instance HasIndents (PyToken a) a where
    _Indents f (TkIndent a i) = TkIndent a <$> f i
    _Indents f (TkLevel a i) = TkLevel a <$> f i
    _Indents _ a = pure a
  
  instance HasIndents (Fundef '[] a) a where
    _Indents fun (MkFundef a b c d e f g h i j k) =
      (\b' c' -> MkFundef a b' c' d e f g h i j) <$>
      (traverse._Indents) fun b <*>
      fun c <*>
      _Indents fun k
  
  instance HasIndents (For '[] a) a where
    _Indents fun (MkFor a b c d e f g h i) =
      (\b' -> MkFor a b' c d e f g) <$>
      fun b <*>
      _Indents fun h <*>
      (traverse._Indents) fun i
  
  instance HasIndents (TryFinally '[] a) a where
    _Indents fun (MkTryFinally a b c d e) =
      (\b' -> MkTryFinally a b' c) <$>
      fun b <*>
      _Indents fun d <*>
      _Indents fun e
  
  instance HasIndents (TryExcept '[] a) a where
    _Indents fun (MkTryExcept a b c d e f g) =
      (\b' -> MkTryExcept a b' c) <$>
      fun b <*>
      _Indents fun d <*>
      (traverse._Indents) fun e <*>
      (traverse._Indents) fun f <*>
      (traverse._Indents) fun g
  
  instance HasIndents (Except '[] a) a where
    _Indents fun (MkExcept a b c d) =
      (\a' -> MkExcept a' b c) <$>
      fun a <*>
      _Indents fun d
  
  instance HasIndents (Finally '[] a) a where
    _Indents fun (MkFinally a b c) =
      (\a' -> MkFinally a' b) <$>
      fun a <*>
      _Indents fun c
  
  instance HasIndents (If '[] a) a where
    _Indents fun (MkIf a b c d e f g) =
      (\b' -> MkIf a b' c d) <$>
      fun b <*>
      _Indents fun e <*>
      (traverse._Indents) fun f <*>
      (traverse._Indents) fun g
  
  instance HasIndents (While '[] a) a where
    _Indents fun (MkWhile a b c d e f) =
      (\b' -> MkWhile a b' c d) <$>
      fun b <*>
      _Indents fun e <*>
      (traverse._Indents) fun f
  
  instance HasIndents (Elif '[] a) a where
    _Indents fun (MkElif a b c d) =
      (\a' -> MkElif a' b c) <$>
      fun a <*>
      _Indents fun d
  
  instance HasIndents (Else '[] a) a where
    _Indents f (MkElse a b c) = MkElse <$> f a <*> pure b <*> _Indents f c
  
  instance HasIndents (SmallStatement '[] a) a where
    _Indents _ (MkSmallStatement a b c d e) =
      pure $ MkSmallStatement a b c d e
  
  instance HasIndents (Statement '[] a) a where
    _Indents f (SmallStatement idnt a) = SmallStatement <$> f idnt <*> _Indents f a
    _Indents f (CompoundStatement c) = CompoundStatement <$> _Indents f c
  
  instance HasIndents (Block '[] a) a where
    _Indents = _Statements._Indents
  
  instance HasIndents (Suite '[] a) a where
    _Indents _ (SuiteOne a b c) = pure $ SuiteOne a b c
    _Indents f (SuiteMany a b c d e) = SuiteMany a b c d <$> _Indents f e
  
  instance HasIndents (Decorator '[] a) a where
    _Indents fun (Decorator a b c d e f g) =
      (\b' -> Decorator a b' c d e f g) <$>
      fun b
  
  instance HasIndents (ClassDef '[] a) a where
    _Indents fun (MkClassDef a b c d e f g) =
      (\b' c' -> MkClassDef a b' c' d e f) <$>
      (traverse._Indents) fun b <*>
      fun c <*>
      _Indents fun g
  
  instance HasIndents (With '[] a) a where
    _Indents fun (MkWith a b c d e f) =
      (\b' -> MkWith a b' c d e) <$>
      fun b <*>
      _Indents fun f
  
  instance HasIndents (CompoundStatement '[] a) a where
    _Indents fun s =
      case s of
        Fundef a decos idnt asyncWs b c d e f g h ->
          (\decos' idnt' -> Fundef a decos' idnt' asyncWs b c d e f g) <$>
          (traverse._Indents) fun decos <*>
          fun idnt <*>
          _Indents fun h
        If a idnt b c d elifs e ->
          (\idnt' -> If a idnt' b c) <$>
          fun idnt <*>
          _Indents fun d <*>
          traverse
            (\(idnt, a, b, c) ->
               (\idnt'  -> (,,,) idnt' a b) <$>
               fun idnt <*>
               _Indents fun c)
            elifs <*>
          traverse
            (\(idnt, a, b) ->
               (\idnt' -> (,,) idnt' a) <$>
               fun idnt <*>
               _Indents fun b)
            e
        While a idnt b c d e ->
          (\idnt' -> While a idnt' b c) <$>
          fun idnt <*>
          _Indents fun d <*>
          traverse
            (\(idnt, a, b) ->
               (\idnt' -> (,,) idnt' a) <$>
               fun idnt <*>
               _Indents fun b)
            e
        TryExcept a idnt b c d e f ->
          (\idnt' -> TryExcept a idnt' b) <$>
          fun idnt <*>
          _Indents fun c <*>
          traverse
            (\(idnt, a, b, c) ->
               (\idnt' -> (,,,) idnt' a b) <$>
               fun idnt <*>
               _Indents fun c)
            d <*>
          traverse
            (\(idnt, a, b) ->
               (\idnt' -> (,,) idnt' a) <$>
               fun idnt <*>
               _Indents fun b)
            e <*>
          traverse
            (\(idnt, a, b) ->
               (\idnt' -> (,,) idnt' a) <$>
               fun idnt <*>
               _Indents fun b)
            f
        TryFinally a idnt b c idnt2 d e ->
          (\idnt' c' idnt2' -> TryFinally a idnt' b c' idnt2' d) <$>
          fun idnt <*>
          _Indents fun c <*>
          fun idnt2 <*>
          _Indents fun e
        For a idnt asyncWs b c d e f g ->
          (\idnt' -> For a idnt' asyncWs b c d e) <$>
          fun idnt <*>
          _Indents fun f <*>
          traverse
            (\(idnt, a, b) ->
               (\idnt' -> (,,) idnt' a) <$>
               fun idnt <*>
               _Indents fun b)
            g
        ClassDef a decos idnt b c d e ->
          (\decos' idnt' -> ClassDef a decos' idnt' b c d) <$>
          traverse (_Indents fun) decos <*>
          fun idnt <*>
          _Indents fun e
        With a b asyncWs c d e ->
          (\b' -> With a b' asyncWs c d) <$>
          fun b <*>
          _Indents fun e
  