Skip to content

Commit 0e57db0

Browse files
SONARPY-657 Rework Project-level Symbol Table (#1024)
1 parent d3aa6d3 commit 0e57db0

19 files changed

+1313
-55
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2011-2021 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.python.index;
21+
22+
import java.util.Arrays;
23+
import java.util.HashSet;
24+
import java.util.Set;
25+
import javax.annotation.Nullable;
26+
27+
public class AmbiguousDescriptor implements Descriptor {
28+
29+
private final Set<Descriptor> descriptors;
30+
private final String name;
31+
private final String fullyQualifiedName;
32+
33+
public AmbiguousDescriptor(String name, @Nullable String fullyQualifiedName, Set<Descriptor> descriptors) {
34+
this.name = name;
35+
this.fullyQualifiedName = fullyQualifiedName;
36+
this.descriptors = descriptors;
37+
}
38+
39+
@Override
40+
public String name() {
41+
return name;
42+
}
43+
44+
@Nullable
45+
@Override
46+
public String fullyQualifiedName() {
47+
return fullyQualifiedName;
48+
}
49+
50+
@Override
51+
public Kind kind() {
52+
return Kind.AMBIGUOUS;
53+
}
54+
55+
public Set<Descriptor> alternatives() {
56+
return descriptors;
57+
}
58+
59+
public static AmbiguousDescriptor create(Descriptor... descriptors) {
60+
return create(new HashSet<>(Arrays.asList(descriptors)));
61+
}
62+
63+
public static AmbiguousDescriptor create(Set<Descriptor> descriptors) {
64+
if (descriptors.size() < 2) {
65+
throw new IllegalArgumentException("Ambiguous symbol should contain at least two descriptors");
66+
}
67+
Descriptor firstSymbol = descriptors.iterator().next();
68+
String resultingSymbolName = firstSymbol.name();
69+
if (!descriptors.stream().map(Descriptor::name).allMatch(symbolName -> symbolName.equals(firstSymbol.name()))) {
70+
throw new IllegalArgumentException("Ambiguous descriptor should contain descriptors with the same name.");
71+
}
72+
return new AmbiguousDescriptor(resultingSymbolName, firstSymbol.fullyQualifiedName(), flattenAmbiguousDescriptors(descriptors));
73+
}
74+
75+
private static Set<Descriptor> flattenAmbiguousDescriptors(Set<Descriptor> descriptors) {
76+
Set<Descriptor> alternatives = new HashSet<>();
77+
for (Descriptor descriptor : descriptors) {
78+
if (descriptor.kind() == Kind.AMBIGUOUS) {
79+
Set<Descriptor> flattenedAlternatives = flattenAmbiguousDescriptors(((AmbiguousDescriptor) descriptor).alternatives());
80+
alternatives.addAll(flattenedAlternatives);
81+
} else {
82+
alternatives.add(descriptor);
83+
}
84+
}
85+
return alternatives;
86+
}
87+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2011-2021 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.python.index;
21+
22+
import java.util.Collection;
23+
import java.util.HashSet;
24+
import javax.annotation.Nullable;
25+
import org.sonar.plugins.python.api.LocationInFile;
26+
27+
public class ClassDescriptor implements Descriptor {
28+
29+
private final String name;
30+
@Nullable
31+
private final String fullyQualifiedName;
32+
private final Collection<String> superClasses;
33+
private final Collection<Descriptor> members;
34+
private final boolean hasDecorators;
35+
private final LocationInFile definitionLocation;
36+
private final boolean hasSuperClassWithoutDescriptor;
37+
private final boolean hasMetaClass;
38+
private final String metaclassFQN;
39+
private final boolean supportsGenerics;
40+
41+
public ClassDescriptor(String name, @Nullable String fullyQualifiedName, Collection<String> superClasses, Collection<Descriptor> members,
42+
boolean hasDecorators, @Nullable LocationInFile definitionLocation, boolean hasSuperClassWithoutDescriptor, boolean hasMetaClass,
43+
@Nullable String metaclassFQN, boolean supportsGenerics) {
44+
45+
this.name = name;
46+
this.fullyQualifiedName = fullyQualifiedName;
47+
this.superClasses = superClasses;
48+
this.members = members;
49+
this.hasDecorators = hasDecorators;
50+
this.definitionLocation = definitionLocation;
51+
this.hasSuperClassWithoutDescriptor = hasSuperClassWithoutDescriptor;
52+
this.hasMetaClass = hasMetaClass;
53+
this.metaclassFQN = metaclassFQN;
54+
this.supportsGenerics = supportsGenerics;
55+
}
56+
57+
@Override
58+
public String name() {
59+
return name;
60+
}
61+
62+
@Override
63+
public String fullyQualifiedName() {
64+
return fullyQualifiedName;
65+
}
66+
67+
@Override
68+
public Kind kind() {
69+
return Kind.CLASS;
70+
}
71+
72+
public Collection<String> superClasses() {
73+
return superClasses;
74+
}
75+
76+
public Collection<Descriptor> members() {
77+
return members;
78+
}
79+
80+
public boolean hasDecorators() {
81+
return hasDecorators;
82+
}
83+
84+
public boolean hasSuperClassWithoutDescriptor() {
85+
return hasSuperClassWithoutDescriptor;
86+
}
87+
88+
public LocationInFile definitionLocation() {
89+
return definitionLocation;
90+
}
91+
92+
public boolean hasMetaClass() {
93+
return hasMetaClass;
94+
}
95+
96+
public String metaclassFQN() {
97+
return metaclassFQN;
98+
}
99+
100+
public boolean supportsGenerics() {
101+
return supportsGenerics;
102+
}
103+
104+
public static class ClassDescriptorBuilder {
105+
106+
private String name;
107+
private String fullyQualifiedName;
108+
private Collection<String> superClasses = new HashSet<>();
109+
private Collection<Descriptor> members = new HashSet<>();
110+
private boolean hasDecorators = false;
111+
private LocationInFile definitionLocation = null;
112+
private boolean hasSuperClassWithoutDescriptor = false;
113+
private boolean hasMetaClass = false;
114+
private String metaclassFQN = null;
115+
private boolean supportsGenerics = false;
116+
117+
public ClassDescriptorBuilder withName(String name) {
118+
this.name = name;
119+
return this;
120+
}
121+
122+
public ClassDescriptorBuilder withFullyQualifiedName(@Nullable String fullyQualifiedName) {
123+
this.fullyQualifiedName = fullyQualifiedName;
124+
return this;
125+
}
126+
127+
public ClassDescriptorBuilder withSuperClasses(Collection<String> superClasses) {
128+
this.superClasses = superClasses;
129+
return this;
130+
}
131+
132+
public ClassDescriptorBuilder withMembers(Collection<Descriptor> members) {
133+
this.members = members;
134+
return this;
135+
}
136+
137+
public ClassDescriptorBuilder withHasDecorators(boolean hasDecorators) {
138+
this.hasDecorators = hasDecorators;
139+
return this;
140+
}
141+
142+
public ClassDescriptorBuilder withHasSuperClassWithoutDescriptor(boolean hasSuperClassWithoutDescriptor) {
143+
this.hasSuperClassWithoutDescriptor = hasSuperClassWithoutDescriptor;
144+
return this;
145+
}
146+
147+
public ClassDescriptorBuilder withDefinitionLocation(@Nullable LocationInFile definitionLocation) {
148+
this.definitionLocation = definitionLocation;
149+
return this;
150+
}
151+
152+
public ClassDescriptorBuilder withHasMetaClass(boolean hasMetaClass) {
153+
this.hasMetaClass = hasMetaClass;
154+
return this;
155+
}
156+
157+
public ClassDescriptorBuilder withMetaclassFQN(@Nullable String metaclassFQN) {
158+
this.metaclassFQN = metaclassFQN;
159+
return this;
160+
}
161+
162+
public ClassDescriptorBuilder withSupportsGenerics(boolean supportsGenerics) {
163+
this.supportsGenerics = supportsGenerics;
164+
return this;
165+
}
166+
167+
public ClassDescriptor build() {
168+
return new ClassDescriptor(name, fullyQualifiedName, superClasses, members, hasDecorators, definitionLocation,
169+
hasSuperClassWithoutDescriptor, hasMetaClass, metaclassFQN, supportsGenerics);
170+
}
171+
}
172+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2011-2021 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.python.index;
21+
22+
import javax.annotation.CheckForNull;
23+
24+
public interface Descriptor {
25+
26+
String name();
27+
28+
@CheckForNull
29+
String fullyQualifiedName();
30+
31+
Kind kind();
32+
33+
enum Kind {
34+
FUNCTION,
35+
CLASS,
36+
VARIABLE,
37+
AMBIGUOUS
38+
}
39+
}

0 commit comments

Comments
 (0)