
Tern - отличный инструмент для Javascript, но иногда мне трудно рассуждать о нем, что ведет меня к черным дырам несогласованной настройки конфигурации, пока он не сработает волшебным образом. Недавно я более глубоко погрузился в понимание этого и хотел поделиться с вами (и со своим будущим, когда я вернусь к поиску в Google)
Tern:
- Http-сервер, который принимает почтовые запросы JSON.
- Обычно запускают в редакторе через плагин (vim, atom и т. Д.)
- Читает из
.tern-projectфайла в корне проекта - При запуске создает файл
.tern-port, чтобы ваш редактор знал, к какому порту подключаться. - Считывает серию файлов из вашего проекта в память и по запросу возвращает тип / автозаполнение и другую полезную информацию.
- См. Больше на https://ternjs.net/doc/manual.html
Проблема, с которой я обычно сталкиваюсь, заключается в том, что он, кажется, время от времени не может завершить [некоторые] вещи. Это можно продемонстрировать, создав конфигурацию и вручную запустив сервер с установленной опцией --verbose. В приложении stockcreate-react-app добавьте в корень проекта следующий файл
.tern-project
{
"libs": [
"browser"
],
"loadEagerly": [],
"dontLoad": [],
"plugins": {
"modules": {},
"es_modules": {},
"requirejs": {},
"commonjs": {}
}
}
Установите и запустите двоичный файл в другом терминале
# if you haven't installed tern already $ yarn global add tern $ cd project-dir $ tern --verbose # Outputs: Listening on port [port#]
теперь, когда у вас есть сервер, работающий в каталоге проекта, ваш редактор (у которого должен быть плагин tern https://ternjs.net/doc/manual.html#editor) должен выбрать файл .tern-port и знать, что там - это запущенный сервер, и ему не нужно запускать новый.
Если я открою новый файл с именем autocompleteme.js в каталоге src и попробую что-то завершить, я увижу следующее…

Так крачка ... работает? ¯_ (ツ) _ / ¯
Ну, вроде… все настроено на работу, но если вы попытаетесь получить доступ к какому-либо свойству импортированного объекта, вы не увидите никаких завершений.

Если вы вернетесь к терминалу, на котором запущен сервер, вы должны увидеть несколько поступивших запросов и ответов (это много JSON, поэтому просто прокрутите мимо, если вам нужно только объяснение).
Request: {
"query": {
"type": "completions",
"types": true,
"depths": true,
"docs": false,
"filter": true,
"caseInsensitive": true,
"guess": true,
"sort": false,
"expandWordForward": true,
"omitObjectPrototype": false,
"includeKeywords": false,
"inLiteral": true,
"file": "#0",
"end": {
"line": 2,
"ch": 0
},
"lineCharPositions": true
},
"files": [
{
"type": "full",
"name": "src/autocompleteme.js",
"text": "import React, { Component } from \"react\";\n\nRea\n"
}
]
}
Response: {
"start": {
"line": 2,
"ch": 0
},
"end": {
"line": 2,
"ch": 3
},
"isProperty": false,
"isObjectKey": false,
"completions": [
{
"name": "React",
"type": "?",
"depth": 0
}
]
}
Вы можете видеть, что он отправляет текущий файл, а также позицию курсора и запрашивает параметры завершения. Ближе к концу получается один ... `React` с типом ?, который мы видели в поле автозаполнения.
Если я прокручиваю вывод терминала вниз, я вижу запрос, который поступил после того, как я попытался получить доступ к свойству объекта.
Request: {
"query": {
"type": "completions",
"types": true,
"depths": true,
"docs": false,
"filter": true,
"caseInsensitive": true,
"guess": true,
"sort": false,
"expandWordForward": true,
"omitObjectPrototype": false,
"includeKeywords": false,
"inLiteral": true,
"file": "#0",
"end": {
"line": 2,
"ch": 6
},
"lineCharPositions": true
},
"files": [
{
"type": "full",
"name": "src/autocompleteme.js",
"text": "import React, { Component } from 'react';\n\nReact.\n"
}
]
}
Response: {
"start": {
"line": 2,
"ch": 6
},
"end": {
"line": 2,
"ch": 6
},
"isProperty": true,
"isObjectKey": false,
"completions": []
}
И есть варианты нулевой доработки… хммм. Заглянув в документацию (https://ternjs.net/doc/manual.html#req_files), я вижу, что есть конечная точка для получения файлов, проанализированных сервером, в основном всех файлов, которые tern может рисовать. доработки из. Примерного запроса нет, поэтому, немного поработав, я смог придумать curl запрос, который был принят ...
# get the port number from the `.tern-port` file $ curl -X POST https://localhost:57242 -d '{"query": {"type": "files"}}' # OUTPUT: {"files":[]}
Ага. Он не нашел никаких файлов, из которых можно было бы рисовать завершения, поэтому он выполняет только завершение из текста, найденного в текущем файле, который был отправлен в запросе от редактора.
По умолчанию локальные файлы загружаются на сервер Tern при выполнении запросов в редакторе. Http://ternjs.net/doc/manual.html#configuration
Это могло бы объяснить, почему он иногда работает, а иногда нет, даже с одним и тем же кодом ... Если у вас был запущен tern server, и он читает файл, то он запомнит его и извлечет из него автозаполнения. Так что, если ваш редактор был открыт долгое время и было открыто много файлов, он мог бы, казалось бы, завершить все, только чтобы вернуться позже в тот же день, не касаясь конфигурации, и все кажется сломанным.
Как это исправить
Чтобы исправить это, убедитесь, что у вас есть правильные строки в конфигурации, которые могут указать серверу, где искать файлы и загружать их сразу при запуске. Для своих целей при написании javascript я обычно использую create-react-app, который использует веб-пакет, поэтому я сосредоточусь на этом плагине, но есть и другие [здесь] (https://ternjs.net/doc/manual.html#plugins)
При использовании create-react-app конфигурация веб-пакета входит в node_modules, поэтому мы должны использовать путь к этому файлу.
{
"libs": [
"browser"
],
"loadEagerly": [],
"dontLoad": [],
"plugins": {
"modules": {},
"webpack": {
"configPath": "./node_modules/react-scripts/config/webpack.config.dev.js"
}
}
}
К сожалению, если мы попытаемся запустить здесь сервер, он выйдет из строя из-за отсутствия переменной среды, которая была бы где-то создана, если бы сценарий выполнялся обычным способом ...
Единственный способ, которым я мог это увидеть, - это создать сценарий оболочки, который устанавливает переменную и вызывает tern
custom-tern
#!/bin/bash # while debugging and experimenting, add the pipe to a log file NODE_ENV=dev tern --persistent --verbose | tee /tmp/tern.log
Как только я добавил это в свой ~/bin и изменил свой редактор, чтобы использовать мой custom-tern в качестве tern исполняемого файла, я смог увидеть доработки во всей их красе. Если мы запросим файлы с curl, можно будет убедиться, что несколько файлов были загружены в память при запуске ...

$ curl -X POST https://localhost:60662 -d '{"query": {"type": "files"}}' {"files": ["src/autocompleteme.js","node_modules/react/index.js","node_modules/react/cjs/react.production.min.js","node_modules/react/cjs/react.development.js","node_modules/object-assign/index.js","node_modules/fbjs/lib/emptyObject.js","node_modules/fbjs/lib/emptyFunction.js","node_modules/fbjs/lib/invariant.js","node_modules/fbjs/lib/warning.js","node_modules/prop-types/checkPropTypes.js","node_modules/prop-types/lib/ReactPropTypesSecret.js"]}
Эта статья больше о внутренней работе tern, а не о настройке вашего редактора, но если вы хотите увидеть мой vimrc, вы можете проверить мою настройку
На что следует обратить внимание:
Поскольку tern по сути загружает и разрешает все модули в конфигурации веб-пакета, время запуска может быть немного медленным, поэтому первое завершение, которое вы пытаетесь выполнить, может не появиться сразу. Подождите несколько секунд и попробуйте еще раз.
Если tern ведет себя не так, как вы ожидаете, попробуйте отправить ему запросы на файлы, подобные приведенному выше примеру, и убедитесь, что исходный файл свойства, которое вы пытаетесь заполнить, находится в списке файлов. У проектов Javascript есть множество макетов, поэтому вам может потребоваться использовать разные плагины tern, чтобы файлы загружались правильно.
Как только все заработает, вы можете удалить перенаправление в скрипте custom-tern. (Если вам нужно снова устранить неполадки, обязательно используйте tee вместо >, потому что перенаправление stdout с >, похоже, все ломает)
Я думаю, что есть много путаницы в том, как работает tern и почему он ломается, потому что большая часть работы абстрагируется в npm пакетах и подключаемых модулях редактора, но место, где необходимо устранить проблему (сервер), часто скрыто в некоторых фоновый процесс. Итак, чтобы понять, что именно нужно исправить, людям нужно
- Вручную запустить сервер в оболочке
- Откройте другую оболочку или инструмент и отправьте ему пользовательские запросы JSON для проверки состояния сервера.
- Вернитесь и прочтите документацию, выясните, где у вас неправильная конфигурация, и попробуйте еще раз, пока не получите правильный ответ.
Я надеюсь, что любой, кто найдет свой путь к этому, будет лучше понимать, что делать, и, надеюсь, я сэкономил вам время! Спасибо