2017-05-28 00:38:50 +02:00
"use strict" ;
/ * *
* @ license
* Copyright 2013 Palantir Technologies , Inc .
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
var tslib _1 = require ( "tslib" ) ;
2017-08-14 05:01:11 +02:00
var tsutils _1 = require ( "tsutils" ) ;
2017-05-28 00:38:50 +02:00
var ts = require ( "typescript" ) ;
var Lint = require ( "../index" ) ;
var utils _1 = require ( "../utils" ) ;
exports . ALL = "all" ;
exports . ARGUMENT _CLASSES = "classes" ;
exports . ARGUMENT _ENUMS = "enums" ;
2017-08-14 05:01:11 +02:00
exports . ARGUMENT _ENUM _MEMBERS = "enum-members" ;
2017-05-28 00:38:50 +02:00
exports . ARGUMENT _FUNCTIONS = "functions" ;
exports . ARGUMENT _INTERFACES = "interfaces" ;
exports . ARGUMENT _METHODS = "methods" ;
exports . ARGUMENT _NAMESPACES = "namespaces" ;
exports . ARGUMENT _PROPERTIES = "properties" ;
exports . ARGUMENT _TYPES = "types" ;
exports . ARGUMENT _VARIABLES = "variables" ;
exports . DESCRIPTOR _LOCATIONS = "locations" ;
exports . DESCRIPTOR _PRIVACIES = "privacies" ;
exports . DESCRIPTOR _VISIBILITIES = "visibilities" ;
exports . LOCATION _INSTANCE = "instance" ;
exports . LOCATION _STATIC = "static" ;
exports . PRIVACY _PRIVATE = "private" ;
exports . PRIVACY _PROTECTED = "protected" ;
exports . PRIVACY _PUBLIC = "public" ;
exports . VISIBILITY _EXPORTED = "exported" ;
exports . VISIBILITY _INTERNAL = "internal" ;
var Rule = ( function ( _super ) {
tslib _1 . _ _extends ( Rule , _super ) ;
function Rule ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
/* tslint:enable:object-literal-sort-keys */
Rule . prototype . applyWithProgram = function ( sourceFile , program ) {
var options = this . getOptions ( ) ;
var completedDocsWalker = new CompletedDocsWalker ( sourceFile , options , program ) ;
completedDocsWalker . setRequirements ( this . getRequirements ( options . ruleArguments ) ) ;
return this . applyWithWalker ( completedDocsWalker ) ;
} ;
Rule . prototype . getRequirements = function ( ruleArguments ) {
if ( ruleArguments . length === 0 ) {
ruleArguments = Rule . defaultArguments ;
}
return Requirement . constructRequirements ( ruleArguments ) ;
} ;
2017-08-14 05:01:11 +02:00
Rule . FAILURE _STRING _EXIST = "Documentation must exist for " ;
Rule . defaultArguments = [
exports . ARGUMENT _CLASSES ,
exports . ARGUMENT _FUNCTIONS ,
exports . ARGUMENT _METHODS ,
exports . ARGUMENT _PROPERTIES ,
] ;
Rule . ARGUMENT _DESCRIPTOR _BLOCK = {
properties : ( _a = { } ,
_a [ exports . DESCRIPTOR _VISIBILITIES ] = {
enum : [
exports . ALL ,
exports . VISIBILITY _EXPORTED ,
exports . VISIBILITY _INTERNAL ,
] ,
type : "string" ,
} ,
_a ) ,
type : "object" ,
} ;
Rule . ARGUMENT _DESCRIPTOR _CLASS = {
properties : ( _b = { } ,
_b [ exports . DESCRIPTOR _LOCATIONS ] = {
enum : [
exports . ALL ,
exports . LOCATION _INSTANCE ,
exports . LOCATION _STATIC ,
] ,
type : "string" ,
} ,
_b [ exports . DESCRIPTOR _PRIVACIES ] = {
enum : [
exports . ALL ,
exports . PRIVACY _PRIVATE ,
exports . PRIVACY _PROTECTED ,
exports . PRIVACY _PUBLIC ,
] ,
type : "string" ,
} ,
_b ) ,
type : "object" ,
} ;
/* tslint:disable:object-literal-sort-keys */
Rule . metadata = {
ruleName : "completed-docs" ,
description : "Enforces documentation for important items be filled out." ,
optionsDescription : ( _c = [ "\n `true` to enable for [\"" , "\", \"" , "\", \"" , "\", \"" , "\"],\n or an array with each item in one of two formats:\n\n * `string` to enable for that type\n * `object` keying types to when their documentation is required:\n * `\"" , "\"` and `\"" , "\"` may specify:\n * `\"" , "\"`:\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`:\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * All other types may specify `\"" , "\"`:\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n\n Types that may be enabled are:\n\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`\n * `\"" , "\"`" ] , _c . raw = [ "\n \\`true\\` to enable for [\"" , "\", \"" , "\", \"" , "\", \"" , "\"],\n or an array with each item in one of two formats:\n\n * \\`string\\` to enable for that type\n * \\`object\\` keying types to when their documentation is required:\n * \\`\"" , "\"\\` and \\`\"" , "\"\\` may specify:\n * \\`\"" , "\"\\`:\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`:\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * All other types may specify \\`\"" , "\"\\`:\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n\n Types that may be enabled are:\n\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`\n * \\`\"" , "\"\\`" ] , Lint . Utils . dedent ( _c , exports . ARGUMENT _CLASSES , exports . ARGUMENT _FUNCTIONS , exports . ARGUMENT _METHODS , exports . ARGUMENT _PROPERTIES , exports . ARGUMENT _METHODS , exports . ARGUMENT _PROPERTIES , exports . DESCRIPTOR _PRIVACIES , exports . ALL , exports . PRIVACY _PRIVATE , exports . PRIVACY _PROTECTED , exports . PRIVACY _PUBLIC , exports . DESCRIPTOR _LOCATIONS , exports . ALL , exports . LOCATION _INSTANCE , exports . LOCATION _STATIC , exports . DESCRIPTOR _VISIBILITIES , exports . ALL , exports . VISIBILITY _EXPORTED , exports . VISIBILITY _INTERNAL , exports . ARGUMENT _CLASSES , exports . ARGUMENT _ENUMS , exports . ARGUMENT _ENUM _MEMBERS , exports . ARGUMENT _FUNCTIONS , exports . ARGUMENT _INTERFACES , exports . ARGUMENT _METHODS , exports . ARGUMENT _NAMESPACES , exports . ARGUMENT _PROPERTIES , exports . ARGUMENT _TYPES , exports . ARGUMENT _VARIABLES ) ) ,
options : {
type : "array" ,
items : {
anyOf : [
{
enum : Rule . defaultArguments ,
type : "string" ,
} ,
{
type : "object" ,
properties : ( _d = { } ,
_d [ exports . ARGUMENT _CLASSES ] = Rule . ARGUMENT _DESCRIPTOR _BLOCK ,
_d [ exports . ARGUMENT _ENUMS ] = Rule . ARGUMENT _DESCRIPTOR _BLOCK ,
_d [ exports . ARGUMENT _ENUM _MEMBERS ] = Rule . ARGUMENT _DESCRIPTOR _BLOCK ,
_d [ exports . ARGUMENT _FUNCTIONS ] = Rule . ARGUMENT _DESCRIPTOR _BLOCK ,
_d [ exports . ARGUMENT _INTERFACES ] = Rule . ARGUMENT _DESCRIPTOR _BLOCK ,
_d [ exports . ARGUMENT _METHODS ] = Rule . ARGUMENT _DESCRIPTOR _CLASS ,
_d [ exports . ARGUMENT _NAMESPACES ] = Rule . ARGUMENT _DESCRIPTOR _BLOCK ,
_d [ exports . ARGUMENT _PROPERTIES ] = Rule . ARGUMENT _DESCRIPTOR _CLASS ,
_d [ exports . ARGUMENT _TYPES ] = Rule . ARGUMENT _DESCRIPTOR _BLOCK ,
_d [ exports . ARGUMENT _VARIABLES ] = Rule . ARGUMENT _DESCRIPTOR _BLOCK ,
_d ) ,
} ,
] ,
} ,
2017-05-28 00:38:50 +02:00
} ,
2017-08-14 05:01:11 +02:00
optionExamples : [
2017-05-28 00:38:50 +02:00
true ,
2017-08-14 05:01:11 +02:00
[ true , exports . ARGUMENT _ENUMS , exports . ARGUMENT _FUNCTIONS , exports . ARGUMENT _METHODS ] ,
[
true ,
( _e = { } ,
_e [ exports . ARGUMENT _ENUMS ] = true ,
_e [ exports . ARGUMENT _FUNCTIONS ] = ( _f = { } ,
_f [ exports . DESCRIPTOR _VISIBILITIES ] = [ exports . VISIBILITY _EXPORTED ] ,
_f ) ,
_e [ exports . ARGUMENT _METHODS ] = ( _g = { } ,
_g [ exports . DESCRIPTOR _LOCATIONS ] = exports . LOCATION _INSTANCE ,
_g [ exports . DESCRIPTOR _PRIVACIES ] = [ exports . PRIVACY _PUBLIC , exports . PRIVACY _PROTECTED ] ,
_g ) ,
_e ) ,
] ,
2017-05-28 00:38:50 +02:00
] ,
2017-08-14 05:01:11 +02:00
type : "style" ,
typescriptOnly : false ,
} ;
return Rule ;
} ( Lint . Rules . TypedRule ) ) ;
2017-05-28 00:38:50 +02:00
exports . Rule = Rule ;
var Requirement = ( function ( ) {
// tslint:disable-next-line no-object-literal-type-assertion
function Requirement ( descriptor ) {
if ( descriptor === void 0 ) { descriptor = { } ; }
this . descriptor = descriptor ;
}
Requirement . constructRequirements = function ( ruleArguments ) {
var requirements = new Map ( ) ;
for ( var _i = 0 , ruleArguments _1 = ruleArguments ; _i < ruleArguments _1 . length ; _i ++ ) {
var ruleArgument = ruleArguments _1 [ _i ] ;
Requirement . addRequirements ( requirements , ruleArgument ) ;
}
return requirements ;
} ;
Requirement . addRequirements = function ( requirements , descriptor ) {
if ( typeof descriptor === "string" ) {
requirements . set ( descriptor , new BlockRequirement ( ) ) ;
return ;
}
for ( var type in descriptor ) {
if ( utils _1 . hasOwnProperty ( descriptor , type ) ) {
requirements . set ( type , ( type === "methods" || type === "properties" )
? new ClassRequirement ( descriptor [ type ] )
: new BlockRequirement ( descriptor [ type ] ) ) ;
}
}
} ;
Requirement . prototype . createSet = function ( values ) {
if ( values === undefined || values . length === 0 ) {
values = [ exports . ALL ] ;
}
return new Set ( values ) ;
} ;
return Requirement ;
} ( ) ) ;
var BlockRequirement = ( function ( _super ) {
tslib _1 . _ _extends ( BlockRequirement , _super ) ;
function BlockRequirement ( ) {
var _this = _super !== null && _super . apply ( this , arguments ) || this ;
_this . visibilities = _this . createSet ( _this . descriptor . visibilities ) ;
return _this ;
}
BlockRequirement . prototype . shouldNodeBeDocumented = function ( node ) {
if ( this . visibilities . has ( exports . ALL ) ) {
return true ;
}
if ( Lint . hasModifier ( node . modifiers , ts . SyntaxKind . ExportKeyword ) ) {
return this . visibilities . has ( exports . VISIBILITY _EXPORTED ) ;
}
return this . visibilities . has ( exports . VISIBILITY _INTERNAL ) ;
} ;
return BlockRequirement ;
} ( Requirement ) ) ;
var ClassRequirement = ( function ( _super ) {
tslib _1 . _ _extends ( ClassRequirement , _super ) ;
function ClassRequirement ( ) {
var _this = _super !== null && _super . apply ( this , arguments ) || this ;
_this . locations = _this . createSet ( _this . descriptor . locations ) ;
_this . privacies = _this . createSet ( _this . descriptor . privacies ) ;
return _this ;
}
ClassRequirement . prototype . shouldNodeBeDocumented = function ( node ) {
return this . shouldLocationBeDocumented ( node ) && this . shouldPrivacyBeDocumented ( node ) ;
} ;
ClassRequirement . prototype . shouldLocationBeDocumented = function ( node ) {
if ( this . locations . has ( exports . ALL ) ) {
return true ;
}
if ( Lint . hasModifier ( node . modifiers , ts . SyntaxKind . StaticKeyword ) ) {
return this . locations . has ( exports . LOCATION _STATIC ) ;
}
return this . locations . has ( exports . LOCATION _INSTANCE ) ;
} ;
ClassRequirement . prototype . shouldPrivacyBeDocumented = function ( node ) {
if ( this . privacies . has ( exports . ALL ) ) {
return true ;
}
if ( Lint . hasModifier ( node . modifiers , ts . SyntaxKind . PrivateKeyword ) ) {
return this . privacies . has ( exports . PRIVACY _PRIVATE ) ;
}
if ( Lint . hasModifier ( node . modifiers , ts . SyntaxKind . ProtectedKeyword ) ) {
return this . privacies . has ( exports . PRIVACY _PROTECTED ) ;
}
return this . privacies . has ( exports . PRIVACY _PUBLIC ) ;
} ;
return ClassRequirement ;
} ( Requirement ) ) ;
var CompletedDocsWalker = ( function ( _super ) {
tslib _1 . _ _extends ( CompletedDocsWalker , _super ) ;
function CompletedDocsWalker ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
CompletedDocsWalker . prototype . setRequirements = function ( requirements ) {
this . requirements = requirements ;
} ;
CompletedDocsWalker . prototype . visitClassDeclaration = function ( node ) {
this . checkNode ( node , exports . ARGUMENT _CLASSES ) ;
_super . prototype . visitClassDeclaration . call ( this , node ) ;
} ;
CompletedDocsWalker . prototype . visitEnumDeclaration = function ( node ) {
this . checkNode ( node , exports . ARGUMENT _ENUMS ) ;
_super . prototype . visitEnumDeclaration . call ( this , node ) ;
} ;
2017-08-14 05:01:11 +02:00
CompletedDocsWalker . prototype . visitEnumMember = function ( node ) {
// Enum members don't have modifiers, so use the parent
// enum declaration when checking the requirements.
this . checkNode ( node , exports . ARGUMENT _ENUM _MEMBERS , node . parent ) ;
_super . prototype . visitEnumMember . call ( this , node ) ;
} ;
2017-05-28 00:38:50 +02:00
CompletedDocsWalker . prototype . visitFunctionDeclaration = function ( node ) {
this . checkNode ( node , exports . ARGUMENT _FUNCTIONS ) ;
_super . prototype . visitFunctionDeclaration . call ( this , node ) ;
} ;
CompletedDocsWalker . prototype . visitInterfaceDeclaration = function ( node ) {
this . checkNode ( node , exports . ARGUMENT _INTERFACES ) ;
_super . prototype . visitInterfaceDeclaration . call ( this , node ) ;
} ;
CompletedDocsWalker . prototype . visitMethodDeclaration = function ( node ) {
this . checkNode ( node , exports . ARGUMENT _METHODS ) ;
_super . prototype . visitMethodDeclaration . call ( this , node ) ;
} ;
CompletedDocsWalker . prototype . visitModuleDeclaration = function ( node ) {
this . checkNode ( node , exports . ARGUMENT _NAMESPACES ) ;
_super . prototype . visitModuleDeclaration . call ( this , node ) ;
} ;
CompletedDocsWalker . prototype . visitPropertyDeclaration = function ( node ) {
this . checkNode ( node , exports . ARGUMENT _PROPERTIES ) ;
_super . prototype . visitPropertyDeclaration . call ( this , node ) ;
} ;
CompletedDocsWalker . prototype . visitTypeAliasDeclaration = function ( node ) {
this . checkNode ( node , exports . ARGUMENT _TYPES ) ;
_super . prototype . visitTypeAliasDeclaration . call ( this , node ) ;
} ;
CompletedDocsWalker . prototype . visitVariableDeclaration = function ( node ) {
2017-08-14 05:01:11 +02:00
this . checkVariable ( node ) ;
2017-05-28 00:38:50 +02:00
_super . prototype . visitVariableDeclaration . call ( this , node ) ;
} ;
2017-08-14 05:01:11 +02:00
CompletedDocsWalker . prototype . checkVariable = function ( node ) {
// Only check variables in variable declaration lists
// and not variables in catch clauses and for loops.
var list = node . parent ;
if ( ! tsutils _1 . isVariableDeclarationList ( list ) ) {
return ;
}
var statement = list . parent ;
if ( ! tsutils _1 . isVariableStatement ( statement ) ) {
return ;
}
// Only check variables at the namespace/module-level or file-level
// and not variables declared inside functions and other things.
switch ( statement . parent . kind ) {
case ts . SyntaxKind . SourceFile :
case ts . SyntaxKind . ModuleBlock :
this . checkNode ( node , exports . ARGUMENT _VARIABLES , statement ) ;
}
} ;
CompletedDocsWalker . prototype . checkNode = function ( node , nodeType , requirementNode ) {
if ( requirementNode === void 0 ) { requirementNode = node ; }
2017-05-28 00:38:50 +02:00
var name = node . name ;
if ( name === undefined ) {
return ;
}
var requirement = this . requirements . get ( nodeType ) ;
2017-08-14 05:01:11 +02:00
if ( requirement === undefined || ! requirement . shouldNodeBeDocumented ( requirementNode ) ) {
2017-05-28 00:38:50 +02:00
return ;
}
var symbol = this . getTypeChecker ( ) . getSymbolAtLocation ( name ) ;
if ( symbol === undefined ) {
return ;
}
var comments = symbol . getDocumentationComment ( ) ;
2017-08-14 05:01:11 +02:00
this . checkComments ( node , this . describeNode ( nodeType ) , comments , requirementNode ) ;
} ;
CompletedDocsWalker . prototype . describeNode = function ( nodeType ) {
return nodeType . replace ( "-" , " " ) ;
2017-05-28 00:38:50 +02:00
} ;
2017-08-14 05:01:11 +02:00
CompletedDocsWalker . prototype . checkComments = function ( node , nodeDescriptor , comments , requirementNode ) {
2017-05-28 00:38:50 +02:00
if ( comments . map ( function ( comment ) { return comment . text ; } ) . join ( "" ) . trim ( ) === "" ) {
2017-08-14 05:01:11 +02:00
this . addDocumentationFailure ( node , nodeDescriptor , requirementNode ) ;
2017-05-28 00:38:50 +02:00
}
} ;
2017-08-14 05:01:11 +02:00
CompletedDocsWalker . prototype . addDocumentationFailure = function ( node , nodeType , requirementNode ) {
2017-05-28 00:38:50 +02:00
var start = node . getStart ( ) ;
var width = node . getText ( ) . split ( /\r|\n/g ) [ 0 ] . length ;
2017-08-14 05:01:11 +02:00
var description = this . describeDocumentationFailure ( requirementNode , nodeType ) ;
2017-05-28 00:38:50 +02:00
this . addFailureAt ( start , width , description ) ;
} ;
CompletedDocsWalker . prototype . describeDocumentationFailure = function ( node , nodeType ) {
var _this = this ;
var description = Rule . FAILURE _STRING _EXIST ;
if ( node . modifiers !== undefined ) {
description += node . modifiers . map ( function ( modifier ) { return _this . describeModifier ( modifier . kind ) ; } ) . join ( "," ) + " " ;
}
return "" + description + nodeType + "." ;
} ;
CompletedDocsWalker . prototype . describeModifier = function ( kind ) {
var description = ts . SyntaxKind [ kind ] . toLowerCase ( ) . split ( "keyword" ) [ 0 ] ;
var alias = CompletedDocsWalker . modifierAliases [ description ] ;
return alias !== undefined ? alias : description ;
} ;
2017-08-14 05:01:11 +02:00
CompletedDocsWalker . modifierAliases = {
export : "exported" ,
} ;
2017-05-28 00:38:50 +02:00
return CompletedDocsWalker ;
} ( Lint . ProgramAwareRuleWalker ) ) ;
var _a , _b , _c , _d , _e , _f , _g ;