-
Notifications
You must be signed in to change notification settings - Fork 1
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
Embed language server instead of starting new JVM #6
Conversation
…irst place, so no licensing worries)
…ally amateurish, but that's how I managed with it so far.
…that doesn't start a separate OS process (a separate JVM), but runs the language server embedded. This in itself was simple. But, because of this, I had to pull in the org.freemarker:freemarker-languageserver dependency somehow (without including binaries in the source code). So I made an OSGi über-bundle over there, then made Tycho pull it in from the standard Maven (m2) repo mechanism. I'm not sure what's the best way of pulling in that dependency is, maybe not this... but for now I just wanted to try if an embedded language server works quickly.
@ddekany I love your idea with LocalStreamConnectionProvider (if it works well you could create a gerrit patch to lsp4e) but the part with target/target-platform-pde.target seems a little complex. I tell me that if /freemarker-languageserver-cli, freemarker-languageserver-core will contains a META-INF/MANISFEST.MF it could work, no? |
BTW, if this comes to Apache (not sure if you want that), then |
@ddekany after thinking about using LocalStreamConnectionProvider, I'm not sure it's a good idea. The LocalStreamConnectionProvider fixes the problem with JVM but we must keep in mind that Freemarker Language Server must work on VSCode too. More with LocalStreamConnectionProvider you are linked to a freemarker version. With a cli, you can set in the classpath the freemarker jar that you wish to use. It means that with the cli solution you could use the freemarker.jar from the user Eclipse Project and have validation with the well version of FreeMarker.
I tell me if it's really interesting to have several JARs for that. Having a jar (cli) with just a simple main class is shame I find. IMHO I think it should better to have one JAR with different package.
I think the 3 projects freemarker-languageserver* must be an OSGi bundle (just contains a MANIFEST.MF). If we have one project, I think it should be enough.
I'm aware with anything if it will motivate other people to work on Freemarker Language Server. Today the main work is in the Freemarker Language Server.
I have not done that for the moment because I would like to VSCode consume it dcortes92/vs-freemarker#15 @ddekany here my proposition. I think we should not consume our time to organize projects but consume our time with angelozerr/freemarker-languageserver#1 Our PR brings advantage like fix problem with java version, could consume JDT in the language server, but loose features like using custom freemarker.jar. We will have too some work with your PR to fix the update site. In otherwise, my idea is to keep the lsp4e-freemarker like today and will see in the future if we need this split and using the freemarker language server in the same JVM. Are you OK with that? The angelozerr/freemarker-languageserver#1 is the most important issue I think. Hope you will understand what I mean and you will keep motivation to help me. |
That's why
If that's a problem, then the earlier
It's not relevant to our current problems as far as I see (ie., how is it best to make the language server a dependency of the lsp4e-freemarker). And
So, I believe that doesn't help us. We already have an OSGi bundle (
As far as I see, that works fine even if you have a single Git repo that generates a dozen of artifacts. Because all they you need (I guess...) is an artifact from the CLI module that's an über jar as well. BTW, I suspect that uniting
I think that will be a key misunderstanding here. Some of us don't understand what's the other is saying. Because as far as I see, the old solution is as bad as the new one when it comes to using a custom
Here again, I believe there's no difference between the old and the new solution in this. True, in the old solution you include a binary copy of the
So, not really, because I think there are misunderstandings regarding the pros/cons of the two solutions.
I have explained my standpoint over there. You see, I want to avoid bringing the old plugin to the ASF (also maintaining it in my personal fork indefinitely). Instead, I want to bring yours there. Now, the old pluging has stopped at the first error as well (furthermore, I have used it like that for ages, and while it's lame, it wasn't a significant problem in practice, because it's not Java, and an error is just typo that you can fix immediately). I only need the new plugin to be able to do what the old one did (no exactly of course, but roughly), ASAP, and without it not working for a lot of users because of dependency issues and other environment differences (the old plugin seems to be quite resilient in this regard). That's the top priority from my point of view. But, everyone works on what he is interested in, so, if you want #1, go ahead of course, it's still very useful. |
At first let's me explain how I would like to manage this freemarker.jar even if it's not possible with lsp4e for the moment. My idea is to consume the freemarker.jar from the project and otherwise consume a default freemarker.jar. To do that we could have lsp4e-freemarker which contains 2 JARs:
When we start the server/freemarker language server we will set the classpath with the 2 JARs. Now when a project has a freemarker.jar we start the freeamrker server by setting sclasspath with server/freemarker language and $rproject/lib/freemarker.jar With LocalStreamConnectionProvider, I'm afraid that is not possible.
I have already done that:
It's a long work and IMHO I think we should consume our time to support completion outline, hyperlink with language server once angelozerr/freemarker-languageserver#1 will be fixed.
Yes sure. My idea is to build this jar with maven and copy it when plugin must be built. If we have a JAR we can create server/freemarker language server.jar without a given freemarker.jar. So after we can choose easily the version of Freemarker to use. With LocalStreamConnectionProvider you will be linked to a freemarker.jar version (you wil lnot have the capibility to choose a freemarker.jar to use it)
Without a FM tolerant parser we cannot manage other features like mark occurences, completion, outline, etc. IMHO it's a very important, no? |
a266b41
to
24fe3af
Compare
Aha, I see. That's a new challenge, and an interesting extra. Though at least before a certain FreeMarker 2 version doing this will be certainly fragile, as you keep adding features to
I don't see problems there (yet?). If you want to re-load a jar (or a system of 2 dependent jar-s in this case), you need a new
Well, the solution I have used seems to work OK as far bridging the p2 and m2 world together goes, even if it also adds some complexity to the build. Though this jar magic now gives a twist to the story, like we don't have an OSGi bundle dependency after all. Anyway, let me repeat my earlier question. If just put these into the same repo and common parent... wouldn't that simplify life? Then the
Yes, but it's just that until there's a syntax error, those features are off. Where that's truly a problem is auto-completion, because when you need it, your template is usually incomplete, and hence certainly very often has a syntax error. So the "FreeMarker IDE" plugin did not need the AST for auto-completion, and you know the core directives and built-ins without that, which is mostly why people want to auto-completion. You just look back at the text, and guess what it is (we are after a |
Glad it pleases you.
Yes sure. It will certainly not work with old version of FreeMarker, but for current version of FreeMarker I think it's a feature which is very important. It's an another topic, but I think freemarker.jar should embed the language server. TypeScript works like this for instance, when you install it, it provides a tsserver.js (TypeScript server) that IDE can consume it. So your sure that your language server and version of your language are synchronyzed.
In theory yes, but we are in OSGi context here. If I understand your idea you want to update the ClassLoader of the OSGi container to use the well freemarker.jar. I think it's an hard work and what about having several version of freemarker (for each project). IMHO I think it's a more simply to update the java command line like this:
And that's all!
I would like just to import projects and not build a P2.
It will simplify, indeed. But I have done that because I hope VSCode, IJ, etc will consume it. I would like to keep that. For dev, you should just import in your workspace the freemarker-languageserver projects without creating a P2. We could even add a git submodule to the project freemarker-languageserver. @pascalleclercq could perhaps help us to build those freemarker-languageserver project and consume it in the update site. But before that I would like just clarify the structure of the project which must be simply I think. I'm really sorry, but today I don't see the benfit to have 3 bundles. It's more clean sure, but more complex for the build (create an uber Jar etc). What is the problem if we have just one OSGi bundle (we could be a maven project too):
IMHO, I think Freemarker Language Server must be hosted in a another project because VSCode, IJ which could contribute doesn't want to have Eclipse code.
"FreeMarker IDE" create a custom AST (see org.jboss.ide.eclipse.freemarker.model.ItemSet) which is consumed to manage completion, outline, etc. So we need an AST and the question is how to create a tolerant AST (like ItemSet):
I have experimented this feature with interpolation which is not closed by hacking FMParser like this: /**
* A production representing the ${...}
* that outputs a variable.
*/
final public DollarVariable StringOutput() throws ParseException {Expression exp;
Token begin, end = null;
begin = jj_consume_token(DOLLAR_INTERPOLATION_OPENING);
exp = Expression();
notHashLiteral(exp, NonStringException.STRING_COERCABLE_TYPES_DESC);
notListLiteral(exp, NonStringException.STRING_COERCABLE_TYPES_DESC);
if (!tolerant) {
end = jj_consume_token(CLOSING_CURLY_BRACKET);
} else {
try {
end = jj_consume_token(CLOSING_CURLY_BRACKET);
} catch (Exception e) {
// Here "}" cannot be found
// The end token is the token which has thrown the error
Token next = token.next;
end = token;
end.next = null;
// marke this end token as end interpolation
token_source.endInterpolation(end);
if (next != null) {
// move the character where token has throw an error
token_source.input_stream.backup(next.endColumn - end.endColumn);
}
}
}
...
} As you can see it's a lot of work to manage a full tolerant parser. It seems that it is not in your priority so I think more and more to develop my custom tolerant parser (like Freemarker IDE does too). So in this case the custom use of freemarker.jar will be less important (just for validation). |
The language server has a lot of dependencies, so we really can't do that with a small library like FreeMarker. Besides, monoliths are considered ugly in the Java world since Maven has become wide spread (while it still has no feature to keep the versions of the related modules in sync... oh well). We have received several complains that
No, I don't care about the OSGi context here. I just plan to load the jars on the most basic way, similarly to as
My main motivation was exactly that I don't expect launching a proper JVM becoming problem free (for all random users), or at least that we don't spend much more time in the future with hacking/maintaining that code even more. I should have come up with this local server POC much earlier, before you have invested into that earlier issue of mine... but don't let it becoming a lost investment fallacy. Loading and re-loading jar-s dynamically is a quite common thing on the JVM, so I guess if once I get it right (which is hopefully simple), it will keep working everywhere. BTW, I still don't know what the problem was in my case, and thus if it won't resurface with an Eclipse-provided Java version too, for someone. Also, the current version needs more investment to find the properly high Java version. I'm not sure what Anyway, the bottom line: If I implement this with
Oh, I do know... I have fixed the FreeMarker IDE parser a few years ago, rewriting quite much of it along the way (but I still kept most of the confusing nomenclature used there, so that it's easier to get the PR accepted by JBoss... maybe I shouldn't have). Plus FM2 syntax is hard to parse properly. It's really a 15 year old monstrosity (not to point a fingers at anyone... :) ), only humans don't care or notice it much. But when you load bigger templates, sometimes your parser will be derailed somewhere, where the real parser has no problem. Anyway, what to do with that... Have you tried the approach shown in Issue #1? Could the real parser be auto-generated from the tolerant one? Because what we should avoid is maintaining two FM2 parsers. If not, then it has to be done on the hard way, and we better get that rights for the FreeMarker IDE source code. |
Ok thanks for the clarification. But I think Freemarker Language Server (without dependencies of lsp4j will be little).
Yes sure, but never played with that in Eclipse word. To study...
Ok let me see how to create a clean FreeMarker Language server (to avoid using P2). I will merge all bundle in one for the moment and we will discuss after about splitting.
Yes, there is just one FTL.jjs which have condition with "tolerant", but I'm a little discouraged with that and I think more and more developping my own parser.
I will prefer developping my own parser which will work directly with lsp4j structure and will not use Eclipse structure like IRegion, etc |
But without the dependencies it doesn't work. So how would it look?
Note that splitting is still orthogonal to the dependency problem. Simply you copy the über jar of BTW my main motivation for the splitting was logging (next to clarity). Not sure how that will work out with or without it, but generally if your environment-specific launcher is separate, it's easier. (It's like when you develop a some web service, and then there's a separate module that packs it into a war, and another that packs it into a Spring Boot application.) |
@ddekany could you please create a new PR with only LocalStreamConnectionProvider Thanks! |
OK, I will do a such PR today. |
Thanks @ddekany ! @mickaelistria I think the class |
Sure!
…--
Mickael Istria
Eclipse IDE <https://www.eclipse.org/downloads/eclipse-packages/>
developer, at Red Hat Developers <https://developers.redhat.com/> community
Elected Committer Representative at the Eclipse Foundation
<https://www.eclipse.org/org/> board of directors
|
So I assume I should create a new PR that builds on the |
@mickaelistria Please see the one in #7 instead. Also note that I have no idea what I'm doing (not an Eclipse plugin developer)... like if |
Only look at the last commit. The ones before it belong to the earlier PR (random small things).
This way we can avoid the mess which is starting a new JVM... Also it's more logical IMO.
The hard part was really to pull in the dependency, as I'm new to Tycho... but see commit message. I guess the CI will fail, as now it needs to see the Maven artifacts from the freemarker-languageserver. That's something I can't solve of course.