Forest Structural Code Editing with Multiple Cursors

2025-05-06 0 0 1.14MB 19 页 10玖币
侵权投诉
Forest: Structural Code Editing with Multiple Cursors
Philippe Voinov
philippevoinov@gmail.com
ETH Zurich
Switzerland
Manuel Rigger
rigger@nus.edu.sg
National University of Singapore
Singapore
Zhendong Su
zhendong.su@inf.ethz.ch
ETH Zurich
Switzerland
Abstract
Software developers frequently refactor code. Often, a single
logical refactoring change involves changing multiple related
components in a source base such as renaming each occur-
rence of a variable or function. While many code editors
can perform such common and generic refactorings, they
do not support more complex refactorings or those that are
specic to a given code base. For those, as a exible—albeit
less interactive—alternative, developers can write refactor-
ing scripts that can implement arbitrarily complex logic by
manipulating the program’s tree representation. In this work,
we present Forest, a structural code editor that aims to bridge
the gap between the interactiveness of code editors and the
expressiveness of refactoring scripts. While structural edi-
tors have occupied a niche as general code editors, the key
insight of this work is that they enable a novel structural
multi-cursor design that allows Forest to reach a similar ex-
pressiveness as refactoring scripts; Forest allows to perform
a single action simultaneously in multiple program locations
and thus support complex refactorings. To support interac-
tivity, Forest provides features typical for text code editors
such as writing and displaying the program through its tex-
tual representation. Our evaluation demonstrates that Forest
allows performing edits similar to those from refactoring
scripts, while still being interactive. We attempted to per-
form edits from 48 real-world refactoring scripts using Forest
and found that 11 were possible, while another 17 would be
possible with added features. We believe that a multi-cursor
setting plays to the strengths of structural editing, since it
benets from reliable and expressive commands. Our results
suggest that multi-cursor structural editors could be practical
for performing small-scale specialized refactorings.
CCS Concepts: Software and its engineering Inte-
grated and visual development environments
;Software
evolution;Software maintenance tools.
Keywords: Structural editing, refactoring, multi-cursor
Onward! ’22, December 8–10, 2022, Auckland, New Zealand
©2022 Copyright held by the owner/author(s). Publication rights licensed
to ACM.
This is the author’s version of the work. It is posted here for your personal
use. Not for redistribution. The denitive Version of Record was published
in Proceedings of the 2022 ACM SIGPLAN International Symposium on New
Ideas, New Paradigms, and Reections on Programming and Software (Onward!
’22), December 8–10, 2022, Auckland, New Zealand,hps://doi.org/10.1145/
3563835.3567663.
ACM Reference Format:
Philippe Voinov, Manuel Rigger, and Zhendong Su. 2022. Forest:
Structural Code Editing with Multiple Cursors. In Proceedings of
the 2022 ACM SIGPLAN International Symposium on New Ideas, New
Paradigms, and Reections on Programming and Software (Onward!
’22), December 8–10, 2022, Auckland, New Zealand. ACM, New York,
NY, USA, 19 pages. hps://doi.org/10.1145/3563835.3567663
1 Introduction
When maintaining and extending software, developers are
often forced to make repetitive edits. For example, when a
developer introduces a new required parameter to a function,
a corresponding argument has to be added at every call site.
Similarly, changes such as splitting a large module or class
into multiple parts require repetitive adjustments at most
usage sites. If the changes aect systems that are used in
many locations in a codebase, such as logging or database
access, refactoring can be especially time-consuming.
Various approaches have been proposed to support repet-
itive refactoring on both textual and structural level (see
Figure 1). These tools dier in terms of interactivity and
whether they can be classied as textual or structural. We
consider a tool more interactive when it provides a workow
similar to conventional single location code editing and im-
mediately shows results in all locations. While textual tools
work with characters in a text le, without an understanding
of the programming language in question, structural tools
parse the program and operate on its Abstract Syntax Tree
Figure 1.
The design space of tools for performing similar
code edits in multiple locations. Forest is the rst tool in the
category of multi-cursor structural editors (underlined).
arXiv:2210.11124v1 [cs.SE] 20 Oct 2022
Onward! ’22, December 8–10, 2022, Auckland, New Zealand Philippe Voinov, Manuel Rigger, and Zhendong Su
(AST). For some common edits, such as renaming a vari-
able and all usages, Integrated Development Environments
(IDEs) contain built-in refactorings that operate structurally.
Existing tools are discussed in detail in Section 6.
Textual tools (left half of Figure 1), such as multi-cursor
text editors or regular expressions, have many advantages
over structural tools. They use familiar concepts from single-
location text editing. Since these tools do not inspect the
syntax of a program, they work with any programming lan-
guage and in programs with invalid syntax. However, this
lack of syntactic understanding makes it complex or im-
possible to perform certain edits in multiple locations. For
example, since many operations in textual tools depend on
the way that a program is formatted, they require the user
to make adjustments to match their code style. Attempting
to use nd-replace with regular expressions to swap the
order of two arguments in every call to a function high-
lights these limitations: If the function calls are always on a
single line and the arguments themselves are syntactically
simple (e.g. numeric literals), then the regular expression is
simple. However, in the general case where a function call
spans multiple lines and its arguments may themselves be
function calls, correctly performing the edit would require
parsing the code. Multi-cursor text editors, editors where ev-
ery movement and text edit is replayed in multiple locations
simultaneously, provide an interactive editing experience
for multiple locations. They allow users to edit multiple lo-
cations using the same commands as for a single location,
letting users apply familiar concepts from conventional text
editors. However, the edits that they can express are limited.
Typically, only commands such as inserting text or moving
in whole words or lines are supported.
Structural tools (right half of Figure 1) can perform more
complex edits than textual tools, and provide commands
which can be reliably applied in many locations. However,
they only work with valid syntax and require explicit sup-
port for each programming language. AST-based refactoring
scripts are programs in a general purpose programming lan-
guage that directly manipulate an AST. They are used to
perform repetitive edits in large scale code bases. At this
scale, operating on an AST is signicantly more reliably
than textual operations. Additionally, since such scripts use
a general purpose programming language, they can encode
more complex editing logic than other tools. However, the
process of developing such scripts is completely dierent to
conventional code editing (the user must write a program to
edit their code, instead of editing it directly), making them
impractical for small-scale repetitive edits. Structural nd-
replace tools are the structural equivalent of nd-replace
with regular expressions. They are more reliable than textual
nd-replace, but require an understanding of the AST and
use a separate set of concepts than conventional text editing.
Additionally, both textual and structural nd-replace have
limited support for encoding logic, such as ltering which
locations should be edited.
At a high level, we propose to combine multi-cursor edit-
ing with structural editing commands. This preserves the
key advantages of multi-cursor text editors: multiple loca-
tions are edited in the same way as a single location and
results are immediately shown. However, by using structural
commands instead of textual commands, more complex edits
are supported, and edits can be performed reliably in many
locations regardless of formatting and nested syntax.
Our prototype editor, Forest, is a multi-cursor structural
editor for TypeScript. In Forest, cursors point to AST nodes.
The user navigates within the AST by using structural oper-
ations like “move to parent”. These operations work reliably
in situations where textual tools are ineective, such as with
complex nested syntax. To retain the strengths and familiar-
ity of text editors, insertions are performed by parsing typed
text. A cursor can be split (e.g., for each child of the selected
AST node) to create multiple cursors that handle editing
commands simultaneously. This allows users to perform
repetitive edits the same way as they would when editing a
single location. A novel hierarchy of cursors concept makes it
practical to work with cursors that were split multiple times.
To understand the strengths and weaknesses of multi-
cursor structural editing, we collected real-world AST-based
refactoring scripts and attempted to perform the correspond-
ing edits interactively in Forest. Of the 48 edits, 11 could
be performed without any signicant issues, and a further
17 would likely become practical with improvements to the
editor. This shows that developers could avoid writing some—
but not all—refactoring scripts and instead use a multi-cursor
structural editor to perform their edit interactively.
We make three main contributions:
We built Forest
1
— a structural editor prototype for
TypeScript. Forest is one of very few structural editors
for modern languages with complex syntax.
We extended Forest to support multiple cursors, with
special integration between multi-cursor editing and
structural editing. This is the only multi-cursor struc-
tural editor with such integration.
We evaluated how Forest compares to refactoring
scripts, showing that Forest can be used to perform
edits from some real-world refactoring scripts.
1Online version of Forest with interactive examples:
hps://forestonward2022.walr.is/
GitHub: hps://github.com/tehwalris/forest
Archive: hps://doi.org/10.5281/zenodo.7225442
Forest: Structural Code Editing with Multiple Cursors Onward! ’22, December 8–10, 2022, Auckland, New Zealand
H
H
Figure 2.
A repetitive code edit where the user starts with the code in the top left and wishes to arrive at the code in the top
right. Each circled letter describes a step of this edit as performed in Forest. Each grey box of code marked by a letter shows
the state after the described edit was performed. The black outlines are cursors (multiple cursors can exist simultaneously in
one step). Steps C through G only show two of the cursors for brevity.
2 Motivating Example
Figure 2shows a repetitive code edit which we will use to
motivate and demonstrate multi-cursor structural editing.
This is an edit to TypeScript code in an old version of Forest’s
own codebase. We wanted to wrap every property value (the
expressions to the right of
:
within the object literal
{ ... }
)
in a function call (
warnOnError
) directly, rather than using a
loop to wrap the values at run time. We made this change to
subsequently add a new property which, unlike the others,
had to be wrapped in ignoreError.
Textual approaches cannot reliably perform such a refac-
toring, because the task is inherently not textual. Selecting
every property is especially dicult, because they span vary-
ing numbers of lines and the property separator comma
appears deep inside the values of some properties. In or-
der to perform the task using textual nd-replace, a regular
expression that captures the property names and values is
required. A reasonable attempt might be:
(".*?"): (.*? ) ,\ n (?= " |} )
However, such a regular expression relies on the exact num-
ber of spaces used for indention in order to discern which
commas separate properties and which are part of deeply
nested expressions. A dierent or inconsistently applied code
style would break this approach. The same issue occurs in
multi-cursor text editors when the user creates multiple cur-
sors by splitting an existing cursor (marked A in Figure
2) using a regular expression that describes the separator
(,(?=\n ")).
Structural tools can perform this refactoring reliably, avoid-
ing text-related issues like identifying separators. However,
there are reasons that discourage the use of existing struc-
tural tools for such a task. The developer could write a refac-
toring script [
3
] that transforms the Abstract Syntax Tree
(AST) of the program. However, writing a refactoring script
is unreasonably heavyweight for an edit that is required in
so few locations. This edit is also too program-specic to
Onward! ’22, December 8–10, 2022, Auckland, New Zealand Philippe Voinov, Manuel Rigger, and Zhendong Su
be available as a built-in refactor in an Integrated Develop-
ment Environment (IDE). Programming-by-demonstration
tools [
16
] [
23
] [
16
], which infer a structural edit based on
an example in one location, are a more lightweight solu-
tion than writing a custom refactoring script. However, such
tools may not always perform the desired edit, since the
inference process may either fail or may misinterpret the
given examples.
Forest allows the user to perform the example refactoring
with the same reliability as other structural tools, while re-
taining the interactivity of multi-cursor text editing. Using
Forest in Figure 2, the user starts their edit by moving their
cursor to the object literal containing all the properties that
they want to modify. This cursor is shown as a black outline
in step A of Figure 2. This cursor points to the AST node
that represents the object literal, but is shown to the user as
a selected text range (see Section 3.2 for details).
The user then applies Forest’s "split cursors" command,
which replaces the single cursor pointing to the object literal
by multiple cursors — one cursor for every node in the AST
that is a child of the object literal. The new cursors are shown
as black outlines in step B of Figure 2. The operation of nd-
ing the boundaries between properties is the key operation
in this example refactoring that structural tools can easily
perform, but that textual tools will struggle with.
In steps C through G, multiple cursors are used. For brevity,
we only show two of the six cursors. Each command issued
by the user is processed by all cursors simultaneously. This al-
lows the user to perform their edit exactly the same way as if
they were editing a single location. This is a major advantage
of multi-cursor editing in general (not just of multi-cursor
structural editing) over tools like refactoring scripts, regu-
lar expressions, and structural nd-replace, which are very
dierent from tools for editing single locations.
In step C, the user moves the selection (of each cursor)
from the object property to its last child in the AST. This is a
structural navigation operation, which would work reliably
even if the left hand side of the property had more compli-
cated content (e.g., a computed property name in TypeScript).
Steps C through G use structural navigation, placeholders,
copy-paste, and continuous pretty printing. These are com-
mon operations in Forest. They are described in Section 3.1.
This example mostly beneted from the structural nature
of Forest to split the cursors. Most of the edits in steps C
through G could be performed as easily in a multi-cursor
text editor as in Forest. In Section 4we discuss operations in
Forest that are unique to multi-cursor structural editors and
that are useful once the cursor has already been split.
3 Forest
This section describes Forest, but without any of its features
related to multi-cursor editing. Our main conceptual con-
tributions are concerned with multi-cursor editing, which
is discussed separately in Section 4. The section establishes
the necessary context to understand our core contribution.
We have recorded a short supplementary video (part of our
archived artifacts — see Footnote 1) to give an intuition of
how Forest’s basic features can be used.
3.1 Overview of Design
Source les in Forest are shown as pretty-printed text. This
text is synchronized with a Forest-specic AST (referred to as
“tree” from now on) which the user can interact with. Forest
is a modal editor — it has a normal mode for navigating and
issuing commands and an insert mode for inserting text. A
full list of available commands is given in the appendix.
Navigation.
The user controls a cursor that always has
part of the source le selected. This selection must corre-
spond to a contiguous selection of siblings in the tree. Forest
provides structural navigation commands (e.g., “go to parent”
or “select next leaf node”) for changing the selection. The
navigation commands treat every node in the tree as a list
of children in text order. This makes it possible to navigate
through any node using the same commands.
Insertion.
To add to the source le, the user enters insert
mode at the text location at the start (or end) of their selection,
types normal source code, and exits insert mode. It is only
possible to exit insert mode when the source le has valid
syntax. This restriction simplies implementation and is
common in structural editors.
Modication.
Existing code can be modied using the
delete, copy and paste commands. These commands are struc-
tural: they modify the tree (not the text) directly, after which
the modied tree is pretty-printed and shown to the user.
Deleting a node may result in a tree that does not correspond
to a valid TypeScript AST (e.g., deleting
b
in
a+b
). In this
case, Forest adds a placeholder (eectively a hole) instead of
the deleted item.
AST.
Most nodes in the Forest tree correspond exactly to
the equivalent TypeScript AST node. However, for nodes
where the TypeScript AST is inconvenient to edit, Forest
uses a dierent structure. For example, chains of property
accesses and calls (
this.data.filter(...).map(...)
) are a
left-associative tree in TypeScript, but a single at list in
Forest (this,data,filter,(...),map,(...)).
3.2 Selections
The behavior of selections in Forest has been signicantly
inuenced by the ABC editor [
17
]. A selection (the focus)
is one or more nodes in the tree, which must be contigu-
ous siblings. Any selections with the same text range are
considered equivalent. Note that although the selection of a
single cursor must consist of continuous siblings, there is no
restriction that multiple cursors must have selections that
are adjacent to each other.
摘要:

Forest:StructuralCodeEditingwithMultipleCursorsPhilippeVoinovphilippevoinov@gmail.comETHZurichSwitzerlandManuelRiggerrigger@nus.edu.sgNationalUniversityofSingaporeSingaporeZhendongSuzhendong.su@inf.ethz.chETHZurichSwitzerlandAbstractSoftwaredevelopersfrequentlyrefactorcode.Often,asinglelogicalrefact...

收起<<
Forest Structural Code Editing with Multiple Cursors.pdf

共19页,预览4页

还剩页未读, 继续阅读

声明:本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。玖贝云文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知玖贝云文库,我们立即给予删除!
分类:图书资源 价格:10玖币 属性:19 页 大小:1.14MB 格式:PDF 时间:2025-05-06

开通VIP享超值会员特权

  • 多端同步记录
  • 高速下载文档
  • 免费文档工具
  • 分享文档赚钱
  • 每日登录抽奖
  • 优质衍生服务
/ 19
客服
关注