-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Ability to register language servers for file names instead of extensions #5107 #5156
Ability to register language servers for file names instead of extensions #5107 #5156
Conversation
Can one of the admins verify this patch? |
@@ -149,7 +149,7 @@ | |||
<version>${project.version}</version> | |||
<executions> | |||
<execution> | |||
<phase>process-sources</phase> | |||
<phase>generate-sources</phase> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
last time we are not able to release with <phase>generate-sources</phase>
I think there is a compilation issue in this phase. Why do you want to change it? Can you compile this artifact in offline mode if you local is empty or doesn't contains che-plugin-languageserver-ide
artifact
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The maven generator plugin is using compiled dependencies to generate the dto classes. Since no dto's are generated from classes in the project itself, this should be fine. In the core.api.languageserver project, there used to be a precompile step in order to be able to generate from classes in the project itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you checked that I've asked? Because we had troubles with this last time during release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's impossible to build in offline mode when the local maven cache is empty. I can remove che stuff from the cache, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's impossible to build in offline mode when the local maven cache is empty
Ok. I wasn't really clear. I mean remove only org.eclipse.che
artifacts or to be more precise che-plugin-languageserver-ide
and when rebuilt che-plugin-languageserver-ide
in offline mode. It's should be possible. Same situation we have when maven release plugin is releasing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. I've checked looks like it's working
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx. I was having trouble building from scratch all last week (some tests failing in unrelated projects)
/** | ||
* @author Evgen Vidolob | ||
*/ | ||
@Singleton | ||
public class LanguageServerFileTypeRegister implements WsAgentComponent { | ||
|
||
private static Logger logger = Logger.getLogger(LanguageServerFileTypeRegister.class.getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOGGER?
private static final String[] EXTENSIONS = new String[]{ProjectAttributes.PYTHON_EXT}; | ||
private static final String MIME_TYPE = "text/x-python"; | ||
static { | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True.
@@ -58,8 +49,7 @@ public boolean isAbleToLaunch() { | |||
} | |||
|
|||
protected LanguageServer connectToLanguageServer(final Process languageServerProcess, LanguageClient client) { | |||
Launcher<LanguageServer> launcher = Launcher.createLauncher(client, LanguageServer.class, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is only formatting, I would include in a seperated PR or commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would mean that I have to create an issue and open a PR just for a formatting change? I politely disagree here. My favorite solution would be to automate formatting completely, then formatting changes would never occur.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
at least seperate in 2 commits in the same PR
this.resources = resources; | ||
this.editorRegistry = editorRegistry; | ||
this.contentTypeRegistrant = contentTypeRegistrant; | ||
this.orionHoverRegistrant = orionHoverRegistrant; | ||
this.orionHoverRegistrant = orionHoverRegistrant; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is not wanted
@Inject | ||
public LanguageServerFileTypeRegister(LanguageServerRegistryServiceClient serverLanguageRegistry, | ||
FileTypeRegistry fileTypeRegistry, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mixing format and changes makes review and merge harder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean here. And Githubs line based diff algorithm does not help at all.
final NotificationManager notificationManager, | ||
final EventBus eventBus) { | ||
protected void subscribeToInitializeEvent(final DtoUnmarshallerFactory unmarshallerFactory, final MessageBusProvider messageBusProvider, | ||
final NotificationManager notificationManager, final EventBus eventBus) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just format ?
Unmarshallable<LanguageServerInitializeEvent> unmarshaller = | ||
unmarshallerFactory.newWSUnmarshaller(LanguageServerInitializeEvent.class); | ||
Unmarshallable<LanguageServerInitializeEvent> unmarshaller = unmarshallerFactory | ||
.newWSUnmarshaller(LanguageServerInitializeEvent.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just format ?
initializeEvent.getServerCapabilities()); | ||
} | ||
|
||
@Override | ||
protected void onErrorReceived(Throwable exception) { | ||
notificationManager.notify(exception.getMessage(), | ||
StatusNotification.Status.FAIL, | ||
notificationManager.notify(exception.getMessage(), StatusNotification.Status.FAIL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just format ?
} | ||
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing space/tab not to be included
} | ||
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing space/tab not to be included
InitializeParams initializeParams = prepareInitializeParams(projectPath); | ||
|
||
LanguageServer server; | ||
try { | ||
server = launcher.launch(projectPath, languageClient); | ||
} catch (LanguageServerException e) { | ||
throw new LanguageServerException( | ||
"Can't initialize Language Server " + languageId + " on " + projectPath + ". " + e.getMessage(), e); | ||
"Can't initialize Language Server " + languageId + " on " + projectPath + ". " + e.getMessage(), e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just format ?
@@ -172,7 +162,7 @@ protected LanguageServer doInitialize(LanguageServerLauncher launcher, String pr | |||
protected void registerCallbacks(LanguageServer server) { | |||
|
|||
if (server instanceof ServerInitializerObserver) { | |||
addObserver((ServerInitializerObserver)server); | |||
addObserver((ServerInitializerObserver) server); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just format ?
I'll get back to this second half of this week. |
8d8b275
to
8392c8b
Compare
|
||
|
||
static { | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused block
"babelrc"}; | ||
private static final String MIME_TYPE = "application/json"; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra spaces
description.setMimeTypes(Arrays.asList(MIME_TYPES)); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra spaces
e17591e
to
4f54fff
Compare
|
||
GinMapBinder<String, WsAgentComponent> wsAgentComponentsBinder = | ||
GinMapBinder.newMapBinder(binder(), String.class, WsAgentComponent.class); | ||
wsAgentComponentsBinder.addBinding("Load Language Server file types.").to(LanguageServerFileTypeRegister.class); | ||
|
||
bind(PublishDiagnosticsReceiver.class).asEagerSingleton(); | ||
bind(ShowMessageJsonRpcReceiver.class).asEagerSingleton(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why you delete this bindings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a mistake. It also explains why notifications don't work in my current working branch. Good catch!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
4f54fff
to
33c3ff3
Compare
@@ -15,15 +15,29 @@ | |||
|
|||
import org.eclipse.che.inject.DynaModule; | |||
import org.eclipse.che.plugin.json.languageserver.JsonLanguageServerLauncher; | |||
|
|||
import static java.util.Arrays.asList; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the static import is not correctly sorted
HoverProvider hoverProvider, | ||
OccurrencesProvider occurrencesProvider) { | ||
OccurrencesProvider occurrencesProvider) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we have trailing spaces ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tsmaeder you have to be consistent, sometimes you add trailing spaces, sometimes not. Can you remove them ?
3840d30
to
74aa83d
Compare
|
||
/** | ||
* Register file type for a language description | ||
* @param type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add description around these type and description or remove the javadoc ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair enough.
/** | ||
* Get the language that is registered for this file. May return null if none is found. | ||
* @param file | ||
* @return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add description around file and what is returned or remove the javadoc ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup
Provider<ProjectManager> projectManagerProvider, ServerInitializer initializer) { | ||
this.languages.addAll(languages); | ||
this.launchers.putAll(languageServerLaunchers.stream() | ||
.collect(Collectors.toMap(LanguageServerLauncher::getLanguageId, launcher -> launcher))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if languages and launchers are initialized there, do we need to initialize the fields and use addAll/putAll after instead of just using the new directly there
this.languages = new ArrayList<>(languages);
vs
List list = new ArrayList<>() (when declaring field)
list.addAll(myElements) (in constructor)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, generally, I like to initialized fields that are not passed as init parameters in the field declaration; it makes sure the field has a usefule value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as it's final fields, we're sure that they're forced to be initialized
} | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return Optional.ofNullable(language.getFileExtensions()).map(Collection::stream).orElse(Stream.empty()).anyMatch(extension -> path.endsWith(extension)); ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, but I strongly disagree here: while your version has fewer characters, I find it enormously more difficult to read. When did we decide that if and for are "harmful" (with my apologies to the late Professor Goto)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be subjective but as JDK8 is out since a long time, I assume that ppl are fluent on using streams.
BTW if getFileExtensions would always return something (like empty) it could have been updated to only
return language.getFileExtensions().stream().anyMatch(extension -> path.endsWith(extension));
which is definitely better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apart from the difficulty enforcing the non-nullness, I disagree with the statement that the stream version is "better". It's shorter, I agree, but try putting a breakpoint into your version, for example.
} | ||
} | ||
} | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could java streams make it more readable/smaller ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above: smaller, maybe, but not more readable.
Signed-off-by: Thomas Mäder <tmader@redhat.com>
Signed-off-by: Thomas Mäder <tmader@redhat.com>
Signed-off-by: Thomas Mäder <tmader@redhat.com>
Signed-off-by: Thomas Mäder <tmader@redhat.com>
Signed-off-by: Thomas Mäder <tmader@redhat.com>
Signed-off-by: Thomas Mäder <tmader@redhat.com>
Signed-off-by: Thomas Mäder <tmader@redhat.com>
Signed-off-by: Thomas Mäder <tmader@redhat.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
} | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, but I strongly disagree here: while your version has fewer characters, I find it enormously more difficult to read. When did we decide that if and for are "harmful" (with my apologies to the late Professor Goto)?
} | ||
} | ||
} | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above: smaller, maybe, but not more readable.
fileTypeRegistry.registerFileType(fileType); | ||
editorRegistry.registerDefaultEditor(fileType, editorProvider); | ||
ext2langId.put(ext, lang.getLanguageId()); | ||
if (lang.getFileExtensions() != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we make getFileExtensions() always returning non-null list
We could avoid almost useless if (lang.getFileExtensions() != null)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds good, but it's not easily possible since LanguageDescription has a setter for the file extensions. So I can't really guarantee that it's not null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tsmaeder yes LanguageDescription has a setter.
But the setter could modify the internal list only if the given element is not null instead of setting the given value directly without any check.
for example in LanguageDescription we could have
constructor : initialize fileExtensions to an empty list
in the setter: update this internal list only if the provided list is not null. (we could also make it immutable list by copying the elements of the provided list to the internal list and not reusing the provided list but it's another topic. Getter returning a copy of the list as well)
we could also in getter, return Collections.emptyList if the internal list is null. (either change setter logic or getter logic)
so, even with a setter, getFileExtensions is always returning a not null list
List<String> mimeTypes = lang.getMimeTypes(); | ||
if (mimeTypes.isEmpty()) { | ||
mimeTypes = newArrayList("text/x-" + lang.getLanguageId()); | ||
if (lang.getFileNames() != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same remark here for getFileNames()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, I can't enforce non-null here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Signed-off-by: Thomas Mäder <tmader@redhat.com>
41cb53c
to
2a53bb0
Compare
Signed-off-by: Thomas Mäder <tmader@redhat.com>
*/ | ||
private List<String> fileExtensions; | ||
private List<String> fileExtensions= Collections.emptyList(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fileExtensions<space>=
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
ServerInitializer initializer) { | ||
public LanguageServerRegistryImpl(Set<LanguageServerLauncher> languageServerLaunchers, Set<LanguageDescription> languages, | ||
Provider<ProjectManager> projectManagerProvider, ServerInitializer initializer) { | ||
this.languages= new ArrayList<>(languages); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a missing space before the =
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for making my point about auto-formatting ;-)
ci-build |
Build # 2976 - FAILED Please check console output at https://ci.codenvycorp.com/job/che-pullrequests-build/2976/ to view the results. |
public void setFileExtensions(final List<String> fileExtensions) { | ||
this.fileExtensions = fileExtensions; | ||
this.fileExtensions = new ArrayList<>(fileExtensions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems per the test result that we should do the assignment only if fileExtensions is not null (or update the test to comply with javadoc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test is bogus.
Signed-off-by: Thomas Mäder <tmader@redhat.com>
ci-build |
Build success. https://ci.codenvycorp.com/job/che-pullrequests-build/2981/ |
…ions eclipse-che#5107 (eclipse-che#5156) * Register languages by file name Signed-off-by: Thomas Mäder <tmader@redhat.com>
What does this PR do?
This PR allows language server plugins to register language servers for specific file names (for example pom.xml). Until now, it is only possible to register for filename extension (like *.xml).
The PR introduces two major changes:
What issues does this PR fix or reference?
fixes #5107
Changelog
Ability to register language servers for file names instead of extensions
Release Notes
Language Server Support: Add ability to register language servers for file names instead of extensions
Docs PR
eclipse-che/che-docs#230