Search in sources :

Example 1 with ClassSymbol

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);
}
Also used : ClassSymbol(org.sonar.plugins.python.api.symbols.ClassSymbol) FunctionSymbol(org.sonar.plugins.python.api.symbols.FunctionSymbol) Symbol(org.sonar.plugins.python.api.symbols.Symbol) ClassSymbol(org.sonar.plugins.python.api.symbols.ClassSymbol) Name(org.sonar.plugins.python.api.tree.Name)

Example 2 with ClassSymbol

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("__");
}
Also used : ClassDef(org.sonar.plugins.python.api.tree.ClassDef) ClassSymbol(org.sonar.plugins.python.api.symbols.ClassSymbol)

Example 3 with ClassSymbol

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));
                }
            });
        });
    });
}
Also used : ClassDef(org.sonar.plugins.python.api.tree.ClassDef) ClassSymbol(org.sonar.plugins.python.api.symbols.ClassSymbol) Parameter(org.sonar.plugins.python.api.tree.Parameter)

Example 4 with ClassSymbol

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);
}
Also used : InferredType(org.sonar.plugins.python.api.types.InferredType) FunctionSymbol(org.sonar.plugins.python.api.symbols.FunctionSymbol) HasSymbol(org.sonar.plugins.python.api.tree.HasSymbol) ClassSymbol(org.sonar.plugins.python.api.symbols.ClassSymbol) FunctionSymbol(org.sonar.plugins.python.api.symbols.FunctionSymbol) Symbol(org.sonar.plugins.python.api.symbols.Symbol) ClassSymbol(org.sonar.plugins.python.api.symbols.ClassSymbol) CallExpression(org.sonar.plugins.python.api.tree.CallExpression) HasSymbol(org.sonar.plugins.python.api.tree.HasSymbol)

Example 5 with ClassSymbol

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__");
}
Also used : InferredType(org.sonar.plugins.python.api.types.InferredType) FunctionSymbol(org.sonar.plugins.python.api.symbols.FunctionSymbol) HasSymbol(org.sonar.plugins.python.api.tree.HasSymbol) ClassSymbol(org.sonar.plugins.python.api.symbols.ClassSymbol) FunctionSymbol(org.sonar.plugins.python.api.symbols.FunctionSymbol) Symbol(org.sonar.plugins.python.api.symbols.Symbol) ClassSymbolImpl(org.sonar.python.semantic.ClassSymbolImpl) CallExpression(org.sonar.plugins.python.api.tree.CallExpression) HasSymbol(org.sonar.plugins.python.api.tree.HasSymbol)

Aggregations

ClassSymbol (org.sonar.plugins.python.api.symbols.ClassSymbol)87 Test (org.junit.Test)64 Symbol (org.sonar.plugins.python.api.symbols.Symbol)55 AmbiguousSymbol (org.sonar.plugins.python.api.symbols.AmbiguousSymbol)48 FileInput (org.sonar.plugins.python.api.tree.FileInput)36 FunctionSymbol (org.sonar.plugins.python.api.symbols.FunctionSymbol)29 ClassDef (org.sonar.plugins.python.api.tree.ClassDef)29 ClassSymbolImpl (org.sonar.python.semantic.ClassSymbolImpl)13 HashMap (java.util.HashMap)11 HashSet (java.util.HashSet)11 Set (java.util.Set)11 List (java.util.List)10 Map (java.util.Map)10 Collectors (java.util.stream.Collectors)10 SymbolImpl (org.sonar.python.semantic.SymbolImpl)9 Collections (java.util.Collections)7 HasSymbol (org.sonar.plugins.python.api.tree.HasSymbol)7 InferredType (org.sonar.plugins.python.api.types.InferredType)7 Arrays (java.util.Arrays)6 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)6