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

org.sonar.python.tree.TokenEnricher 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.tree;

import com.sonar.sslr.api.Token;
import java.util.List;
import java.util.Map;
import org.sonar.plugins.python.api.tree.Trivia;
import org.sonar.python.EscapeCharPositionInfo;
import org.sonar.python.IPythonLocation;

public class TokenEnricher {

  private TokenEnricher() {
  }

  public static List enrichTokens(List tokens, Map offsetMap) {
    return tokens.stream().map(token -> enrichToken(token, offsetMap)).toList();
  }

  public static TokenImpl enrichToken(Token token, Map offsetMap) {
    if (!offsetMap.isEmpty()) {
      IPythonLocation location = offsetMap.get(token.getLine());
      if (location == null) {
        throw new IllegalStateException(String.format("No IPythonLocation found for line %s", token.getLine()));
      }
      List escapeCharPositionInfos = location.colOffsets();
      int startCol = token.getColumn();
      int endCol = token.getColumn() + token.getValue().length();
      int ipynbStartCol = computeColWithEscapes(location.column(), startCol, escapeCharPositionInfos);
      int escapedCharInToken = computeEscapeCharsInToken(escapeCharPositionInfos, startCol, endCol);
      List trivia = token.getTrivia().stream()
        .map(t -> computeTriviaLocation(t, location.line(), ipynbStartCol, token.getLine(), offsetMap))
        .toList();

      return new TokenImpl(token, location.line(), ipynbStartCol, escapedCharInToken, trivia, location.isCompresssed());
    }
    return new TokenImpl(token);
  }

  private static Trivia computeTriviaLocation(com.sonar.sslr.api.Trivia trivia, int parentLine, int parentCol, int parentPythonLine,
    Map offsetMap) {
    var line = parentLine;
    int escapedCharInToken = computeEscapeCharsInTrivia(trivia, offsetMap);
    var col = parentCol - escapedCharInToken - trivia.getToken().getValue().length();
    var isCompressed = false;
    if (parentPythonLine != trivia.getToken().getLine()) {
      IPythonLocation location = offsetMap.get(trivia.getToken().getLine());
      line = location.line();
      List escapeCharPositionInfos = location.colOffsets();
      col = computeColWithEscapes(location.column(), trivia.getToken().getColumn(), escapeCharPositionInfos);
      isCompressed = location.isCompresssed();
    }
    return new TriviaImpl(new TokenImpl(trivia.getToken(), line, col,
      escapedCharInToken, List.of(), isCompressed));
  }

  private static int computeColWithEscapes(int offsetColumn, int currentCol, List escapeCharPositionInfos) {
    int escapedCharsOffset = computeEscapeCharsInToken(escapeCharPositionInfos, 0, currentCol);
    return offsetColumn + currentCol + escapedCharsOffset;
  }

  private static int computeEscapeCharsInTrivia(com.sonar.sslr.api.Trivia trivia, Map offsetMap) {
    IPythonLocation location = offsetMap.get(trivia.getToken().getLine());
    Token token = trivia.getToken();
    int startCol = token.getColumn();
    int endCol = token.getColumn() + token.getValue().length();
    return computeEscapeCharsInToken(location.colOffsets(), startCol, endCol);
  }

  private static int computeEscapeCharsInToken(List escapeCharPositionInfos, int startCol, int endCol) {
    return escapeCharPositionInfos.stream()
      .filter(entry -> entry.columnInIpynbFile() >= startCol && entry.columnInIpynbFile() < endCol)
      .mapToInt(EscapeCharPositionInfo::numberOfExtraChars)
      .sum();
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy