This repository was archived by the owner on May 15, 2025. It is now read-only.
Conversation
* Support projects in subdirectories This commit makes the language server work with Smithy projects in subdirectories of the folder (or folders, in the case of e.g. vscode workspace folders) open in the editor. I previously added support for multiple _workspace folders_ (an LSP concept), but I assumed only one _project_ (Smithy LS concept) per workspace folder. So this commit fixes that mixing, allowing many projects per workspace folder. Now, the language server will search through subdirectories of all workspace folders (by default, one workspace folder is open in the client) to find projects. Changes to build files, i.e. smithy-build.json, .smithy-project.json, are now tracked at the workspace level, so you can add a new project to an existing workspace. I also did _some_ cleanup of the project/workspace synchronization code, and moved some things around. A note on some tests: I'm using a `Files.createTempDirectory`, and adding the `TestWorkspace` as a subdir. In a follow-up commit, I will be changing `TestWorkspace` to be something like `TestProject`, which is more accurate. I didn't include it here to avoid a bunch of noise. * Fix deadlock in didChangeWorkspaceFolders Blocking on the future creating the progress token with the client means the server can't actually receive the response from the client for that request. Tests don't catch this because the mock client is called directly, rather than through the server proxy. I decided to just remove the progress token code for now so didChangeWorkspaceFolders can work at all, rather than trying to make the method work asynchronously, which is a larger lift considering it mutates the server state. That change is coming though.
Co-authored-by: Smithy Automation <github-aws-smithy-automation@amazon.com>
This change makes the server register for document lifecycle events like didChange for build files. Previous behavior was to register for file system change events for build files, but eventually we want to give diagnostics, completions, etc. for build files as you type, so we need to track all changes. This change keeps existing behavior from the user's perspective, as we still only reload projects on save, so it serves mostly as a refactor. I also extracted the state managed by SmithyLanguageServer to its own class, ServerState, and flattened ProjectManager into that class, so we can manage the state of the server in a more centralized location.
What is changed? * Updated SmithyLanguageServer.java to improve location for diagnostics. * Added a new method to find contiguousRange for non-whitespace characters given a source location. Why is it necessary? * To improve location for diagnostics. * See [Issue smithy-lang#76](smithy-lang#76) How was the change tested? * Updated unit tests in SmithyLanguageServerTest.java and DocumentParserTest.java * Ran the full test suite to ensure no regressions * Manually tested the language server with various Smithy documents to verify improvements
Fixes a bug in smithy-lang#168 where the server would send the wrong registration for didSave on Smithy files.
Co-authored-by: Smithy Automation <github-aws-smithy-automation@amazon.com>
Lsp4j provides default implementations of these methods in the LanguageServer interface, which throw exceptions. Even though we don't support this server side, better to give a warning than shutdown the server.
* Upgrade completions, definition, hover
This commit is a rewrite of how language features (i.e. completions,
definition, hover) are implemented. It improves the accuracy and expands
the functionality of each feature significantly. Improvements include:
- Completions
- Trait values
- Builtin control keys and metadata
- Namespaces, based on other namespaces in the project
- Keywords
- Member names (like inside resources, maps)
- Member values (like inside the list of operation errors, resource
property targets, etc.)
- Elided members
- Some trait values have special completions, like `examples` has
completions for the target operation's input/output parameters
- Definition
- Trait values
- Elided members
- Shape ids referenced within trait values
- Hover
- Trait values
- Elided members
- Builtin metadata
There's a lot going on here, but there's a few key pieces of this commit
that all work together to make this work:
At the core of these improvements is the addition of a custom parser for
the IDL that provides the needed syntactic information to implement
these features. See the javadoc on the Syntax class for more details on
how the parser works, and why it was written that way. At a high level
though, the parser produces a flat list of `Syntax.Statement`, and that
list is searched through to find things, such as the statement the
cursor is currently in. It is also used to search 'around' a statement,
like to find the shape a trait is being applied to.
Another key piece of these changes is `NodeCursor` and `NodeSearch`.
There are a few places in the syntax of a smithy file where you may have
a node value whose structure is (or can be) described by a Smithy model.
For example, trait values. `NodeCursor` is basically two things: 1. A
path from the start of a `Node` to a position within that `Node`, 2. An
index into that path. `NodeSearch` is used to search a model along the
path of a `NodeCursor`, from a starting shape. For example, when the
cursor is within a trait value, the `NodeCursor` is that path from the
root of the trait value, to the cursor position, and `NodeSearch` is
used to search in the model, starting at the trait's definition, along
the path of the `NodeCursor`, to find what shape corresponds to the
cursor's location. That shape can then be used e.g. to provide completions.
Finally, there's the `Builtins` class, and the corresponding Smithy
model it uses. I originally had a completely different abstraction for
describing the structure of metadata, different shape types' members,
and even `smithy-build.json`. But it was basically just a 'structured
graph', like a Smithy model. So I decided to just _use_ a Smithy model
itself, since I already had the abstractions for traversing it (like I
had to for trait values). The `Builtins` model contains shapes that
define the structure of certain Smithy constructs. For example, I use it
to model the shape of builtin metadata, like suppressions. I also use it
to model the shape of shapes, that is, what members shapes have, and
what their targets are. Some shapes in this model are considered
'builtins' (in the builtins.smithy files). Builtins are shapes that
require some custom processing, or have some special meaning, like
`AnyNamespace`, which is used for describing a namespace that can be
used in
https://smithy.io/2.0/spec/model-validation.html#suppression-metadata.
The builtin model pretty 'meta', and I don't _love_ it, but it reduces a
significant amount of duplicated logic. For example, if we want to give
documentation for some metadata, it is as easy as adding it to the
builtins model. We can also use it to add support for smithy-build.json
completions, hover, and even validation, later. It would be nice if
these definitions lived elsewhere, so other tooling could consume them,
like the Smithy docs for example, and I have some other ideas on how we
can use it, but they're out of scope here.
Testing for this commit comes mostly from the completions, definitions,
and hover tests, which indirectly test lower-level components like the
parser (there are still some parser tests, though).
* Address feedback
* Refactoring
This commit keeps the functionality added to the language features in
the previous commits, but does some broad refactoring of those changes
to clean up the APIs, get rid of some footguns, and reduce the chance of
some concurrency/parallelism issues.
The main changes are:
- Syntax.Ident/Syntax.Node.Str produced by the new parser now copy the
actual string value. Previously, they only stored the start/end
positions, and required you to copy the value out of the Document
on-demand. This reduced the memory footprint of parsing, but I was
concerned about the Document being changed at the same time another
thread is trying to copy a value out of it. Copying eagerly avoids
this. Plus, we can avoid most of the memory issues by doing partial
reparsing (more on that later).
- Project now stores an index of files -> shapes defined in that file,
instead of storing the shapes on the SmithyFile. This index is only
needed to help determine which shapes need to be removed when
rebuilding the model, so it doesn't make sense for SmithyFile to know
about it. This also ties into the next change...
- Multiple changes to SmithyFile. SmithyFile now has a subclass,
IdlFile, which stores its parse result. With the addition of the
parser, and the changes to make
DocumentVersion/DocumentImports/DocumentNamespace be computed from the
parse result, SmithyFile can't represent both IDL and AST files.
Arguably, it never really did because AST files don't have
namespaces/imports. Either way, IdlFile now provides access to the
parse result, which contains DocumentNamespace/Version/Imports, as
well as the parsed statements. I also added synchronization to handle
access to the parse result, since it will be mutated on every change.
I don't really like how this works, but I'm going to address that in a
future update (which I will describe below).
- Added StatementView, which wraps a list of parsed statements and a
specific index in that list, providing methods to look "around" that
index. This replaces the error-prone and unreadable SyntaxSearch,
which required you to pass around int indicies everywhere.
Some more minor changes to note:
- Moved diagnostics computation into SmithyDiagnostics. It already
belonged there probably, but especially with the addition of IdlFile I
just had to do it.
- Moved document symbols into a 'handler' like definition, etc.
- Added `uri` and `isDetached` properties to ProjectAndFile, for
convenience.
There are still some rough edges with this code, but I plan on making a
follow up PR to address them, so I this one doesn't become even larger.
Specifically, I want to only parse opened/managed files. This could let
us get rid of the whole ProjectFile thing, or at least not require going
through a project to find a file (it would be stored directly on
ServerState). This also makes the synchronization story much simpler,
improves initialization time, and should make it easier to eventually
load projects async.
* Fix hover on member defs
* Fix replace text range
In some cases, when a completion is meant to replace existing text, the
range it was supposed to replace would leave an extra character at the
end. This was because the range's end position was not exclusive.
* Fix test class name
* Hide ServerState data members * Store only one collection of projects * Collapse Project data members into RebuildIndex * Dont read from disk multiple times When loading a project, SmithyFiles were being read from disk multiple times. This commit refactors ProjectLoader to only read from disk once, and also cleans up some stuff. * Add interface for getting managed files Project loading can now depend on a single interface that provides access to managed files, rather than ServerState itself. * Add documentation to new methods * Rename DocumentLifecycleManager * Cleanup some of Project's api * Get rid of extraneous Document methods
Addresses smithy-lang#191. I had to disable our test for watcher registrations because (as described in the issue) PathMatcher behaves differently that whatever VSCode is using to match glob patterns. For testing, I may need to followup with a more robust way of verifying changes against specific clients.
This commit makes the language server send diagnostics back to build
files, i.e. smithy-build.json. Previously, any issues in build files
would result in the project failing to load, and those errors would be
reported to the client's window. With this change, issues are recomputed
on change, and sent back as diagnostics so you get squigglies. Much
better.
To accomplish this, a number of changes were needed:
1. Reparse build files on change. Previously, we just updated the
document.
2. Have a way to run some sort of validation on build files that can
tolerate errors. This is split into two parts:
1. A regular validation stage that takes the parsed build file and
tries to map it to its specific java representation, collecting
any errors that occur. For example, smithy-build.json is turned
into SmithyBuildConfig.
2. A resolution stage that takes the java representation and tries to
resolve maven dependencies, and recursively find all model paths
from sources and imports.
3. Keep track of events emitted from this validation so they can be sent
back to the client.
2 is the most complicated part. SmithyBuildConfig does some extra work
under the hood when it is deserialized from a Node, like environment
variable replacement. I wanted to make sure there wasn't any drift
between the language server and other Smithy tools, so I kept using
SmithyBuildConfig::fromNode, but now any exception thrown from this will
be mapped to a validation event. Each of the other build files work the
same way. I also kept the same merging logic for aggregating config from
multiple build files.
Next is the resolution part. Maven resolution can fail in multiple ways.
We have to try to map any exceptions back to a source location, because
we don't have access to the original source locations. For finding
source/import files, I wanted to be able to report when files aren't
found (this also helps to make sure assembling the model doesn't fail
due to files not being found), so we have to do the same thing (that is,
map back to a source location). Resolution in general is expensive, as
it could be hitting maven central, but doing this mapping could also be
expensive, so we don't perform the resolution step when build files
change - only when a project is actually loaded. We will have to see how
this validation feels, and make improvements where necessary.
Additional changes:
- Report Smithy's json parse errors
- Added a 'use-smithy-build' diagnostic to 'legacy' build files
- Fix json node parsing to properly handle commas in the IDL vs actual
json
…mithy-lang#195) This change better aligns with LSP spec and fixes smithy-lang#194
The server now can provide completions for smithy-build.json and .smithy-project.json. The implementation works roughly the same as other node-like completions, using a new builtins model that specifies the structure of the build files. I also had to override the completion item mapper to make sure it wrapped object keys in strings, which is necessary in json.
Added folds for imports, blocks, multiline traits, and node values. Also fixed parser to not skip ')' in trait applications, and to make enum values not contain the rest of their trailing whitespace.
The rebuild index checks which shapes have traits that are applied in other files (i.e. via an `apply`), so we can preserve those traits in a reload. However, if a trait's source location is `SourceLocation.NONE`, which can happen if it wasn't set on the trait's builder, the rebuild index would consider that "a trait applied from another file". If the trait isn't actually being applied from another file, this would cause a duplicate trait conflict, since the trait would be added both from the rebuild index, and the ModelAssembler reparsing. This commit changes two things: 1. The trait's _node_ source location is now used for the comparison, since it should always have a source location as it is constructed within smithy-model, not by trait provider implementations 2. This source location is checked to see if it is NONE.
Co-authored-by: Smithy Automation <github-aws-smithy-automation@amazon.com>
smithy-lang#190 fixed trait application parsing for traits like `@foo()`, making it so the end of the trait doesn't include trailing whitespace. This commit fixes the case for non-empty traits, like `@foo(bar: "")`. It also fixes parsing of empty strings. Previously the character _after_ the end of the string would be skipped.
Logging for unknown file in ServerState is unnecessary because it will always log for newly opened detached files, plus callers have to handle a file not being found anyway. Logging for deprecated properties in SmithyBuildExtensions aren't going to be visible enough to customers to be useful, plus we emit a warning for build exts anyways. I also had some old debugging code lingering in tests that I cleaned up.
smithy-lang#168 started tracking build file changes via lifecycle methods, didOpen, etc. But it didn't make a distinction between what was a build file, and what was a Smithy file. There are two paths didOpen can take - the first is when the file being opened is known to be part of a project. In this case, the file is already tracked by its owning Project, so its basically a no-op. The second path is when the file does not belong to any project, in which case we created a "detached" project, which is a project with no build files and just a single Smithy file. So if you opened a build file that wasn't known to be part of a Project, the language server tried to make a detached project containing the build file as a smithy file. This is obviously wrong, but wasn't observable to clients AFAICT because clients weren't set up to send requests to the server for build files (specifically, you wouldn't get diagnostics or anything, only for .smithy files). However, recent commits, including smithy-lang#188, now want to provide language support for smithy-build.json. In testing these new commits with local changes to have VSCode send requests for smithy-build.json, the issue could be observed. Specifically, the issue happens when you open a new smithy-build.json before we receive the didChangeWatchedFiles notification that tells us a new build file was created. didChangeWatchedFiles is the way we actually updated the state of projects to include new build files, or create new Projects. Since we can receive didOpen for a build file before didChangeWatchedFiles, we needed to do something with the build file on didOpen. This commit addresses the problem by adding a new Project type, UNRESOLVED, which is a project containing a single build file that no existing projects are aware of. We do this by modifying the didOpen path when the file isn't known to any project, checking if it is a build file using a PathMatcher, and if it is, creating an unresolved project for it. Then, when we load projects following a didChangeWatchedFiles, we just drop any unresolved projects with the same path as any of the build files in the newly loaded projects (see ServerState::resolveProjects). I also made some (upgrades?) to FilePatterns to better handle the discrepancy between matching behavior of PathMatchers and clients (see smithy-lang#191). Now there are (private) *PatternOptions enums that FilePatterns uses to configure the pattern for different use cases. For example, the new FilePatterns::getSmithyFileWatchPathMatchers provides a list of PathMatchers which should match the same paths as the watcher patterns we send back to clients, which is useful for testing. I also fixed an issue where parsing an empty build file would cause an NPE when trying to map validation events to ranges. Document::rangeBetween would return null if the document was empty, but I wasn't checking for that in ToSmithyNode (which creates parse events). The reason the range is null is because Document.lineOfIndex returns oob for an index of 0 into an empty document. Makes sense, as an empty document has no lines. I updated a DocumentTest to clarify this behavior. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
Was just `1`, which doesn't match the docs' default of `1.0`.
The language server now provides hover content for smithy-build.json. Specifically, when hovering on json keys (and only the keys), hover content will include the documentation for that property from https://smithy.io/2.0/guides/smithy-build-json.html, in addition to a link to the corresponding section in the docs page where applicable. This uses the `build.smithy` builtin model. I've added documentation traits to all relevant members, including externalDocumentation for the links. I didn't do the same for .smithy-project.json, as I'll need to think through properly documenting that and plan on doing so later. This commit will have a few followups based on things I've learned from this commit: 1. I should add support for externalDocumentation to IDL hover. Can probably share a lot of the code. 2. I can probably remove the serialization of validation events into IDL hover content. I'm not sure why exactly I put them there, maybe it was an artifact from the history of the language server, but I think that diagnostics are already displayed with hover content, so doing the extra work is unnecessary.
* Added Inlay Hint Feature for LSP * Fixed style check errors. * Fixed style check errors. * Fixed style check errors. * Added LspMatcher for inlay hint test, modified inlayhint generation process * Fixed style check errors. * Modified redundant if statement.
This adds hover info for a bunch of things that I didn't get around to in the initial hover upgrade, including: All shape types Non shape type keywords, metadata, namespace, use, apply, with, and for Member names in service, resource, and operation shapes Links to Smithy docs site for all these "builtins" Documentation traits on user-defined members (before it just wasn't rendered) I had to add new builtin model for the non-shape keywords, but reused ShapeMemberTargets for shape type keyword hover. I also had to add a way to check if the cursor was inside the keyword of a statement, which simplifies IdlPosition a bit too. The Smithy docs links use externalDocumentation, like the smithy-build.json model, and I also added a way to include docs links to all members of a builtin shape, because there's some things which don't have a great link for themselves specifically, but it would still be nice to allow navigating to some docs page that could be useful. This works by adding the externalDocumentation trait to the root shape in the builtins model, and having the hover implementation add any external docs from the container shape when constructing hover for a builtin. So, for example, hovering over "version": "1.0" in smithy-build.json now also includes a link to the smithy-build.json page.
|
|
Co-authored-by: Smithy Automation <github-aws-smithy-automation@amazon.com>
The original implementation didn't check members for the idRef trait, and in general didn't handle idRefs in trait values. This commit fixes both of those issues by adding a `targetOf` field to TerminalShape, so that member can be checked for the idRef trait, and uses ShapeCompleter when a trait value completion is for an idRef. I also added some extra tests for definition and hover to make sure it was working correctly there too.
RebuildIndex checks the source location of traits to see if they are SourceLocation.NONE when determining which files depend on eachother. SourceLocation's equals does a toString to compare though, which is unnecessarily slow, so I changed our comparison to just check the filename.
There could have been an infinite loop if you had something that wasn't
an identifier in a mixin, like:
```
structure Foo with [123] {}
structure Foo with 123 {}
```
so I changed the parser to recover to either an identifier, or some
structural breakpoint when that happens. I don't think this specific
strategy generalizes enough to just put it in `ident()`, but if we find
any other cases where this can happen we could add some more error
recover methods, or specific `ident()` methods that recover in a
particular way.
I also modified the invalid test cases in IdlParserTest to include
blocks - for some reason I had the test filtering out blocks before the
assertion, but we definitely want to check for them.
I also removed an erroneous `ShapeNode` Statement type.
* Implement references and rename Adds support for 'textDocument/references', 'textDocument/rename', and 'textDocument/prepareRename'. These all work very similarly, so I implemented them together. This implementation only works for root shapes, not members or resource identifiers/properties (which I call resource fields for brevity). Originally I intended to make it work for members, but for 'complete' member support, you really need to support resource fields, otherwise if you tried to rename a member, it wouldn't rename the resource field it references, and finding references wouldn't show fully accurate information. The problem is, the relationship between members and resource fields can be implicit, and/or determined by a number of different traits (`resourceIdentifier`, `property`, `references`, `nestedProperties`). And some of these traits refer to the resource field by string name. Current KnowledgeIndex implementations don't support going from an arbitrary member -> field bindings and back. Plus, we can't reliably use KnowledgeIndicies because they usually operate on a complete, valid model, whereas the language server wants to operate on the minimum subset of a possibly invalid model. I think it would be possible still to support members in the future, either with some clever code in the language server or enhancements to the smithy library, but I didn't want to block rename/references for regular shapes on that. Some specific implementation details to note: 1. Rename/References throw ResponseErrorException on an unsupported position (like a member name), or when the rename would be invalid (i.e. renaming a shape from a dependency, or providing an invalid shape name). This is what the spec says you should do, and we should update other features to do the same. 2. Rename disambiguates shapes that would be conflicting after the rename by using an absolute shape id, and removes conflicting use statements. 3. Rename/References both work on references to members of the target shape, i.e. `com.foo#Foo$bar`, only if the request position is before the `$`, otherwise it assumes you're getting the reference of a member. 4. Prepare returns the range of the identifier to be renamed (or throws an error as specified in 1.), so if you go to rename `com.foo#Bar`, the rename range will be the range of `Bar`. Other notable changes: 1. Changed `DocumentId` to only have distinct types for root shapes and members. The type will be `ROOT` when the cursor is in any part of the shape id before a member, and `MEMBER` only when the cursor is actually within the member part of the shape id. The rest of the other possible id types didn't seem to be useful enough to keep. 2. Added a `line` field to Syntax.Node.Str, which makes it _much_ more efficient to get the range of a Str or Ident. 3. Fixed an issue in TextWithPositions when there are multiple positions on the same line. * Fix shape search resolution Fixes an issue with ShapeSearch::findShape where the local namespace was checked before imports. It was inconsistent with the way the model loader resolves shapes, so you could end up jumping to the wrong definition/references, or renaming the wrong shape.
Previously, NodeSearch used NodeCursor::setCheckpoint to store the current position in the cursor, inspect previous edges for computing dynamic member targets, and return to the checkpoint to continue traversal. Maybe I thought there were complex use-cases that had to look further back in the path, but right now all we need is to look at the previous Node. So I updated NodeSearch to use the previous Node to compute dynamic member targets, and removed the checkpoint stuff from NodeCursor.
Diagnostics are already displayed by clients when hovering, so adding them in our hover implementation duplicates them.
When I re-wrote the language feature implementations in smithy-lang#166, I refactored documentSymbol. But it mostly just copied the previous implementation, which produced a flat list of symbols. This meant that member symbols would appear at the top-level, but documentSymbol is meant to provide a tree-like view, where symbols can have children. So this commit re-writes documentSymbol to produce a list of only the top-level shapes' symbols (and the namespace statement's symbol), with members' symbols being added as children to the top-level symbols, and members of inline i/o are children of the inline i/o symbol. I also changed up the Symbol kind a bit, so root shapes are of type `Class` (except enum/intEnum, which are of type `Enum`), members are of type `Field` (except enum/intEnum members, which are of type `EnumMember`), and service/resource/operation members are of type `Property`. I explored having different symbol kinds for different types of shapes, like making service-type shapes be of kind `Interface`, and primitive types being of their corresponding kind (for example, an integer shape would have kind `Number`), but I wasn't sure what some shape types should be. For example, what should a `blob` shape be? So I decided to just make all top-level shapes just be of kind `Class`. I also fixed the range and selection range of symbols. Range now covers everything from shape type -> end of block (if applicable), and selection range is just the shape/member name. I considered adding more children for service-type shape members, like making the `operations` child symbol of a service shape have a child for each of the operations in the list, but I think it would make the tree view more noisy, plus I think the intent is to show symbol definitions. I also made a minor adjustment to the parsing of operations members, making them always be inline or node member defs, instead of possibly a regular member def for non-inline i/o. This is consistent with resource/service members, which are always node members.
Fixes a possible npe when checking if the client supports dynamically registering for synchronization notifications. The property being checked is a nullable `Boolean`, and the possible null value wasn't being accounted for.
Co-authored-by: Smithy Automation <github-aws-smithy-automation@amazon.com>
…thy-lang#212) * Expand tests on parser to achieve higher coverage * Delete unreachable branch * Add fix for Node with leading comma * Add fix for duplicate statement when invalid member def statement appears * Add fix for unset end of kvp
* add runtime plugin for generating stand-alone images * add JReleaser configuration for github release and runtimes * Use runtime plugin fork Updates the runtime plugin to a fork with support for java 21, instead of the upstream https://github.com/beryx/badass-runtime-plugin. See beryx/badass-runtime-plugin#154 for more details. Also changed the java version back to 21. * Remove deploy github workflow We had a github workflow that would run on a tag push, creating a new release and uploading a zip of the language server. Jreleaser should take care of all that now, so the workflow is unnecessary. * Add changelog to github release notes So we don't have to manually add the release notes to the github release after it is published. I added a custom task to read in the full changelog, and parse out the entry for the latest version. The result is written out to a resources file that I pointed the github release config to. The jreleaser docs don't seem to be 100% clear on whether the changelog is actually what ends up in the release notes, but it would make sense to me, and the text in https://jreleaser.org/guide/latest/reference/release/github.html#_release_notes suggests it. --------- Co-authored-by: Miles Ziemer <mziemer@amazon.com>
Updates the runtime plugin config to include the same modules the smithy-cli does: https://github.com/smithy-lang/smithy/blob/fb9ef6dafe89742eefb87f0072b4c7762afd70d9/smithy-cli/build.gradle.kts#L99. Otherwise, we get some class defs not found when resolving dependencies. I don't have a good idea for how to avoid the duplication between the repos.
Add the argument parser feature to the LSP and modified the Main class. The argument parser will be able to parse the help and port-number arguments for now. For port-number argument, both flag argument and positional argument are supported. Port number is optional, and defaults to `0` to use standard in/out. The positional port argument is deprecated, but still supported.
Kotlin is easier to understand for me, and Intellij apparently. I tried to keep this as much as a 1:1 conversion as I could for this commit, but will followup with another to clean it up.
Member
Author
|
Closing, we'll probably deprecate the fork. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue #, if available:
Description of changes:
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.