function JsCpd() {}n/a
function StorageMemory() {
this.codeHashes = {};
}n/a
function TokenizerBase() {
this.skipComments = false;
this.tokenTypes = [];
}n/a
function TokenizerCodeMirror() {
this.tokenize = bind(this.tokenize, this);
return TokenizerCodeMirror.__super__.constructor.apply(this, arguments);
}n/a
function TokenizerFactory() {}n/a
function StorageMemory() {
this.codeHashes = {};
}n/a
addHash = function (hash, file, line, language) {
var ref;
this.codeHashes[language] = (ref = this.codeHashes[language]) != null ? ref : {};
return this.codeHashes[language][hash] = {
line: line,
file: file
};
}...
} 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;
...getHash = function (hash, language) {
var ref;
return (ref = this.codeHashes[language]) != null ? ref[hash] : void 0;
}...
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));
}
};
...hasHash = function (hash, language) {
return this.codeHashes[language] && hash in this.codeHashes[language];
}...
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 {
...function TokenizerBase() {
this.skipComments = false;
this.tokenTypes = [];
}n/a
createMap = function (type, value) {
return String.fromCharCode(this.getTokenTypeId(type)) + crypto.createHash('md5').update(value.toString()).digest('hex');
}...
ref = this.tokens;
for (i = 0, len = ref.length; i < len; i++) {
ref1 = ref[i], type = ref1[0], value = ref1[1], lineNumber = ref1[2];
if (!(this.validToken(type))) {
continue;
}
tokensPositions.push(lineNumber);
currentMap = currentMap + this.createMap(type, value);
}
return {
tokensPositions: tokensPositions,
currentMap: currentMap
};
};
...generateMap = function () {}...
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)) {
...getTokenTypeId = function (name) {
var result;
result = 0;
if (indexOf.call(this.tokenTypes, name) >= 0) {
result = this.tokenTypes.indexOf(name);
} else {
result = this.tokenTypes.length;
this.tokenTypes.push(name);
}
return result;
}...
result = this.tokenTypes.length;
this.tokenTypes.push(name);
}
return result;
};
TokenizerBase.prototype.createMap = function(type, value) {
return String.fromCharCode(this.getTokenTypeId(type)) + crypto.createHash('md5
').update(value.toString()).digest('hex');
};
return TokenizerBase;
})();
module.exports = TokenizerBase;
...getType = function () {}...
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;
...isEmptyToken = function (value) {
return value.replace(/^\s+|\s+$/g, '').length === 0;
}...
this.tokens = [];
this.loadType(this.type);
CodeMirror.runMode(code, this.mode, (function(_this) {
return function(value, tokenType, lineNumber) {
if (!lineNumber) {
return;
}
tokenType = _this.isEmptyToken(value) ? 'empty' : tokenType;
tokenType = tokenType != null ? tokenType : 'default';
return _this.tokens.push([tokenType, value, lineNumber]);
};
})(this));
return this;
};
...tokenize = function (code) {}...
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)) {
...validToken = function (type) {
var ref;
return (((ref = this.type) === 'coffeescript' || ref === 'python' || ref === 'ruby') || type !== 'empty') && (!this.skipComments
|| type !== 'comment');
}...
TokenizerCodeMirror.prototype.generateMap = function() {
var currentMap, i, len, lineNumber, ref, ref1, tokensPositions, type, value;
currentMap = "";
tokensPositions = [];
ref = this.tokens;
for (i = 0, len = ref.length; i < len; i++) {
ref1 = ref[i], type = ref1[0], value = ref1[1], lineNumber = ref1[2];
if (!(this.validToken(type))) {
continue;
}
tokensPositions.push(lineNumber);
currentMap = currentMap + this.createMap(type, value);
}
return {
tokensPositions: tokensPositions,
...function TokenizerCodeMirror() {
this.tokenize = bind(this.tokenize, this);
return TokenizerCodeMirror.__super__.constructor.apply(this, arguments);
}n/a
function TokenizerCodeMirror() {
this.tokenize = bind(this.tokenize, this);
return TokenizerCodeMirror.__super__.constructor.apply(this, arguments);
}n/a
generateMap = function () {
var currentMap, i, len, lineNumber, ref, ref1, tokensPositions, type, value;
currentMap = "";
tokensPositions = [];
ref = this.tokens;
for (i = 0, len = ref.length; i < len; i++) {
ref1 = ref[i], type = ref1[0], value = ref1[1], lineNumber = ref1[2];
if (!(this.validToken(type))) {
continue;
}
tokensPositions.push(lineNumber);
currentMap = currentMap + this.createMap(type, value);
}
return {
tokensPositions: tokensPositions,
currentMap: currentMap
};
}...
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)) {
...getType = function () {
return this.type;
}...
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;
...loadType = function (type) {
var e;
try {
CodeMirror.loadMode(type);
} catch (error) {
e = error;
if (e.code === 'MODULE_NOT_FOUND') {
logger.debug("" + e);
console.error("JSCPD Error 01: " + type + " in not supported");
}
}
return this;
}...
}
}
return this;
};
TokenizerCodeMirror.prototype.tokenize = function(code) {
this.tokens = [];
this.loadType(this.type);
CodeMirror.runMode(code, this.mode, (function(_this) {
return function(value, tokenType, lineNumber) {
if (!lineNumber) {
return;
}
tokenType = _this.isEmptyToken(value) ? 'empty' : tokenType;
tokenType = tokenType != null ? tokenType : 'default';
...setTypeAndMode = function (language) {
switch (language) {
case "csharp":
case "java":
this.type = 'clike';
return this.mode = "text/" + language;
case 'typescript':
this.type = 'javascript';
return this.mode = "text/" + language;
case 'jsx':
this.type = 'javascript';
return this.mode = "text/javascript";
default:
this.type = language;
return this.mode = language;
}
}...
}
language = TokenizerFactory.prototype.getLanguageByExtension(extension);
if (indexOf.call(supportedLanguages, language) < 0) {
return false;
}
if (!(language in TokenizerFactory.prototype.tokenizers)) {
TokenizerFactory.prototype.tokenizers[language] = new TokenizerCodeMirror();
TokenizerFactory.prototype.tokenizers[language].setTypeAndMode(language);
}
return TokenizerFactory.prototype.tokenizers[language];
};
return TokenizerFactory;
})();
...tokenize = function (code) {
this.tokens = [];
this.loadType(this.type);
CodeMirror.runMode(code, this.mode, (function(_this) {
return function(value, tokenType, lineNumber) {
if (!lineNumber) {
return;
}
tokenType = _this.isEmptyToken(value) ? 'empty' : tokenType;
tokenType = tokenType != null ? tokenType : 'default';
return _this.tokens.push([tokenType, value, lineNumber]);
};
})(this));
return this;
}...
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)) {
...function TokenizerFactory() {}n/a
getExtensionsByLanguages = function (languages) {
var language, result;
if (typeof languages === 'string') {
languages = [languages];
}
result = [];
for (language in TokenizerFactory.prototype.LANGUAGES) {
if (indexOf.call(languages, language) >= 0) {
result.push.apply(result, TokenizerFactory.prototype.LANGUAGES[language]);
}
}
return result;
}...
TokenizerFactory.prototype.LANGUAGES[lang] = exts;
}
}
}
if (typeof optionsNew.languages === 'string') {
optionsNew.languages = optionsNew.languages.split(',');
}
optionsNew.extensions = TokenizerFactory.prototype.getExtensionsByLanguages(optionsNew
.languages);
return optionsNew;
};
readConfig = function(file) {
var doc, error;
file = path.normalize(file);
try {
...getLanguageByExtension = function (extension) {
var language;
for (language in TokenizerFactory.prototype.LANGUAGES) {
if (indexOf.call(TokenizerFactory.prototype.LANGUAGES[language], extension) >= 0) {
return language;
}
}
return false;
}...
TokenizerFactory.prototype.makeTokenizer = function(filename, supportedLanguages) {
var extension, language, matches, ref;
extension = '';
matches = filename.match(/\.(\w*)$/);
if (matches) {
extension = (ref = matches[1]) != null ? ref.toLowerCase() : void 0;
}
language = TokenizerFactory.prototype.getLanguageByExtension(extension);
if (indexOf.call(supportedLanguages, language) < 0) {
return false;
}
if (!(language in TokenizerFactory.prototype.tokenizers)) {
TokenizerFactory.prototype.tokenizers[language] = new TokenizerCodeMirror();
TokenizerFactory.prototype.tokenizers[language].setTypeAndMode(language);
}
...makeTokenizer = function (filename, supportedLanguages) {
var extension, language, matches, ref;
extension = '';
matches = filename.match(/\.(\w*)$/);
if (matches) {
extension = (ref = matches[1]) != null ? ref.toLowerCase() : void 0;
}
language = TokenizerFactory.prototype.getLanguageByExtension(extension);
if (indexOf.call(supportedLanguages, language) < 0) {
return false;
}
if (!(language in TokenizerFactory.prototype.tokenizers)) {
TokenizerFactory.prototype.tokenizers[language] = new TokenizerCodeMirror();
TokenizerFactory.prototype.tokenizers[language].setTypeAndMode(language);
}
return TokenizerFactory.prototype.tokenizers[language];
}...
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 {
...function Clone(firstFile, secondFile, firstFileStart, secondFileStart, linesCount, tokensCount) {
this.firstFile = firstFile;
this.secondFile = secondFile;
this.firstFileStart = firstFileStart;
this.secondFileStart = secondFileStart;
this.linesCount = linesCount;
this.tokensCount = tokensCount;
this.firstFileAnnotatedCode = {};
this.secondFileAnnotatedCode = {};
}n/a
function Detector(strategy) {
this.strategy = strategy;
}n/a
function JsCpd() {}n/a
execPreProcessors = function (list) {
var i, len, preProcessor;
logger.profile('Preprocessors running time:');
for (i = 0, len = list.length; i < len; i++) {
preProcessor = list[i];
preProcessor(this);
}
return logger.profile('Preprocessors running time:');
}...
}
return logger.profile('Preprocessors running time:');
};
JsCpd.prototype.run = function(options) {
var clone, codeMap, detector, generateReport, report, strategy;
this.options = options;
this.execPreProcessors(this.preProcessors);
if (!this.options.debug) {
logger.profile('Scanning for duplicates time:');
if (this.options.selectedFiles.length) {
logger.info("Scanning " + this.options.selectedFiles.length + " files for duplicates...");
}
strategy = new Strategy(this.options);
detector = new Detector(strategy);
...run = function (options) {
var clone, codeMap, detector, generateReport, report, strategy;
this.options = options;
this.execPreProcessors(this.preProcessors);
if (!this.options.debug) {
logger.profile('Scanning for duplicates time:');
if (this.options.selectedFiles.length) {
logger.info("Scanning " + this.options.selectedFiles.length + " files for duplicates...");
}
strategy = new Strategy(this.options);
detector = new Detector(strategy);
report = new Report(this.options);
codeMap = detector.start(this.options.selectedFiles, this.options['min-lines'], this.options['min-tokens']);
logger.profile('Scanning for duplicates time:');
logger.info('Scanning... done!\n');
logger.profile('Generate report time:');
logger.info('Start report generation...\n');
generateReport = (function(_this) {
return function() {
var reportResult;
reportResult = report.generate(codeMap);
logger.profile('Generate report time:');
_this.report = reportResult;
_this.map = codeMap;
return {
report: _this.report,
map: _this.map
};
};
})(this);
if (this.options.blame) {
return Promise.all((function() {
var i, len, ref, results;
ref = codeMap.clones;
results = [];
for (i = 0, len = ref.length; i < len; i++) {
clone = ref[i];
results.push(clone.blame());
}
return results;
})()).then(generateReport).error(generateReport);
} else {
return generateReport();
}
}
}...
});
cli.main(function(args, options) {
var jscpd;
jscpd = new JsCpd;
logger.profile("All time:");
logger.info("jscpd - copy/paste detector for programming source code, developed by Andrey Kucherenko");
jscpd.run(options);
return logger.profile("All time:");
});
}).call(this);
...0 = function (jscpd) {
var config, options;
if (jscpd.options.config != null) {
config = readConfig(jscpd.options.config);
if (!config) {
throw new Error("JSCPD Error 02: can't read config file " + jscpd.options.config);
}
process.chdir(path.dirname(jscpd.options.config));
} else {
config = readConfig('.cpd.yaml') || readConfig('.cpd.yml') || {};
}
options = prepareOptions(jscpd.options, config);
if (!path.isAbsolute(options.path || '')) {
options.path = path.resolve(process.cwd(), options.path || '');
}
return jscpd.options = options;
}n/a
1 = function (jscpd) {
prepareOptions(jscpd);
return jscpd.options.selectedFiles = findFiles(jscpd);
}n/a
2 = function (jscpd) {
var file, i, len, name, option, ref, ref1;
if (jscpd.options.debug) {
logger.info('----------------------------------------');
logger.info('Options:');
ref = jscpd.options;
for (name in ref) {
option = ref[name];
if (name !== 'selectedFiles') {
logger.info(name + " = " + option);
}
}
logger.info('----------------------------------------');
logger.info('Files:');
ref1 = jscpd.options.selectedFiles;
for (i = 0, len = ref1.length; i < len; i++) {
file = ref1[i];
logger.info(file);
}
logger.info('----------------------------------------');
return logger.info('Run without debug option for start detection process');
}
}n/a
function Map() {
this.clones = [];
this.clonesByFile = {};
this.numberOfDuplication = 0;
this.numberOfLines = 0;
this.numberOfFiles = 0;
}n/a
function Report(options) {
var cwd, ext, isAbsolute, reporter;
this.options = options;
reporter = this.options.reporter;
if (this.options.output) {
ext = this.options.output.split('.').pop();
}
if (ext === 'xml' && reporter === 'json' || ext === 'json' && reporter === 'xml') {
logger.warn("output file extention '" + this.options.output + "' does not match reporter '" + reporter + "'");
}
switch (reporter) {
case 'xml':
reporter = './reporters/xml-pmd';
break;
case 'json':
reporter = './reporters/json';
break;
default:
cwd = process.cwd();
reporter = path.normalize(reporter);
isAbsolute = reporter.indexOf(cwd) === 0;
if (!isAbsolute) {
reporter = path.join(cwd, reporter);
}
}
this.reporter = require(reporter);
this.stdReporter = require('./reporters/_std-log');
}n/a
function Strategy(options) {
this.options = options;
this.languages = options.languages;
this.storage = new Storage();
}n/a