Skip to content

Commit

Permalink
Fix issue where an annotation referencing a class defined later on in…
Browse files Browse the repository at this point in the history
… the file would be reported as an error.
  • Loading branch information
fabioz committed Sep 5, 2023
1 parent 9f2db5b commit d102e94
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public Object visitClassDef(ClassDef node) throws Exception {
* used so that the token is added to the names to ignore...
*/
protected void addToNamesToIgnore(SimpleNode node, boolean finishClassScope, boolean checkBuiltins) {
SourceToken token = AbstractVisitor.makeToken(node, "", nature, this.current);
final SourceToken token = AbstractVisitor.makeToken(node, "", nature, this.current);

if (checkBuiltins) {
if (checkCurrentScopeForAssignmentsToBuiltins()) {
Expand All @@ -311,9 +311,9 @@ protected void addToNamesToIgnore(SimpleNode node, boolean finishClassScope, boo
}
}

ScopeItems currScopeItems = scope.getCurrScopeItems();
final ScopeItems currScopeItems = scope.getCurrScopeItems();

Found found = new Found(token, token, scope.getCurrScopeId(), scope.getCurrScopeItems());
final Found found = new Found(token, token, scope.getCurrScopeId(), scope.getCurrScopeItems());
org.python.pydev.shared_core.structure.Tuple<IToken, Found> tup = new org.python.pydev.shared_core.structure.Tuple<IToken, Found>(
token, found);
addToNamesToIgnore(token, currScopeItems, tup);
Expand All @@ -324,22 +324,25 @@ protected void addToNamesToIgnore(SimpleNode node, boolean finishClassScope, boo
Found n = it.next();

GenAndTok single = n.getSingle();
int foundScopeType = single.scopeFound.getScopeType();
final ScopeItems scopeFound = single.scopeFound;
final int foundScopeType = scopeFound.getScopeType();
final int globalClassOrMethodScopeType = scopeFound.globalClassOrMethodScopeType;
//ok, if we are in a scope method, we may not get things that were defined in a class scope.
if (((foundScopeType & Scope.ACCEPTED_METHOD_AND_LAMBDA) != 0)
if (((globalClassOrMethodScopeType & Scope.ACCEPTED_METHOD_AND_LAMBDA) != 0)
&& scope.getCurrScopeItems().getScopeType() == Scope.SCOPE_TYPE_CLASS) {
continue;
}
IToken tok = single.tok;
String firstPart = FullRepIterable.getFirstPart(tok.getRepresentation());
final IToken tok = single.tok;
final String firstPart = FullRepIterable.getFirstPart(tok.getRepresentation());

if (firstPart.equals(token.getRepresentation())) {
//found match in names to ignore...

if (finishClassScope && scope.getCurrScopeId() < single.scopeFound.getScopeId()
if (finishClassScope && scope.getCurrScopeId() < scopeFound.getScopeId()
&& !(foundScopeType == Scope.SCOPE_TYPE_ANNOTATION_STR)
&& (!futureAnnotationsImported && foundScopeType == Scope.SCOPE_TYPE_CLASS ||
(!futureAnnotationsImported && foundScopeType == Scope.SCOPE_TYPE_ANNOTATION))) {
&& (!futureAnnotationsImported && (globalClassOrMethodScopeType == Scope.SCOPE_TYPE_CLASS
|| foundScopeType == Scope.SCOPE_TYPE_ANNOTATION)
&& (globalClassOrMethodScopeType & Scope.ACCEPTED_METHOD_AND_LAMBDA) == 0)) {
it.remove();
onAddUndefinedMessage(tok, found);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ public final class Scope implements Iterable<ScopeItems> {
public static final int ACCEPTED_ALL_SCOPES = SCOPE_TYPE_GLOBAL | SCOPE_TYPE_METHOD | SCOPE_TYPE_LAMBDA
| SCOPE_TYPE_CLASS | SCOPE_TYPE_LIST_COMP | SCOPE_TYPE_ANNOTATION | SCOPE_TYPE_ANNOTATION_STR;

/**
* The scopes which may be considered a parent (because when we're in an annotation or list comp, etc
* we still want to know whether we're in the global/method/lamba/class scope).
*/
public static final int ACCEPTED_GLOBAL_CLASS_OR_METHOD_SCOPE_TYPES = SCOPE_TYPE_GLOBAL | SCOPE_TYPE_METHOD
| SCOPE_TYPE_LAMBDA
| SCOPE_TYPE_CLASS;

/**
* Constant defining that method and lambda are accepted.
*/
Expand Down Expand Up @@ -306,9 +314,23 @@ public void startScope(int scopeType) {
this.visitingStrTypeAnnotation += 1;
}
int newId = getNewId();
scope.push(new ScopeItems(newId, scopeType));
scopeId.push(newId);

int globalClassOrMethodScopeType = 0;
if ((scopeType & ACCEPTED_GLOBAL_CLASS_OR_METHOD_SCOPE_TYPES) != 0) {
globalClassOrMethodScopeType = scopeType;

} else {
for (int i = scope.size() - 1; i >= 0; i--) {
ScopeItems parent = scope.get(i);
int found = parent.getScopeType();
if ((found & ACCEPTED_GLOBAL_CLASS_OR_METHOD_SCOPE_TYPES) != 0) {
globalClassOrMethodScopeType = found;
break;
}
}
}
scope.push(new ScopeItems(newId, scopeType, globalClassOrMethodScopeType));
scopeId.push(newId);
}

public int getCurrScopeId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,18 @@ public ScopeItems.TryExceptInfo getTryExceptImportError() {
/**
* Stack for names that should not generate warnings, such as builtins, method names, etc.
*/
public Map<String, Tuple<IToken, Found>> namesToIgnore = new HashMap<String, Tuple<IToken, Found>>();
public final Map<String, Tuple<IToken, Found>> namesToIgnore = new HashMap<String, Tuple<IToken, Found>>();

public int ifSubScope = 0;
public FastStack<TryExceptInfo> tryExceptSubScope = new FastStack<TryExceptInfo>(10);
private int scopeId;
private int scopeType;
public final FastStack<TryExceptInfo> tryExceptSubScope = new FastStack<TryExceptInfo>(10);
private final int scopeId;
private final int scopeType;
public final int globalClassOrMethodScopeType;

public ScopeItems(int scopeId, int scopeType) {
public ScopeItems(int scopeId, int scopeType, int globalClassOrMethodScopeType) {
this.scopeId = scopeId;
this.scopeType = scopeType;
this.globalClassOrMethodScopeType = globalClassOrMethodScopeType;
}

public Found getLastAppearance(String rep) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,17 @@ public void testTypingInfoInStrOk() {
checkNoError();
}

public void testTypingInfoOk() {
doc = new Document(""
+ "def method(): \n"
+ " a: SomeClass\n"
+ " print(a)\n"
+ "class SomeClass:\n"
+ " pass \n"
+ "");
checkNoError();
}

public void testTypingInfoInStrOk2() {
doc = new Document(""
+ ""
Expand Down

0 comments on commit d102e94

Please sign in to comment.