Skip to content

feat: add Beta support for Inline Completion Request #886

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonahgraham I'd like to solicit your input on this idea of having our own Beta annotation, and its proposed implementation. In its current form it has been copied from Guava. Does it necessitate a separate IP review for this PR? In that case, I'd probably prefer to define a similar annotation from scratch.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is correct.

I have just removed the @GwtCompatible annotation and adapted the copyright to add and othres.

I could start from zero if needed, but other than having a different javadoc, there is not much room for deviating.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the question is whether a review from the Eclipse IP Team would be required because of that and if so, whether it would be more straightforward if we could do without the elaborate Javadoc and make our own annotation from scratch instead.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2010 The Guava Authors and others
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package org.eclipse.lsp4j.jsonrpc;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Signifies that a public API (public class, method or field) is subject to incompatible changes,
* or even removal, in a future release. An API bearing this annotation is exempt from any
* compatibility guarantees made by its containing library. Note that the presence of this
* annotation implies nothing about the quality or performance of the API in question, only the fact
* that it is not "API-frozen."
*
* <p>It is generally safe for <i>applications</i> to depend on beta APIs, at the cost of some extra
* work during upgrades. However it is generally inadvisable for <i>libraries</i> (which get
* included on users' CLASSPATHs, outside the library developers' control) to do so.
*
* @author Kevin Bourrillion
*/
@Retention(RetentionPolicy.CLASS)
@Target({
ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.METHOD,
ElementType.TYPE
})
@Documented
public @interface Beta {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/******************************************************************************
* Copyright (c) 2025 Avaloq Group AG.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
******************************************************************************/
package org.eclipse.lsp4j;

import org.eclipse.lsp4j.jsonrpc.Beta;

/**
* Describes how an {@link InlineCompletionItem} was triggered.
* <p>
* @since 3.18.0
*/
@Beta
public enum InlineCompletionTriggerKind {
/**
* Completion was triggered explicitly by a user gesture. Return multiple
* completion items to enable cycling through them.
*/
Invoked(1),

/**
* Completion was triggered automatically while editing. It is sufficient to
* return a single completion item in this case.
*/
Automatic(2);

private final int value;

InlineCompletionTriggerKind(final int value) {
this.value = value;
}

public int getValue() {
return value;
}

public static InlineCompletionTriggerKind forValue(final int value) {
InlineCompletionTriggerKind[] allValues = InlineCompletionTriggerKind.values();
if (value < 1 || value > allValues.length) {
throw new IllegalArgumentException("Illegal enum value: " + value);
}
return allValues[value - 1];
}
}
259 changes: 259 additions & 0 deletions org.eclipse.lsp4j/src/main/java/org/eclipse/lsp4j/Protocol.xtend
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.eclipse.lsp4j.adapters.VersionedTextDocumentIdentifierTypeAdapter
import org.eclipse.lsp4j.adapters.WorkspaceDocumentDiagnosticReportListAdapter
import org.eclipse.lsp4j.adapters.WorkspaceSymbolLocationTypeAdapter
import org.eclipse.lsp4j.generator.JsonRpcData
import org.eclipse.lsp4j.jsonrpc.Beta
import org.eclipse.lsp4j.jsonrpc.json.adapters.JsonElementTypeAdapter
import org.eclipse.lsp4j.jsonrpc.messages.Either
import org.eclipse.lsp4j.jsonrpc.messages.Either3
Expand Down Expand Up @@ -2241,6 +2242,14 @@ class TextDocumentClientCapabilities {
*/
DiagnosticCapabilities diagnostic

/**
* Capabilities specific to the `textDocument/inlineCompletion` request.
* <p>
* @since 3.18.0
*/
@Beta
InlineCompletionClientCapabilities inlineCompletion

new() {
}
}
Expand Down Expand Up @@ -6061,6 +6070,14 @@ class ServerCapabilities {
*/
Either<Boolean, InlineValueRegistrationOptions> inlineValueProvider

/**
* The server provides inline completions.
* <p>
* @since 3.18.0
*/
@Beta
Either<Boolean, InlineCompletionRegistrationOptions> inlineCompletionProvider;

/**
* The server has support for pull model diagnostics.
* <p>
Expand Down Expand Up @@ -11161,3 +11178,245 @@ class NotebookDocumentIdentifier {
this.uri = Preconditions.checkNotNull(uri, 'uri')
}
}

/**
* Describes the StringValue kind
* <p>
* Since 3.18.0
*/
@Beta
final class StringKind {
/**
* Snippet text is supported as a StringValue kind.
*/
public static val SNIPPET = 'snippet'
}
/**
* A string value used as a snippet is a template which allows to insert text
* and to control the editor cursor when insertion happens.
* <p>
* A snippet can define tab stops and placeholders with `$1`, `$2`
* and `${3:foo}`. `$0` defines the final tab stop, it defaults to
* the end of the snippet. Variables are defined with `$name` and
* `${name:default value}`.
* <p>
* @since 3.18.0
*/
@Beta
@JsonRpcData
class StringValue {
/**
* The type of the StringValue.
* <p>
* See {@link StringKind} for allowed values.
*/
@NonNull
String kind

/**
* The snippet string.
*/
@NonNull
String value

new(@NonNull String kind, @NonNull String value) {
this.kind = Preconditions.checkNotNull(kind, 'kind')
this.value = Preconditions.checkNotNull(value, 'value')
}
}

/**
* Client capabilities specific to inline completions.
* <p>
* @since 3.18.0
*/
@Beta
@JsonRpcData
class InlineCompletionClientCapabilities extends DynamicRegistrationCapabilities {
new() {
}

new(Boolean dynamicRegistration) {
super(dynamicRegistration)
}
}

/**
* Inline completion options used during static or dynamic registration.
* <p>
* @since 3.18.0
*/
@Beta
@JsonRpcData
class InlineCompletionRegistrationOptions extends StaticRegistrationOptions implements WorkDoneProgressOptions {
Boolean workDoneProgress
}

/**
* A parameter literal used in inline completion requests.
* <p>
* @since 3.18.0
*/
@Beta
@JsonRpcData
class InlineCompletionParams extends TextDocumentPositionAndWorkDoneProgressParams {
/**
* Additional information about the context in which inline completions
* were requested.
*/
@NonNull
InlineCompletionContext context

new() {
}

new(@NonNull TextDocumentIdentifier textDocument, @NonNull Position position, @NonNull InlineCompletionContext context) {
super(textDocument, position)
this.context = Preconditions.checkNotNull(context, 'context')
}
}

/**
* Provides information about the context in which an inline completion was
* requested.
* <p>
* @since 3.18.0
*/
@Beta
@JsonRpcData
class InlineCompletionContext {
/**
* Describes how the inline completion was triggered.
*/
@NonNull
InlineCompletionTriggerKind triggerKind

/**
* Provides information about the currently selected item in the
* autocomplete widget if it is visible.
*
* If set, provided inline completions must extend the text of the
* selected item and use the same range, otherwise they are not shown as
* preview.
* As an example, if the document text is `console.` and the selected item
* is `.log` replacing the `.` in the document, the inline completion must
* also replace `.` and start with `.log`, for example `.log()`.
*
* Inline completion providers are requested again whenever the selected
* item changes.
*/
SelectedCompletionInfo selectedCompletionInfo

new() {
}

new(@NonNull InlineCompletionTriggerKind triggerKind) {
this.triggerKind = Preconditions.checkNotNull(triggerKind, 'triggerKind')
}

new(@NonNull InlineCompletionTriggerKind triggerKind, SelectedCompletionInfo selectedCompletionInfo) {
this.triggerKind = Preconditions.checkNotNull(triggerKind, 'triggerKind')
this.selectedCompletionInfo = selectedCompletionInfo
}
}

/**
* Describes the currently selected completion item.
* <p>
* @since 3.18.0
*/
@Beta
@JsonRpcData
class SelectedCompletionInfo {
/**
* The range that will be replaced if this completion item is accepted.
*/
@NonNull
Range range

/**
* The text the range will be replaced with if this completion is
* accepted.
*/
@NonNull
String text

new() {
}

new(@NonNull Range range, @NonNull String text) {
this.range = Preconditions.checkNotNull(range, 'range')
this.text = Preconditions.checkNotNull(text, 'text')
}
}

/**
* Represents a collection of {@link InlineCompletionItem} to be presented in the editor.
* <p>
* @since 3.18.0
*/
@Beta
@JsonRpcData
class InlineCompletionList {
/**
* The inline completion items.
*/
@NonNull
List<InlineCompletionItem> items

new() {
}

new(@NonNull List<InlineCompletionItem> items) {
this.items = Preconditions.checkNotNull(items, 'items')
}
}

/**
* An inline completion item represents a text snippet that is proposed inline
* to complete text that is being typed.
* <p>
* @since 3.18.0
*/
@Beta
@JsonRpcData
class InlineCompletionItem {
/**
* The text to replace the range with. Must be set.
* Is used both for the preview and the accept operation.
*/
@NonNull
Either<String, StringValue> insertText

/**
* A text that is used to decide if this inline completion should be
* shown. When `falsy`, the {@link InlineCompletionItem#insertText} is
* used.
* <p>
* An inline completion is shown if the text to replace is a prefix of the
* filter text.
*/
String filterText

/**
* The range to replace.
* Must begin and end on the same line.
* <p>
* Prefer replacements over insertions to provide a better experience when
* the user deletes typed text.
*/
Range range

/**
* An optional {@link Command} that is executed *after* inserting this
* completion.
*/
Command command

new() {
}

new(@NonNull Either<String, StringValue> insertText) {
this.insertText = Preconditions.checkNotNull(insertText, 'insertText')
}
}
Loading