UNPKG

jscpd

Version:

Copy/paste detector for programming code, support JavaScript, CoffeeScript, PHP, Ruby, Python, Less, Go, Java, Yaml, C#, C++, C languages

89 lines (76 loc) 3.21 kB
// Generated by CoffeeScript 1.10.0 (function() { var Clone, Storage, Strategy, TokenizerFactory, crypto, shjs; shjs = require('shelljs'); TokenizerFactory = require('./tokenizer/TokenizerFactory'); crypto = require('crypto'); Storage = require('./storage/StorageMemory'); Clone = require('./clone').Clone; Strategy = (function() { function Strategy(options) { this.options = options; this.languages = options.languages; this.storage = new Storage(); } Strategy.prototype.detect = function(map, file, minLines, minTokens) { var code, currentMap, firstHash, firstLine, firstToken, hash, isClone, language, lastToken, lines, mapFrame, ref, tokenNumber, tokenizer, tokensPositions; this.minLines = minLines; this.minTokens = minTokens; tokenizer = TokenizerFactory.prototype.makeTokenizer(file, this.languages); if (!tokenizer) { return false; } language = tokenizer.getType(); if (shjs.test('-f', file)) { code = shjs.cat(file); } else { return false; } lines = code.split('\n'); map.numberOfLines = map.numberOfLines + lines.length; tokenizer.skipComments = this.options['skip-comments']; ref = tokenizer.tokenize(code).generateMap(), tokensPositions = ref.tokensPositions, currentMap = ref.currentMap; firstLine = 0; tokenNumber = 0; isClone = false; while (tokenNumber <= tokensPositions.length - this.minTokens) { mapFrame = currentMap.substring(tokenNumber * 33, tokenNumber * 33 + this.minTokens * 33); hash = crypto.createHash('md5').update(mapFrame).digest('hex'); if (this.storage.hasHash(hash, language)) { isClone = true; if (firstLine === 0) { firstLine = tokensPositions[tokenNumber]; firstHash = hash; firstToken = tokenNumber; } } else { if (isClone) { lastToken = tokenNumber + this.minTokens - 2; this.addClone(map, file, firstHash, firstToken, lastToken, firstLine, tokensPositions[lastToken], language); firstLine = 0; isClone = false; } this.storage.addHash(hash, file, tokensPositions[tokenNumber], language); } tokenNumber = tokenNumber + 1; } if (isClone) { lastToken = tokenNumber + this.minTokens - 2; this.addClone(map, file, firstHash, firstToken, lastToken, firstLine, tokensPositions[lastToken], language); return isClone = false; } }; Strategy.prototype.addClone = function(map, file, hash, firstToken, lastToken, firstLine, lastLine, language) { var fileA, firstLineA, hashInfo, numLines; hashInfo = this.storage.getHash(hash, language); fileA = hashInfo.file; firstLineA = hashInfo.line; numLines = lastLine + 1 - firstLine; if (numLines >= this.minLines && (fileA !== file || firstLineA !== firstLine)) { return map.addClone(new Clone(fileA, file, firstLineA, firstLine, numLines, lastToken - firstToken + 1)); } }; return Strategy; })(); exports.Strategy = Strategy; }).call(this);