mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 22:17:41 +00:00
Merge branch 'typeLibrary'
This commit is contained in:
commit
b25a644f50
22 files changed
+302
-63
No files matched your search
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2011 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -21,24 +21,49 @@
|
||||
*/
|
||||
package lombok.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Library of types, which can be used to look up potential matching types.
|
||||
*
|
||||
* For example, if you put 'foo.Spork' and 'bar.Spork' into the library, and then ask for
|
||||
* all compatible types given the type 'Spork', you'll get both of them, but you'll only
|
||||
* get the one if you ask for compatible types given 'foo.Spork'.
|
||||
*
|
||||
* Useful to 'guess' if a given annotation AST node matches an annotation handler's target annotation.
|
||||
* For example, if you put {@code foo.Spork} and {@code bar.Spork} into the library, and then ask for
|
||||
* all compatible types given the type {@code Spork}, you'll get both of them, but you'll only
|
||||
* get the one if you ask for compatible types given {@code foo.Spork}.
|
||||
* <p>
|
||||
* When adding {@code foo.Spork}, that FQN (Fully Qualified Name) will be returned as an option for any of these queries:
|
||||
* <ul><li>foo.Spork</li><li>Spork</li><li>foo.*</li></ul>
|
||||
*/
|
||||
public class TypeLibrary {
|
||||
private final Map<String, Set<String>> simpleToQualifiedMap = new HashMap<String, Set<String>>();
|
||||
private final Map<String, List<String>> keyToFqnMap;
|
||||
private final String singletonValue;
|
||||
private final List<String> singletonKeys;
|
||||
|
||||
public TypeLibrary() {
|
||||
keyToFqnMap = new HashMap<String, List<String>>();
|
||||
singletonKeys = null;
|
||||
singletonValue = null;
|
||||
}
|
||||
|
||||
private TypeLibrary(String fqnSingleton) {
|
||||
keyToFqnMap = null;
|
||||
singletonValue = fqnSingleton;
|
||||
int idx = fqnSingleton.lastIndexOf('.');
|
||||
if (idx == -1) {
|
||||
singletonKeys = Collections.singletonList(fqnSingleton);
|
||||
} else {
|
||||
singletonKeys = Arrays.asList(fqnSingleton, fqnSingleton.substring(idx + 1), fqnSingleton.substring(0, idx) + ".*");
|
||||
}
|
||||
}
|
||||
|
||||
public static TypeLibrary createLibraryForSingleType(String fqnSingleton) {
|
||||
return new TypeLibrary(fqnSingleton);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a type to the library.
|
||||
@@ -46,6 +71,7 @@ public class TypeLibrary {
|
||||
* @param fullyQualifiedTypeName the FQN type name, such as 'java.lang.String'.
|
||||
*/
|
||||
public void addType(String fullyQualifiedTypeName) {
|
||||
if (keyToFqnMap == null) throw new IllegalStateException("SingleType library");
|
||||
int idx = fullyQualifiedTypeName.lastIndexOf('.');
|
||||
if (idx == -1) throw new IllegalArgumentException(
|
||||
"Only fully qualified types are allowed (and stuff in the default package is not palatable to us either!)");
|
||||
@@ -53,27 +79,33 @@ public class TypeLibrary {
|
||||
final String simpleName = fullyQualifiedTypeName.substring(idx +1);
|
||||
final String packageName = fullyQualifiedTypeName.substring(0, idx);
|
||||
|
||||
if (simpleToQualifiedMap.put(fullyQualifiedTypeName, Collections.singleton(fullyQualifiedTypeName)) != null) return;
|
||||
if (keyToFqnMap.put(fullyQualifiedTypeName, Collections.singletonList(fullyQualifiedTypeName)) != null) return;
|
||||
|
||||
addToMap(simpleName, fullyQualifiedTypeName);
|
||||
addToMap(packageName + ".*", fullyQualifiedTypeName);
|
||||
}
|
||||
|
||||
private TypeLibrary addToMap(String keyName, String fullyQualifiedTypeName) {
|
||||
Set<String> existing = simpleToQualifiedMap.get(keyName);
|
||||
Set<String> set = (existing == null) ? new HashSet<String>() : new HashSet<String>(existing);
|
||||
set.add(fullyQualifiedTypeName);
|
||||
simpleToQualifiedMap.put(keyName, Collections.unmodifiableSet(set));
|
||||
List<String> list = keyToFqnMap.get(keyName);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
keyToFqnMap.put(keyName, list);
|
||||
}
|
||||
|
||||
list.add(fullyQualifiedTypeName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all items in the type library that may be a match to the provided type.
|
||||
*
|
||||
* @param typeReference something like 'String' or even 'java.lang.String'.
|
||||
* @param typeReference something like 'String', 'java.lang.String', or 'java.lang.*'.
|
||||
* @return A list of Fully Qualified Names for all types in the library that fit the reference.
|
||||
*/
|
||||
public Collection<String> findCompatible(String typeReference) {
|
||||
Set<String> result = simpleToQualifiedMap.get(typeReference);
|
||||
return result == null ? Collections.<String>emptySet() : result;
|
||||
if (singletonKeys != null) return singletonKeys.contains(typeReference) ? Collections.singletonList(singletonValue) : Collections.<String>emptyList();
|
||||
|
||||
List<String> result = keyToFqnMap.get(typeReference);
|
||||
return result == null ? Collections.<String>emptyList() : Collections.unmodifiableList(result);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2011 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -30,17 +30,17 @@ import lombok.core.AST.Kind;
|
||||
|
||||
/**
|
||||
* Capable of resolving a simple type name such as 'String' into 'java.lang.String'.
|
||||
* <p>
|
||||
* NB: This resolver gives wrong answers when there's a class in the local package with the same name as a class in a star-import,
|
||||
* and this importer also can't find inner types from superclasses/interfaces.
|
||||
*/
|
||||
public class TypeResolver {
|
||||
private final TypeLibrary library;
|
||||
private Collection<String> imports;
|
||||
|
||||
/**
|
||||
* Creates a new TypeResolver that can be used to resolve types in a given library, encountered in
|
||||
* a source file with the provided package and import statements.
|
||||
* Creates a new TypeResolver that can be used to resolve types in a source file with the given package and import statements.
|
||||
*/
|
||||
public TypeResolver(TypeLibrary library, String packageString, Collection<String> importStrings) {
|
||||
this.library = library;
|
||||
public TypeResolver(String packageString, Collection<String> importStrings) {
|
||||
this.imports = makeImportList(packageString, importStrings);
|
||||
}
|
||||
|
||||
@@ -51,41 +51,76 @@ public class TypeResolver {
|
||||
return imports;
|
||||
}
|
||||
|
||||
public boolean typeMatches(LombokNode<?, ?, ?> context, String fqn, String typeRef) {
|
||||
return !findTypeMatches(context, TypeLibrary.createLibraryForSingleType(fqn), typeRef).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds type matches for the stated type reference. The provided context is scanned for local type names
|
||||
* that shadow type names listed in import statements. If such a shadowing occurs, no matches are returned
|
||||
* for any shadowed types, as you would expect.
|
||||
*/
|
||||
public Collection<String> findTypeMatches(LombokNode<?, ?, ?> context, String typeRef) {
|
||||
public Collection<String> findTypeMatches(LombokNode<?, ?, ?> context, TypeLibrary library, String typeRef) {
|
||||
// When asking if 'Foo' could possibly be referring to 'bar.Baz', the answer is obviously no.
|
||||
Collection<String> potentialMatches = library.findCompatible(typeRef);
|
||||
if (potentialMatches.isEmpty()) return Collections.emptyList();
|
||||
|
||||
// If input type appears to be fully qualified, we found a winner.
|
||||
int idx = typeRef.indexOf('.');
|
||||
if (idx > -1) return potentialMatches;
|
||||
String simpleName = typeRef.substring(idx+1);
|
||||
|
||||
//If there's an import statement that explicitly imports a 'Getter' that isn't any of our potentials, return no matches.
|
||||
if (nameConflictInImportList(simpleName, potentialMatches)) return Collections.emptyList();
|
||||
// If there's an import statement that explicitly imports a 'Getter' that isn't any of our potentials, return no matches,
|
||||
// because if you want to know if 'Foo' could refer to 'bar.Foo' when 'baz.Foo' is explicitly imported, the answer is no.
|
||||
if (nameConflictInImportList(typeRef, potentialMatches)) return Collections.emptyList();
|
||||
|
||||
//Check if any of our potentials is even imported in the first place. If not: no matches.
|
||||
potentialMatches = eliminateImpossibleMatches(potentialMatches);
|
||||
// Check if any of our potentials are even imported in the first place. If not: no matches.
|
||||
// Note that (ourPackage.*) is added to the imports.
|
||||
potentialMatches = eliminateImpossibleMatches(potentialMatches, library);
|
||||
if (potentialMatches.isEmpty()) return Collections.emptyList();
|
||||
|
||||
//Find a lexically accessible type of the same simple name in the same Compilation Unit. If it exists: no matches.
|
||||
// Now the hard part - inner classes or method local classes in our own scope.
|
||||
// For method locals, this refers to any statements that are 'above' the type reference with the same name.
|
||||
// For inners, this refers to siblings of us or any parent node that are type declarations.
|
||||
LombokNode<?, ?, ?> n = context;
|
||||
|
||||
mainLoop:
|
||||
while (n != null) {
|
||||
if (n.getKind() == Kind.TYPE) {
|
||||
String name = n.getName();
|
||||
if (name != null && name.equals(simpleName)) return Collections.emptyList();
|
||||
if (n.getKind() == Kind.TYPE && typeRef.equals(n.getName())) {
|
||||
// Our own class or one of our outer classes is named 'typeRef' so that's what 'typeRef' is referring to, not one of our type library classes.
|
||||
return Collections.emptyList();
|
||||
}
|
||||
n = n.up();
|
||||
|
||||
if (n.getKind() == Kind.STATEMENT || n.getKind() == Kind.LOCAL) {
|
||||
LombokNode<?, ?, ?> newN = n.directUp();
|
||||
if (newN == null) break mainLoop;
|
||||
|
||||
if (newN.getKind() == Kind.STATEMENT || newN.getKind() == Kind.INITIALIZER || newN.getKind() == Kind.METHOD) {
|
||||
for (LombokNode<?, ?, ?> child : newN.down()) {
|
||||
// We found a method local with the same name above our code. That's the one 'typeRef' is referring to, not
|
||||
// anything in the type library we're trying to find, so, no matches.
|
||||
if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return Collections.emptyList();
|
||||
if (child == n) break;
|
||||
}
|
||||
}
|
||||
n = newN;
|
||||
continue mainLoop;
|
||||
}
|
||||
|
||||
if (n.getKind() == Kind.TYPE || n.getKind() == Kind.COMPILATION_UNIT) {
|
||||
for (LombokNode<?, ?, ?> child : n.down()) {
|
||||
// Inner class that's visible to us has 'typeRef' as name, so that's the one being referred to, not one of our type library classes.
|
||||
if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
n = n.directUp();
|
||||
}
|
||||
|
||||
// The potential matches we found by comparing the import statements is our matching set. Return it.
|
||||
// No class in this source file is a match, therefore the potential matches found via the import statements must be it. Return those.
|
||||
return potentialMatches;
|
||||
}
|
||||
|
||||
private Collection<String> eliminateImpossibleMatches(Collection<String> potentialMatches) {
|
||||
private Collection<String> eliminateImpossibleMatches(Collection<String> potentialMatches, TypeLibrary library) {
|
||||
Set<String> results = new HashSet<String>();
|
||||
|
||||
for (String importedType : imports) {
|
||||
|
||||
@@ -173,11 +173,11 @@ public class HandlerLibrary {
|
||||
String pkgName = annotationNode.getPackageDeclaration();
|
||||
Collection<String> imports = annotationNode.getImportStatements();
|
||||
|
||||
TypeResolver resolver = new TypeResolver(typeLibrary, pkgName, imports);
|
||||
TypeResolver resolver = new TypeResolver(pkgName, imports);
|
||||
TypeReference rawType = annotation.type;
|
||||
if (rawType == null) return;
|
||||
|
||||
for (String fqn : resolver.findTypeMatches(annotationNode, toQualifiedName(annotation.type.getTypeName()))) {
|
||||
for (String fqn : resolver.findTypeMatches(annotationNode, typeLibrary, toQualifiedName(annotation.type.getTypeName()))) {
|
||||
boolean isPrintAST = fqn.equals(PrintAST.class.getName());
|
||||
if (isPrintAST == skipPrintAst) continue;
|
||||
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -46,7 +45,6 @@ import lombok.core.AnnotationValues.AnnotationValue;
|
||||
import lombok.eclipse.EclipseAST;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
import lombok.core.TransformationsUtil;
|
||||
import lombok.core.TypeLibrary;
|
||||
import lombok.core.TypeResolver;
|
||||
|
||||
import org.eclipse.core.runtime.ILog;
|
||||
@@ -260,16 +258,9 @@ public class EclipseHandlerUtil {
|
||||
if (!lastPartA.equals(lastPartB)) return false;
|
||||
String typeName = toQualifiedName(typeRef.getTypeName());
|
||||
|
||||
TypeLibrary library = new TypeLibrary();
|
||||
library.addType(type.getName());
|
||||
TypeResolver resolver = new TypeResolver(library, node.getPackageDeclaration(), node.getImportStatements());
|
||||
Collection<String> typeMatches = resolver.findTypeMatches(node, typeName);
|
||||
TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
|
||||
return resolver.typeMatches(node, type.getName(), typeName);
|
||||
|
||||
for (String match : typeMatches) {
|
||||
if (match.equals(type.getName())) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Annotation copyAnnotation(Annotation annotation, ASTNode source) {
|
||||
|
||||
@@ -171,9 +171,9 @@ public class HandlerLibrary {
|
||||
* @param annotation 'node.get()' - convenience parameter.
|
||||
*/
|
||||
public void handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation) {
|
||||
TypeResolver resolver = new TypeResolver(typeLibrary, node.getPackageDeclaration(), node.getImportStatements());
|
||||
TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
|
||||
String rawType = annotation.annotationType.toString();
|
||||
for (String fqn : resolver.findTypeMatches(node, rawType)) {
|
||||
for (String fqn : resolver.findTypeMatches(node, typeLibrary, rawType)) {
|
||||
boolean isPrintAST = fqn.equals(PrintAST.class.getName());
|
||||
if (isPrintAST && phase != 2) continue;
|
||||
if (!isPrintAST && phase == 2) continue;
|
||||
|
||||
@@ -28,7 +28,6 @@ import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
@@ -38,7 +37,6 @@ import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.TypeLibrary;
|
||||
import lombok.core.TypeResolver;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues.AnnotationValue;
|
||||
@@ -139,16 +137,8 @@ public class JavacHandlerUtil {
|
||||
public static boolean typeMatches(Class<?> type, JavacNode node, JCTree typeNode) {
|
||||
String typeName = typeNode.toString();
|
||||
|
||||
TypeLibrary library = new TypeLibrary();
|
||||
library.addType(type.getName());
|
||||
TypeResolver resolver = new TypeResolver(library, node.getPackageDeclaration(), node.getImportStatements());
|
||||
Collection<String> typeMatches = resolver.findTypeMatches(node, typeName);
|
||||
|
||||
for (String match : typeMatches) {
|
||||
if (match.equals(type.getName())) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
TypeResolver resolver = new TypeResolver(node.getPackageDeclaration(), node.getImportStatements());
|
||||
return resolver.typeMatches(node, type.getName(), typeName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -108,6 +108,7 @@ public class PatchDelegate {
|
||||
for (Annotation ann : field.annotations) {
|
||||
if (ann.type == null) continue;
|
||||
TypeBinding tb = ann.type.resolveType(decl.initializerScope);
|
||||
if (tb == null) continue;
|
||||
if (!charArrayEquals("lombok", tb.qualifiedPackageName())) continue;
|
||||
if (!charArrayEquals("Delegate", tb.qualifiedSourceName())) continue;
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class SimpleTypeResolutionFail {
|
||||
@Getter
|
||||
private int x;
|
||||
}
|
||||
class SimpleTypeResolutionSuccess {
|
||||
private int x;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import lombok.*;
|
||||
class TrickyDoNothing {
|
||||
@interface Getter {
|
||||
}
|
||||
@Getter
|
||||
int x;
|
||||
}
|
||||
class TrickyDoNothing2 {
|
||||
@Getter
|
||||
int x;
|
||||
@interface Getter {
|
||||
}
|
||||
}
|
||||
class TrickySuccess {
|
||||
int x;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
}
|
||||
class TrickyDoNothing3 {
|
||||
void test() {
|
||||
class val {
|
||||
}
|
||||
val x = null;
|
||||
}
|
||||
}
|
||||
class TrickyDoSomething {
|
||||
void test() {
|
||||
final java.lang.Object x = null;
|
||||
class val {
|
||||
}
|
||||
}
|
||||
}
|
||||
class DoubleTrickyDoNothing {
|
||||
void test() {
|
||||
class val {
|
||||
}
|
||||
for (int i = 10; i < 20; i++) {
|
||||
val y = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
class DoubleTrickyDoSomething {
|
||||
void test() {
|
||||
for (int j = 10; j < 20; j++) {
|
||||
class val {
|
||||
}
|
||||
}
|
||||
for (int i = 10; i < 20; i++) {
|
||||
final java.lang.Object y = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import lombok.*;
|
||||
class DoNothingDueToTopLevel {
|
||||
void test() {
|
||||
val x = null;
|
||||
}
|
||||
}
|
||||
class val {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class SimpleTypeResolutionFail {
|
||||
private @Getter int x;
|
||||
SimpleTypeResolutionFail() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
class SimpleTypeResolutionSuccess {
|
||||
private @lombok.Getter int x;
|
||||
public @java.lang.SuppressWarnings("all") int getX() {
|
||||
return this.x;
|
||||
}
|
||||
SimpleTypeResolutionSuccess() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
//ignore
|
||||
@@ -0,0 +1 @@
|
||||
//ignore
|
||||
@@ -0,0 +1,15 @@
|
||||
class SimpleTypeResolutionFail {
|
||||
private @Getter int x;
|
||||
SimpleTypeResolutionFail() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
class SimpleTypeResolutionSuccess {
|
||||
private @lombok.Getter int x;
|
||||
public @java.lang.SuppressWarnings("all") int getX() {
|
||||
return this.x;
|
||||
}
|
||||
SimpleTypeResolutionSuccess() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
//ignore
|
||||
@@ -0,0 +1 @@
|
||||
//ignore
|
||||
@@ -0,0 +1,7 @@
|
||||
class SimpleTypeResolutionFail {
|
||||
@Getter private int x;
|
||||
}
|
||||
|
||||
class SimpleTypeResolutionSuccess {
|
||||
@lombok.Getter private int x;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import lombok.*;
|
||||
class TrickyDoNothing {
|
||||
@interface Getter {}
|
||||
@Getter int x;
|
||||
}
|
||||
|
||||
class TrickyDoNothing2 {
|
||||
@Getter int x;
|
||||
@interface Getter {}
|
||||
}
|
||||
|
||||
class TrickySuccess {
|
||||
@Getter int x;
|
||||
}
|
||||
|
||||
class TrickyDoNothing3 {
|
||||
void test() {
|
||||
class val {}
|
||||
val x = null;
|
||||
}
|
||||
}
|
||||
|
||||
class TrickyDoSomething {
|
||||
void test() {
|
||||
val x = null;
|
||||
class val {}
|
||||
}
|
||||
}
|
||||
|
||||
class DoubleTrickyDoNothing {
|
||||
void test() {
|
||||
class val {}
|
||||
for (int i = 10; i < 20; i++) {
|
||||
val y = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DoubleTrickyDoSomething {
|
||||
void test() {
|
||||
for (int j = 10; j < 20; j++) {
|
||||
class val {}
|
||||
}
|
||||
|
||||
for (int i = 10; i < 20; i++) {
|
||||
val y = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import lombok.*;
|
||||
class DoNothingDueToTopLevel {
|
||||
void test() {
|
||||
val x = null;
|
||||
}
|
||||
}
|
||||
|
||||
class val {}
|
||||
@@ -0,0 +1,9 @@
|
||||
2:10 ERROR cannot find symbol
|
||||
symbol : class Getter
|
||||
location: class SimpleTypeResolutionFail
|
||||
2:10 ERROR cannot find symbol
|
||||
symbol : class Getter
|
||||
location: class SimpleTypeResolutionFail
|
||||
2:10 ERROR cannot find symbol
|
||||
symbol : class Getter
|
||||
location: class SimpleTypeResolutionFail
|
||||
@@ -0,0 +1 @@
|
||||
2 error Getter cannot be resolved to a type
|
||||
@@ -0,0 +1,9 @@
|
||||
2:10 ERROR cannot find symbol
|
||||
symbol : class Getter
|
||||
location: class SimpleTypeResolutionFail
|
||||
2:10 ERROR cannot find symbol
|
||||
symbol : class Getter
|
||||
location: class SimpleTypeResolutionFail
|
||||
2:10 ERROR cannot find symbol
|
||||
symbol : class Getter
|
||||
location: class SimpleTypeResolutionFail
|
||||
Reference in new issue
Block a user