Spec-Zone.ru › Elixir 1.13

Code.Fragment

Этот модуль предоставляет удобные функции для анализа фрагментов текстового кода и извлечения доступной информации, когда это возможно.

Большинство функций в этом модуле работают по принципу «лучшее, что возможно», и могут быть неточными во всех обстоятельствах. Обратитесь к каждой документации для получения дополнительной информации.

Этот модуль следует рассматривать как экспериментальный.

Краткое описание

Типы

position()

Функции

container_cursor_to_quoted(fragment, opts \\ [])

Принимает фрагмент кода и возвращает выражение в кавычках с курсором в ближайшей позиции аргумента.

cursor_context(fragment, opts \\ [])

Принимает строку и возвращает контекст курсора.

surround_context(fragment, position, options \\ [])

Принимает строку и возвращает окружающий контекст.

Типы

position()Source

@type position() :: {line :: pos_integer(), column :: pos_integer()}

Функции

container_cursor_to_quoted(fragment, opts \\ [])Источник

@spec container_cursor_to_quoted(
  List.Chars.t(),
  keyword()
) ::
  {:ok, Macro.t()}
  | {:error, {location :: keyword(), binary() | {binary(), binary()}, binary()}}

Принимает фрагмент кода и возвращает цитируемое выражение с курсором в позиции ближайшего аргумента.

Контейнер — любое выражение Elixir, начинающееся с (, {, и [. Это включает вызовы функций, кортежи, списки, карты и так далее. Например, рассмотрим этот код, который будет передан в качестве входных данных:

max(some_value,

Эта функция вернёт AST, эквивалентный:

max(some_value, __cursor__())

Другими словами, эта функция способна закрыть любые открытые скобки и вставить позицию курсора. Любое содержимое в позиции курсора, находящееся после запятой или открывающей скобки, будет отброшено. Например, если в качестве входных данных подан:

max(some_value, another_val

Она вернёт тот же AST:

max(some_value, __cursor__())

Аналогично, если задано только:

max(some_va

Тогда она возвращает:

max(__cursor__())

Также поддерживаются вызовы без скобок, так как мы предполагаем, что скобки подразумеваются.

Операторы и анонимные функции не являются контейнерами и поэтому будут отброшены. Следующее всё вернёт один и тот же AST:

max(some_value,
max(some_value, fn x -> x end
max(some_value, 1 + another_val
max(some_value, 1 |> some_fun() |> another_fun

С другой стороны, кортежи, списки, карты и т. д. сохраняют позицию курсора:

max(some_value, [1, 2,

Возвращает следующий AST:

max(some_value, [1, 2, __cursor__()])

Списки ключевых слов (и блоки do-end) также сохраняются. Следующее:

if(some_value, do:
if(some_value, do: :token
if(some_value, do: 1 + val

всё возвращает:

if(some_value, do: __cursor__())

AST, возвращаемый этой функцией, не безопасен для вычисления, но его можно проанализировать и расширить.

Примеры

iex> Code.Fragment.container_cursor_to_quoted("max(some_value, ")
{:ok, {:max, [line: 1], [{:some_value, [line: 1], nil}, {:__cursor__, [line: 1], []}]}}

Параметры

  • :file — имя файла, которое будет сообщено в случае ошибок разбора. По умолчанию "nofile".

  • :line — начальная строка анализируемой строки. По умолчанию 1.

  • :column — начальная колонка анализируемой строки. По умолчанию 1.

  • :columns — когда true, добавить ключ :column к метаданным цитирования. По умолчанию false.

  • :token_metadata — когда true, включает метаданные, связанные с токенами, в выражение AST, такие как метаданные для do и end токенов, для закрывающих токенов, конца выражений, а также разделители для сигилов. См. Macro.metadata/0. По умолчанию false.

cursor_context(fragment, opts \\ [])Источник

@spec cursor_context(
  List.Chars.t(),
  keyword()
) ::
  {:alias, charlist()}
  | {:dot, inside_dot, charlist()}
  | {:dot_arity, inside_dot, charlist()}
  | {:dot_call, inside_dot, charlist()}
  | :expr
  | {:local_or_var, charlist()}
  | {:local_arity, charlist()}
  | {:local_call, charlist()}
  | {:module_attribute, charlist()}
  | {:operator, charlist()}
  | {:operator_arity, charlist()}
  | {:operator_call, charlist()}
  | :none
  | {:sigil, charlist()}
  | {:struct, charlist()}
  | {:unquoted_atom, charlist()}
when inside_dot:
       {:alias, charlist()}
       | {:dot, inside_dot, charlist()}
       | {:module_attribute, charlist()}
       | {:unquoted_atom, charlist()}
       | {:var, charlist()}

Принимает строку и возвращает контекст курсора.

Эта функция получает строку с фрагментом кода Elixir, представляющим позицию курсора, и на основе строки предоставляет контекстную информацию об указанной позиции. Результат этой функции можно использовать для предоставления подсказок, предложений и функциональности автодополнения.

Эта функция обеспечивает обнаружение с наилучшим результатом и может быть неточной во всех случаях. См. раздел «Ограничения» ниже.

Рассмотрите добавление универсального раздела при обработке возвращаемого типа этой функции, так как в будущих выпусках могут быть добавлены новые сведения о курсоре.

Примеры

iex> Code.Fragment.cursor_context("")
:expr

iex> Code.Fragment.cursor_context("hello_wor")
{:local_or_var, 'hello_wor'}

Возвращаемые значения

  • {:alias, charlist} — контекст является псевдонимом, потенциально вложенным, например, Hello.Wor или HelloWor

  • {:dot, inside_dot, charlist} — контекст является точкой, где inside_dot является либо {:var, charlist}, {:alias, charlist}, {:module_attribute, charlist}, {:unquoted_atom, charlist} или самим dot. Если задана переменная, это может быть удалённый вызов или доступ к полю карты. Примеры Hello.wor, :hello.wor, hello.wor, Hello.nested.wor, hello.nested.wor, и @hello.world

  • {:dot_arity, inside_dot, charlist} — контекст — арифметическая точка, где inside_dot является либо {:var, charlist}, {:alias, charlist}, {:module_attribute, charlist}, {:unquoted_atom, charlist} или самим dot. Если задана переменная, она должна быть удалённой арифметической точкой. Примеры Hello.world/, :hello.world/, hello.world/2, и @hello.world/2

  • {:dot_call, inside_dot, charlist} — контекст — вызов точки. Это означает, что после выражения добавлены скобки или пробел. где inside_dot является либо {:var, charlist}, {:alias, charlist}, {:module_attribute, charlist}, {:unquoted_atom, charlist} или самим dot. Если задана переменная, она должна быть удалённым вызовом. Примеры Hello.world(, :hello.world(, Hello.world, hello.world(, hello.world, и @hello.world(

  • :expr — может быть любым выражением. Автодополнение может предложить псевдоним, локальную или переменную.

  • {:local_or_var, charlist} — контекст — переменная или локальный вызов (импорт или локальный), такой как hello_wor

  • {:local_arity, charlist} — контекст — локальная арифметическая точка (импорт или локальный), например hello_world/

  • {:local_call, charlist} — контекст — локальный вызов (импорт или локальный), например hello_world( и hello_world

  • {:module_attribute, charlist} — контекст — атрибут модуля, например @hello_wor

  • {:operator, charlist} — контекст — оператор, например + или ==. Обратите внимание, что текстовые операторы, такие как when не отображаются как операторы, а скорее как :local_or_var. @ никогда не является :operator и всегда :module_attribute

  • {:operator_arity, charlist} — контекст — арифметическая точка оператора, которая является оператором, за которым следует /, например +/, not/ или when/

  • {:operator_call, charlist} — контекст — вызов оператора, который является оператором, за которым следует пробел, например left +, not или x when

  • :none — контекст недоступен

  • {:sigil, charlist} — контекст — сигил. Это может быть либо начало сигила, например ~ или ~s, либо оператор, начинающийся с ~, например ~> и ~>>

  • {:struct, charlist} — контекст — структура, например %, %UR или %URI

  • {:unquoted_atom, charlist} — контекст — нецитируемый атом. Это может быть любой атом или атом, представляющий модуль.

Ограничения

Текущий алгоритм учитывает только последнюю строку входных данных. Это означает, что он также будет показывать предложения внутри строк, heredocs и т. д., что преднамеренно, так как это помогает с doctests, ссылками и другими задачами.

surround_context(fragment, position, options \\ [])Источник

@spec surround_context(List.Chars.t(), position(), keyword()) ::
  %{begin: position(), end: position(), context: context} | :none
when context:
       {:alias, charlist()}
       | {:dot, inside_dot, charlist()}
       | {:local_or_var, charlist()}
       | {:local_arity, charlist()}
       | {:local_call, charlist()}
       | {:module_attribute, charlist()}
       | {:operator, charlist()}
       | {:unquoted_atom, charlist()},
     inside_dot:
       {:alias, charlist()}
       | {:dot, inside_dot, charlist()}
       | {:module_attribute, charlist()}
       | {:unquoted_atom, charlist()}
       | {:var, charlist()}

Принимает строку и возвращает контекст окружающего выражения.

Эта функция принимает строку с фрагментом кода Elixir и position. Она возвращает карту, содержащую начало и конец идентификатора вместе с его контекстом, или :none если нет ничего с известным контекстом.

Разница между cursor_context/2 и surround_context/3 заключается в том, что первая предполагает, что выражение во фрагменте кода неполное. Например, do в cursor_context/2 может быть ключевым словом, переменной или локальным вызовом, в то время как surround_context/3 предполагает, что выражение во фрагменте кода полное, поэтому do всегда будет ключевым словом.

Массив position содержит как line, так и column, оба начинаются с индекса 1. Колонка должна предшествовать окружающему выражению. Например, выражение foo, вернёт что-то для столбцов 1, 2 и 3, но не 4:

foo
^ column 1

foo
 ^ column 2

foo
  ^ column 3

foo
   ^ column 4

Возвращаемая карта содержит колонку, с которой начинается выражение, и первую колонку после завершения выражения.

Аналогично cursor_context/2, эта функция также предоставляет обнаружение с наилучшим результатом и может быть неточной во всех случаях. См. раздел «Возвращаемые значения» и «Ограничения» в cursor_context/2 для получения дополнительной информации.

Примеры

iex> Code.Fragment.surround_context("foo", {1, 1})
%{begin: {1, 1}, context: {:local_or_var, 'foo'}, end: {1, 4}}

Отличия от cursor_context/2

Так как surround_context/3 работает с полным кодом, у него есть некоторые отличия от cursor_context/2:

  • dot_call/dot_arity и operator_call/operator_arity сводятся к dot и operator соответственно, так как между ними нет значимых различий

  • С другой стороны, эта функция всё ещё различает local_call/local_arity и local_or_var, так как последнее может быть локальным или переменной

  • @ при отсутствии последующего идентификатора возвращается как {:operator, '@'} (в отличие от {:module_attribute, ''} в cursor_context/2

  • Эта функция никогда не возвращает пустые сигилы {:sigil, ''} или пустые структуры {:struct, ''} в качестве контекста

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.13.4/Code.Fragment.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API