Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ Parser.prototype._parseBlockElements = function(indexApiBlocks, detectedElements
preventGlobal = elementParser.preventGlobal === true;

// allow multiple inserts into pathTo
allowMultiple = elementParser.allowMultiple === true;
allowMultiple = true;


// path to an array, where the values should be attached
Expand Down
2 changes: 1 addition & 1 deletion lib/parsers/api_private.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function parse(content) {
function parse() {
return 'private';
}

Expand Down
100 changes: 59 additions & 41 deletions lib/workers/api_use.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,70 +66,88 @@ function postProcess(parsedFiles, filenames, preProcess, packageInfos, source, t

parsedFiles.forEach(function(parsedFile, parsedFileIndex) {
parsedFile.forEach(function(block) {
if ( ! block.local[target])
return;

block.local[target].forEach(function(definition) {
var name = definition.name;
var version = block.version || packageInfos.defaultVersion;

if ( ! preProcess[source] || ! preProcess[source][name]) {
throw new WorkerError('Referenced groupname does not exist / it is not defined with @apiDefine.',
var loopCounter = 0; //add a loop counter to have a break condition when the recursion depth exceed a predifined limit
while (block.local[target]) {
if (loopCounter > 10) {
throw new WorkerError('recursion depth exceeds limit with @apiUse',
filenames[parsedFileIndex],
block.index,
messages.common.element,
messages.common.usage,
messages.common.example,
[
{ 'Groupname': name }
{ 'Groupname': block.name }
]
);
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line has whitespaces (we should really have an automatic tool to look/fix these minor issues...)

//create a copy of the elements for save iterating of the elements
var blockClone = block.local[target].slice();

var matchedData = {};
if (preProcess[source][name][version]) {
// found the version
matchedData = preProcess[source][name][version];
} else {
// find nearest matching version
var foundIndex = -1;
var lastVersion = packageInfos.defaultVersion;

var versionKeys = Object.keys(preProcess[source][name]);
versionKeys.forEach(function(currentVersion, versionIndex) {
if (semver.gte(version, currentVersion) && semver.gte(currentVersion, lastVersion)) {
lastVersion = currentVersion;
foundIndex = versionIndex;
}
});
// remove unneeded target before starting the loop, to allow a save insertion of new elements
// TODO: create a cleanup filter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you expand on that? It's not great to add a TODO ;)

Copy link
Contributor Author

@tommy87 tommy87 May 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not from me. I only moved the ToDo and the delete upwards. Before my change both were located in the foreach loop at line 127

Copy link
Contributor Author

@tommy87 tommy87 May 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the connected ticket you can see the changes i made in a better overview. Githubs pull request didnt resolve the extra space i add for the new while loop

delete block.local[target];

if (foundIndex === -1) {
throw new WorkerError('Referenced definition has no matching or a higher version. ' +
'Check version number in referenced define block.',
for (var blockIndex = 0; blockIndex < blockClone.length; ++blockIndex) {
var definition = blockClone[blockIndex];
var name = definition.name;
var version = block.version || packageInfos.defaultVersion;

if ( ! preProcess[source] || ! preProcess[source][name]) {
throw new WorkerError('Referenced groupname does not exist / it is not defined with @apiDefine.',
filenames[parsedFileIndex],
block.index,
messages.common.element,
messages.common.usage,
messages.common.example,
[
{ 'Groupname': name },
{ 'Version': version },
{ 'Defined versions': versionKeys },
{ 'Groupname': name }
]
);
}

var versionName = versionKeys[foundIndex];
matchedData = preProcess[source][name][versionName];
}
var matchedData = {};
if (preProcess[source][name][version]) {
// found the version
matchedData = preProcess[source][name][version];
} else {
// find nearest matching version
var foundIndex = -1;
var lastVersion = packageInfos.defaultVersion;

var versionKeys = Object.keys(preProcess[source][name]);
for (var versionIndex = 0; versionIndex < versionKeys.length; ++versionIndex) {
var currentVersion = versionKeys[versionIndex];
if (semver.gte(version, currentVersion) && semver.gte(currentVersion, lastVersion)) {
lastVersion = currentVersion;
foundIndex = versionIndex;
}
}

// remove target, not needed anymore
// TODO: create a cleanup filter
delete block.local[target];
if (foundIndex === -1) {
throw new WorkerError('Referenced definition has no matching or a higher version. ' +
'Check version number in referenced define block.',
filenames[parsedFileIndex],
block.index,
messages.common.element,
messages.common.usage,
messages.common.example,
[
{ 'Groupname': name },
{ 'Version': version },
{ 'Defined versions': versionKeys },
]
);
}

// copy matched elements into parsed block
_recursiveMerge(block.local, matchedData);
});
var versionName = versionKeys[foundIndex];
matchedData = preProcess[source][name][versionName];
}

// copy matched elements into parsed block
_recursiveMerge(block.local, matchedData);
}
}
});
});
}
Expand Down
211 changes: 211 additions & 0 deletions test/worker_api_use_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/*jshint unused:false*/

/**
* Test: Parser apiParam
*/

// node modules
var should = require('should');

// lib modules
var worker = require('../lib/workers/api_use');

describe('Worker: apiUse', function() {

var packageInfos = {
name: 'Test recursive apiUse',
version: '0.0.1',
description: 'i am a dummy description',
title: 'Test recursive apiUse',
url: 'http://localhost:18080',
order: [ 'GetUser', 'PostUser' ],
template: { withCompare: false, withGenerator: true },
sampleUrl: false,
defaultVersion: '0.0.0'
};

var filenames = [ 'fileA', 'fileB', 'fileC' ];

// TODO: Add 1.000 more possible cases ;-)
// the tree is build like
// root
// l
var parsedFilesSimpleTest = [
//file
[
{
global: { },
local: {
use: [
{ name: 'leaf_l' }
],
name: 'root',
test: ['root']
},
expected: 'root',
},
{
global: {
define: {
name: 'leaf_l',
title: '',
description: '',
}
},
local: {
test: ['l']
},
expected: 'l'
}
]
];

// the tree is build like
// root
// l, r
// ll, rr
// rrl, rrr
var parsedFilesRecursiveTest = [
//file
[
{
global: { },
local: {
use: [
{ name: 'leaf_l' },
{ name: 'leaf_r' },
],
name: 'root',
test: ['root']
},
expected: 'root',
}
],
[
{
global: {
define: {
name: 'leaf_l',
title: '',
description: '',
}
},
local: {
test: ['l'],
use: [
{ name: 'leaf_ll' }
],
},
expected: 'l'
},
{
global: {
define: {
name: 'leaf_rr',
title: '',
description: '',
}
},
local: {
test: ['rr'],
use: [
{ name: 'leaf_rrr' },
{ name: 'leaf_rrl' }
],
},
expected: 'rr'
}
],
[
{
global: {
define: {
name: 'leaf_ll',
title: '',
description: '',
}
},
local: {
test: ['ll']
},
expected: 'll'
},
{
global: {
define: {
name: 'leaf_r',
title: '',
description: '',
}
},
local: {
test: ['r'],
use: [
{ name: 'leaf_rr' }
],
},
expected: 'r'
},
{
global: {
define: {
name: 'leaf_rrr',
title: '',
description: '',
}
},
local: {
test: ['rrr']
},
expected: 'rrr'
},
{
global: {
define: {
name: 'leaf_rrl',
title: '',
description: '',
}
},
local: {
test: ['rrl']
},
expected: 'rrl'
}
]
];

// create
it('case 1: simple test', function(done) {
var preProcess = worker.preProcess(parsedFilesSimpleTest, filenames, packageInfos);
worker.postProcess(parsedFilesSimpleTest, filenames, preProcess, packageInfos);

var rootBlock = parsedFilesSimpleTest[0][0];
rootBlock.local.name.should.eql('root');

//check if the root block contains the expected value from every other block
parsedFilesSimpleTest.forEach(function(parsedFile, parsedFileIndex) {
parsedFile.forEach(function(block) {
rootBlock.local.test.should.containEql(block.expected);
});
});
done();
});

it('case 2: recursive test', function(done) {
var preProcess = worker.preProcess(parsedFilesRecursiveTest, filenames, packageInfos);
worker.postProcess(parsedFilesRecursiveTest, filenames, preProcess, packageInfos);

var rootBlock = parsedFilesRecursiveTest[0][0];
rootBlock.local.name.should.eql('root');

//check if the root block contains the expected value from every other block
parsedFilesRecursiveTest.forEach(function(parsedFile, parsedFileIndex) {
parsedFile.forEach(function(block) {
rootBlock.local.test.should.containEql(block.expected);
});
});
done();
});

});