You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PmdBlockChunker.java 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2018 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.duplications.internal.pmd;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import javax.annotation.concurrent.Immutable;
  24. import org.sonar.api.batch.sensor.cpd.internal.TokensLine;
  25. import org.sonar.duplications.block.Block;
  26. import org.sonar.duplications.block.ByteArray;
  27. /**
  28. * Differences with {@link org.sonar.duplications.block.BlockChunker}:
  29. * works with {@link TokensLine},
  30. * sets {@link Block#getStartUnit() startUnit} and {@link Block#getEndUnit() endUnit} - indexes of first and last token for this block.
  31. */
  32. @Immutable
  33. public class PmdBlockChunker {
  34. private static final long PRIME_BASE = 31;
  35. private final int blockSize;
  36. private final long power;
  37. public PmdBlockChunker(int blockSize) {
  38. this.blockSize = blockSize;
  39. long pow = 1;
  40. for (int i = 0; i < blockSize - 1; i++) {
  41. pow = pow * PRIME_BASE;
  42. }
  43. this.power = pow;
  44. }
  45. /**
  46. * @return ArrayList as we need a serializable object
  47. */
  48. public List<Block> chunk(String resourceId, List<TokensLine> fragments) {
  49. List<TokensLine> filtered = new ArrayList<>();
  50. int i = 0;
  51. while (i < fragments.size()) {
  52. TokensLine first = fragments.get(i);
  53. int j = i + 1;
  54. while (j < fragments.size() && fragments.get(j).getValue().equals(first.getValue())) {
  55. j++;
  56. }
  57. filtered.add(fragments.get(i));
  58. if (i < j - 1) {
  59. filtered.add(fragments.get(j - 1));
  60. }
  61. i = j;
  62. }
  63. fragments = filtered;
  64. if (fragments.size() < blockSize) {
  65. return new ArrayList<>();
  66. }
  67. TokensLine[] fragmentsArr = fragments.toArray(new TokensLine[fragments.size()]);
  68. List<Block> blocks = new ArrayList<>(fragmentsArr.length - blockSize + 1);
  69. long hash = 0;
  70. int first = 0;
  71. int last = 0;
  72. for (; last < blockSize - 1; last++) {
  73. hash = hash * PRIME_BASE + fragmentsArr[last].getHashCode();
  74. }
  75. Block.Builder blockBuilder = Block.builder().setResourceId(resourceId);
  76. for (; last < fragmentsArr.length; last++, first++) {
  77. TokensLine firstFragment = fragmentsArr[first];
  78. TokensLine lastFragment = fragmentsArr[last];
  79. // add last statement to hash
  80. hash = hash * PRIME_BASE + lastFragment.getHashCode();
  81. // create block
  82. Block block = blockBuilder
  83. .setBlockHash(new ByteArray(hash))
  84. .setIndexInFile(first)
  85. .setLines(firstFragment.getStartLine(), lastFragment.getEndLine())
  86. .setUnit(firstFragment.getStartUnit(), lastFragment.getEndUnit())
  87. .build();
  88. blocks.add(block);
  89. // remove first statement from hash
  90. hash -= power * firstFragment.getHashCode();
  91. }
  92. return blocks;
  93. }
  94. }