<commit_before>package com.jetbrains.python.packaging;

import com.google.common.collect.ImmutableMap;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author vlan
 */
public class PyRequirement {
  private static final Pattern NAME = Pattern.compile("\\s*(\\w(\\w|[-.])*)\\s*(.*)");
  private static final Pattern VERSION_SPEC = Pattern.compile("\\s*(<=?|>=?|==|!=)\\s*((\\w|[-.])+)");
  private static final Pattern EDITABLE_EGG = Pattern.compile("\\s*(-e)?\\s*([^#]*)#egg=(.*)");
  private static final Pattern RECURSIVE_REQUIREMENT = Pattern.compile("\\s*-r\\s+(.*)");

  public enum Relation {
    LT("<"),
    LTE("<="),
    GT(">"),
    GTE(">="),
    EQ("=="),
    NE("!=");

    @NotNull private final String myValue;

    Relation(@NotNull String value) {
      myValue = value;
    }

    @NotNull
    @Override
    public String toString() {
      return myValue;
    }

    @Nullable
    public static Relation fromString(@NotNull String value) {
      for (Relation relation : Relation.values()) {
        if (relation.myValue.equals(value)) {
          return relation;
        }
      }
      return null;
    }

    public boolean isSuccessful(int comparisonResult) {
      switch (this) {
        case LT:
          return comparisonResult < 0;
        case LTE:
          return comparisonResult <= 0;
        case GT:
          return comparisonResult > 0;
        case GTE:
          return comparisonResult >= 0;
        case EQ:
          return comparisonResult == 0;
        case NE:
          return comparisonResult != 0;
      }
      return false;
    }
  }

  public static class VersionSpec {
    @NotNull private final Relation myRelation;
    @NotNull private final String myVersion;

    public VersionSpec(@NotNull Relation relation, @NotNull String version) {
      myRelation = relation;
      myVersion = version;
    }

    @Override
    public String toString() {
      return myRelation + myVersion;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      VersionSpec spec = (VersionSpec)o;
      if (myRelation != spec.myRelation) return false;
      if (!myVersion.equals(spec.myVersion)) return false;
      return true;
    }

    @Override
    public int hashCode() {
      int result = myRelation.hashCode();
      result = 31 * result + myVersion.hashCode();
      return result;
    }

    @NotNull
    public Relation getRelation() {
      return myRelation;
    }

    @NotNull
    public String getVersion() {
      return myVersion;
    }
  }

  @NotNull private final String myName;
  @NotNull private final List<VersionSpec> myVersionSpecs;
  @Nullable private final String myURL;
  private final boolean myEditable;

  public static final Comparator<String> VERSION_COMPARATOR = new Comparator<String>() {
    @Override
    public int compare(String version1, String version2) {
      final List<String> vs1 = parse(version1);
      final List<String> vs2 = parse(version2);
      int result = 0;
      for (int i = 0; i < vs1.size() && i < vs2.size(); i++) {
        result = vs1.get(i).compareTo(vs2.get(i));
        if (result != 0) {
          break;
        }
      }
      if (result == 0) {
        return vs1.size() - vs2.size();
      }
      return result;
    }

    @Nullable
    private String replace(@NotNull String s) {
      final Map<String, String> sub = ImmutableMap.of("pre", "c",
                                                      "preview", "c",
                                                      "rc", "c",
                                                      "dev", "@");
      final String tmp = sub.get(s);
      if (tmp != null) {
        s = tmp;
      }
      if (s.equals(".") || s.equals("-")) {
        return null;
      }
      if (s.matches("[0-9]+")) {
        final long value = Long.parseLong(s);
        return String.format("%08d", value);
      }
      return "*" + s;
    }

    @NotNull
    private List<String> parse(@Nullable String s) {
      // Version parsing from pkg_resources ensures that all the "pre", "alpha", "rc", etc. are sorted correctly
      final Pattern COMPONENT_RE = Pattern.compile("\\d+|[a-z]+|\\.|-|.+");
      final List<String> results = new ArrayList<String>();
      final Matcher matcher = COMPONENT_RE.matcher(s);
      while (matcher.find()) {
        final String component = replace(matcher.group());
        if (component == null) {
          continue;
        }
        results.add(component);
      }
      for (int i = results.size() - 1; i > 0; i--) {
        if ("00000000".equals(results.get(i))) {
          results.remove(i);
        }
        else {
          break;
        }
      }
      results.add("*final");
      return results;
    }
  };

  public PyRequirement(@NotNull String name) {
    this(name, Collections.<VersionSpec>emptyList());
  }<commit_msg>Fixed NPE in version comparator inside PyRequirement<commit_after>package com.jetbrains.python.packaging;

import com.google.common.collect.ImmutableMap;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author vlan
 */
public class PyRequirement {
  private static final Pattern NAME = Pattern.compile("\\s*(\\w(\\w|[-.])*)\\s*(.*)");
  private static final Pattern VERSION_SPEC = Pattern.compile("\\s*(<=?|>=?|==|!=)\\s*((\\w|[-.])+)");
  private static final Pattern EDITABLE_EGG = Pattern.compile("\\s*(-e)?\\s*([^#]*)#egg=(.*)");
  private static final Pattern RECURSIVE_REQUIREMENT = Pattern.compile("\\s*-r\\s+(.*)");

  public enum Relation {
    LT("<"),
    LTE("<="),
    GT(">"),
    GTE(">="),
    EQ("=="),
    NE("!=");

    @NotNull private final String myValue;

    Relation(@NotNull String value) {
      myValue = value;
    }

    @NotNull
    @Override
    public String toString() {
      return myValue;
    }

    @Nullable
    public static Relation fromString(@NotNull String value) {
      for (Relation relation : Relation.values()) {
        if (relation.myValue.equals(value)) {
          return relation;
        }
      }
      return null;
    }

    public boolean isSuccessful(int comparisonResult) {
      switch (this) {
        case LT:
          return comparisonResult < 0;
        case LTE:
          return comparisonResult <= 0;
        case GT:
          return comparisonResult > 0;
        case GTE:
          return comparisonResult >= 0;
        case EQ:
          return comparisonResult == 0;
        case NE:
          return comparisonResult != 0;
      }
      return false;
    }
  }

  public static class VersionSpec {
    @NotNull private final Relation myRelation;
    @NotNull private final String myVersion;

    public VersionSpec(@NotNull Relation relation, @NotNull String version) {
      myRelation = relation;
      myVersion = version;
    }

    @Override
    public String toString() {
      return myRelation + myVersion;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      VersionSpec spec = (VersionSpec)o;
      if (myRelation != spec.myRelation) return false;
      if (!myVersion.equals(spec.myVersion)) return false;
      return true;
    }

    @Override
    public int hashCode() {
      int result = myRelation.hashCode();
      result = 31 * result + myVersion.hashCode();
      return result;
    }

    @NotNull
    public Relation getRelation() {
      return myRelation;
    }

    @NotNull
    public String getVersion() {
      return myVersion;
    }
  }

  @NotNull private final String myName;
  @NotNull private final List<VersionSpec> myVersionSpecs;
  @Nullable private final String myURL;
  private final boolean myEditable;

  public static final Comparator<String> VERSION_COMPARATOR = new Comparator<String>() {
    @Override
    public int compare(String version1, String version2) {
      final List<String> vs1 = parse(version1);
      final List<String> vs2 = parse(version2);
      int result = 0;
      for (int i = 0; i < vs1.size() && i < vs2.size(); i++) {
        result = vs1.get(i).compareTo(vs2.get(i));
        if (result != 0) {
          break;
        }
      }
      if (result == 0) {
        return vs1.size() - vs2.size();
      }
      return result;
    }

    @Nullable
    private String replace(@NotNull String s) {
      final Map<String, String> sub = ImmutableMap.of("pre", "c",
                                                      "preview", "c",
                                                      "rc", "c",
                                                      "dev", "@");
      final String tmp = sub.get(s);
      if (tmp != null) {
        s = tmp;
      }
      if (s.equals(".") || s.equals("-")) {
        return null;
      }
      if (s.matches("[0-9]+")) {
        final long value = Long.parseLong(s);
        return String.format("%08d", value);
      }
      return "*" + s;
    }

    @NotNull
    private List<String> parse(@Nullable String s) {
      // Version parsing from pkg_resources ensures that all the "pre", "alpha", "rc", etc. are sorted correctly
      if (s == null) {
        return Collections.emptyList();
      }
      final Pattern COMPONENT_RE = Pattern.compile("\\d+|[a-z]+|\\.|-|.+");
      final List<String> results = new ArrayList<String>();
      final Matcher matcher = COMPONENT_RE.matcher(s);
      while (matcher.find()) {
        final String component = replace(matcher.group());
        if (component == null) {
          continue;
        }
        results.add(component);
      }
      for (int i = results.size() - 1; i > 0; i--) {
        if ("00000000".equals(results.get(i))) {
          results.remove(i);
        }
        else {
          break;
        }
      }
      results.add("*final");
      return results;
    }
  };

  public PyRequirement(@NotNull String name) {
    this(name, Collections.<VersionSpec>emptyList());
  }
{'fraction_non_alphanumeric': 0.13592054441787751, 'fraction_numerical': 0.0069891484274416035, 'mean_word_length': 2.236607142857143, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1116533', 'n_tokens_mistral': 3281, 'n_tokens_neox': 3178, 'n_words': 815}