use of org.sonar.plugins.python.api.symbols.ClassSymbol in project sonar-python by SonarSource.
the class UselessStatementCheck method checkName.
private static void checkName(SubscriptionContext ctx) {
Name name = (Name) ctx.syntaxNode();
Symbol symbol = name.symbol();
if (symbol != null && symbol.is(Symbol.Kind.CLASS)) {
ClassSymbol classSymbol = (ClassSymbol) symbol;
// Creating an exception without raising it is covered by S3984
if (classSymbol.canBeOrExtend("BaseException")) {
return;
}
}
if (symbol != null && symbol.usages().stream().anyMatch(u -> u.kind().equals(Usage.Kind.IMPORT)) && symbol.usages().size() == 2) {
// Avoid raising on useless statements made to suppress issues due to "unused" import
return;
}
checkNode(ctx);
}
use of org.sonar.plugins.python.api.symbols.ClassSymbol in project sonar-python by SonarSource.
the class SpecialMethodParamListCheck method isRelevantMethodDefinition.
private static boolean isRelevantMethodDefinition(FunctionDef def) {
if (!def.isMethodDefinition()) {
return false;
}
ClassDef classDef = (ClassDef) TreeUtils.firstAncestorOfKind(def, Tree.Kind.CLASSDEF);
ClassSymbol classSymbol = TreeUtils.getClassSymbolFromDef(classDef);
if (classSymbol == null) {
return false;
}
if (classSymbol.isOrExtends("zope.interface.Interface")) {
return false;
}
String name = def.name().name();
return name.startsWith("__") && name.endsWith("__");
}
use of org.sonar.plugins.python.api.symbols.ClassSymbol in project sonar-python by SonarSource.
the class InstanceMethodSelfAsFirstCheck method initialize.
@Override
public void initialize(Context context) {
context.registerSyntaxNodeConsumer(Tree.Kind.CLASSDEF, ctx -> {
ClassDef classDef = (ClassDef) ctx.syntaxNode();
ClassSymbol classSymbol = TreeUtils.getClassSymbolFromDef(classDef);
// Do not raise on nested classes - they might use a different name for "self" in order to avoid confusion.
if (classSymbol == null || TreeUtils.firstAncestorOfKind(classDef, Tree.Kind.CLASSDEF) != null) {
return;
}
// We consider that a class MIGHT be a metaclass, either if the class is decorated, inherits from "type",
// "typing.Protocol" or has an unresolved type hiearchy. In this case we shall also accept "cls" or "mcs"
// as the name of the first parameter.
boolean mightBeMetaclass = !classDef.decorators().isEmpty() || classSymbol.isOrExtends("type") || classSymbol.isOrExtends("typing.Protocol") || classSymbol.hasUnresolvedTypeHierarchy();
TreeUtils.topLevelFunctionDefs(classDef).forEach(functionDef -> {
List<Parameter> parameters = TreeUtils.positionalParameters(functionDef);
if (parameters.isEmpty()) {
return;
}
Parameter first = parameters.get(0);
if (first.starToken() != null) {
return;
}
Optional.ofNullable(first.name()).map(Name::name).ifPresent(name -> {
if (!ALLOWED_NAMES.contains(name) && isRelevantMethod(classDef, classSymbol, functionDef) && !isValidExceptionForCls(functionDef, name, mightBeMetaclass)) {
ctx.addIssue(first, String.format("Rename \"%s\" to \"self\" or add the missing \"self\" parameter.", name));
}
});
});
});
}
use of org.sonar.plugins.python.api.symbols.ClassSymbol in project sonar-python by SonarSource.
the class ItemOperationsTypeCheck method isValidSubscription.
@Override
public boolean isValidSubscription(Expression subscriptionObject, String requiredMethod, @Nullable String classRequiredMethod, Map<LocationInFile, String> secondaries) {
if (subscriptionObject.is(Tree.Kind.GENERATOR_EXPR)) {
return false;
}
if (subscriptionObject.is(Tree.Kind.CALL_EXPR)) {
Symbol subscriptionCalleeSymbol = ((CallExpression) subscriptionObject).calleeSymbol();
if (subscriptionCalleeSymbol != null && subscriptionCalleeSymbol.is(FUNCTION) && ((FunctionSymbol) subscriptionCalleeSymbol).isAsynchronous()) {
FunctionSymbol functionSymbol = (FunctionSymbol) subscriptionCalleeSymbol;
secondaries.put(functionSymbol.definitionLocation(), String.format(SECONDARY_MESSAGE, functionSymbol.name()));
return false;
}
}
if (subscriptionObject instanceof HasSymbol) {
Symbol symbol = ((HasSymbol) subscriptionObject).symbol();
if (symbol == null || isTypingOrCollectionsSymbol(symbol)) {
return true;
}
if (symbol.is(FUNCTION, CLASS)) {
secondaries.put(symbol.is(FUNCTION) ? ((FunctionSymbol) symbol).definitionLocation() : ((ClassSymbol) symbol).definitionLocation(), String.format(SECONDARY_MESSAGE, symbol.name()));
return canHaveMethod(symbol, requiredMethod, classRequiredMethod);
}
}
InferredType type = subscriptionObject.type();
String typeName = InferredTypes.typeName(type);
String secondaryMessage = typeName != null ? String.format(SECONDARY_MESSAGE, typeName) : DEFAULT_SECONDARY_MESSAGE;
secondaries.put(typeClassLocation(type), secondaryMessage);
return type.canHaveMember(requiredMethod);
}
use of org.sonar.plugins.python.api.symbols.ClassSymbol in project sonar-python by SonarSource.
the class IterationOnNonIterableCheck method isValidIterable.
boolean isValidIterable(Expression expression, Map<LocationInFile, String> secondaries) {
if (expression.is(Tree.Kind.CALL_EXPR)) {
CallExpression callExpression = (CallExpression) expression;
Symbol calleeSymbol = callExpression.calleeSymbol();
if (calleeSymbol != null && calleeSymbol.is(Symbol.Kind.FUNCTION) && ((FunctionSymbol) calleeSymbol).isAsynchronous()) {
FunctionSymbol functionSymbol = (FunctionSymbol) calleeSymbol;
secondaries.put(functionSymbol.definitionLocation(), String.format(SECONDARY_MESSAGE, functionSymbol.name()));
return false;
}
}
if (expression instanceof HasSymbol) {
Symbol symbol = ((HasSymbol) expression).symbol();
if (symbol != null) {
if (symbol.is(Symbol.Kind.FUNCTION)) {
FunctionSymbol functionSymbol = (FunctionSymbol) symbol;
secondaries.put(functionSymbol.definitionLocation(), String.format(SECONDARY_MESSAGE, functionSymbol.name()));
return functionSymbol.hasDecorators();
}
if (symbol.is(Symbol.Kind.CLASS)) {
ClassSymbolImpl classSymbol = (ClassSymbolImpl) symbol;
secondaries.put(classSymbol.definitionLocation(), String.format(SECONDARY_MESSAGE, classSymbol.name()));
// Metaclasses might add the method by default
return classSymbol.hasSuperClassWithUnknownMetaClass() || classSymbol.hasUnresolvedTypeHierarchy();
}
}
}
InferredType type = expression.type();
String typeName = InferredTypes.typeName(type);
String secondaryMessage = typeName != null ? String.format(SECONDARY_MESSAGE, typeName) : DEFAULT_SECONDARY_MESSAGE;
secondaries.put(InferredTypes.typeClassLocation(type), secondaryMessage);
return type.canHaveMember("__iter__") || type.canHaveMember("__getitem__");
}
Aggregations