Is it possible to add completion items to a Microsoft Language Server in runtime? - intellij-plugin

I am trying to develop a IntelliJ plugin which provides a Language Server with help of lsp4intellij by ballerina.
Thing is, i've got a special condition: The list of completion items should be editable in runtime.
But I've not found any way to communicate new completionItems to the LanguageServer process once its running.
My current idea is to add an action to the plugin which builds a new jar and then restarts the server with the new jar, using the Java Compiler API.
The problem with that is, i need to get the source code from the plugin project including the gradle dependencies accessable from the running plugin... any ideas?

If your requirement is to modify the completion items (coming from the language server) before displaying them in the IntelliJ UI, you can do that by implementing the LSP4IntelliJ's
LSPExtensionManager in your plugin.
Currently, we do not have proper documentation for the LSP4IntelliJ's extension points but you can refer to our Ballerina IntelliJ plugin as a reference implementation, where it has implemented Ballerina LSP Extension manager to override/modify completion items at the client runtime in here.

For those who might stumble upon this - it is indeed possible to change the amount of CompletionItems the LanguageServer can provide during runtime.
I simply edited the TextDocumentService.java (the library I used is LSP4J).
It works like this:
The main function of the LanguageServer needs to be started with an additional argument, which is the path to the config file in which you define the CompletionItems.
Being called from LSP4IntelliJ it would look like this:
String[] command = new String[]{"java", "-jar",
"path\\to\\LangServer.jar", "path\\to\\config.json"};
IntellijLanguageClient.addServerDefinition(new RawCommandServerDefinition("md,java", command));
The path String will then be passed through to the Constructor of your CustomTextDocumentServer.java, which will parse the config.json in a new Timer thread.
An Example:
public class CustomTextDocumentService implements TextDocumentService {
private List<CompletionItem> providedItems;
private String pathToConfig;
public CustomTextDocumentService(String pathToConfig) {
this.pathToConfig = pathToConfig;
Timer timer = new Timer();
timer.schedule(new ReloadCompletionItemsTask(), 0, 10000);
loadCompletionItems();
}
#Override
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams completionParams) {
return CompletableFuture.supplyAsync(() -> {
List<CompletionItem> completionItems;
completionItems = this.providedItems;
// Return the list of completion items.
return Either.forLeft(completionItems);
});
}
#Override
public void didOpen(DidOpenTextDocumentParams didOpenTextDocumentParams) {
}
#Override
public void didChange(DidChangeTextDocumentParams didChangeTextDocumentParams) {
}
#Override
public void didClose(DidCloseTextDocumentParams didCloseTextDocumentParams) {
}
#Override
public void didSave(DidSaveTextDocumentParams didSaveTextDocumentParams) {
}
private void loadCompletionItems() {
providedItems = new ArrayList<>();
CustomParser = new CustomParser(pathToConfig);
ArrayList<String> variables = customParser.getTheParsedItems();
for(String variable : variables) {
String itemTxt = "$" + variable + "$";
CompletionItem completionItem = new CompletionItem();
completionItem.setInsertText(itemTxt);
completionItem.setLabel(itemTxt);
completionItem.setKind(CompletionItemKind.Snippet);
completionItem.setDetail("CompletionItem");
providedItems.add(completionItem);
}
}
class ReloadCompletionItemsTask extends TimerTask {
#Override
public void run() {
loadCompletionItems();
}
}
}

Related

Flurry push - issue with Kotlin

I am not finding an easy way to integrate Flurry push with Kotlin.
I added the first parts of the auto installation. and I get red lines under key parts of the script.
Mainly .withFlurryMessagingListener(flurryMessagingListener)
seems it can't find flurryMessagingListener
val flurryMessagingOptions = FlurryMarketingOptions.Builder()
.setupMessagingWithAutoIntegration()
.withDefaultNotificationChannelId()
.withDefaultNotificationIconResourceId(R.drawable.ic_dialog_alert)
.withDefaultNotificationIconAccentColor()
.withFlurryMessagingListener(flurryMessagingListener)
.build()
The other issue is I don't want to put an .withDefaultNotificationChannelId(). According to the how to on their website - which seem out of date. I don't need to yet it tells me I have too.
Question why could this not be as easy as iOS version - that was a lot easier to install. But if anyone has a how to install with Kotlin - since Flurry support has not gotten back to me I would be grateful.
You need to define your listener. E.g.,
import com.flurry.android.marketing.messaging.FlurryMessagingListener;
FlurryMessagingListener flurryMessagingListener = new FlurryMessagingListener() {
#Override
public boolean onNotificationReceived(FlurryMessage flurryMessage) {
return false;
}
#Override
public boolean onNotificationClicked(FlurryMessage flurryMessage) {
return false;
}
#Override
public void onNotificationCancelled(FlurryMessage flurryMessage) {
}
#Override
public void onTokenRefresh(String s) {
}
#Override
public void onNonFlurryNotificationReceived(Object o) {
}
};
And No, it's not required to define your own channel ID (by withDefaultNotificationChannelId). Flurry SDK will apply the default if no explicitly defined.

Adding a DeclarativeComponent in a UIComponent at runtime. Oracle JDeveloper 12c

I've been working in this project for abou a week and haven't find a solution to my problem.
For testing purposes I create a simple new DeclarativeComponent which is a panelGroupLayout that contains 2 OutputText. After that I deploy the jar file and add it to my other Fusion web application libraries.
I want to add this DeclarativeComponent in another UIComponent at runtime by pressing a button which contains the next code in the javabean:
`public void addComponent(ActionEvent actionEvent)
{
// Add event code here...
createOutputComponent();
}
private void createOutputComponent()
{
CuadroDeTextoComponent ui = new CuadroDeTextoComponent(); //This is my Declarative Component
UIComponent parentUIComponent = getPglComponente(); This is the panelGrouopLayout in which i want to add my declarativeComponent
addComponent(parentUIComponent, ui);
}
public void addComponent(UIComponent parentUIComponent, UIXDeclarativeComponent childUIComponent)
{
parentUIComponent.getChildren().add(childUIComponent);
AdfFacesContext.getCurrentInstance().addPartialTarget(parentUIComponent);
}`
I have tried draging the declarative component and it works, but when I do it dynamically the component doesn't display
For your component to display you may need to add a PPR refresh to it's parent element :
In your case :
public void addComponent(ActionEvent actionEvent)
{
// Add event code here...
createOutputComponent();
}
private void createOutputComponent()
{
CuadroDeTextoComponent ui = new CuadroDeTextoComponent(); //This is my Declarative Component
UIComponent parentUIComponent = getPglComponente(); This is the panelGrouopLayout in which i want to add my declarativeComponent
addComponent(parentUIComponent, ui);
addPPR(parentUIComponent); //Refresh the parent component
}
public void addComponent(UIComponent parentUIComponent, UIXDeclarativeComponent childUIComponent)
{
parentUIComponent.getChildren().add(childUIComponent);
AdfFacesContext.getCurrentInstance().addPartialTarget(parentUIComponent);
}
public static void addPPR(UIComponent component) {
if (component != null) {
AdfFacesContext.getCurrentInstance().addPartialTarget(component.getParent());
}
}

Toggling App.Config settings at runtime C#

I am wondering what the best approach to toggling App.Config settings for C# would be. This is involving our test suite, and we would like the option to either choose a remote or local environment to kick the tests off. We use LeanFT and NUnit as our testing framework, and currently in order to get tests to run remote we have to add an <leanft></leanft> config in the App.config file. How can I specify different configurations at run time when I kick these tests off thru the command line? Thanks!
Any leanft configuration can be modified at runtime, by using the SDK namespace or the Report namespace.
Here's an example using NUnit 3 showing how you can achieve this
using NUnit.Framework;
using HP.LFT.SDK;
using HP.LFT.Report;
using System;
namespace LeanFtTestProject
{
[TestFixture]
public class LeanFtTest
{
[OneTimeSetUp]
public void TestFixtureSetUp()
{
// Initialize the SDK
SDK.Init(new SdkConfiguration()
{
AutoLaunch = true,
ConnectTimeoutSeconds = 20,
Mode = SDKMode.Replay,
ResponseTimeoutSeconds = 20,
ServerAddress = new Uri("ws://127.0.0.1:5095") // local or remote, decide at runtime
});
// Initialize the Reporter (if you want to use it, ofc)
Reporter.Init(new ReportConfiguration()
{
Title = "The Report title",
Description = "The report description",
ReportFolder = "RunResults",
IsOverrideExisting = true,
TargetDirectory = "", // which means the current parent directory
ReportLevel = ReportLevel.All,
SnapshotsLevel = CaptureLevel.All
});
}
[SetUp]
public void SetUp()
{
// Before each test
}
[Test]
public void Test()
{
Reporter.ReportEvent("Doing something", "Description");
}
[TearDown]
public void TearDown()
{
// Clean up after each test
}
[OneTimeTearDown]
public void TestFixtureTearDown()
{
// If you used the reporter, invoke this at the end of the tests
Reporter.GenerateReport();
// And perform this cleanup as the last leanft step
SDK.Cleanup();
}
}
}

Gradle : how to use BuildConfig in an android-library with a flag that gets set in an app

My (gradle 1.10 and gradle plugin 0.8)-based android project consists of a big android-library that is a dependency for 3 different android-apps
In my library, I would love to be able to use a structure like this
if (BuildConfig.SOME_FLAG) {
callToBigLibraries()
}
as proguard would be able to reduce the size of the produced apk, based on the final value of SOME_FLAG
But I can't figure how to do it with gradle as :
* the BuildConfig produced by the library doesn't have the same package name than the app
* I have to import the BuildConfig with the library package in the library
* The apk of an apps includes the BuildConfig with the package of the app but not the one with the package of the library.
I tried without success to play with BuildTypes and stuff like
release {
// packageNameSuffix "library"
buildConfigField "boolean", "SOME_FLAG", "true"
}
debug {
//packageNameSuffix "library"
buildConfigField "boolean", "SOME_FLAG", "true"
}
What is the right way to builds a shared BuildConfig for my library and my apps whose flags will be overridden at build in the apps?
As a workaround, you can use this method, which uses reflection to get the field value from the app (not the library):
/**
* Gets a field from the project's BuildConfig. This is useful when, for example, flavors
* are used at the project level to set custom fields.
* #param context Used to find the correct file
* #param fieldName The name of the field-to-access
* #return The value of the field, or {#code null} if the field is not found.
*/
public static Object getBuildConfigValue(Context context, String fieldName) {
try {
Class<?> clazz = Class.forName(context.getPackageName() + ".BuildConfig");
Field field = clazz.getField(fieldName);
return field.get(null);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
To get the DEBUG field, for example, just call this from your Activity:
boolean debug = (Boolean) getBuildConfigValue(this, "DEBUG");
I have also shared this solution on the AOSP Issue Tracker.
Update: With newer versions of the Android Gradle plugin publishNonDefault is deprecated and has no effect anymore. All variants are now published.
The following solution/workaround works for me. It was posted by some guy in the google issue tracker:
Try setting publishNonDefault to true in the library project:
android {
...
publishNonDefault true
...
}
And add the following dependencies to the app project that is using the library:
dependencies {
releaseCompile project(path: ':library', configuration: 'release')
debugCompile project(path: ':library', configuration: 'debug')
}
This way, the project that uses the library includes the correct build type of the library.
You can't do what you want, because BuildConfig.SOME_FLAG isn't going to get propagated properly to your library; build types themselves aren't propagated to libraries -- they're always built as RELEASE. This is bug https://code.google.com/p/android/issues/detail?id=52962
To work around it: if you have control over all of the library modules, you could make sure that all the code touched by callToBigLibraries() is in classes and packages that you can cleave off cleanly with ProGuard, then use reflection so that you can access them if they exist and degrade gracefully if they don't. You're essentially doing the same thing, but you're making the check at runtime instead of compile time, and it's a little harder.
Let me know if you're having trouble figuring out how to do this; I could provide a sample if you need it.
I use a static BuildConfigHelper class in both the app and the library, so that I can have the packages BuildConfig set as final static variables in my library.
In the application, place a class like this:
package com.yourbase;
import com.your.application.BuildConfig;
public final class BuildConfigHelper {
public static final boolean DEBUG = BuildConfig.DEBUG;
public static final String APPLICATION_ID = BuildConfig.APPLICATION_ID;
public static final String BUILD_TYPE = BuildConfig.BUILD_TYPE;
public static final String FLAVOR = BuildConfig.FLAVOR;
public static final int VERSION_CODE = BuildConfig.VERSION_CODE;
public static final String VERSION_NAME = BuildConfig.VERSION_NAME;
}
And in the library:
package com.your.library;
import android.support.annotation.Nullable;
import java.lang.reflect.Field;
public class BuildConfigHelper {
private static final String BUILD_CONFIG = "com.yourbase.BuildConfigHelper";
public static final boolean DEBUG = getDebug();
public static final String APPLICATION_ID = (String) getBuildConfigValue("APPLICATION_ID");
public static final String BUILD_TYPE = (String) getBuildConfigValue("BUILD_TYPE");
public static final String FLAVOR = (String) getBuildConfigValue("FLAVOR");
public static final int VERSION_CODE = getVersionCode();
public static final String VERSION_NAME = (String) getBuildConfigValue("VERSION_NAME");
private static boolean getDebug() {
Object o = getBuildConfigValue("DEBUG");
if (o != null && o instanceof Boolean) {
return (Boolean) o;
} else {
return false;
}
}
private static int getVersionCode() {
Object o = getBuildConfigValue("VERSION_CODE");
if (o != null && o instanceof Integer) {
return (Integer) o;
} else {
return Integer.MIN_VALUE;
}
}
#Nullable
private static Object getBuildConfigValue(String fieldName) {
try {
Class c = Class.forName(BUILD_CONFIG);
Field f = c.getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Then, anywhere in your library where you want to check BuildConfig.DEBUG, you can check BuildConfigHelper.DEBUG and access it from anywhere without a context, and the same for the other properties. I did it this way so that the library will work with all my applications, without needing to pass a context in or set the package name some other way, and the application class only needs the import line changed to suit when adding it into a new application
Edit: I'd just like to reiterate, that this is the easiest (and only one listed here) way to get the values to be assigned to final static variables in the library from all of your applications without needing a context or hard coding the package name somewhere, which is almost as good as having the values in the default library BuildConfig anyway, for the minimal upkeep of changing that import line in each application.
For the case where the applicationId is not the same as the package (i.e. multiple applicationIds per project) AND you want to access from a library project:
Use Gradle to store the base package in resources.
In main/AndroidManifest.xml:
android {
applicationId "com.company.myappbase"
// note: using ${applicationId} here will be exactly as above
// and so NOT necessarily the applicationId of the generated APK
resValue "string", "build_config_package", "${applicationId}"
}
In Java:
public static boolean getDebug(Context context) {
Object obj = getBuildConfigValue("DEBUG", context);
if (obj instanceof Boolean) {
return (Boolean) o;
} else {
return false;
}
}
private static Object getBuildConfigValue(String fieldName, Context context) {
int resId = context.getResources().getIdentifier("build_config_package", "string", context.getPackageName());
// try/catch blah blah
Class<?> clazz = Class.forName(context.getString(resId) + ".BuildConfig");
Field field = clazz.getField(fieldName);
return field.get(null);
}
use both
my build.gradle
// ...
productFlavors {
internal {
// applicationId "com.elevensein.sein.internal"
applicationIdSuffix ".internal"
resValue "string", "build_config_package", "com.elevensein.sein"
}
production {
applicationId "com.elevensein.sein"
}
}
I want to call like below
Boolean isDebug = (Boolean) BuildConfigUtils.getBuildConfigValue(context, "DEBUG");
BuildConfigUtils.java
public class BuildConfigUtils
{
public static Object getBuildConfigValue (Context context, String fieldName)
{
Class<?> buildConfigClass = resolveBuildConfigClass(context);
return getStaticFieldValue(buildConfigClass, fieldName);
}
public static Class<?> resolveBuildConfigClass (Context context)
{
int resId = context.getResources().getIdentifier("build_config_package",
"string",
context.getPackageName());
if (resId != 0)
{
// defined in build.gradle
return loadClass(context.getString(resId) + ".BuildConfig");
}
// not defined in build.gradle
// try packageName + ".BuildConfig"
return loadClass(context.getPackageName() + ".BuildConfig");
}
private static Class<?> loadClass (String className)
{
Log.i("BuildConfigUtils", "try class load : " + className);
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private static Object getStaticFieldValue (Class<?> clazz, String fieldName)
{
try { return clazz.getField(fieldName).get(null); }
catch (NoSuchFieldException e) { e.printStackTrace(); }
catch (IllegalAccessException e) { e.printStackTrace(); }
return null;
}
}
For me this is the ONLY ONE AND ACCEPTABLE* SOLUTION TO determine the ANDROID APPLICATION BuildConfig.class:
// base entry point
// abstract application
// which defines the method to obtain the desired class
// the definition of the application is contained in the library
// that wants to access the method or in a superior library package
public abstract class BasApp extends android.app.Application {
/*
* GET BUILD CONFIG CLASS
*/
protected Class<?> getAppBuildConfigClass();
// HELPER METHOD TO CAST CONTEXT TO BASE APP
public static BaseApp getAs(android.content.Context context) {
BaseApp as = getAs(context, BaseApp.class);
return as;
}
// HELPER METHOD TO CAST CONTEXT TO SPECIFIC BASEpp INHERITED CLASS TYPE
public static <I extends BaseApp> I getAs(android.content.Context context, Class<I> forCLass) {
android.content.Context applicationContext = context != null ?context.getApplicationContext() : null;
return applicationContext != null && forCLass != null && forCLass.isAssignableFrom(applicationContext.getClass())
? (I) applicationContext
: null;
}
// STATIC HELPER TO GET BUILD CONFIG CLASS
public static Class<?> getAppBuildConfigClass(android.content.Context context) {
BaseApp as = getAs(context);
Class buildConfigClass = as != null
? as.getAppBuildConfigClass()
: null;
return buildConfigClass;
}
}
// FINAL APP WITH IMPLEMENTATION
// POINTING TO DESIRED CLASS
public class MyApp extends BaseApp {
#Override
protected Class<?> getAppBuildConfigClass() {
return somefinal.app.package.BuildConfig.class;
}
}
USAGE IN LIBRARY:
Class<?> buildConfigClass = BaseApp.getAppBuildConfigClass(Context);
if(buildConfigClass !- null) {
// do your job
}
*there are couple of things need to be watched out:
getApplicationContext() - could return a context which is not an App ContexWrapper implementation - see what Applicatio class extends & get to know of the possibilities of context wrapping
the class returned by final app could be loaded by different class loaders than those who will use it - depends of loader implementation and some principals typical (chierarchy, visibility) for loaders
everything depends on the implemmentation of as in this case simple DELEGATION!!! - the solution could be more sophisticetaded - i wanted only to show here the usage of DELEGATION pattern :)
** why i downwoted all of reflection based patterns because they all have weak points and they all in some certain conditions will fail:
Class.forName(className); - because of not speciified loader
context.getPackageName() + ".BuildConfig"
a) context.getPackageName() - "by default - else see b)" returns not package defined in manifest but application id (somtimes they both are the same), see how the manifest package property is used and its flow - at the end apt tool will replace it with applicaton id (see ComponentName class for example what the pkg stands for there)
b) context.getPackageName() - will return what the implementaio wants to :P
*** what to change in my solution to make it more flawless
replace class with its name that will drop the problems wchich could appear when many classes loaded with different loaders accessing / or are used to obtain a final result involving class (get to know what describes the equality between two classes (for a compiler at runtime) - in short a class equality defines not a self class but a pair which is constituted by the loader and the class. (some home work - try load a inner class with different loader and access it by outer class loaded with different loader) - it would turns out that we will get illegal access error :) even the inner class is in the same package has all modificators allowing access to it outer class :) compiler/linker "VM" treats them as two not related classes...

Global object onStart fails all my tests

I had a number of tests, it ran perfectly, untill I write Global object:
#Override
public void onStart(Application app) {
Mails.plugin = app.plugin(MailerPlugin.class).email();
Mails.from = app.configuration().getString("smtp.from");
if (Mails.plugin != null) Logger.info("Mailer plugin successfully loaded");
if (Mails.from != null) Logger.info("Mail account is " + Mails.from);
}
Here I am loading plugin for email messages. Now when I try to run my fakeApplication with inMemoryDatabase I get a null pointer exception. Probably it is becouse fakeApplication don't use configuration file, and can't load configuration from this file. Please help me to sort out this problem.
Try adding custom config parameters in your FakeApplication:
Map<String, Object> additionalConfiguration = new HashMap<String, Object>();
additionalConfiguration.put("smtp.from", "foo#bar.com");
running(fakeApplication(additionalConfiguration), new Runnable() {
...
I find the solution , for this reason I create fake Global class (or you also can mock it):
class Global extends GlobalSettings{
}
and Then can pass it:
#BeforeClass
public static void startApp() {
app = Helpers.fakeApplication(new Global());
Helpers.start(app);
}