Spec-Zone.ru › Elixir 1.17

Исходный код Code.Fragment

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

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

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

Типы

position()

Функции

container_cursor_to_quoted(fragment, opts \\ [])

Принимает строку и возвращает выражение с цитированием, содержащее позицию курсора AST в родительском выражении.

cursor_context(fragment, opts \\ [])

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

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

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

Типы

position()Исходный код

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

Функции

container_cursor_to_quoted(fragment, opts \\ [])Source

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

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

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

Например, рассмотрите этот код, который будет передан в качестве входных данных:

max(some_value,

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

max(some_value, __cursor__())

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

max(some_value, another_val

Будет возвращён тот же AST:

max(some_value, __cursor__())

Аналогично, если подаётся только это:

max(some_va

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

max(__cursor__())

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

Кортежи, списки, карты и двоичные данные сохраняют позицию курсора:

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], []}]}}

Контейнеры (например, список):

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

Если выражение завершено, тогда всё выражение отбрасывается и возвращается только родительский элемент:

iex> Code.Fragment.container_cursor_to_quoted("if(is_atom(var)")
{:ok, {:if, [line: 1], [{:__cursor__, [line: 1], []}]}}

это означает, что завершённые выражения сами возвращают только курсор:

iex> Code.Fragment.container_cursor_to_quoted("if(is_atom(var))")
{:ok, {:__cursor__, [line: 1], []}}

Операторы также включаются с версии Elixir v1.15:

iex> Code.Fragment.container_cursor_to_quoted("foo +")
{:ok, {:+, [line: 1], [{:foo, [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.

  • :literal_encoder - функция для кодирования литералов в AST. См. документацию для Code.string_to_quoted/2 для получения дополнительной информации.

cursor_context(fragment, opts \\ [])Source

@spec cursor_context(
  List.Chars.t(),
  keyword()
) ::
  {:alias, charlist()}
  | {:alias, inside_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()}
  | {:anonymous_call, inside_caller}
  | {:module_attribute, charlist()}
  | {:operator, charlist()}
  | {:operator_arity, charlist()}
  | {:operator_call, charlist()}
  | :none
  | {:sigil, charlist()}
  | {:struct, inside_struct}
  | {:unquoted_atom, charlist()}
when inside_dot:
       {:alias, charlist()}
       | {:alias, inside_alias, charlist()}
       | {:dot, inside_dot, charlist()}
       | {:module_attribute, charlist()}
       | {:unquoted_atom, charlist()}
       | {:var, charlist()}
       | :expr,
     inside_alias: {:local_or_var, charlist()} | {:module_attribute, charlist()},
     inside_struct:
       charlist()
       | {:alias, inside_alias, charlist()}
       | {:local_or_var, charlist()}
       | {:module_attribute, charlist()}
       | {:dot, inside_dot, charlist()},
     inside_caller: {:var, charlist()} | {:module_attribute, charlist()}

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

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

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

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

Примеры

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

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

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

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

  • {:alias, inside_alias, charlist} - контекст является псевдонимом, потенциально вложенным, где inside_alias является выражением {:module_attribute, charlist} или {:local_or_var, charlist}, а charlist — статической частью. Примерами являются __MODULE__.Submodule или @hello.Submodule

  • {: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. Если charlist пусто, а inside_dot является псевдонимом, тогда автозаполнение может быть либо псевдонимом, либо удалённым вызовом.

  • {: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

  • {:anonymous_call, inside_caller} - контекст — анонимный вызов, такой как fun.( и @fun.(.

  • {: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, inside_struct} - контекст — структура, такая как %, %UR или %URI. inside_struct может быть либо charlist в случае статического псевдонима, либо выражением {:alias, inside_alias, charlist}, {:module_attribute, charlist}, {:local_or_var, charlist}, {:dot, inside_dot, charlist}

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

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

Ограничения

Анализ основан на текущем марке, анализируя последнюю строку входных данных. Например, этот код:

iex> Code.Fragment.cursor_context("%URI{")
:expr

возвращает :expr, что предполагает, что можно использовать любую переменную, локальную функцию или псевдоним. Однако, учитывая, что мы находимся внутри структуры, лучшим предложением будет поле структуры. В таких случаях можно использовать container_cursor_to_quoted, которая вернёт контейнер AST, в котором находится курсор. Затем вы можете проанализировать этот AST для завершения имен полей.

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

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

@spec surround_context(List.Chars.t(), position(), keyword()) ::
  %{begin: position(), end: position(), context: context} | :none
when context:
       {:alias, charlist()}
       | {:alias, inside_alias, charlist()}
       | {:dot, inside_dot, charlist()}
       | {:local_or_var, charlist()}
       | {:local_arity, charlist()}
       | {:local_call, charlist()}
       | {:module_attribute, charlist()}
       | {:operator, charlist()}
       | {:sigil, charlist()}
       | {:struct, inside_struct}
       | {:unquoted_atom, charlist()}
       | {:keyword, charlist()},
     inside_dot:
       {:alias, charlist()}
       | {:alias, inside_alias, charlist()}
       | {:dot, inside_dot, charlist()}
       | {:module_attribute, charlist()}
       | {:unquoted_atom, charlist()}
       | {:var, charlist()}
       | :expr,
     inside_alias: {:local_or_var, charlist()} | {:module_attribute, charlist()},
     inside_struct:
       charlist()
       | {:alias, inside_alias, charlist()}
       | {:local_or_var, charlist()}
       | {:module_attribute, charlist()}
       | {:dot, inside_dot, 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, ~c"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, ''} как контекст

  • Эта функция возвращает ключевые слова как {:keyword, 'do'}

  • Эта функция никогда не возвращает :expr

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

Скачать версию ePub

Создано с помощью ExDoc (v0.34.1) для языка программирования Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.17.2/Code.Fragment.html

Spec-Zone.ru

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