All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.python.semantic.v2.ScopeV2 Maven / Gradle / Ivy

The newest version!
/*
 * SonarQube Python Plugin
 * Copyright (C) 2011-2024 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the Sonar Source-Available License for more details.
 *
 * You should have received a copy of the Sonar Source-Available License
 * along with this program; if not, see https://sonarsource.com/license/ssal/
 */
package org.sonar.python.semantic.v2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.plugins.python.api.tree.Name;
import org.sonar.plugins.python.api.tree.Parameter;
import org.sonar.plugins.python.api.tree.Tree;

public class ScopeV2 {
  private final ScopeV2 parent;
  private final Tree rootTree;
  private final List childrenScopes;
  private final Map symbolsByName = new HashMap<>();
  private final Set symbols = new HashSet<>();
  private final Set globalNames = new HashSet<>();
  private final Set nonlocalNames = new HashSet<>();

  public ScopeV2(@Nullable ScopeV2 parent, Tree rootTree) {
    this.parent = parent;
    this.rootTree = rootTree;
    this.childrenScopes = new ArrayList<>();
  }

  public ScopeV2 parent() {
    return parent;
  }

  public Tree root() {
    return rootTree;
  }

  void addBindingUsage(Name nameTree, UsageV2.Kind kind) {
    String symbolName = nameTree.name();
    if (!isExistingSymbol(symbolName)) {
      SymbolV2 symbol = new SymbolV2(symbolName);
      symbols.add(symbol);
      symbolsByName.put(symbolName, symbol);
    }
    SymbolV2 symbol = resolve(symbolName);
    if (symbol != null) {
      symbol.addUsage(nameTree, kind);
    }
  }

  @CheckForNull
  SymbolV2 resolve(String symbolName) {
    SymbolV2 symbol = symbolsByName.get(symbolName);
    if (parent == null || symbol != null) {
      return symbol;
    }
    // parent scope of a symbol inside of a class its the classes parent scope
    if (parent.rootTree.is(Tree.Kind.CLASSDEF)) {
      return parent.parent.resolve(symbolName);
    }
    return parent.resolve(symbolName);
  }

  private boolean isExistingSymbol(String symbolName) {
    return symbolsByName.containsKey(symbolName) || globalNames.contains(symbolName) || nonlocalNames.contains(symbolName);
  }

  void createSelfParameter(Parameter parameter) {
    Name nameTree = parameter.name();
    if (nameTree == null) {
      return;
    }
    String symbolName = nameTree.name();
    //TODO: SONARPY-1865 Represent "self"
    SymbolV2 symbol = new SymbolV2(symbolName);
    symbols.add(symbol);
    symbolsByName.put(symbolName, symbol);
    symbol.addUsage(nameTree, UsageV2.Kind.PARAMETER);
  }

  public void addGlobalName(Name name) {
    this.globalNames.add(name.name());
  }

  public void addNonLocalName(Name name) {
    this.nonlocalNames.add(name.name());
  }

  public Map symbols() {
    return symbolsByName;
  }

  public List childrenScopes() {
    return childrenScopes;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy