@@ -5389,18 +5389,20 @@ module ts {
5389
5389
// Parses out a JSDoc type expression. The starting position should be right at the open
5390
5390
// curly in the type expression. Returns 'undefined' if it encounters any errors while parsing.
5391
5391
/* @internal */
5392
- export function parseJSDocTypeExpression ( content : string , start ?: number , length ?: number ) : JSDocType {
5392
+ export function parseJSDocTypeExpression ( content : string , start ?: number , length ?: number ) : JSDocTypeExpression {
5393
5393
let scanner = createScanner ( ScriptTarget . Latest , /*skipTrivia:*/ true , content , /*onError:*/ undefined , start , length ) ;
5394
5394
5395
5395
// Prime the first token for us to start processing.
5396
5396
let token = nextToken ( ) ;
5397
5397
let error = false ;
5398
5398
5399
+ let result = < JSDocTypeExpression > createNode ( SyntaxKind . JSDocTypeExpression ) ;
5400
+
5399
5401
parseExpected ( SyntaxKind . OpenBraceToken ) ;
5400
- let type = parseJSDocType ( ) ;
5402
+ result . type = parseJSDocType ( ) ;
5401
5403
parseExpected ( SyntaxKind . CloseBraceToken ) ;
5402
5404
5403
- return error ? undefined : type ;
5405
+ return error ? undefined : finishNode ( result ) ;
5404
5406
5405
5407
function nextToken ( ) : SyntaxKind {
5406
5408
return token = scanner . scan ( ) ;
@@ -5738,10 +5740,12 @@ module ts {
5738
5740
5739
5741
let error = false ;
5740
5742
let type : JSDocType ;
5741
- let parameterTypes : JSDocType [ ] ;
5743
+ let parameters : JSDocParameter [ ] ;
5742
5744
let returnType : JSDocType ;
5743
5745
let typeParameterNames : string [ ] ;
5744
5746
5747
+ let pos : number ;
5748
+
5745
5749
if ( length >= "/** */" . length ) {
5746
5750
if ( content . charCodeAt ( start ) === CharacterCodes . slash &&
5747
5751
content . charCodeAt ( start + 1 ) === CharacterCodes . asterisk &&
@@ -5753,9 +5757,21 @@ module ts {
5753
5757
let canParseTag = true ;
5754
5758
let seenAsterisk = true ;
5755
5759
5756
- for ( let i = start + 3 ; ! error && i < end ; i ++ ) {
5757
- let ch = content . charCodeAt ( i ) ;
5760
+ for ( pos = start + 3 ; ! error && pos < end ; ) {
5761
+ let ch = content . charCodeAt ( pos ) ;
5762
+
5763
+ if ( ch === CharacterCodes . at && canParseTag ) {
5764
+ // Don't update 'pos' in this block. that will be handled inside the
5765
+ // parseTag function.
5766
+
5767
+ parseTag ( ) ;
5768
+
5769
+ // Once we parse out a tag, we cannot keep parsing out tags on this line.
5770
+ canParseTag = false ;
5771
+ continue ;
5772
+ }
5758
5773
5774
+ pos ++ ;
5759
5775
if ( isLineBreak ( ch ) ) {
5760
5776
// After a line break, we can parse a tag, and we haven't seen as asterisk
5761
5777
// on the next line yet.
@@ -5769,14 +5785,6 @@ module ts {
5769
5785
continue ;
5770
5786
}
5771
5787
5772
- if ( ch === CharacterCodes . at && canParseTag ) {
5773
- i = parseTag ( i ) ;
5774
-
5775
- // Once we parse out a tag, we cannot keep parsing out tags on this line.
5776
- canParseTag = false ;
5777
- continue ;
5778
- }
5779
-
5780
5788
// Ignore the first asterisk on a line.
5781
5789
if ( ch === CharacterCodes . asterisk ) {
5782
5790
if ( seenAsterisk ) {
@@ -5799,126 +5807,125 @@ module ts {
5799
5807
return error ? undefined : createJSDocComment ( ) ;
5800
5808
5801
5809
function createJSDocComment ( ) : JSDocComment {
5802
- if ( ! returnType && ! type && ! parameterTypes && ! typeParameterNames ) {
5810
+ if ( ! returnType && ! type && ! parameters && ! typeParameterNames ) {
5803
5811
return undefined ;
5804
5812
}
5805
5813
5806
- return { returnType, type, parameterTypes , typeParameterNames } ;
5814
+ return { returnType, type, parameters , typeParameterNames } ;
5807
5815
}
5808
5816
5809
- function skipWhitespace ( pos : number ) : number {
5817
+ function skipWhitespace ( ) : void {
5810
5818
while ( pos < end && isWhiteSpace ( content . charCodeAt ( pos ) ) ) {
5811
5819
pos ++ ;
5812
5820
}
5813
-
5814
- return pos ;
5815
5821
}
5816
5822
5817
- function parseTag ( pos : number ) : number {
5823
+ function parseTag ( ) : void {
5818
5824
Debug . assert ( content . charCodeAt ( pos ) === CharacterCodes . at ) ;
5825
+
5826
+ // Skip the @ sign.
5827
+ pos ++ ;
5819
5828
5820
- // Scan forward to figure out the tag name.
5821
- for ( var i = pos + 1 ; i < end ; i ++ ) {
5822
- if ( ! isIdentifierStart ( content . charCodeAt ( i ) , ScriptTarget . Latest ) ) {
5823
- break ;
5824
- }
5825
- }
5826
-
5827
- let tagName = content . substring ( pos + 1 , i ) ;
5829
+ let tagName = scanIdentifier ( ) ;
5828
5830
switch ( tagName ) {
5829
5831
case "param" :
5830
- return handleParamTag ( i ) ;
5832
+ return handleParamTag ( ) ;
5831
5833
case "return" :
5832
- return handleReturnTag ( i ) ;
5834
+ return handleReturnTag ( ) ;
5833
5835
case "template" :
5834
- return handleTemplateTag ( i ) ;
5836
+ return handleTemplateTag ( ) ;
5835
5837
case "type" :
5836
- return handleTypeTag ( i ) ;
5838
+ return handleTypeTag ( ) ;
5837
5839
}
5838
-
5839
- return i ;
5840
5840
}
5841
5841
5842
- function handleParamTag ( pos : number ) {
5843
- let typeExpr = parseJSDocTypeExpression ( content , pos , end - pos ) ;
5844
- if ( ! typeExpr ) {
5842
+ function parseType ( ) : JSDocType {
5843
+ let typeExpression = parseJSDocTypeExpression ( content , pos , end - pos ) ;
5844
+ if ( ! typeExpression ) {
5845
5845
error = true ;
5846
- return pos ;
5846
+ return undefined ;
5847
+ }
5848
+
5849
+ pos = typeExpression . end ;
5850
+ return typeExpression . type ;
5851
+ }
5852
+
5853
+ function handleParamTag ( ) {
5854
+ let type = parseType ( ) ;
5855
+ if ( ! type ) {
5856
+ return ;
5847
5857
}
5848
5858
5849
- parameterTypes = parameterTypes || [ ] ;
5850
- parameterTypes . push ( typeExpr ) ;
5851
- return typeExpr . end ;
5859
+ skipWhitespace ( ) ;
5860
+
5861
+ let name = scanIdentifier ( ) ;
5862
+ parameters = parameters || [ ] ;
5863
+ parameters . push ( { name, type } ) ;
5852
5864
}
5853
5865
5854
- function handleReturnTag ( pos : number ) {
5866
+ function handleReturnTag ( ) : void {
5855
5867
if ( ! returnType ) {
5856
- let typeExpr = parseJSDocTypeExpression ( content , pos , end - pos ) ;
5857
- if ( typeExpr ) {
5858
- returnType = typeExpr ;
5859
- return typeExpr . end ;
5868
+ returnType = parseType ( ) ;
5869
+ if ( returnType ) {
5870
+ return ;
5860
5871
}
5861
5872
}
5862
5873
5863
5874
error = true ;
5864
- return pos ;
5865
5875
}
5866
5876
5867
- function handleTypeTag ( pos : number ) {
5877
+ function handleTypeTag ( ) : void {
5868
5878
if ( ! type ) {
5869
- let typeExpr = parseJSDocTypeExpression ( content , pos , end - pos ) ;
5870
- if ( typeExpr ) {
5871
- type = typeExpr ;
5872
- return typeExpr . end ;
5879
+ type = parseType ( ) ;
5880
+ if ( type ) {
5881
+ return ;
5873
5882
}
5874
5883
}
5875
5884
5876
5885
error = true ;
5877
- return pos ;
5878
5886
}
5879
5887
5880
- function handleTemplateTag ( pos : number ) : number {
5888
+ function handleTemplateTag ( ) : void {
5881
5889
if ( ! typeParameterNames ) {
5882
5890
typeParameterNames = [ ] ;
5883
5891
5884
5892
while ( ! error ) {
5885
- pos = skipWhitespace ( pos ) ;
5886
- scanTypeParameterName ( ) ;
5887
- pos = skipWhitespace ( pos ) ;
5893
+ skipWhitespace ( ) ;
5894
+ let name = scanIdentifier ( ) ;
5895
+ typeParameterNames . push ( name ) ;
5896
+
5897
+ skipWhitespace ( ) ;
5888
5898
if ( content . charCodeAt ( pos ) !== CharacterCodes . comma ) {
5889
- break ;
5899
+ return ;
5890
5900
}
5891
- }
5892
5901
5893
- if ( typeParameterNames . length > 0 ) {
5894
- return pos ;
5902
+ pos ++ ;
5895
5903
}
5896
5904
}
5897
5905
5898
5906
error = true ;
5899
- return pos ;
5900
-
5901
- function scanTypeParameterName ( ) {
5902
- for ( var i = pos ; i < end ; i ++ ) {
5903
- let ch = content . charCodeAt ( i ) ;
5904
- if ( i === pos && isIdentifierStart ( ch , ScriptTarget . Latest ) ) {
5905
- continue ;
5906
- }
5907
- else if ( i > pos && isIdentifierPart ( ch , ScriptTarget . Latest ) ) {
5908
- continue ;
5909
- }
5907
+ }
5910
5908
5911
- break ;
5909
+ function scanIdentifier ( ) : string {
5910
+ let startPos = pos ;
5911
+ for ( ; pos < end ; pos ++ ) {
5912
+ let ch = content . charCodeAt ( pos ) ;
5913
+ if ( pos === startPos && isIdentifierStart ( ch , ScriptTarget . Latest ) ) {
5914
+ continue ;
5912
5915
}
5913
-
5914
- if ( i === pos ) {
5915
- error = true ;
5916
- return ;
5916
+ else if ( pos > startPos && isIdentifierPart ( ch , ScriptTarget . Latest ) ) {
5917
+ continue ;
5917
5918
}
5918
5919
5919
- typeParameterNames . push ( content . substring ( pos , i ) ) ;
5920
- pos = i ;
5920
+ break ;
5921
+ }
5922
+
5923
+ if ( startPos === pos ) {
5924
+ error = true ;
5925
+ return ;
5921
5926
}
5927
+
5928
+ return content . substring ( startPos , pos ) ;
5922
5929
}
5923
5930
}
5924
5931
0 commit comments