Русский
Русский
English
Статистика
Реклама

Dsl

Front End Meetup от Facebook Developer Circle Moscow

07.10.2020 10:05:19 | Автор: admin

Второй год сообщество Facebook Developer Circle: Moscow активно развивается в области JavaScript и Front End'а. И я рад вам сообщить, что скоро в сообществе будет проводиться очередной митап. Но этот митап будет не один, а три дня! Вы сможете посмотреть гораздо больше интересных докладов)

Day 1 - 15 октября

7:00pm - 7:45pm - DSL approach with JS component libraries
Andrey Kobets / Head of Front-end Development at Yandex

How to write modern frontend application using React/Vue/Angular/..., and
1 Do it the way you like it, but not the way the library requires it.
2 Use only the best solutions for your task.
3 Not to fear major updates of dependencies.
4 Not to rewrite project every time with a new extra fast/robust/flexible library.


7:45pm - 8:30pm - Quo vadis, Frontend?
Evgeny Kot / Director of Development at Wrike

There is no industry that is more rapidly developing than the frontend. You can argue, but how many more ecosystems do you know where frameworks are emerging at this rate? Web standards are being implemented and immediately become obsolete. The most important question is: where are we going, and where will we come to? The question is not rhetorical: how not to stay out of business in this bubbling stream and capture only the most important, what will be the trend in 2021.


8:30pm - 9:15pm - Dive into effector
Yan Lavryushev / Frontend Developer

Mental health issues is the main epidemic of the 21st century, could we reduce it a bit? I guess so



Day 2 - 16 октября

7:00pm - 7:45pm - What's beyond CRA*?
Vitaly Kosenko / Head of Search Interfaces Architecture at Yandex

The Yandex Search page result doesnt look the same for every search request. A great amount of such requests transforms the search page into complex services like hotel booking services or streaming services. We optimized the performance of the interfaces for users and the performance for developers, and then, we decided to rewrite everything using a different technological stack. Ill tell you how the migration was technically done. Of course, well discuss every key step in detail. Be ready for a series of advice from real-world projects.

7:45pm - 8:30pm - Practical Serverless & Edge Computing
Aleksey Taktarov / resume.io

While serverless is way beyond its hype point, it is still an underestimated technology that could open up new approaches in how we build our apps. In this talk I'm going to give an overview of practical applications of serverless JS. We're going to cover serverless frontend microservices, authorization methods, Smart CDNs, caching (including stale-while-revalidate) with Vercel and Cloudflare Workers. I'll illustrate these methods with practical examples from the tools we build internally at [resume.io](http://personeltest.ru/away/resume.io): OG image generation, PDF/DOCX rendering, automatic Critical CSS injection and more.

Day 3 - 17 октября

10:45am - 11:30am - Pipelinekiller. Life after create-react-app
Aleksey Zolotykh / Lead Software Developer at EPAM

With the release of react-scripts, next and other parsel, it seems that here it's happiness left only to write code and enjoy life. But it's not so. Life doesn't stop at create-react-app. After all, front-end is not enough just to build, it also needs to be checked. My presentation will be about how to do it without noise and dust.


11:30am - 12:15asssm - Binary JS saga
Aleksandr Korotaev / Senior Software Developer at VK.com

I want to talk about parsing binary files using Node.js.
How to read and write binary data structures on JS. How to speedup mass creation files process.
And stories of parsing data chunks of formats for which there is no specification.


Событие будет проводиться на английском языке, а зарегистрироваться вы можете здесь.
До встречи на митапе!)

Подробнее..

Перевод Создание DSL для генерации изображений

22.07.2020 16:08:14 | Автор: admin
Привет, Хабр! Считанные дни остаются до запуска нового курса от OTUS Backend-разработка на Kotlin. В преддверии старта курса мы подготовили для вас перевод еще одного интересного материала.



Часто при решении задач, связанных с компьютерным зрением, недостаток данных становится большой проблемой. Это особенно актуально при работе с нейронными сетями.

Как было бы здорово, будь у нас безграничный источник новых оригинальных данных?

Эта мысль натолкнула меня на разработку предметно-ориентированного языка (Domain Specific Language), который позволяет создавать изображения в различных конфигурациях. Эти изображения можно использовать для обучения и тестирования моделей машинного обучения. Как следует из названия, генерируемые DSL изображения обычно могут использоваться только в узко направленной области.

Требования к языку


В моем конкретном случае необходимо сосредоточиться на обнаружении объектов. Компилятор языка должен генерировать изображения, соответствующие следующим критериям:

  • изображения содержат различные формы (например, смайлики);
  • количество и положение отдельных фигур настраивается;
  • размер изображения и форм настраивается.

Сам язык должен быть максимально простым. Сначала я хочу определить размер выходного изображения, а затем размер фигур. После этого я хочу выразить фактическую конфигурацию изображения. Чтобы упростить задачу, я рассматриваю изображение как таблицу, где каждая фигура помещается в ячейку. Каждый новый ряд заполняется формами слева направо.

Реализация


Для создания DSL я выбрал комбинацию ANTLR, Kotlin и Gradle. ANTLR является генератором парсера. Kotlin это JVM язык, похожий на Scala. Gradle это система сборки, похожая на sbt.

Необходимое окружение


Для выполнения описанных действий вам понадобится Java 1.8 и Gradle 4.6.

Первоначальная настройка


Создайте папку, которая будет содержать DSL.

> mkdir shaperdsl> cd shaperdsl

Создайте файл build.gradle. Этот файл нужен для перечисления зависимостей проекта и настройки дополнительных задач Gradle. Если вы захотите повторно использовать этот файл, вам придется изменить лишь пространства имен и основной класс.

> touch build.gradle

Ниже приведено содержание файла:

buildscript {   ext.kotlin_version = '1.2.21'   ext.antlr_version = '4.7.1'   ext.slf4j_version = '1.7.25'   repositories {     mavenCentral()     maven {        name 'JFrog OSS snapshot repo'        url  'https://oss.jfrog.org/oss-snapshot-local/'     }     jcenter()   }   dependencies {     classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"     classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'   }}apply plugin: 'kotlin'apply plugin: 'java'apply plugin: 'antlr'apply plugin: 'com.github.johnrengelman.shadow'repositories {  mavenLocal()  mavenCentral()  jcenter()}dependencies {  antlr "org.antlr:antlr4:$antlr_version"  compile "org.antlr:antlr4-runtime:$antlr_version"  compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"  compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"  compile "org.apache.commons:commons-io:1.3.2"  compile "org.slf4j:slf4j-api:$slf4j_version"  compile "org.slf4j:slf4j-simple:$slf4j_version"  compile "com.audienceproject:simple-arguments_2.12:1.0.1"}generateGrammarSource {    maxHeapSize = "64m"    arguments += ['-package', 'com.example.shaperdsl']    outputDirectory = new File("build/generated-src/antlr/main/com/example/shaperdsl".toString())}compileJava.dependsOn generateGrammarSourcejar {    manifest {        attributes "Main-Class": "com.example.shaperdsl.compiler.Shaper2Image"    }    from {        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }    }}task customFatJar(type: Jar) {    manifest {        attributes 'Main-Class': 'com.example.shaperdsl.compiler.Shaper2Image'    }    baseName = 'shaperdsl'    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }    with jar}

Парсер языка


Парсер построен как грамматика ANTLR.

mkdir -p src/main/antlrtouch src/main/antlr/ShaperDSL.g4

со следующим содержанием:

grammar ShaperDSL;shaper      : 'img_dim:' img_dim ',shp_dim:' shp_dim '>>>' ( row ROW_SEP)* row '<<<' NEWLINE* EOF;row       : ( shape COL_SEP )* shape ;shape     : 'square' | 'circle' | 'triangle';img_dim   : NUM ;shp_dim   : NUM ;NUM       : [1-9]+ [0-9]* ;ROW_SEP   : '|' ;COL_SEP   : ',' ;NEWLINE   : '\r\n' | 'r' | '\n';

Теперь вы видите, как структура языка становится понятнее. Для генерации исходного кода грамматики выполните:

> gradle generateGrammarSource

В итоге вы получите сгенерированный код в build/generate-src/antlr.

> ls build/generated-src/antlr/main/com/example/shaperdsl/ShaperDSL.interp  ShaperDSL.tokens  ShaperDSLBaseListener.java  ShaperDSLLexer.interp  ShaperDSLLexer.java  ShaperDSLLexer.tokens  ShaperDSLListener.java  ShaperDSLParser.java

Абстрактное синтаксическое дерево


Парсер преобразует исходный код в дерево объектов. Дерево объектов это то, что компилятор использует в качестве источника данных. Чтобы получить АСД, сначала необходимо определить метамодель дерева.

> mkdir -p src/main/kotlin/com/example/shaperdsl/ast> touch src/main/kotlin/com/example/shaper/ast/MetaModel.kt

MetaModel.kt содержит определения классов объектов, используемых в языке, начиная с корня. Все они наследуются от интерфейса Node. Древовидная иерархия видна в определении классов.

package com.example.shaperdsl.astinterface Nodedata class Shaper(val img_dim: Int, val shp_dim: Int, val rows: List<Row>): Nodedata class Row(val shapes: List<Shape>): Nodedata class Shape(val type: String): Node

Далее необходимо сопоставить класс с АСД:

> touch src/main/kotlin/com/example/shaper/ast/Mapping.kt

Mapping.kt используется для построения АСД с использованием классов, определенных в MetaModel.kt, используя данные от парсера.

package com.example.shaperdsl.astimport com.example.shaperdsl.ShaperDSLParserfun ShaperDSLParser.ShaperContext.toAst(): Shaper = Shaper(this.img_dim().text.toInt(), this.shp_dim().text.toInt(), this.row().map { it.toAst() })fun ShaperDSLParser.RowContext.toAst(): Row = Row(this.shape().map { it.toAst() })fun ShaperDSLParser.ShapeContext.toAst(): Shape = Shape(text)

Код на нашем DSL:

img_dim:100,shp_dim:8>>>square,square|circle|triangle,circle,square<<<

Будет преобразован к следующему АСД:



Компилятор


Компилятор это последняя часть. Он использует АСД для получения конкретного результата, в данном случае, изображения.

> mkdir -p src/main/kotlin/com/example/shaperdsl/compiler> touch src/main/kotlin/com/example/shaper/compiler/Shaper2Image.kt

В этом файле много кода. Я постараюсь пояснить основные моменты.

ShaperParserFacade это оболочка поверх ShaperAntlrParserFacade, которая создает фактическое АСД из предоставленного исходного кода.

Shaper2Image является основным классом компилятора. После того, как он получает АСД от парсера, он проходит по всем объектам внутри него и создает графические объекты, которые затем вставляет в изображение. Затем он возвращает двоичное представление изображения. Также предусмотрена функция main в объекте-компаньоне класса, позволяющая проводить тестирование.

package com.example.shaperdsl.compilerimport com.audienceproject.util.cli.Argumentsimport com.example.shaperdsl.ShaperDSLLexerimport com.example.shaperdsl.ShaperDSLParserimport com.example.shaperdsl.ast.Shaperimport com.example.shaperdsl.ast.toAstimport org.antlr.v4.runtime.CharStreamsimport org.antlr.v4.runtime.CommonTokenStreamimport org.antlr.v4.runtime.TokenStreamimport java.awt.Colorimport java.awt.image.BufferedImageimport java.io.ByteArrayInputStreamimport java.io.ByteArrayOutputStreamimport java.io.Fileimport java.io.InputStreamimport javax.imageio.ImageIOobject ShaperParserFacade {    fun parse(inputStream: InputStream) : Shaper {        val lexer = ShaperDSLLexer(CharStreams.fromStream(inputStream))        val parser = ShaperDSLParser(CommonTokenStream(lexer) as TokenStream)        val antlrParsingResult = parser.shaper()        return antlrParsingResult.toAst()    }}class Shaper2Image {    fun compile(input: InputStream): ByteArray {        val root = ShaperParserFacade.parse(input)        val img_dim = root.img_dim        val shp_dim = root.shp_dim        val bufferedImage = BufferedImage(img_dim, img_dim, BufferedImage.TYPE_INT_RGB)        val g2d = bufferedImage.createGraphics()        g2d.color = Color.white        g2d.fillRect(0, 0, img_dim, img_dim)        g2d.color = Color.black        var j = 0        root.rows.forEach{            var i = 0            it.shapes.forEach {                when(it.type) {                    "square" -> {                        g2d.fillRect(i * (shp_dim + 1), j * (shp_dim + 1), shp_dim, shp_dim)                    }                    "circle" -> {                        g2d.fillOval(i * (shp_dim + 1), j * (shp_dim + 1), shp_dim, shp_dim)                    }                    "triangle" -> {                        val x = intArrayOf(i * (shp_dim + 1), i * (shp_dim + 1) + shp_dim / 2, i * (shp_dim + 1) + shp_dim)                        val y = intArrayOf(j * (shp_dim + 1) + shp_dim, j * (shp_dim + 1), j * (shp_dim + 1) + shp_dim)                        g2d.fillPolygon(x, y, 3)                    }                }                i++            }            j++        }        g2d.dispose()        val baos = ByteArrayOutputStream()        ImageIO.write(bufferedImage, "png", baos)        baos.flush()        val imageInByte = baos.toByteArray()        baos.close()        return imageInByte    }    companion object {        @JvmStatic        fun main(args: Array<String>) {            val arguments = Arguments(args)            val code = ByteArrayInputStream(arguments.arguments()["source-code"].get().get().toByteArray())            val res = Shaper2Image().compile(code)            val img = ImageIO.read(ByteArrayInputStream(res))            val outputfile = File(arguments.arguments()["out-filename"].get().get())            ImageIO.write(img, "png", outputfile)        }    }}

Теперь, когда все готово, соберем проект и получим jar-файл со всеми зависимостями (uber jar).

> gradle shadowJar> ls build/libsshaper-dsl-all.jar

Тестирование


Все, что нам осталось сделать, это проверить, все ли работает, поэтому попробуйте ввести такой код:

> java -cp build/libs/shaper-dsl-all.jar com.example.shaperdsl.compiler.Shaper2Image \--source-code "img_dim:100,shp_dim:8>>>circle,square,square,triangle,triangle|triangle,circle|square,circle,triangle,square|circle,circle,circle|triangle<<<" \--out-filename test.png

Создастся файл:

.png

который будет выглядеть следующим образом:



Заключение


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

Полный пример DSL можно найти в моем репозитории на GitHub: github.com/cosmincatalin/shaper.

Читать ещё


Подробнее..

Мультивселенная и задачи о переправе

16.06.2021 04:11:19 | Автор: admin

Как-то прочел на Хабре статью Перевозим волка, козу и капусту через реку с эффектами на Haskell, которая так понравилась, что решил написать фреймворк для всего класса задач о переправах, используя мультипарадигменное проектирование. Наконец удалось найти время, и вот, спустя почти год, фреймворк готов. Теперь персонажи, их взаимодействия и описание искомого результата задаются через domain-specific language, который позволяет решать любые головоломки подобного рода с пошаговым выводом. Ниже приводится поэтапный разбор реализации DSL. Статья подойдет тем кто изучает язык Kotlin или просто интересуется примерами его использования. Некоторые малозначимые детали (вроде импортов и вывода) для кратости опущены.

Персонажа легко можно описать открытым для наследования классом:

open class Person(private val name: String)

Также просто определим понятие берега, как набора персонажей задачи:

typealias Riverside = Set<Person>

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

abstract class QuantumBoat(  val left: Riverside, val right: Riverside) {    abstract fun invert(): List<QuantumBoat>    fun where(    condition: Riverside.() -> Boolean,     selector: QuantumBoat.() -> Boolean  ) = Multiverse(this, condition).search(selector)}

Лодка также снабжена высокоуровневым методом where, для поиска необходимого состояния через N шагов по реке. Условие (condition) определяет валидность берегов в процессе, а селектор (selector) задает искомое конечное состояние. Обратите внимание, что при использовании этого метода лодка на самом деле не двигается с места, а перебирает альтернативные вселенные, пока не обнаружит подоходящую :)
Но об этом мы поговорим позже, а пока что перейдем к простой имплементации лодки для перемещения слева направо:

class LeftBoat(left: Riverside, right: Riverside) : QuantumBoat(left, right) {  override fun invert() =    left.map {      RightBoat(left - it - Farmer, right + it + Farmer)    } + RightBoat(left - Farmer, right + Farmer)}

Инверсия состояния возвращает сразу все возможные варианты перемещения на другую сторону. Это пригодится для реализации нашего мультиверсума. Поскольку по условиям таких задач, фермер выступает необходимым условием передвижения лодки, то перемещаем его во всех случаях вместе с ней. Аналогичным образом имплементируем и перемещение справа налево. Заметьте, насколько лаконичен наш код за счет предопределенных высокоуровневых функций Kotlin и перегрузки операторов для работы с множествами.

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

typealias History = LinkedList<QuantumBoat>  fun Sequence<History>.fork() = sequence {  for (history in this@fork) {    for (forked in history.last.invert()) {      yield((history.clone() as History).apply {        add(forked)      })    }  }}

Заодно описали функцию форка мультиверсума (историй перемещений) в следующий набор состояний (шаг). Чтобы все это добро не забивало лишний раз память, используем ленивые последовательности и yield.

Теперь нам осталось всего лишь описать мультиверсум (а код для поиска состояний у нас уже есть):

/** * Мультиверсум для лодки * @param boat исходное состояние лодки * @param condition валидатор промежуточных состояний */class Multiverse(boat: QuantumBoat, val condition: Riverside.() -> Boolean) {  /**   * Все смоделированные истории передвижений лодки   */  private var multiverse = sequenceOf(historyOf(boat))  /**   * Найти историю подходящей нам лодки   * @param selector нужное состояние берегов и лодки   * @return все найденные варианты достижения состояния   */  tailrec fun search(selector: QuantumBoat.() -> Boolean): List<History> {    multiverse = multiverse.fork().distinct().filter {      it.last.left.condition()        && it.last.right.condition()    }    val results = multiverse.filter { it.last.selector() }.toList()    return when {      results.isNotEmpty() -> results      else -> search(selector)    }  }}

Здесь мы заиспользовали оптимизацию хвостовой рекурсии, благодаря чему kotlinc сгенерирует импертивный цикл для повышения производительности. Что здесь происходит: на каждом шаге мы делаем форк всех состояний мультиверсума перемещая все возможные объекты на другой берег в параллельных вселенных. Затем отбрасываем дубликаты и невалидные состояния (коза и капуста например), а оставшиеся последовательности и будут ответами к задаче. Вуаля!

Наконец, пример использования DSL на всем известной задачке про волка, козу и капусту:

object Wolf : Person("")object Goat : Person("")object Cabbage : Person("")fun Riverside.rule() =  contains(Farmer) ||    (!contains(Wolf) || !contains(Goat)) &&    (!contains(Goat) || !contains(Cabbage))fun main() {  val property = setOf(Wolf, Goat, Cabbage)  // стартовали с левого берега  LeftBoat(property)     // отбросили все невалидные состояния    .where(Riverside::rule)    // выбрали из оставшихся те варианты,    // где все имущество оказалось на правом берегу    { right.containsAll(property) }     // выводим на экран пошаговое решение    .forEach(History::prettyPrint)}

Вот что получилось, вставляю скриншотом, потому что смайлики хабр не переваривает:

Всем удачного дня и побольше времени на написание собственных DSL :)

Исходный код здесь: demidko/Wolf-Goat-Cabbage
Приветствуется критика и предложения как сделать лучше.

Подробнее..

Представляем MPS 2020.3

11.01.2021 22:22:18 | Автор: admin

Несколько месяцев мы работали над тем, чтобы сделать MPS еще удобнее, и исправляли проблемы, о которых вы нам сообщали. Скачать новый MPS 2020.3 можно на нашем сайте или с помощью приложения Toolbox.


image

Новый макрос генератора


Мы добавили новый макрос $CALL-SITE$. Он упрощает вставку узла, на который указывает макрос SWITCH/CALL, в указанное место в вызванном шаблоне. Раньше узел с прикрепленным макросом SWITCH/CALL обычно игнорировался. Теперь, если вызванный template/switch пытается использовать call site node, то узел обрабатывается как обычный шаблон, и результат передается в вызванный template/switch как неявный аргумент, который можно вставить в желаемое место.


Вот как выглядит вызов шаблона reduce_Comment, служащего местом вызова шаблона reduce_MethodDeclaration:



Если мы заглянем в шаблон, увидим, что там есть call site node с оператором $CALL-SITE$ в теле метода:



Также теперь есть вызов переключателя reduce_Expressions, параметризованного узлом шаблона (вызов метода трассировки) с помощью макроса свойства и макроса ссылки (который обеспечивает то, что вызов метода указывает на правильное объявление метода в другом месте). Внутри переключателя $CALL-SITE$ заменяет вызов метода-заполнителя на тот, который является call site node:



В объявлениях шаблона и переключателя есть флаг, который специально переключается, чтобы указать, что должен использоваться call site node. Использовать макрос $CALL-SITE$ внутри шаблона/переключателя, который не указывает на необходимость получения $CALL-SITE$, будет ошибкой. Нет необходимости указывать явный аргумент в CALL/SWITCH генератор MPS может определить, нужен ли вызываемому шаблону/переключателю call site, и вычисляет шаблон, включая макросы, CALL/SWITCH перед обработкой.


Эта функциональность полезна в таких сценариях, как приведение условных типов, например в выражениях <strong>IF</strong> needCast (<strong>Type</strong>), ELSE

, или в преобразованиях, когда есть несколько источников выражения, которые могут служить входными данными, например switch { <strong>case</strong> <strong>Double</strong> : <strong>Double</strong>.valueOf(expression); <strong>case</strong> <strong>Integer</strong> : <strong>Integer</strong>.valueOf(expression, 16); }. Поэтому нецелесообразно иметь специальный переключатель/шаблон для каждого случая.

Динамическая подсветка в редакторе


В редакторе появилась долгожданная динамическая подсветка. Эта функция очень похожа на действие Highlight Usages (Ctrl/Cmd+Shift+F7). Разница в том, что динамическая подсветка срабатывает автоматически при вводе кода или навигации по нему. Ссылки на узел, находящийся под курсором, подсвечиваются в редактируемом документе практически сразу. Вы по-прежнему можете использовать действие Highlight Usages, чтобы видеть использования выбранного узла, когда навигируетесь в другое место. При этом динамическая подсветка продолжит выделять использования узла под курсором.


Функция включается и выключается в настройках редактора MPS (опция Highlight selected node).



Улучшенный switch-оператор в BaseLanguage


В дополнение к улучшениям в редакторе, концепт switch теперь поддерживает использование нескольких case для одного и того же оператора.



Полоса ошибки на панели Project


На панели Project ошибки, предупреждения и сообщения отображаются по-новому. Полосы ошибок помогают упорядочить сообщения. Вы можете отключить их с помощью кнопки в настройках Logical View.



Изменения в обработке фасетов модулей


Вы больше не обязаны использовать какой-то определенный фасет модуля с любым модулем. Фасеты, связанные с модулем, записываются в файл дескриптора модуля, который теперь является основным источником информации. В предыдущих версиях мы уже сделали фасет Tests необязательным, теперь это касается и последнего фасета Java. Обратите внимание, что снятие галочки с фасета Java в модуле Language исключит язык из механизма загрузки классов, и все будет работать по-другому. Мы внесли это изменение, чтобы улучшить поддержку других языков.


Улучшенная аннотация корня в VCS


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


Каждую ячейку в редакторе теперь можно аннотировать с помощью опции Annotate cells:


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



Вы можете выбрать версию в столбце Annotation, и MPS подсветит все ячейки, в которые были внесены изменения:



Отслеживание перемещенных узлов в окне Diff


Предыдущий алгоритм расчета различий между двумя моделями не мог обнаружить некоторые типы изменений. Перемещение узла рассматривалось как два независимых изменения: вставка и удаление. Теперь это отображается как одно действие. Кроме того, можно отследить изменения внутри перемещаемого фрагмента:



Вы можете выбрать, следует отслеживать перемещенные узлы в окне Diff или нет:


Иногда порядок узлов одного уровня не имеет значения. Вы можете скрыть несущественные перестановки, используя новую опцию Hide Unordered Moves.


Обновленный начальный экран


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



Другие улучшения


Обновленное меню VCS


Меню VCS теперь называется в соответствии с той системой контроля версий, которую вы используете. Если у вас в проекте используется только Git, меню VCS будет выглядеть так:



Еще мы улучшили его внешний вид и убрали из него все действия, кроме самых актуальных. Теперь легко получить доступ к ключевым функциям Git они больше не спрятаны в подменю.


Кнопка Commit and Push


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


Улучшенные ветки


Некоторые улучшения в этой версии касаются работы с ветками. Теперь MPS автоматически исправляет недопустимые символы в именах веток, и вы видите все действия, связанные с текущей веткой.


Удобное управление вкладками в редакторе


При работе над большим проектом удобно держать открытыми несколько вкладок. Теперь вы можете разделить главный экран редактора по горизонтали или по вертикали, просто перетащив вкладку в удобное место. Редактор подсветит, где она может быть закреплена. Закрепленные вкладки теперь отображаются в самом начале панели вкладок.


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


Хорошего дня и будьте здоровы!


Ваша команда MPS
The Drive to Develop

Подробнее..

Вышел MPS 2021.1

04.06.2021 20:14:20 | Автор: admin

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




Редактор


Масштабирование


Размер шрифта теперь можно быстро настроить в открытом окне редактора просто зажмите клавишу CTRL и прокрутите колесико мыши. Размер шрифта не запоминается когда вы снова откроете файл, будет использовано значение по умолчанию. Вы можете включить/отключить эту опцию в разделе Preferences | Editor | General: Change font size with Ctrl/Cmd+Mouse Wheel.


Улучшение производительности форматирования с отступами


Для наиболее частых сценариев реализация форматирования с отступами (indent layout) стала инкрементальной это ускорит отрисовку редакторов больших моделей, которые используют форматирование с отступами (например, BaseLanguage). Вы можете отключить эту опцию при помощи параметра VM mps.indent_layout.disable_incremental.


Настройки толщины шрифта


При длительной работе над кодом важно подобрать шрифт, который бы не сильно утомлял глаза. Мы добавили настройки типографики, чтобы вы могли подобрать идеальные размеры шрифта. Версия 2021.1 позволяет настраивать толщину обычных и жирных шрифтов через меню Preferences | Editor | Fonts.





Система контроля версий


Улучшения аннотирования кода


Использование дополнительной информации от системы контроля версий позволило нам улучшить аннотацию кода. Новый алгоритм вычисления изменений ревизии отслеживает перемещение узлов в модели. Цвет строк/ячеек с аннотациями определяется только на основе тех ревизий, где были фактически произведены изменения. Если столбец с аннотациями раскрыт, то в контекстном меню ячеек в основном редакторе появится новая группа опций, таких как Copy Revision Number, Show Diff и другие.





Окно Diff для коммитов слияния


Для коммитов, уже слитых с основной веткой, в Git-логе доступно окно Diff. Оно включает три панели: левая и правая отображают ветки, которые подверглись слиянию, центральная демонстрирует результат слияния.





Синхронизация прокрутки в редакторе Diff


Мы добавили кнопку, позволяющую выключить синхронизацию прокрутки в окне редактора Diff.





Использование графа ревизий в алгоритмах для аннотации и истории кода


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


Действие Save to Shelf


Новое действие Save to Shelf копирует изменения на вкладку Shelf, сохраняя их в локальной истории изменений. Чтобы запустить это действие, нажмите A на macOS или Ctrl+Shift+A на Windows или Linux и введите Safe to Shelf.


Генератор


Упрощенный доступ к параметрам макроса $LOOP$


Теперь вы можете обратиться к входному узлу макроса LOOP при помощи выражения LOOP.inputNode вам не нужно использовать макрос VAR. В том же пространстве имен можно получить доступ к индексу LOOP: используя LOOP.index вместо необходимой ранее контекстной переменной.





Обновленный оператор Transform в объявлении GenPlan


Для улучшения расширяемости планов генерации теперь есть новый механизм, позволяющий подключить заранее неизвестный набор языков и генераторов. Вы можете использовать оператор transform для подключения языка, расширяющего текущий язык или считающего его целевым. Говоря, что язык Б считает язык А целевым, мы подразумеваем, что генератор языка Б производит конструкции языка А.


Улучшение скомпилированных шаблонов


В IDE в настройках генератора имеется опция Warn when child cannot be placed into role, которая проверяет, может ли создаваемый образец узла быть использован в указанной роли родительского узла. Эта опция также доступна в настройках сборки проектов. Генератор может показать предупреждение, которое обычно означает, что в шаблонах имеются несоответствия, например неправильно размещенные фрагменты шаблона или аннотация COPY-SRC.


Такая проверка отсутствовала при использовании скомпилированных шаблонов. В MPS 2021.1 при включении соответствующей опции скомпилированные шаблоны проверяют, правильно ли дочерние узлы размещены в родительских.


Разное


Java-компилятор для модулей MPS с фасетом Java


Мы существенно изменили подход к компиляции модулей MPS в Java. Это напрямую связано с задачей по поддержке обработки аннотаций, получившей большое количество голосов. Мы перевели инфраструктуру Java-компилятора для MPS на набор API javax.tools.JavaCompiler теперь MPS может использовать любой компилятор, который реализует стандартный API javax.tools. На данный момент MPS применяет тот компилятор, который назначен стандартным для данного API. При желании вы можете выбрать Eclipse Compiler for Java (ECJ), если он доступен. Когда в classpath есть библиотеки ECJ, можно переключить MPS на использование ECJ, задав mps.compiler.java=ecj в качестве свойства системы (например, изменив mps.vmpoptions). Следует отметить, что если при использовании инфраструктуры нового компилятора возникнут неустраняемые проблемы, то можно задействовать устаревший механизм API прямой компиляции ECJ, изменив конфигурацию на mps.compiler.java=ecjlegacy в качестве свойства системы.


Кроме того, сейчас мы запускаем компилятор с опцией -release с версией, указанной в настройках проекта (Preferences -> Java Compiler). Эта опция строже, чем сочетание -source/-target, которое использовалось MPS в предыдущих релизах, поскольку она контролирует применение API библиотек, которые были доступны в определенных релизах. Если из-за использования API, недоступных в некоторых релизах, вы столкнетесь с проблемами компиляции, возможно, придется обновить версию Java в проекте.


Исходная версия MPS для миграции проекта


При создании проекта теперь сохраняется значение исходной версии MPS. Миграции с версий MPS, предшествующих исходной, не применяются. Это дает авторам возможность назначить исходный порог для миграций проекта (версию можно изменить в интерфейсе для миграции проектов, используя метод getBaselineVersion():int).


Если для проекта отсутствует версия, при миграции версией по умолчанию будет 2018.1. Миграцию любого проекта можно запустить вручную из меню Migrations.


Улучшения рефакторинга Method signature


В окне рефакторинга Method Signature теперь можно указать значения по умолчанию для новых аргументов или аргументов, у которых поменялись типы. Если вы удалите параметр метода, но в коде останутся его использования, MPS введет новую локальную переменную и таким образом восстановит связь. Кроме того, теперь обрабатываются параметры типа vararg.


Когда вызов метода не соответствует его сигнатуре, MPS предложит поправить сигнатуру метода в соответствии с вызовом при помощи intention-действия. Мы усовершенствовали это intention-действие: теперь оно более грамотно сопоставляет существующие параметры, при этом повторно используется их максимальное количество и сохраняются их ссылки.





Новые возможности для комментариев BaseLanguage


Язык lang.text получил несколько новых возможностей это напрямую улучшило работу с однострочными и многострочными комментариями в BaseLanguage.



  • Выделяя текст сверху вниз или снизу вверх, вы теперь можете захватывать строки частично.
  • Теперь вы можете сделать жирным, выделить курсивом или подчеркиванием выделенный текст.
  • Работает копирование/вставка обычного текста.
  • Вы можете добавлять маркированные и нумерованные списки.


Улучшенные выражения lang.smodel


Выражения model.roots(), model.rootsIncludingImported() и model.nodesIncludingImported() теперь, аналогично model.nodes(), поддерживают #expression для указания концептов.


Управление видимостью модулей плагина


Долгое время в MPS считалось, что конечному пользователю видны все модули из языковых плагинов. Из-за увеличения числа языков и усложнения плагинов бывают случаи, когда разработчики языков хотят скрыть определенные модули, чтобы не запутать и не перегрузить конечного пользователя огромным количеством невостребованных языков или функций. Плагины сообщают MPS о том, какие модули они затрагивают, при помощи расширения com.intellij.mps.LanguageLibrary. Теперь у расширений есть опциональный атрибут hide=true, который разрешает фильтровать модули плагина на основе образца, указанного в com.intellij.mps.VisibleModuleMask. У большинства плагинов MPS появился флажок для удобства фильтрации собственных языков MPS, если разработчику языков необходимо их скрыть. MPS обеспечивает для своих модулей маски в составе плагина jetbrains.mps.ide.devkit, причем разработчики собственных IDE обычно не включают этот плагин в дистрибутив и полностью контролируют отображаемые модули своего продукта.


Другие улучшения


Предварительный просмотр HTML-файлов


Мы добавили встроенное превью для HTML-файлов. Чтобы его открыть, нажмите на логотип MPS в виджете в правом верхнем углу редактора. Превью обновляется в реальном времени, когда вы редактируете HTML-код или изменяете связанные CSS и JavaScript-файлы.





Поддержка Apple Silicon


Теперь вы можете пользоваться MPS на Mac-устройствах с чипом M1. Скачать установщик JetBrains MPS для Apple Silicon можно с нашего сайта либо из Toolbox App.


Автоматический импорт настроек


Раньше окно Import Settings появлялось каждый раз, когда вы устанавливали новую версию MPS. Теперь, если IDE найдет необходимые конфигурационные файлы, окно не появится.


Специальные возможности


В этом выпуске мы добавили больше меток к элементам интерфейса начального экрана, панели Project Structure и VCS-лога. Теперь эти элементы, как и значки на полях редактора, корректно обрабатываются программами чтения с экрана. Мы также занимаемся расширением поддержки специальных возможностей для пользователей macOS.


Незначительные изменения



  • Теперь показывается выполнение intention-действия макроса Call-Site. (MPS-32928)
  • Внесены изменения в диалоговое окно новой модели. (MPS-30787)


Кроме того, исправлен ряд ошибок. Поделитесь с нами своими впечатлениями о новой функциональности. Мы очень рассчитываем на ваши отзывы в комментариях ниже. Напоминаем, что в нашем баг-трекере можно оставлять запросы о добавлении новой функциональности и голосовать за любые существующие запросы. Это помогает нам определиться, какие функциональности следует включить в ближайшие релизы.



Ваша команда JetBrains MPS
The Drive to Develop
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru