chore(doc-gen): remove Traceur bits

This commit is contained in:
Peter Bacon Darwin 2015-05-15 13:57:38 +01:00
parent b2da2978ee
commit 25a952755e
22 changed files with 5 additions and 785 deletions

View File

@ -19,9 +19,9 @@ var titleCase = function(text) {
*
*/
module.exports = function addJadeDataDocsProcessor(EXPORT_DOC_TYPES) {
module.exports = function addJadeDataDocsProcessor() {
return {
$runAfter: ['adding-extra-docs', 'cloneExportedFromDocs'],
$runAfter: ['adding-extra-docs'],
$runBefore: ['extra-docs-added'],
$process: function(docs) {
var extraDocs = [];

View File

@ -15,16 +15,6 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
// Register the services and file readers
.factory(require('./services/modules'))
.factory(require('./services/atParser'))
.factory(require('./services/getJSDocComment'))
.factory(require('./services/SourceFile'))
.factory(require('./services/TraceurParser'))
.factory(require('./services/traceurOptions'))
.factory(require('./services/ParseTreeVisitor'))
.factory(require('./services/AttachCommentTreeVisitor'))
.factory(require('./services/ExportTreeVisitor'))
.factory(require('./readers/atScript'))
.factory(require('./readers/ngdoc'))
.factory('EXPORT_DOC_TYPES', function() {
@ -38,11 +28,6 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
// Register the processors
.processor(require('./processors/captureModuleExports'))
.processor(require('./processors/captureClassMembers'))
.processor(require('./processors/captureModuleDocs'))
.processor(require('./processors/attachModuleDocs'))
.processor(require('./processors/cloneExportedFromDocs'))
.processor(require('./processors/generateNavigationDoc'))
.processor(require('./processors/extractTitleFromGuides'))
.processor(require('./processors/createOverviewDump'))
@ -55,16 +40,10 @@ module.exports = new Package('angular', [jsdocPackage, nunjucksPackage, linksPac
// Configure file reading
.config(function(readFilesProcessor, atScriptFileReader, ngdocFileReader) {
readFilesProcessor.fileReaders = [atScriptFileReader, ngdocFileReader];
.config(function(readFilesProcessor, ngdocFileReader) {
readFilesProcessor.fileReaders = [ngdocFileReader];
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
readFilesProcessor.sourceFiles = [
{ include: 'modules/*/*.js', basePath: 'modules' },
{ include: 'modules/*/src/**/*.js', basePath: 'modules' },
{ include: 'modules/*/*.es6', basePath: 'modules' },
{ include: 'modules/*/src/**/*.es6', basePath: 'modules' },
{ include: 'modules/*/*.ts', basePath: 'modules' },
{ include: 'modules/*/src/**/*.ts', basePath: 'modules' },
{ include: 'modules/*/docs/**/*.md', basePath: 'modules' },
{ include: 'docs/content/**/*.md', basePath: 'docs/content' }
];

View File

@ -1,22 +0,0 @@
var _ = require('lodash');
module.exports = function attachModuleDocs(log) {
return {
$runAfter: ['tags-extracted'],
$runBefore: ['computing-ids'],
$process: function(docs) {
return _.filter(docs, function(doc) {
if (doc.docType !== 'moduleDoc') {
return true;
}
if (doc.module || doc.module === '') {
doc.moduleDoc.description = doc.description;
doc.moduleDoc.public = doc.public;
log.debug('attached', doc.moduleDoc.id, doc.moduleDoc.description);
}
return false;
});
}
};
};

View File

@ -1,70 +0,0 @@
var _ = require('lodash');
module.exports = function captureClassMembers(log, getJSDocComment) {
return {
$runAfter: ['captureModuleExports'],
$runBefore: ['parsing-tags'],
ignorePrivateMembers: false,
$process: function(docs) {
var memberDocs = [];
var ignorePrivateMembers = this.ignorePrivateMembers;
_.forEach(docs, function(classDoc) {
if ( classDoc.docType === 'class' ) {
classDoc.members = [];
// Create a new doc for each member of the class
_.forEach(classDoc.elements, function(memberDoc) {
var memberName = memberDoc.name.location.toString();
if (ignorePrivateMembers && memberName.charAt(0) === '_') return;
memberDocs.push(memberDoc);
memberDoc.docType = 'member';
memberDoc.classDoc = classDoc;
memberDoc.name = memberName;
if (memberDoc.parameterList) {
memberDoc.params = memberDoc.parameterList.parameters.map(function(param) {
return param.location.toString();
});
}
if (memberDoc.commentBefore ) {
// If this export has a comment, remove it from the list of
// comments collected in the module
var index = classDoc.moduleDoc.comments.indexOf(memberDoc.commentBefore);
if ( index !== -1 ) {
classDoc.moduleDoc.comments.splice(index, 1);
}
_.assign(memberDoc, getJSDocComment(memberDoc.commentBefore));
}
// Constuctor is a special case member
if (memberName === 'constructor') {
classDoc.constructorDoc = memberDoc;
} else {
insertSorted(classDoc.members, memberDoc, 'name');
}
});
}
});
return docs.concat(memberDocs);
}
};
};
function insertSorted(collection, item, property) {
var index = collection.length;
while(index>0) {
if(collection[index-1][property] < item[property]) break;
index -= 1;
}
collection.splice(index, 0, item);
}

View File

@ -1,31 +0,0 @@
var _ = require('lodash');
module.exports = function captureModuleDocs(log, getJSDocComment) {
return {
$runAfter: ['captureClassMembers'],
$runBefore: ['parsing-tags'],
$process: function(docs) {
// Generate docs for each module's file's comments not already captured
_.forEach(docs, function(moduleDoc) {
if ( moduleDoc.docType !== 'module' ) return;
moduleDoc.extraComments = [];
_.forEach(moduleDoc.comments, function(comment) {
var jsDocComment = getJSDocComment(comment);
if (jsDocComment) {
jsDocComment.docType = 'moduleDoc';
jsDocComment.moduleDoc = moduleDoc;
moduleDoc.extraComments.push(jsDocComment);
docs.push(jsDocComment);
// console.log('found', jsDocComment.content);
}
});
if ( moduleDoc.extraComments.length > 0 ) {
// console.log(moduleDoc.extraComments.length);
}
});
}
};
};

View File

@ -1,46 +0,0 @@
var _ = require('lodash');
module.exports = function captureModuleExports(log, ExportTreeVisitor, getJSDocComment) {
return {
$runAfter: ['files-read'],
$runBefore: ['parsing-tags'],
$process: function(docs) {
var extraDocs = [];
_.forEach(docs, function(doc) {
if ( doc.docType === 'module' ) {
log.debug('processing', doc.moduleTree.moduleName);
doc.exports = [];
if ( doc.moduleTree.visit ) {
var visitor = new ExportTreeVisitor();
visitor.visit(doc.moduleTree);
_.forEach(visitor.exports, function(exportDoc) {
doc.exports.push(exportDoc);
extraDocs.push(exportDoc);
exportDoc.moduleDoc = doc;
if (exportDoc.comment) {
// If this export has a comment, remove it from the list of
// comments collected in the module
var index = doc.comments.indexOf(exportDoc.comment);
if ( index !== -1 ) {
doc.comments.splice(index, 1);
}
_.assign(exportDoc, getJSDocComment(exportDoc.comment));
}
});
}
}
});
return docs.concat(extraDocs);
}
};
};

View File

@ -1,39 +0,0 @@
var _ = require('lodash');
module.exports = function cloneExportedFromDocs(modules, EXPORT_DOC_TYPES) {
return {
$runAfter: ['tags-parsed', 'attachModuleDocs'],
$runBefore: ['computing-ids'],
$process: function(docs) {
var extraPublicDocs = [];
_.forEach(docs, function(doc) {
if (EXPORT_DOC_TYPES.indexOf(doc.docType) === -1 || !doc.exportedAs) return;
_.forEach(doc.exportedAs, function(exportedAs) {
var exportedAsModule = modules[exportedAs];
if (!exportedAsModule) {
throw new Error('Missing module definition: "' + doc.exportedAs + '"\n' +
'Referenced in "@exportedAs" tag on class: "' + doc.moduleDoc.id + '/' + doc.name + '"');
} else {
if(exportedAsModule !== doc.moduleDoc) {
// Add a clone of export to its "exportedAs" module
var clonedDoc = _.clone(doc);
clonedDoc.moduleDoc = exportedAsModule;
exportedAsModule.exports.push(clonedDoc);
extraPublicDocs.push(clonedDoc);
}
}
});
});
docs = docs.concat(extraPublicDocs);
return docs;
}
};
};

View File

@ -3,7 +3,7 @@ var _ = require('lodash');
module.exports = function createOverviewDump() {
return {
$runAfter: ['captureModuleExports', 'captureClassMembers'],
$runAfter: ['processing-docs'],
$runBefore: ['docs-processed'],
$process: function(docs) {
var overviewDoc = {

View File

@ -1,31 +0,0 @@
var path = require('canonical-path');
/**
* @dgService atScriptFileReader
* @description
* This file reader will create a simple doc for each
* file including a code AST of the AtScript in the file.
*/
module.exports = function atScriptFileReader(log, atParser, modules) {
var reader = {
name: 'atScriptFileReader',
defaultPattern: /\.js|\.es6|\.ts$/,
getDocs: function(fileInfo) {
var moduleDoc = atParser.parseModule(fileInfo);
moduleDoc.docType = 'module';
moduleDoc.id = moduleDoc.moduleTree.moduleName;
moduleDoc.aliases = [moduleDoc.id];
modules[moduleDoc.id] = moduleDoc;
// Readers return a collection of docs read from the file
// but in this read there is only one document (module) to return
return [moduleDoc];
}
};
return reader;
};

View File

@ -1,55 +0,0 @@
var mockPackage = require('../mocks/mockPackage');
var Dgeni = require('dgeni');
describe('atScript file reader', function() {
var dgeni, injector, reader;
var fileContent =
'import {CONST} from "facade/lang";\n' +
'\n' +
'/**\n' +
'* A parameter annotation that creates a synchronous eager dependency.\n' +
'*\n' +
'* class AComponent {\n' +
'* constructor(@Inject("aServiceToken") aService) {}\n' +
'* }\n' +
'*\n' +
'*/\n' +
'export class Inject {\n' +
'token;\n' +
'@CONST()\n' +
'constructor(token) {\n' +
'this.token = token;\n' +
'}\n' +
'}';
beforeEach(function() {
dgeni = new Dgeni([mockPackage()]);
injector = dgeni.configureInjector();
reader = injector.get('atScriptFileReader');
});
it('should provide a default pattern', function() {
expect(reader.defaultPattern).toEqual(/\.js|\.es6|\.ts$/);
});
it('should parse the file using the atParser and return a single doc', function() {
var atParser = injector.get('atParser');
spyOn(atParser, 'parseModule').and.callThrough();
var docs = reader.getDocs({
content: fileContent,
relativePath: 'di/src/annotations.js'
});
expect(atParser.parseModule).toHaveBeenCalled();
expect(docs.length).toEqual(1);
expect(docs[0].docType).toEqual('module');
});
});

View File

@ -1,54 +0,0 @@
module.exports = function AttachCommentTreeVisitor(ParseTreeVisitor, log) {
function AttachCommentTreeVisitorImpl() {
ParseTreeVisitor.call(this);
}
AttachCommentTreeVisitorImpl.prototype = {
__proto__: ParseTreeVisitor.prototype,
visit: function(tree, comments) {
this.comments = comments;
this.index = 0;
this.currentComment = this.comments[this.index];
if (this.currentComment) log.silly('comment: ' +
this.currentComment.range.start.line + ' - ' +
this.currentComment.range.end.line + ' : ' +
this.currentComment.range.toString());
ParseTreeVisitor.prototype.visit.call(this, tree);
},
// Really we ought to subclass ParseTreeVisitor but this is fiddly in ES5 so
// it is easier to simply override the prototype's method on the instance
visitAny: function(tree) {
if (tree && tree.location && tree.location.start && this.currentComment &&
this.currentComment.range.end.offset < tree.location.start.offset) {
log.silly('tree: ' + tree.constructor.name + ' - ' + tree.location.start.line);
while (this.currentComment &&
this.currentComment.range.end.offset < tree.location.start.offset) {
var commentText = this.currentComment.range.toString();
// Only store the comment if it is JSDOC style (e.g. /** some comment */)
if (/^\/\*\*([\w\W]*)\*\/$/.test(commentText)) {
log.silly('comment: ' + this.currentComment.range.start.line + ' - ' +
this.currentComment.range.end.line + ' : ' +
commentText);
tree.commentBefore = this.currentComment;
this.currentComment.treeAfter = tree;
}
this.index++;
this.currentComment = this.comments[this.index];
}
}
return ParseTreeVisitor.prototype.visitAny.call(this, tree);
}
};
return AttachCommentTreeVisitorImpl;
};

View File

@ -1,105 +0,0 @@
module.exports = function ExportTreeVisitor(ParseTreeVisitor, log) {
function ExportTreeVisitorImpl() {
ParseTreeVisitor.call(this);
}
ExportTreeVisitorImpl.prototype = {
__proto__: ParseTreeVisitor.prototype,
visitExportDeclaration: function(tree) {
// We are entering an export declaration - create an object to track it
this.currentExport = {
comment: tree.commentBefore,
location: tree.location
};
log.silly('enter', tree.type, tree.commentBefore ? 'has comment' : '');
ParseTreeVisitor.prototype.visitExportDeclaration.call(this, tree);
log.silly('exit', this.currentExport);
if(this.currentExport) {
// We are exiting the export declaration - store the export object
this.exports.push(this.currentExport);
}
this.currentExport = null;
},
visitVariableDeclaration: function(tree) {
if ( this.currentExport ) {
this.updateExport(tree);
this.currentExport.docType = 'var';
this.currentExport.name = tree.lvalue.identifierToken.value;
this.currentExport.variableDeclaration = tree;
}
},
visitFunctionDeclaration: function(tree) {
if ( this.currentExport ) {
this.updateExport(tree);
this.currentExport.name = tree.name.identifierToken.value;
this.currentExport.functionKind = tree.functionKind;
this.currentExport.parameters = tree.parameterList.parameters.map(function(param) {
return param.location.toString();
});
this.currentExport.typeAnnotation = tree.typeAnnotation;
this.currentExport.annotations = tree.annotations;
this.currentExport.docType = 'function';
log.silly(tree.type, tree.commentBefore ? 'has comment' : '');
}
},
visitClassDeclaration: function(tree) {
if ( this.currentExport ) {
this.updateExport(tree);
this.currentExport.name = tree.name.identifierToken.value;
this.currentExport.superClass = tree.superClass;
this.currentExport.annotations = tree.annotations;
this.currentExport.elements = tree.elements;
this.currentExport.docType = 'class';
}
},
visitAsyncFunctionDeclaration: function(tree) {
if ( this.currentExport ) {
this.updateExport(tree);
}
},
visitExportDefault: function(tree) {
if ( this.currentExport ) {
this.updateExport(tree);
this.currentExport.name = 'DEFAULT';
this.currentExport.defaultExport = tree;
// Default exports are either classes, functions or expressions
// So we let the super class continue down...
ParseTreeVisitor.prototype.visitExportDefault.call(this, tree);
}
},
visitNamedExport: function(tree) {
this.currentExport = null;
// if ( this.currentExport ) {
// this.updateExport(tree);
// this.currentExport.namedExport = tree;
// this.currentExport.name = 'NAMED_EXPORT';
// // TODO: work out this bit!!
// // We need to cope with any export specifiers in the named export
// }
},
// TODO - if the export is an expression, find the thing that is being
// exported and use it and its comments for docs
updateExport: function(tree) {
this.currentExport.comment = this.currentExport.comment || tree.commentBefore;
this.currentExport.docType = tree.type;
},
visit: function(tree) {
this.exports = [];
ParseTreeVisitor.prototype.visit.call(this, tree);
}
};
return ExportTreeVisitorImpl;
};

View File

@ -1,6 +0,0 @@
var traceur = require('traceur/src/node/traceur.js');
module.exports = function ParseTreeVisitor() {
console.log(System.map.traceur);
return System.get(System.map.traceur + '/src/syntax/ParseTreeVisitor.js').ParseTreeVisitor;
};

View File

@ -1,5 +0,0 @@
var traceur = require('traceur/src/node/traceur.js');
module.exports = function SourceFile() {
return System.get(System.map.traceur + '/src/syntax/SourceFile.js').SourceFile;
};

View File

@ -1,3 +0,0 @@
module.exports = function TraceurParser() {
return System.get('transpiler/src/parser').Parser;
};

View File

@ -1,79 +0,0 @@
var file2modulename = require('../../../tools/build/file2modulename');
/**
* Wrapper around traceur that can parse the contents of a file
*/
module.exports = function atParser(AttachCommentTreeVisitor, SourceFile, TraceurParser, traceurOptions, log) {
var service = {
/**
* The options to pass to traceur
*/
traceurOptions: {
annotations: true, // parse annotations
types: true, // parse types
memberVariables: true, // parse class fields
commentCallback: true // handle comments
},
/**
* Parse a module AST from the contents of a file.
* @param {Object} fileInfo information about the file to parse
* @return { { moduleTree: Object, comments: Array } } An object containing the parsed module
* AST and an array of all the comments found in the file
*/
parseModule: parseModule
};
return service;
// Parse the contents of the file using traceur
function parseModule(fileInfo) {
var moduleName = file2modulename(fileInfo.relativePath);
var sourceFile = new SourceFile(moduleName, fileInfo.content);
var comments = [];
var moduleTree;
var errorReporter = {
reportError: function(position, message) {
}
};
traceurOptions.setFromObject(service.traceurOptions);
var parser = new TraceurParser(sourceFile, errorReporter, traceurOptions);
// Configure the parser
parser.handleComment = function(range) {
comments.push({ range: range });
};
try {
// Parse the file as a module, attaching the comments
moduleTree = parser.parseModule();
attachComments(moduleTree, comments);
} catch(ex) {
// HACK: sometime traceur crashes for various reasons including
// Not Yet Implemented (NYI)!
log.error(ex.stack);
moduleTree = {};
}
log.debug(moduleName);
moduleTree.moduleName = moduleName;
// We return the module AST but also a collection of all the comments
// since it can be helpful to iterate through them without having to
// traverse the AST again
return {
moduleTree: moduleTree,
comments: comments
};
}
// attach the comments to their nearest code tree
function attachComments(tree, comments) {
var visitor = new AttachCommentTreeVisitor();
// Visit every node of the tree using our custom method
visitor.visit(tree, comments);
}
};

View File

@ -1,80 +0,0 @@
var mockPackage = require('../mocks/mockPackage');
var Dgeni = require('dgeni');
describe('atParser service', function() {
var dgeni, injector, parser;
var fileContent =
'import {CONST} from "facade/lang";\n' +
'\n' +
'/**\n' +
'* A parameter annotation that creates a synchronous eager dependency.\n' +
'*\n' +
'* class AComponent {\n' +
'* constructor(@Inject("aServiceToken") aService) {}\n' +
'* }\n' +
'*\n' +
'*/\n' +
'export class Inject {\n' +
'token;\n' +
'@CONST()\n' +
'constructor({a,b}:{a:string, b:string}) {\n' +
'this.token = a;\n' +
'}\n' +
'}';
beforeEach(function() {
dgeni = new Dgeni([mockPackage()]);
injector = dgeni.configureInjector();
parser = injector.get('atParser');
});
it('should extract the comments from the file', function() {
var result = parser.parseModule({
content: fileContent,
relativePath: 'di/src/annotations.js'
});
expect(result.comments[0].range.toString()).toEqual(
'/**\n' +
'* A parameter annotation that creates a synchronous eager dependency.\n' +
'*\n' +
'* class AComponent {\n' +
'* constructor(@Inject("aServiceToken") aService) {}\n' +
'* }\n' +
'*\n' +
'*/'
);
});
it('should extract a module AST from the file', function() {
var result = parser.parseModule({
content: fileContent,
relativePath: 'di/src/annotations.js'
});
expect(result.moduleTree.moduleName).toEqual('di/src/annotations');
expect(result.moduleTree.scriptItemList[0].type).toEqual('IMPORT_DECLARATION');
expect(result.moduleTree.scriptItemList[1].type).toEqual('EXPORT_DECLARATION');
});
it('should attach comments to their following AST', function() {
var result = parser.parseModule({
content: fileContent,
relativePath: 'di/src/annotations.js'
});
expect(result.moduleTree.scriptItemList[1].commentBefore.range.toString()).toEqual(
'/**\n' +
'* A parameter annotation that creates a synchronous eager dependency.\n' +
'*\n' +
'* class AComponent {\n' +
'* constructor(@Inject("aServiceToken") aService) {}\n' +
'* }\n' +
'*\n' +
'*/'
);
});
});

View File

@ -1,28 +0,0 @@
var LEADING_STAR = /^[^\S\r\n]*\*[^\S\n\r]?/gm;
/**
* Extact comment info from a comment object
* @param {Object} comment object to process
* @return { {startingLine, endingLine, content, codeTree}= } a comment info object
* or undefined if the comment is not a jsdoc style comment
*/
module.exports = function getJSDocComment() {
return function(comment) {
var commentInfo;
// we need to check for `/**` at the start of the comment to find all the jsdoc style comments
comment.range.toString().replace(/^\/\*\*([\w\W]*)\*\/$/g, function(match, commentBody) {
commentBody = commentBody.replace(LEADING_STAR, '').trim();
commentInfo = {
startingLine: comment.range.start.line,
endingLine: comment.range.end.line,
content: commentBody,
codeTree: comment.treeAfter
};
});
return commentInfo;
};
};

View File

@ -1,67 +0,0 @@
var mockPackage = require('../mocks/mockPackage');
var Dgeni = require('dgeni');
describe('getJSDocComment service', function() {
var dgeni, injector, getJSDocComment;
function createComment(commentString, start, end, codeTree) {
return {
range: {
toString: function() { return commentString; },
start: { line: start },
end: { line: end },
},
treeAfter: codeTree
};
}
beforeEach(function() {
dgeni = new Dgeni([mockPackage()]);
injector = dgeni.configureInjector();
getJSDocComment = injector.get('getJSDocComment');
});
it('should only return an object if the comment starts with /** and ends with */', function() {
var result = getJSDocComment(createComment('/** this is a jsdoc comment */'));
expect(result).toBeDefined();
result = getJSDocComment(createComment('/* this is a normal comment */'));
expect(result).toBeUndefined();
result = getJSDocComment(createComment('this is not a valid comment */'));
expect(result).toBeUndefined();
result = getJSDocComment(createComment('nor is this'));
expect(result).toBeUndefined();
result = getJSDocComment(createComment('/* or even this'));
expect(result).toBeUndefined();
result = getJSDocComment(createComment('/** and this'));
expect(result).toBeUndefined();
});
it('should return a result that contains info about the comment', function() {
var codeTree = {};
var result = getJSDocComment(createComment('/** this is a comment */', 10, 20, codeTree));
expect(result.startingLine).toEqual(10);
expect(result.endingLine).toEqual(20);
expect(result.codeTree).toBe(codeTree);
});
it('should strip off leading stars from each line', function() {
var result = getJSDocComment(createComment(
'/** this is a jsdoc comment */\n' +
' *\n' +
' * some content\n' +
' */'
));
expect(result.content).toEqual(
'this is a jsdoc comment */\n' +
'\n' +
'some content'
);
});
});

View File

@ -1,4 +0,0 @@
module.exports = function traceurOptions() {
var Options = System.get(System.map.traceur + "/src/Options.js").Options;
return new Options();
};

View File

@ -3,12 +3,6 @@ var basePackage = require('../dgeni-package');
module.exports = new Package('angular-public', [basePackage])
.processor(require('./processors/filterPublicDocs'))
.config(function(captureClassMembers) {
captureClassMembers.ignorePrivateMembers = true;
})
// Configure file writing
.config(function(writeFilesProcessor) {
writeFilesProcessor.outputFolder = 'dist/public_docs';

View File

@ -1,28 +0,0 @@
var _ = require('lodash');
module.exports = function filterPublicDocs(modules, EXPORT_DOC_TYPES) {
return {
$runAfter: ['tags-parsed', 'cloneExportedFromDocs'],
$runBefore: ['computing-ids'],
$process: function(docs) {
// Filter out the documents that are not public
return _.filter(docs, function(doc) {
if (doc.docType === 'module') {
// doc is a module - is it public?
return doc.public;
}
if (EXPORT_DOC_TYPES.indexOf(doc.docType) === -1) {
// doc is not a type we care about
return true;
}
// doc is in a public module
return doc.moduleDoc && doc.moduleDoc.public;
});
}
};
};