# Buggy code
def process(
    self, *, in_str: str, fname: Optional[str] = None, config=None
) -> Tuple[Optional[TemplatedFile], list]:
    """Process a string and return the new string.

    Note that the arguments are enforced as keywords
    because Templaters can have differences in their
    `process` method signature.
    A Templater that only supports reading from a file
    would need the following signature:
        process(*, fname, in_str=None, config=None)
    (arguments are swapped)

    Args:
        in_str (:obj:`str`): The input string.
        fname (:obj:`str`, optional): The filename of this string. This is
            mostly for loading config files at runtime.
        config (:obj:`FluffConfig`): A specific config to use for this
            templating operation. Only necessary for some templaters.

    """
    if not config:
        raise ValueError(
            "For the jinja templater, the `process()` method requires a config object."
        )

    # Load the context
    live_context = self.get_context(fname=fname, config=config)
    # Apply dbt builtin functions if we're allowed.
    apply_dbt_builtins = config.get_section(
        (self.templater_selector, self.name, "apply_dbt_builtins")
    )
    if apply_dbt_builtins:
        # This feels a bit wrong defining these here, they should probably
        # be configurable somewhere sensible. But for now they're not.
        # TODO: Come up with a better solution.
        dbt_builtins = self._generate_dbt_builtins()
        for name in dbt_builtins:
            # Only apply if it hasn't already been set at this stage.
            if name not in live_context:
                live_context[name] = dbt_builtins[name]

    # Load config macros
    env = self._get_jinja_env()
    ctx = self._extract_macros_from_config(config=config, env=env, ctx=live_context)
    # Load macros from path (if applicable)
    macros_path = config.get_section(
        (self.templater_selector, self.name, "load_macros_from_path")
    )
    if macros_path:
        ctx.update(
            self._extract_macros_from_path(macros_path, env=env, ctx=live_context)
        )
    live_context.update(ctx)

    # Load the template, passing the global context.
    try:
        template = env.from_string(in_str, globals=live_context)
    except TemplateSyntaxError as err:
        # Something in the template didn't parse, return the original
        # and a violation around what happened.
        (len(line) for line in in_str.split("\n")[: err.lineno])
        return (
            TemplatedFile(source_str=in_str, fname=fname),
            [
                SQLTemplaterError(
                    "Failure to parse jinja template: {0}.".format(err),
                    pos=FilePositionMarker(
                        None,
                        err.lineno,
                        None,
                        # Calculate the charpos for sorting.
                        sum(len(line) for line in in_str.split("\n")[: err.lineno - 1]),
                    ),
                )
            ],
        )

    violations = []

    # Attempt to identify any undeclared variables. The majority
    # will be found during the _crawl_tree step rather than this
    # first Exception which serves only to catch catastrophic errors.
    try:
        syntax_tree = env.parse(in_str)
        undefined_variables = meta.find_undeclared_variables(syntax_tree)
    except Exception as err:
        # TODO: Add a url here so people can get more help.
        raise SQLTemplaterError(
            "Failure in identifying Jinja variables: {0}.".format(err)
        )

    # Get rid of any that *are* actually defined.
    for val in live_context:
        if val in undefined_variables:
            undefined_variables.remove(val)

    if undefined_variables:
        # Lets go through and find out where they are:
        for val in self._crawl_tree(syntax_tree, undefined_variables, in_str):
            violations.append(val)

    try:
        # NB: Passing no context. Everything is loaded when the template is loaded.
        out_str = template.render()
        # Slice the file once rendered.
        raw_sliced, sliced_file = self.slice_file(in_str, out_str)
        return (
            TemplatedFile(
                source_str=in_str,
                templated_str=out_str,
                fname=fname,
                sliced_file=sliced_file,
                raw_sliced=raw_sliced,
            ),
            violations,
        )
    except (TemplateError, TypeError) as err:
        templater_logger.info("Unrecoverable Jinja Error: %s", err)
        violations.append(
            SQLTemplaterError(
                (
                    "Unrecoverable failure in Jinja templating: {0}. Have you configured "
                    "your variables? https://docs.sqlfluff.com/en/latest/configuration.html"
                ).format(err)
            )
        )
        return None, violations


# Traceback (IndexError)
Traceback (most recent call last):
File "/Users/niallwoodward/dev/pull_requests/dbt_sqlfluff_venv/bin/sqlfluff", line 11, in <module>
load_entry_point('sqlfluff', 'console_scripts', 'sqlfluff')()
File "/Users/niallwoodward/dev/pull_requests/dbt_sqlfluff_venv/lib/python3.6/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/Users/niallwoodward/dev/pull_requests/dbt_sqlfluff_venv/lib/python3.6/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/Users/niallwoodward/dev/pull_requests/dbt_sqlfluff_venv/lib/python3.6/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/Users/niallwoodward/dev/pull_requests/dbt_sqlfluff_venv/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/Users/niallwoodward/dev/pull_requests/dbt_sqlfluff_venv/lib/python3.6/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/Users/niallwoodward/dev/pull_requests/sqlfluff/src/sqlfluff/cli/commands.py", line 323, in lint
ignore_files=not disregard_sqlfluffignores,
File "/Users/niallwoodward/dev/pull_requests/sqlfluff/src/sqlfluff/core/linter.py", line 1161, in lint_paths
ignore_files=ignore_files,
File "/Users/niallwoodward/dev/pull_requests/sqlfluff/src/sqlfluff/core/linter.py", line 1139, in lint_path
target_file.read(), fname=fname, fix=fix, config=config
File "/Users/niallwoodward/dev/pull_requests/sqlfluff/src/sqlfluff/core/linter.py", line 939, in lint_string
parsed = self.parse_string(in_str=in_str, fname=fname, config=config)
File "/Users/niallwoodward/dev/pull_requests/sqlfluff/src/sqlfluff/core/linter.py", line 723, in parse_string
tokens, lex_vs = lexer.lex(templated_file)
File "/Users/niallwoodward/dev/pull_requests/sqlfluff/src/sqlfluff/core/parser/lexer.py", line 343, in lex
return self.enrich_segments(segment_buff, raw), violations
File "/Users/niallwoodward/dev/pull_requests/sqlfluff/src/sqlfluff/core/parser/lexer.py", line 373, in enrich_segments
templated_slice
File "/Users/niallwoodward/dev/pull_requests/sqlfluff/src/sqlfluff/core/templaters/base.py", line 283, in templated_slice_to_source_slice
elif start_slices[0][0] == "literal":
IndexError: list index out of range

# Fixed code
def process(
    self, *, in_str: str, fname: Optional[str] = None, config=None
) -> Tuple[Optional[TemplatedFile], list]:
    """Process a string and return the new string.

    Note that the arguments are enforced as keywords
    because Templaters can have differences in their
    `process` method signature.
    A Templater that only supports reading from a file
    would need the following signature:
        process(*, fname, in_str=None, config=None)
    (arguments are swapped)

    Args:
        in_str (:obj:`str`): The input string.
        fname (:obj:`str`, optional): The filename of this string. This is
            mostly for loading config files at runtime.
        config (:obj:`FluffConfig`): A specific config to use for this
            templating operation. Only necessary for some templaters.

    """
    if not config:
        raise ValueError(
            "For the jinja templater, the `process()` method requires a config object."
        )

    # Load the context
    live_context = self.get_context(fname=fname, config=config)
    # Apply dbt builtin functions if we're allowed.
    apply_dbt_builtins = config.get_section(
        (self.templater_selector, self.name, "apply_dbt_builtins")
    )
    if apply_dbt_builtins:
        # This feels a bit wrong defining these here, they should probably
        # be configurable somewhere sensible. But for now they're not.
        # TODO: Come up with a better solution.
        dbt_builtins = self._generate_dbt_builtins()
        for name in dbt_builtins:
            # Only apply if it hasn't already been set at this stage.
            if name not in live_context:
                live_context[name] = dbt_builtins[name]

    # Load config macros
    env = self._get_jinja_env()
    ctx = self._extract_macros_from_config(config=config, env=env, ctx=live_context)
    # Load macros from path (if applicable)
    macros_path = config.get_section(
        (self.templater_selector, self.name, "load_macros_from_path")
    )
    if macros_path:
        ctx.update(
            self._extract_macros_from_path(macros_path, env=env, ctx=live_context)
        )
    live_context.update(ctx)

    # Load the template, passing the global context.
    try:
        template = env.from_string(in_str, globals=live_context)
    except TemplateSyntaxError as err:
        # Something in the template didn't parse, return the original
        # and a violation around what happened.
        (len(line) for line in in_str.split("\n")[: err.lineno])
        return (
            TemplatedFile(source_str=in_str, fname=fname),
            [
                SQLTemplaterError(
                    "Failure to parse jinja template: {0}.".format(err),
                    pos=FilePositionMarker(
                        None,
                        err.lineno,
                        None,
                        # Calculate the charpos for sorting.
                        sum(len(line) for line in in_str.split("\n")[: err.lineno - 1]),
                    ),
                )
            ],
        )

    violations = []

    # Attempt to identify any undeclared variables. The majority
    # will be found during the _crawl_tree step rather than this
    # first Exception which serves only to catch catastrophic errors.
    try:
        syntax_tree = env.parse(in_str)
        undefined_variables = meta.find_undeclared_variables(syntax_tree)
    except Exception as err:
        # TODO: Add a url here so people can get more help.
        raise SQLTemplaterError(
            "Failure in identifying Jinja variables: {0}.".format(err)
        )

    # Get rid of any that *are* actually defined.
    for val in live_context:
        if val in undefined_variables:
            undefined_variables.remove(val)

    if undefined_variables:
        # Lets go through and find out where they are:
        for val in self._crawl_tree(syntax_tree, undefined_variables, in_str):
            violations.append(val)

    try:
        # NB: Passing no context. Everything is loaded when the template is loaded.
        out_str = template.render()
        # Slice the file once rendered.
        raw_sliced, sliced_file, out_str = self.slice_file(
            in_str, out_str, config=config
        )
        return (
            TemplatedFile(
                source_str=in_str,
                templated_str=out_str,
                fname=fname,
                sliced_file=sliced_file,
                raw_sliced=raw_sliced,
            ),
            violations,
        )
    except (TemplateError, TypeError) as err:
        templater_logger.info("Unrecoverable Jinja Error: %s", err)
        violations.append(
            SQLTemplaterError(
                (
                    "Unrecoverable failure in Jinja templating: {0}. Have you configured "
                    "your variables? https://docs.sqlfluff.com/en/latest/configuration.html"
                ).format(err)
            )
        )
        return None, violations