Why cannot I get PsiClass from Kotlin but successful in Java - intellij-plugin

I try to get PsiClass from Kotlin file (the PsiFile instance is KtFile), but aways get null, In Java case is successful.
PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
Editor editor = e.getData(CommonDataKeys.EDITOR);
// null in kotlin
PsiClass psiClass = getPsiClass(editor, psiFile);
.....
private PsiClass getPsiClass(Editor editor, PsiFile file) {
int offset = editor.getCaretModel().getOffset();
PsiElement element = file.findElementAt(offset);
if (element == null)
element = file.findElementAt(offset - 1);
if (element == null) {
return null;
} else {
PsiClass target = (PsiClass) PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (target == null) {
element = file.findElementAt(offset - 1);
if (element == null)
return null;
target = (PsiClass) PsiTreeUtil.getParentOfType(element, PsiClass.class);
}
return target instanceof SyntheticElement ? null : target;
}
}

PsiClass is used only for java classes. For Kotlin you should use KtClass.

Related

Setting local variables inside a function for unit testing kotlin

I'm trying to testing a function in android.For the function to be tested ,have to set local variable inside the function. Heres the code:
fun needToBeTested(serviceContext: Context):Int
{
val manager = serviceContext.getSystemService(Context.USB_SERVICE) as UsbManager
val deviceList = manager.deviceList
if(deviceList.size != 0){
val deviceIterator = deviceList.values.iterator()
while (deviceIterator.hasNext()) {
val device = deviceIterator.next()
if ((device != null)&&(device.deviceClass == 255)) { // USB_CLASS_VENDOR_SPEC - HUB
val permitToRead:Boolean = manager.hasPermission(device)
if(permitToRead){
setUpConnection(device,serviceContext)
} else{
manager.requestPermission(device, permissionIntent)
}
deviceConnectionStatus = 1
} else if((device != null) &&(device.deviceClass == 0)){ // USB_CLASS_PER_INTERFACE - USB STICK
}
}
} else (deviceList.size == 0){
connectionStatus = 0
}
}
Test class
class Test {
val mockContext = ApplicationProvider.getApplicationContext<Context>()
#Test
fun needTobeTested_returnOne(){
asserThat(sample.needToBeTested(mockContext)==1) //successcase
}
}
For testing this class,need to set the value of deviceList.Is there any way to set the value of 'x' from the test class for testing this function. Im new to android and testing.Any help would be really helpful.

Is there any method in ByteBuddy to convert a TypeDescription.Generic into an appropriate java.lang.reflect.Type?

(The surface area of the ByteBuddy API is overwhelmingly enormous, which is why I'm asking the question.)
I'm aware that I can take a TypeDescription.Generic and determine its "sort" and proceed rather laboriously "by hand" from there, but often times I've found there is a method buried somewhere that will do this sort of tedious work for me.
EDIT: a commenter asked for the "tedious" recipe. Here it is (stand back; please note the various implementations of various Types are more or less what you'd expect them to be):
public static final Type toType(final TypeDefinition type) throws ReflectiveOperationException {
final Type returnValue;
if (type == null) {
returnValue = null;
} else {
final TypeDescription.Generic genericType = type.asGenericType();
switch (type.getSort()) {
case GENERIC_ARRAY:
returnValue = new DefaultGenericArrayType(toType(type.getComponentType()));
break;
case NON_GENERIC:
returnValue = Class.forName(type.getTypeName(), false, Thread.currentThread().getContextClassLoader());
break;
case PARAMETERIZED:
final TypeDefinition ownerType = genericType.getOwnerType();
final TypeDefinition rawType = type.asErasure();
final List<? extends TypeDefinition> actualTypeArguments = genericType.getTypeArguments();
if (actualTypeArguments == null || actualTypeArguments.isEmpty()) {
returnValue = new DefaultParameterizedType(toType(ownerType), toType(rawType));
} else {
final Type[] actualJavaTypeArguments = new Type[actualTypeArguments.size()];
for (int i = 0; i < actualTypeArguments.size(); i++) {
actualJavaTypeArguments[i] = toType(actualTypeArguments.get(i));
}
returnValue = new DefaultParameterizedType(toType(ownerType), toType(rawType), actualJavaTypeArguments);
}
break;
case VARIABLE:
final TypeVariableSource typeVariableSource = genericType.getTypeVariableSource();
final GenericDeclaration gd;
if (typeVariableSource instanceof TypeDefinition typeDefinition) {
gd = Class.forName(typeDefinition.asErasure().getTypeName(), false, Thread.currentThread().getContextClassLoader());
} else if (typeVariableSource instanceof MethodDescription.InDefinedShape methodDescription) {
// Reflection time
final String name = methodDescription.getName();
final Class<?> cls = Class.forName(methodDescription.getDeclaringType().asErasure().getTypeName(), false, Thread.currentThread().getContextClassLoader());
final List<? extends TypeDefinition> parameterTypes = methodDescription.getParameters().asTypeList();
final Class<?>[] parameterClasses = new Class<?>[parameterTypes.size()];
for (int i = 0; i < parameterTypes.size(); i++) {
parameterClasses[i] = Class.forName(parameterTypes.get(i).asErasure().getName(), false, Thread.currentThread().getContextClassLoader());
}
if (MethodDescription.CONSTRUCTOR_INTERNAL_NAME.equals(name)) {
assert TypeDescription.VOID.equals(methodDescription.getReturnType());
gd = cls.getDeclaredConstructor(parameterClasses);
} else {
assert !MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME.equals(name);
gd = cls.getDeclaredMethod(name, parameterClasses);
}
} else {
throw new IllegalArgumentException("Unexpected type variable source: " + typeVariableSource);
}
final TypeVariable<?>[] typeVariables = gd.getTypeParameters();
TypeVariable<?> temp = null;
for (final TypeVariable<?> typeVariable : typeVariables) {
if (typeVariable.getName().equals(genericType.getSymbol())) {
temp = typeVariable;
break;
}
}
assert temp != null;
returnValue = temp;
break;
case VARIABLE_SYMBOLIC:
throw new IllegalArgumentException("Unexpected type: " + type);
case WILDCARD:
final List<? extends TypeDefinition> upperBounds = genericType.getUpperBounds();
final List<? extends TypeDefinition> lowerBounds = genericType.getLowerBounds();
if (lowerBounds == null || lowerBounds.isEmpty()) {
if (upperBounds == null || upperBounds.isEmpty() || (upperBounds.size() == 1 && TypeDescription.Generic.OBJECT.equals(upperBounds.get(0)))) {
returnValue = UnboundedWildcardType.INSTANCE;
} else {
// Upper bounded.
final Type[] upperJavaBounds = new Type[upperBounds.size()];
for (int i = 0; i < upperBounds.size(); i++) {
upperJavaBounds[i] = toType(upperBounds.get(i)); // XXX recursive
}
returnValue = new UpperBoundedWildcardType(upperJavaBounds);
}
} else {
assert upperBounds == null || upperBounds.isEmpty() || (upperBounds.size() == 1 && TypeDescription.Generic.OBJECT.equals(upperBounds.get(0))) : "Unexpected upper bounds: " + upperBounds + "; lower bounds: " + lowerBounds;
// Lower bounded.
assert lowerBounds.size() == 1 : "Unexpected size in lower bounds: " + lowerBounds;
returnValue = new LowerBoundedWildcardType(toType(lowerBounds.get(0))); // XXX recursive
}
break;
default:
throw new IllegalArgumentException("Unexpected type: " + type);
}
}
return returnValue;
}
No, you can only convert a Type to a TypeDescription.Generic but there is no option to do it the other way. The easiest option to emulate this would probably be to define a class that defines a field of the given Type, to load this class and to read the field type using Java reflection.
The reason Byte Buddy cannot convert a description to a Type is that Byte Buddy abstracts out class loaders and that type variables might be detached from their declaring source.

How to create url with complex query

I use dart and flutter for mobile app. I use my api to get data from server. But I found a problem, maybe its dart core problem.
I need to add complex queryParams to my URL like
Map<String, Map<String, List<String>>>{"a": {"b": ["c","d"]}, "e": {}}
I use Uri.parse(url).replace(queryParams: myQueryParams).toString()
But Uri.replace() accepts only Map<String, Iterable<String>> and throws an error
Unhandled Exception: type '_InternalLinkedHashMap<String, List<String>>' is not a subtype of type 'Iterable<dynamic>'
I found method which throws this error
static String _makeQuery(String query, int start, int end,
Map<String, dynamic /*String|Iterable<String>*/ > queryParameters) {
if (query != null) {
if (queryParameters != null) {
throw ArgumentError('Both query and queryParameters specified');
}
return _normalizeOrSubstring(query, start, end, _queryCharTable,
escapeDelimiters: true);
}
if (queryParameters == null) return null;
var result = StringBuffer();
var separator = "";
void writeParameter(String key, String value) {
result.write(separator);
separator = "&";
result.write(Uri.encodeQueryComponent(key));
if (value != null && value.isNotEmpty) {
result.write("=");
result.write(Uri.encodeQueryComponent(value));
}
}
queryParameters.forEach((key, value) {
if (value == null || value is String) {
writeParameter(key, value);
} else {
Iterable values = value;
for (String value in values) {
writeParameter(key, value);
}
}
});
return result.toString();
}
So my question is there is some method in dart to add my queryParams to url or I need to create it by my own?
I have modified original method and now its work.
class UrlCreator {
static String addQueryParams(String url, Map<String, dynamic> queryParams) {
var result = StringBuffer();
var separator = "";
void writeParameter(String key, String value) {
result.write(separator);
separator = "&";
result.write(Uri.encodeQueryComponent(key));
if (value != null && value.isNotEmpty) {
result.write("=");
result.write(Uri.encodeQueryComponent(value));
}
}
void buildQuery(Map queryParams, {parentKey}){
queryParams.forEach((key, value){
print("parentKey = $parentKey Key = $key value = $value");
if (value == null || value is String) {
var newKey = parentKey != null ? "$parentKey[$key]" : key;
writeParameter(newKey, value);
} else if (value is Map) {
buildQuery(value, parentKey: key);
} else {
Iterable values = value;
var newKey = parentKey != null ? "$parentKey[$key][]" : "$key[]";
for (String value in values) {
writeParameter(newKey, value);
}
}
});
}
buildQuery(queryParams);
return url + "?" + result.toString();
}
}

Code upgrade in Vuejs

I have below code in vue.js method.
if(element == 'name'){
var address_data = {
name : this.name
}
}
I would like to replace name using element like below
if(element == 'name'){
var address_data = {
element : this.element
}
}
How can I do it ?
EZ PZ like this:
if (element == 'name') {
var address_data = { element }
}
If element is a variable holding the name of the property in address_data which you want to set, and also the name of the property on this, go like this:
if (element == 'name') {
var address_data = {}
address_data[element] = this[element]
}

Create a Gson TypeAdapter for a Guava Range

I am trying to serialize Guava Range objects to JSON using Gson, however the default serialization fails, and I'm unsure how to correctly implement a TypeAdapter for this generic type.
Gson gson = new Gson();
Range<Integer> range = Range.closed(10, 20);
String json = gson.toJson(range);
System.out.println(json);
Range<Integer> range2 = gson.fromJson(json,
new TypeToken<Range<Integer>>(){}.getType());
System.out.println(range2);
assertEquals(range2, range);
This fails like so:
{"lowerBound":{"endpoint":10},"upperBound":{"endpoint":20}}
PASSED: typeTokenInterface
FAILED: range
java.lang.RuntimeException: Unable to invoke no-args constructor for
com.google.common.collect.Cut<java.lang.Integer>. Register an
InstanceCreator with Gson for this type may fix this problem.
at com.google.gson.internal.ConstructorConstructor$12.construct(
ConstructorConstructor.java:210)
...
Note that the default serialization actually loses information - it fails to report whether the endpoints are open or closed. I would prefer to see it serialized similar to its toString(), e.g. [10‥20] however simply calling toString() won't work with generic Range instances, as the elements of the range may not be primitives (Joda-Time LocalDate instances, for example). For the same reason, implementing a custom TypeAdapter seems difficult, as we don't know how to deserialize the endpoints.
I've implemented most of a TypeAdaptorFactory based on the template provided for Multimap which ought to work, but now I'm stuck on the generics. Here's what I have so far:
public class RangeTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Type type = typeToken.getType();
if (typeToken.getRawType() != Range.class
|| !(type instanceof ParameterizedType)) {
return null;
}
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
TypeAdapter<?> elementAdapter = (TypeAdapter<?>)gson.getAdapter(TypeToken.get(elementType));
// Bound mismatch: The generic method newRangeAdapter(TypeAdapter<E>) of type
// GsonUtils.RangeTypeAdapterFactory is not applicable for the arguments
// (TypeAdapter<capture#4-of ?>). The inferred type capture#4-of ? is not a valid
// substitute for the bounded parameter <E extends Comparable<?>>
return (TypeAdapter<T>) newRangeAdapter(elementAdapter);
}
private <E extends Comparable<?>> TypeAdapter<Range<E>> newRangeAdapter(final TypeAdapter<E> elementAdapter) {
return new TypeAdapter<Range<E>>() {
#Override
public void write(JsonWriter out, Range<E> value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
String repr = (value.lowerBoundType() == BoundType.CLOSED ? "[" : "(") +
(value.hasLowerBound() ? elementAdapter.toJson(value.lowerEndpoint()) : "-\u221e") +
'\u2025' +
(value.hasLowerBound() ? elementAdapter.toJson(value.upperEndpoint()) : "+\u221e") +
(value.upperBoundType() == BoundType.CLOSED ? "]" : ")");
out.value(repr);
}
public Range<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
String[] endpoints = in.nextString().split("\u2025");
E lower = elementAdapter.fromJson(endpoints[0].substring(1));
E upper = elementAdapter.fromJson(endpoints[1].substring(0,endpoints[1].length()-1));
return Range.range(lower, endpoints[0].charAt(0) == '[' ? BoundType.CLOSED : BoundType.OPEN,
upper, endpoints[1].charAt(endpoints[1].length()-1) == '[' ? BoundType.CLOSED : BoundType.OPEN);
}
};
}
}
However the return (TypeAdapter<T>) newRangeAdapter(elementAdapter); line has a compilation error and I'm now at a loss.
What's the best way to resolve this error? Is there a better way to serialize Range objects that I'm missing? What about if I want to serialize RangeSets?
Rather frustrating that the Google utility library and Google serialization library seem to require so much glue to work together :(
This feels somewhat like reinventing the wheel, but it was a lot quicker to put together and test than the time spent trying to get Gson to behave, so at least presently I'll be using the following Converters to serialize Range and RangeSet*, rather than Gson.
/**
* Converter between Range instances and Strings, essentially a custom serializer.
* Ideally we'd let Gson or Guava do this for us, but presently this is cleaner.
*/
public static <T extends Comparable<? super T>> Converter<Range<T>, String> rangeConverter(final Converter<T, String> elementConverter) {
final String NEG_INFINITY = "-\u221e";
final String POS_INFINITY = "+\u221e";
final String DOTDOT = "\u2025";
return new Converter<Range<T>, String>() {
#Override
protected String doForward(Range<T> range) {
return (range.hasLowerBound() && range.lowerBoundType() == BoundType.CLOSED ? "[" : "(") +
(range.hasLowerBound() ? elementConverter.convert(range.lowerEndpoint()) : NEG_INFINITY) +
DOTDOT +
(range.hasUpperBound() ? elementConverter.convert(range.upperEndpoint()) : POS_INFINITY) +
(range.hasUpperBound() && range.upperBoundType() == BoundType.CLOSED ? "]" : ")");
}
#Override
protected Range<T> doBackward(String range) {
String[] endpoints = range.split(DOTDOT);
Range<T> ret = Range.all();
if(!endpoints[0].substring(1).equals(NEG_INFINITY)) {
T lower = elementConverter.reverse().convert(endpoints[0].substring(1));
ret = ret.intersection(Range.downTo(lower, endpoints[0].charAt(0) == '[' ? BoundType.CLOSED : BoundType.OPEN));
}
if(!endpoints[1].substring(0,endpoints[1].length()-1).equals(POS_INFINITY)) {
T upper = elementConverter.reverse().convert(endpoints[1].substring(0,endpoints[1].length()-1));
ret = ret.intersection(Range.upTo(upper, endpoints[1].charAt(endpoints[1].length()-1) == ']' ? BoundType.CLOSED : BoundType.OPEN));
}
return ret;
}
};
}
/**
* Converter between RangeSet instances and Strings, essentially a custom serializer.
* Ideally we'd let Gson or Guava do this for us, but presently this is cleaner.
*/
public static <T extends Comparable<? super T>> Converter<RangeSet<T>, String> rangeSetConverter(final Converter<T, String> elementConverter) {
return new Converter<RangeSet<T>, String>() {
private final Converter<Range<T>, String> rangeConverter = rangeConverter(elementConverter);
#Override
protected String doForward(RangeSet<T> rs) {
ArrayList<String> ls = new ArrayList<>();
for(Range<T> range : rs.asRanges()) {
ls.add(rangeConverter.convert(range));
}
return Joiner.on(", ").join(ls);
}
#Override
protected RangeSet<T> doBackward(String rs) {
Iterable<String> parts = Splitter.on(",").trimResults().split(rs);
ImmutableRangeSet.Builder<T> build = ImmutableRangeSet.builder();
for(String range : parts) {
build.add(rangeConverter.reverse().convert(range));
}
return build.build();
}
};
}
*For inter-process communication, Java serialization would likely work just fine, as both classes implement Serializable. However I'm serializing to disk for more permanent storage, meaning I need a format I can trust won't change over time. Guava's serialization doesn't provide that guarantee.
Here is a Gson JsonSerializer and JsonDeserializer that generically supports a Range: https://github.com/jamespedwards42/Fava/wiki/Range-Marshaller
#Override
public JsonElement serialize(final Range src, final Type typeOfSrc, final JsonSerializationContext context) {
final JsonObject jsonObject = new JsonObject();
if ( src.hasLowerBound() ) {
jsonObject.add( "lowerBoundType", context.serialize( src.lowerBoundType() ) );
jsonObject.add( "lowerBound", context.serialize( src.lowerEndpoint() ) );
} else
jsonObject.add( "lowerBoundType", context.serialize( BoundType.OPEN ) );
if ( src.hasUpperBound() ) {
jsonObject.add( "upperBoundType", context.serialize( src.upperBoundType() ) );
jsonObject.add( "upperBound", context.serialize( src.upperEndpoint() ) );
} else
jsonObject.add( "upperBoundType", context.serialize( BoundType.OPEN ) );
return jsonObject;
}
#Override
public Range<? extends Comparable<?>> deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
if ( !( typeOfT instanceof ParameterizedType ) )
throw new IllegalStateException( "typeOfT must be a parameterized Range." );
final JsonObject jsonObject = json.getAsJsonObject();
final JsonElement lowerBoundTypeJsonElement = jsonObject.get( "lowerBoundType" );
final JsonElement upperBoundTypeJsonElement = jsonObject.get( "upperBoundType" );
if ( lowerBoundTypeJsonElement == null || upperBoundTypeJsonElement == null )
throw new IllegalStateException( "Range " + json
+ "was not serialized with this serializer! The default serialization does not store the boundary types, therfore we can not deserialize." );
final Type type = ( ( ParameterizedType ) typeOfT ).getActualTypeArguments()[0];
final BoundType lowerBoundType = context.deserialize( lowerBoundTypeJsonElement, BoundType.class );
final JsonElement lowerBoundJsonElement = jsonObject.get( "lowerBound" );
final Comparable<?> lowerBound = lowerBoundJsonElement == null ? null : context.deserialize( lowerBoundJsonElement, type );
final BoundType upperBoundType = context.deserialize( upperBoundTypeJsonElement, BoundType.class );
final JsonElement upperBoundJsonElement = jsonObject.get( "upperBound" );
final Comparable<?> upperBound = upperBoundJsonElement == null ? null : context.deserialize( upperBoundJsonElement, type );
if ( lowerBound == null && upperBound != null )
return Range.upTo( upperBound, upperBoundType );
else if ( lowerBound != null && upperBound == null )
return Range.downTo( lowerBound, lowerBoundType );
else if ( lowerBound == null && upperBound == null )
return Range.all();
return Range.range( lowerBound, lowerBoundType, upperBound, upperBoundType );
}
Here is a straight forward solution. Works very well
import com.google.common.collect.BoundType;
import com.google.common.collect.Range;
import com.google.gson.*;
import java.lang.reflect.Type;
public class GoogleRangeAdapter implements JsonSerializer, JsonDeserializer {
public static String TK_hasLowerBound = "hasLowerBound";
public static String TK_hasUpperBound = "hasUpperBound";
public static String TK_lowerBoundType = "lowerBoundType";
public static String TK_upperBoundType = "upperBoundType";
public static String TK_lowerBound = "lowerBound";
public static String TK_upperBound = "upperBound";
#Override
public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = (JsonObject)json;
boolean hasLowerBound = jsonObject.get(TK_hasLowerBound).getAsBoolean();
boolean hasUpperBound = jsonObject.get(TK_hasUpperBound).getAsBoolean();
if (!hasLowerBound && !hasUpperBound) {
return Range.all();
}
else if (!hasLowerBound && hasUpperBound){
double upperBound = jsonObject.get(TK_upperBound).getAsDouble();
BoundType upperBoundType = BoundType.valueOf(jsonObject.get(TK_upperBoundType).getAsString());
if (upperBoundType == BoundType.OPEN)
return Range.lessThan(upperBound);
else
return Range.atMost(upperBound);
}
else if (hasLowerBound && !hasUpperBound){
double lowerBound = jsonObject.get(TK_lowerBound).getAsDouble();
BoundType lowerBoundType = BoundType.valueOf(jsonObject.get(TK_lowerBoundType).getAsString());
if (lowerBoundType == BoundType.OPEN)
return Range.greaterThan(lowerBound);
else
return Range.atLeast(lowerBound);
}
else {
double lowerBound = jsonObject.get(TK_lowerBound).getAsDouble();
double upperBound = jsonObject.get(TK_upperBound).getAsDouble();
BoundType upperBoundType = BoundType.valueOf(jsonObject.get(TK_upperBoundType).getAsString());
BoundType lowerBoundType = BoundType.valueOf(jsonObject.get(TK_lowerBoundType).getAsString());
if (lowerBoundType == BoundType.OPEN && upperBoundType == BoundType.OPEN)
return Range.open(lowerBound, upperBound);
else if (lowerBoundType == BoundType.OPEN && upperBoundType == BoundType.CLOSED)
return Range.openClosed(lowerBound, upperBound);
else if (lowerBoundType == BoundType.CLOSED && upperBoundType == BoundType.OPEN)
return Range.closedOpen(lowerBound, upperBound);
else
return Range.closed(lowerBound, upperBound);
}
}
#Override
public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
Range<Double> range = (Range<Double>)src;
boolean hasLowerBound = range.hasLowerBound();
boolean hasUpperBound = range.hasUpperBound();
jsonObject.addProperty(TK_hasLowerBound, hasLowerBound);
jsonObject.addProperty(TK_hasUpperBound, hasUpperBound);
if (hasLowerBound) {
jsonObject.addProperty(TK_lowerBound, range.lowerEndpoint());
jsonObject.addProperty(TK_lowerBoundType, range.lowerBoundType().name());
}
if (hasUpperBound) {
jsonObject.addProperty(TK_upperBound, range.upperEndpoint());
jsonObject.addProperty(TK_upperBoundType, range.upperBoundType().name());
}
return jsonObject;
}
}