@@ -1211,7 +1211,7 @@ namespace ts {
1211
1211
bind ( node . statement ) ;
1212
1212
popActiveLabel ( ) ;
1213
1213
if ( ! activeLabel . referenced && ! options . allowUnusedLabels ) {
1214
- errorOrSuggestionOnFirstToken ( unusedLabelIsError ( options ) , node , Diagnostics . Unused_label ) ;
1214
+ errorOrSuggestionOnNode ( unusedLabelIsError ( options ) , node . label , Diagnostics . Unused_label ) ;
1215
1215
}
1216
1216
if ( ! node . statement || node . statement . kind !== SyntaxKind . DoStatement ) {
1217
1217
// do statement sets current flow inside bindDoStatement
@@ -1918,9 +1918,16 @@ namespace ts {
1918
1918
file . bindDiagnostics . push ( createFileDiagnostic ( file , span . start , span . length , message , arg0 , arg1 , arg2 ) ) ;
1919
1919
}
1920
1920
1921
- function errorOrSuggestionOnFirstToken ( isError : boolean , node : Node , message : DiagnosticMessage , arg0 ?: any , arg1 ?: any , arg2 ?: any ) {
1922
- const span = getSpanOfTokenAtPosition ( file , node . pos ) ;
1923
- const diag = createFileDiagnostic ( file , span . start , span . length , message , arg0 , arg1 , arg2 ) ;
1921
+ function errorOrSuggestionOnNode ( isError : boolean , node : Node , message : DiagnosticMessage ) : void {
1922
+ errorOrSuggestionOnRange ( isError , node , node , message ) ;
1923
+ }
1924
+
1925
+ function errorOrSuggestionOnRange ( isError : boolean , startNode : Node , endNode : Node , message : DiagnosticMessage ) : void {
1926
+ addErrorOrSuggestionDiagnostic ( isError , { pos : getTokenPosOfNode ( startNode , file ) , end : endNode . end } , message ) ;
1927
+ }
1928
+
1929
+ function addErrorOrSuggestionDiagnostic ( isError : boolean , range : TextRange , message : DiagnosticMessage ) : void {
1930
+ const diag = createFileDiagnostic ( file , range . pos , range . end - range . pos , message ) ;
1924
1931
if ( isError ) {
1925
1932
file . bindDiagnostics . push ( diag ) ;
1926
1933
}
@@ -2792,14 +2799,46 @@ namespace ts {
2792
2799
node . declarationList . declarations . some ( d => ! ! d . initializer )
2793
2800
) ;
2794
2801
2795
- errorOrSuggestionOnFirstToken ( isError , node , Diagnostics . Unreachable_code_detected ) ;
2802
+ eachUnreachableRange ( node , ( start , end ) => errorOrSuggestionOnRange ( isError , start , end , Diagnostics . Unreachable_code_detected ) ) ;
2796
2803
}
2797
2804
}
2798
2805
}
2799
2806
return true ;
2800
2807
}
2801
2808
}
2802
2809
2810
+ function eachUnreachableRange ( node : Node , cb : ( start : Node , last : Node ) => void ) : void {
2811
+ if ( isStatement ( node ) && isExecutableStatement ( node ) && isBlock ( node . parent ) ) {
2812
+ const { statements } = node . parent ;
2813
+ const slice = sliceAfter ( statements , node ) ;
2814
+ getRangesWhere ( slice , isExecutableStatement , ( start , afterEnd ) => cb ( slice [ start ] , slice [ afterEnd - 1 ] ) ) ;
2815
+ }
2816
+ else {
2817
+ cb ( node , node ) ;
2818
+ }
2819
+ }
2820
+ // As opposed to a pure declaration like an `interface`
2821
+ function isExecutableStatement ( s : Statement ) : boolean {
2822
+ // Don't remove statements that can validly be used before they appear.
2823
+ return ! isFunctionDeclaration ( s ) && ! isPurelyTypeDeclaration ( s ) &&
2824
+ // `var x;` may declare a variable used above
2825
+ ! ( isVariableStatement ( s ) && ! ( getCombinedNodeFlags ( s ) & ( NodeFlags . Let | NodeFlags . Const ) ) && s . declarationList . declarations . some ( d => ! d . initializer ) ) ;
2826
+ }
2827
+
2828
+ function isPurelyTypeDeclaration ( s : Statement ) : boolean {
2829
+ switch ( s . kind ) {
2830
+ case SyntaxKind . InterfaceDeclaration :
2831
+ case SyntaxKind . TypeAliasDeclaration :
2832
+ return true ;
2833
+ case SyntaxKind . ModuleDeclaration :
2834
+ return getModuleInstanceState ( s as ModuleDeclaration ) !== ModuleInstanceState . Instantiated ;
2835
+ case SyntaxKind . EnumDeclaration :
2836
+ return hasModifier ( s , ModifierFlags . Const ) ;
2837
+ default :
2838
+ return false ;
2839
+ }
2840
+ }
2841
+
2803
2842
/* @internal */
2804
2843
export function isExportsOrModuleExportsOrAlias ( sourceFile : SourceFile , node : Expression ) : boolean {
2805
2844
return isExportsIdentifier ( node ) ||
0 commit comments