Pull to refresh

Comments 35

Надо заметить, попахивает очень плохой практикой. Например, тот же "Data class inheritance from other classes is forbidden" запрещен не просто так, и это "чтобы они не мозолили глаза" может потом привести к неочевидным поведениям и с трудом отлавливаемым ошибкам.

При чем тут практика вообще?
Это таблица всех существующих сообщений.
Нигде не написано что их все нужно или можно маскировать.

> Предупреждения и ошибки, которые генерирует компилятор Kotlin часто нужно замаскировать

если вы действительно делаете это часто, то явно делаете что-то не то. Хотя сама по себе таблица вещь очень полезная, спасибо!

Все зависит от того чем заниматься.
Если писать приложение, то воевать с ошибками приходится чрезвычайно редко.
Если же писать либу, то часто.
У меня безусловный победитель по количеству использований — это UNCHECKED_CAST, 90% применений которого приходится на бездарные шаблоны (женерики), которые неспособны приводить типы.
Но бывают и эксклюзивы, типа:


class PLog(private val allowlog : Boolean = true) {
...
  @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
  inline fun log( cb:()->String ) =
    if (allowlog) note(indent.indent() + cb() + "\n")
...

Открывать поле я не хочу, а избавиться от ошибки синтаксическими способами я не смог.

да, это правда — unchecked cast это основной suppress и в моем коде, а вот NON_PUBLIC_CALL_FROM_PUBLIC_INLINE я использовать постеснялся, честно говоря, не уверен, что это хорошая идея. Может быть кто-то знает, почему компилятор это запрещает?

Т.к. функция inline, то все ее тело подставляется в место использования и как бы получается что приватные поля и методы "используются" за пределами класса.
Я голосую за обыкновенный баг.

Так они и на самом деле используются, просто для них вгенерятся синтетический геттер с названием access$getAllowlog$p. Если не предупредить об этом разработчика, то у приватного поля появится геттер (в виде статического метода), доступный из Java.

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

У приватных полей нет геттеров, но появляются статические методы для их чтения, если вы делаете публичную инлайн-функцию с их использованием. От того, что функция инлайн меняется то, что напрямую через взятие поля это поле приватное поле не прочитать (без setAccessible), поэтому тело этой функции будет содержать вызов специального метода на стороне "вызова". Посмотрите сами в bytecode viewer.

Да, извиняюсь, не сообразил с доступом.
Тем не менее (и даже более), выдавать сообщения основанные на внутренних собенностях реализации, о которых никто знать не должен и которые никак не влияют на выполнение программы, на мой взгляд, совершенно бессмысленно.

Они влияют на API с точки зрения java, некоторым это может быть важно.

Хмм… не понимаю о чем речь.
Можете привести пример?

Для этих целей в 1.1 появилась аннотация @PublishedApi, применимая к internal-декларациям

  1. Мне совершенно не нужно, чтобы это поле было доступно конечному юзеру.

class A {
  @PublishedApi
  internal val allow = false

  inline fun F(cb : () -> String) {
    if (allow) println(cb())
  }
}

fun main(a : Array<String>) {
  val a = A()
  println( a.allow )  //Мне НЕ надо чтобы был доступ
}

  1. Если бы я захотел сделать поле доступным, то я бы это сделал просто указав public, зачем вообще эта аннотация нужна?
    Можете привести пример ее осмысленного использования?

Слово internal означает "доступно внутри модуля". Ваш main в том же модуле.


Мы не разрешаем ссылки и inline функций на приватные декларации, потому что это нарушает главный принцип работы с ними: изменения приватных деклараций не должно ломать клиентский бинарный код. Там выше подробно объяснили, почему код сломается, если разрешить ссылку на private.


Мы разрешаем ссылки на internal-декларации со специальной аннотацией, чтобы была возможность что-то не показывать клиентам из другого модуля. Лучше сделать не можем, к сожалению.

UFO just landed and posted this here

Вообще вопроса не понял.


А насчет создания списка для использования автодополнения (для чего ты, наверное, и сделал класс) я думал.
С этого начал, но оказалось, что пользоваться этим ничуть не удобнее чем отдельной таблицей т.к. искать сообщение все равно можно только по тексту.
Да и как-то жаба душит тащить кучу абсолютно ненужного кода в либу. По привычке.

UFO just landed and posted this here

У меня в статье выдержка только сообщений котлина, взятая из его исходников, так что ничего универсального в ней и быть не может.


Иметь авто-дополнение для известных типов, конечно, хорошо, но только ради этого тащить кучу кода в любой проект, по моему, неадекватно и для эксклюзивов это никак не поможет.
Типовой кейс: вылезает ошибка, которую надо исключить, копирую уникальную часть текста (с этим самые большие сложности т.к. в IntelliJ окно с сообщениями об ошибках — это боль), ищу его в таблице, копирую тип и втыкаю в исходник.
В кнопках, помимо войны с текстом сообщения в IntelliJ, это все очень быстро: Alt-Tab, F4, F7, Ctrl-V, Enter пара шевелений стрелками, Ctrl-C и уже Alt-Tab обратно с типом.

Хочу заметить, что это все — внутренние особенности компилятора, и мы не гарантируем, что они будут поддерживаться в будущем :)

UFO just landed and posted this here
Это не enum, потому что существуют диагностики, специфичные для конкретных бэкэндов, и если бы мы собрали их все в один enum, это создало бы очень неприятный coupling.

Ну вы, наверное, заметили, что у этих штук разные типы :)

Причина, почему мы не публикуем эту информацию — во-первых, то, что сказал Андрей (диагностики регулярно меняются, разделяются и объединяются), а во-вторых, не предполагается, что кто-то будет писать аннотации @Suppress руками, а не через квикфикс. Если вы знаете конкретные случаи, в которых квикфикс на сообщении от компилятора недоступен или не работает — пожалуйста, сообщите нам, и мы это исправим.

А если я в vim пишу на Котлине?

В таком случае вы сам себе злой Буратино.

И почему же? Язык, на котором можно писать только в одной IDE? Только не разводите холивар на тему "vim — не IDE", речь не об этом.

У нас есть официальные плагины для трёх IDE — IntelliJ IDEA, Eclipse и NetBeans. Если кто-то хочет программировать на Kotlin в другой среде — это их выбор, но мы не делаем ничего, чтобы как-то специально облегчить их жизнь.

А если хочется узнать, что означает конкретный Suppress, и это непонятно из названия?

Сейчас нормального способа для этого нет (хотя я не помню, чтобы кто-то когда-то этого просил). В будущем мы планируем сделать для каждого диагностического сообщения страничку с документацией, в которой написано, в каких случаях оно возникает и как его правильно избегать, и тогда можно будет сделать навигацию с @Suppress на соответствующую страничку.

Спасибо. Я спрашиваю из праздного интереса, пока Котлином не пользуюсь. Ключевое слово — пока :)

То что все меняется — это понятно и никто (надеюсь) не рассчитывает что этот список сообщений будет вечен
А вто то что ни нигде не опубликованы — это плохо т.к. писать программу надо здесь и сейчас, на этой версии языка, а не на некоей идеальной, которая когда-то появится.
Я это не к тому, что надо все бросать и делать немедленно этот список
В языке пока есть много принципиальных проблем, которые меня лично волнуют значительно больше чем список сообщений, типа практически виснущего процесса компиляции на некоторых инлайновых функций или рразмножение одинаковых классов при использовнии ::StatFunction.
Для меня лично отсутствие списка ошибок особой проблемы не составляет т.к. "на скорость не влияет"

Не вижу там ссылки на реквест в трекере

Sign up to leave a comment.

Articles