///<reference path='references.ts' />
// <auto-generated />
var TypeScript;
(function (TypeScript) {
    TypeScript.DiagnosticCode = {
        error_TS_0_1: "error TS{0}: {1}",
        warning_TS_0_1: "warning TS{0}: {1}",
        Unrecognized_escape_sequence: "Unrecognized escape sequence.",
        Unexpected_character_0: "Unexpected character {0}.",
        Missing_close_quote_character: "Missing close quote character.",
        Identifier_expected: "Identifier expected.",
        _0_keyword_expected: "'{0}' keyword expected.",
        _0_expected: "'{0}' expected.",
        Identifier_expected_0_is_a_keyword: "Identifier expected; '{0}' is a keyword.",
        Automatic_semicolon_insertion_not_allowed: "Automatic semicolon insertion not allowed.",
        Unexpected_token_0_expected: "Unexpected token; '{0}' expected.",
        Trailing_separator_not_allowed: "Trailing separator not allowed.",
        AsteriskSlash_expected: "'*/' expected.",
        public_or_private_modifier_must_precede_static: "'public' or 'private' modifier must precede 'static'.",
        Unexpected_token: "Unexpected token.",
        Catch_clause_parameter_cannot_have_a_type_annotation: "Catch clause parameter cannot have a type annotation.",
        A_rest_parameter_must_be_last_in_a_parameter_list: "A rest parameter must be last in a parameter list.",
        Parameter_cannot_have_question_mark_and_initializer: "Parameter cannot have question mark and initializer.",
        A_required_parameter_cannot_follow_an_optional_parameter: "A required parameter cannot follow an optional parameter.",
        Index_signatures_cannot_have_rest_parameters: "Index signatures cannot have rest parameters.",
        Index_signature_parameter_cannot_have_accessibility_modifiers: "Index signature parameter cannot have accessibility modifiers.",
        Index_signature_parameter_cannot_have_a_question_mark: "Index signature parameter cannot have a question mark.",
        Index_signature_parameter_cannot_have_an_initializer: "Index signature parameter cannot have an initializer.",
        Index_signature_must_have_a_type_annotation: "Index signature must have a type annotation.",
        Index_signature_parameter_must_have_a_type_annotation: "Index signature parameter must have a type annotation.",
        Index_signature_parameter_type_must_be_string_or_number: "Index signature parameter type must be 'string' or 'number'.",
        extends_clause_already_seen: "'extends' clause already seen.",
        extends_clause_must_precede_implements_clause: "'extends' clause must precede 'implements' clause.",
        Classes_can_only_extend_a_single_class: "Classes can only extend a single class.",
        implements_clause_already_seen: "'implements' clause already seen.",
        Accessibility_modifier_already_seen: "Accessibility modifier already seen.",
        _0_modifier_must_precede_1_modifier: "'{0}' modifier must precede '{1}' modifier.",
        _0_modifier_already_seen: "'{0}' modifier already seen.",
        _0_modifier_cannot_appear_on_a_class_element: "'{0}' modifier cannot appear on a class element.",
        Interface_declaration_cannot_have_implements_clause: "Interface declaration cannot have 'implements' clause.",
        super_invocation_cannot_have_type_arguments: "'super' invocation cannot have type arguments.",
        Only_ambient_modules_can_use_quoted_names: "Only ambient modules can use quoted names.",
        Statements_are_not_allowed_in_ambient_contexts: "Statements are not allowed in ambient contexts.",
        A_function_implementation_cannot_be_declared_in_an_ambient_context: "A function implementation cannot be declared in an ambient context.",
        A_declare_modifier_cannot_be_used_in_an_already_ambient_context: "A 'declare' modifier cannot be used in an already ambient context.",
        Initializers_are_not_allowed_in_ambient_contexts: "Initializers are not allowed in ambient contexts.",
        _0_modifier_cannot_appear_on_a_module_element: "'{0}' modifier cannot appear on a module element.",
        A_declare_modifier_cannot_be_used_with_an_interface_declaration: "A 'declare' modifier cannot be used with an interface declaration.",
        A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file: "A 'declare' modifier is required for a top level declaration in a .d.ts file.",
        A_rest_parameter_cannot_be_optional: "A rest parameter cannot be optional.",
        A_rest_parameter_cannot_have_an_initializer: "A rest parameter cannot have an initializer.",
        set_accessor_must_have_exactly_one_parameter: "'set' accessor must have exactly one parameter.",
        set_accessor_parameter_cannot_be_optional: "'set' accessor parameter cannot be optional.",
        set_accessor_parameter_cannot_have_an_initializer: "'set' accessor parameter cannot have an initializer.",
        set_accessor_cannot_have_rest_parameter: "'set' accessor cannot have rest parameter.",
        get_accessor_cannot_have_parameters: "'get' accessor cannot have parameters.",
        Modifiers_cannot_appear_here: "Modifiers cannot appear here.",
        Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher: "Accessors are only available when targeting ECMAScript 5 and higher.",
        Enum_member_must_have_initializer: "Enum member must have initializer.",
        Export_assignment_cannot_be_used_in_internal_modules: "Export assignment cannot be used in internal modules.",
        Ambient_enum_elements_can_only_have_integer_literal_initializers: "Ambient enum elements can only have integer literal initializers.",
        module_class_interface_enum_import_or_statement: "module, class, interface, enum, import or statement",
        constructor_function_accessor_or_variable: "constructor, function, accessor or variable",
        statement: "statement",
        case_or_default_clause: "case or default clause",
        identifier: "identifier",
        call_construct_index_property_or_function_signature: "call, construct, index, property or function signature",
        expression: "expression",
        type_name: "type name",
        property_or_accessor: "property or accessor",
        parameter: "parameter",
        type: "type",
        type_parameter: "type parameter",
        A_declare_modifier_cannot_be_used_with_an_import_declaration: "A 'declare' modifier cannot be used with an import declaration.",
        Invalid_reference_directive_syntax: "Invalid 'reference' directive syntax.",
        Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher: "Octal literals are not available when targeting ECMAScript 5 and higher.",
        Accessors_are_not_allowed_in_ambient_contexts: "Accessors are not allowed in ambient contexts.",
        _0_modifier_cannot_appear_on_a_constructor_declaration: "'{0}' modifier cannot appear on a constructor declaration.",
        _0_modifier_cannot_appear_on_a_parameter: "'{0}' modifier cannot appear on a parameter.",
        Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement: "Only a single variable declaration is allowed in a 'for...in' statement.",
        Type_parameters_cannot_appear_on_a_constructor_declaration: "Type parameters cannot appear on a constructor declaration.",
        Type_annotation_cannot_appear_on_a_constructor_declaration: "Type annotation cannot appear on a constructor declaration.",
        Type_parameters_cannot_appear_on_an_accessor: "Type parameters cannot appear on an accessor.",
        Type_annotation_cannot_appear_on_a_set_accessor: "Type annotation cannot appear on a 'set' accessor.",
        Index_signature_must_have_exactly_one_parameter: "Index signature must have exactly one parameter.",
        _0_list_cannot_be_empty: "'{0}' list cannot be empty.",
        variable_declaration: "variable declaration",
        type_argument: "type argument",
        Invalid_use_of_0_in_strict_mode: "Invalid use of '{0}' in strict mode.",
        with_statements_are_not_allowed_in_strict_mode: "'with' statements are not allowed in strict mode.",
        delete_cannot_be_called_on_an_identifier_in_strict_mode: "'delete' cannot be called on an identifier in strict mode.",
        Invalid_left_hand_side_in_for_in_statement: "Invalid left-hand side in 'for...in' statement.",
        continue_statement_can_only_be_used_within_an_enclosing_iteration_statement: "'continue' statement can only be used within an enclosing iteration statement.",
        break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement: "'break' statement can only be used within an enclosing iteration or switch statement.",
        Jump_target_not_found: "Jump target not found.",
        Jump_target_cannot_cross_function_boundary: "Jump target cannot cross function boundary.",
        return_statement_must_be_contained_within_a_function_body: "'return' statement must be contained within a function body.",
        Expression_expected: "Expression expected.",
        Type_expected: "Type expected.",
        Duplicate_identifier_0: "Duplicate identifier '{0}'.",
        The_name_0_does_not_exist_in_the_current_scope: "The name '{0}' does not exist in the current scope.",
        The_name_0_does_not_refer_to_a_value: "The name '{0}' does not refer to a value.",
        super_can_only_be_used_inside_a_class_instance_method: "'super' can only be used inside a class instance method.",
        The_left_hand_side_of_an_assignment_expression_must_be_a_variable_property_or_indexer: "The left-hand side of an assignment expression must be a variable, property or indexer.",
        Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: "Value of type '{0}' is not callable. Did you mean to include 'new'?",
        Value_of_type_0_is_not_callable: "Value of type '{0}' is not callable.",
        Value_of_type_0_is_not_newable: "Value of type '{0}' is not newable.",
        An_index_expression_argument_must_be_string_number_or_any: "An index expression argument must be 'string', 'number', or 'any'.",
        Operator_0_cannot_be_applied_to_types_1_and_2: "Operator '{0}' cannot be applied to types '{1}' and '{2}'.",
        Type_0_is_not_assignable_to_type_1: "Type '{0}' is not assignable to type '{1}'.",
        Type_0_is_not_assignable_to_type_1_NL_2: "Type '{0}' is not assignable to type '{1}':{NL}{2}",
        Expected_var_class_interface_or_module: "Expected var, class, interface, or module.",
        Getter_0_already_declared: "Getter '{0}' already declared.",
        Setter_0_already_declared: "Setter '{0}' already declared.",
        Exported_class_0_extends_private_class_1: "Exported class '{0}' extends private class '{1}'.",
        Exported_class_0_implements_private_interface_1: "Exported class '{0}' implements private interface '{1}'.",
        Exported_interface_0_extends_private_interface_1: "Exported interface '{0}' extends private interface '{1}'.",
        Exported_class_0_extends_class_from_inaccessible_module_1: "Exported class '{0}' extends class from inaccessible module {1}.",
        Exported_class_0_implements_interface_from_inaccessible_module_1: "Exported class '{0}' implements interface from inaccessible module {1}.",
        Exported_interface_0_extends_interface_from_inaccessible_module_1: "Exported interface '{0}' extends interface from inaccessible module {1}.",
        Public_static_property_0_of_exported_class_has_or_is_using_private_type_1: "Public static property '{0}' of exported class has or is using private type '{1}'.",
        Public_property_0_of_exported_class_has_or_is_using_private_type_1: "Public property '{0}' of exported class has or is using private type '{1}'.",
        Property_0_of_exported_interface_has_or_is_using_private_type_1: "Property '{0}' of exported interface has or is using private type '{1}'.",
        Exported_variable_0_has_or_is_using_private_type_1: "Exported variable '{0}' has or is using private type '{1}'.",
        Public_static_property_0_of_exported_class_is_using_inaccessible_module_1: "Public static property '{0}' of exported class is using inaccessible module {1}.",
        Public_property_0_of_exported_class_is_using_inaccessible_module_1: "Public property '{0}' of exported class is using inaccessible module {1}.",
        Property_0_of_exported_interface_is_using_inaccessible_module_1: "Property '{0}' of exported interface is using inaccessible module {1}.",
        Exported_variable_0_is_using_inaccessible_module_1: "Exported variable '{0}' is using inaccessible module {1}.",
        Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_type_1: "Parameter '{0}' of constructor from exported class has or is using private type '{1}'.",
        Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_type_1: "Parameter '{0}' of public static property setter from exported class has or is using private type '{1}'.",
        Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_type_1: "Parameter '{0}' of public property setter from exported class has or is using private type '{1}'.",
        Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_type_1: "Parameter '{0}' of constructor signature from exported interface has or is using private type '{1}'.",
        Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_type_1: "Parameter '{0}' of call signature from exported interface has or is using private type '{1}'.",
        Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_type_1: "Parameter '{0}' of public static method from exported class has or is using private type '{1}'.",
        Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_type_1: "Parameter '{0}' of public method from exported class has or is using private type '{1}'.",
        Parameter_0_of_method_from_exported_interface_has_or_is_using_private_type_1: "Parameter '{0}' of method from exported interface has or is using private type '{1}'.",
        Parameter_0_of_exported_function_has_or_is_using_private_type_1: "Parameter '{0}' of exported function has or is using private type '{1}'.",
        Parameter_0_of_constructor_from_exported_class_is_using_inaccessible_module_1: "Parameter '{0}' of constructor from exported class is using inaccessible module {1}.",
        Parameter_0_of_public_static_property_setter_from_exported_class_is_using_inaccessible_module_1: "Parameter '{0}' of public static property setter from exported class is using inaccessible module {1}.",
        Parameter_0_of_public_property_setter_from_exported_class_is_using_inaccessible_module_1: "Parameter '{0}' of public property setter from exported class is using inaccessible module {1}.",
        Parameter_0_of_constructor_signature_from_exported_interface_is_using_inaccessible_module_1: "Parameter '{0}' of constructor signature from exported interface is using inaccessible module {1}.",
        Parameter_0_of_call_signature_from_exported_interface_is_using_inaccessible_module_1: "Parameter '{0}' of call signature from exported interface is using inaccessible module {1}",
        Parameter_0_of_public_static_method_from_exported_class_is_using_inaccessible_module_1: "Parameter '{0}' of public static method from exported class is using inaccessible module {1}.",
        Parameter_0_of_public_method_from_exported_class_is_using_inaccessible_module_1: "Parameter '{0}' of public method from exported class is using inaccessible module {1}.",
        Parameter_0_of_method_from_exported_interface_is_using_inaccessible_module_1: "Parameter '{0}' of method from exported interface is using inaccessible module {1}.",
        Parameter_0_of_exported_function_is_using_inaccessible_module_1: "Parameter '{0}' of exported function is using inaccessible module {1}.",
        Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_type_0: "Return type of public static property getter from exported class has or is using private type '{0}'.",
        Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_type_0: "Return type of public property getter from exported class has or is using private type '{0}'.",
        Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_type_0: "Return type of constructor signature from exported interface has or is using private type '{0}'.",
        Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_type_0: "Return type of call signature from exported interface has or is using private type '{0}'.",
        Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_type_0: "Return type of index signature from exported interface has or is using private type '{0}'.",
        Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_type_0: "Return type of public static method from exported class has or is using private type '{0}'.",
        Return_type_of_public_method_from_exported_class_has_or_is_using_private_type_0: "Return type of public method from exported class has or is using private type '{0}'.",
        Return_type_of_method_from_exported_interface_has_or_is_using_private_type_0: "Return type of method from exported interface has or is using private type '{0}'.",
        Return_type_of_exported_function_has_or_is_using_private_type_0: "Return type of exported function has or is using private type '{0}'.",
        Return_type_of_public_static_property_getter_from_exported_class_is_using_inaccessible_module_0: "Return type of public static property getter from exported class is using inaccessible module {0}.",
        Return_type_of_public_property_getter_from_exported_class_is_using_inaccessible_module_0: "Return type of public property getter from exported class is using inaccessible module {0}.",
        Return_type_of_constructor_signature_from_exported_interface_is_using_inaccessible_module_0: "Return type of constructor signature from exported interface is using inaccessible module {0}.",
        Return_type_of_call_signature_from_exported_interface_is_using_inaccessible_module_0: "Return type of call signature from exported interface is using inaccessible module {0}.",
        Return_type_of_index_signature_from_exported_interface_is_using_inaccessible_module_0: "Return type of index signature from exported interface is using inaccessible module {0}.",
        Return_type_of_public_static_method_from_exported_class_is_using_inaccessible_module_0: "Return type of public static method from exported class is using inaccessible module {0}.",
        Return_type_of_public_method_from_exported_class_is_using_inaccessible_module_0: "Return type of public method from exported class is using inaccessible module {0}.",
        Return_type_of_method_from_exported_interface_is_using_inaccessible_module_0: "Return type of method from exported interface is using inaccessible module {0}.",
        Return_type_of_exported_function_is_using_inaccessible_module_0: "Return type of exported function is using inaccessible module {0}.",
        new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead.",
        A_parameter_list_must_follow_a_generic_type_argument_list_expected: "A parameter list must follow a generic type argument list. '(' expected.",
        Multiple_constructor_implementations_are_not_allowed: "Multiple constructor implementations are not allowed.",
        Cannot_find_external_module_0: "Cannot find external module '{0}'.",
        Module_cannot_be_aliased_to_a_non_module_type: "Module cannot be aliased to a non-module type.",
        A_class_may_only_extend_another_class: "A class may only extend another class.",
        A_class_may_only_implement_another_class_or_interface: "A class may only implement another class or interface.",
        An_interface_may_only_extend_a_class_or_another_interface: "An interface may only extend a class or another interface.",
        Unable_to_resolve_type: "Unable to resolve type.",
        Unable_to_resolve_type_of_0: "Unable to resolve type of '{0}'.",
        Unable_to_resolve_type_parameter_constraint: "Unable to resolve type parameter constraint.",
        Type_parameter_constraint_cannot_be_a_primitive_type: "Type parameter constraint cannot be a primitive type.",
        Supplied_parameters_do_not_match_any_signature_of_call_target: "Supplied parameters do not match any signature of call target.",
        Supplied_parameters_do_not_match_any_signature_of_call_target_NL_0: "Supplied parameters do not match any signature of call target:{NL}{0}",
        Cannot_use_new_with_an_expression_whose_type_lacks_a_signature: "Cannot use 'new' with an expression whose type lacks a signature.",
        Only_a_void_function_can_be_called_with_the_new_keyword: "Only a void function can be called with the 'new' keyword.",
        Could_not_select_overload_for_new_expression: "Could not select overload for 'new' expression.",
        Type_0_does_not_satisfy_the_constraint_1: "Type '{0}' does not satisfy the constraint '{1}'.",
        Could_not_select_overload_for_call_expression: "Could not select overload for 'call' expression.",
        Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: "Cannot invoke an expression whose type lacks a call signature.",
        Calls_to_super_are_only_valid_inside_a_class: "Calls to 'super' are only valid inside a class.",
        Generic_type_0_requires_1_type_argument_s: "Generic type '{0}' requires {1} type argument(s).",
        Type_of_array_literal_cannot_be_determined_Best_common_type_could_not_be_found_for_array_elements: "Type of array literal cannot be determined. Best common type could not be found for array elements.",
        Could_not_find_enclosing_symbol_for_dotted_name_0: "Could not find enclosing symbol for dotted name '{0}'.",
        Property_0_does_not_exist_on_value_of_type_1: "Property '{0}' does not exist on value of type '{1}'.",
        Cannot_find_name_0: "Cannot find name '{0}'.",
        get_and_set_accessor_must_have_the_same_type: "'get' and 'set' accessor must have the same type.",
        this_cannot_be_referenced_in_current_location: "'this' cannot be referenced in current location.",
        Static_members_cannot_reference_class_type_parameters: "Static members cannot reference class type parameters.",
        Type_0_recursively_references_itself_as_a_base_type: "Type '{0}' recursively references itself as a base type.",
        super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class: "'super' property access is permitted only in a constructor, member function, or member accessor of a derived class.",
        super_can_only_be_referenced_in_a_derived_class: "'super' can only be referenced in a derived class.",
        A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties: "A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.",
        Constructors_for_derived_classes_must_contain_a_super_call: "Constructors for derived classes must contain a 'super' call.",
        Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors: "Super calls are not permitted outside constructors or in nested functions inside constructors.",
        _0_1_is_inaccessible: "'{0}.{1}' is inaccessible.",
        this_cannot_be_referenced_in_a_module_body: "'this' cannot be referenced in a module body.",
        Invalid_expression_types_not_known_to_support_the_addition_operator: "Invalid '+' expression - types not known to support the addition operator.",
        The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.",
        The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: "The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.",
        An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: "An arithmetic operand must be of type 'any', 'number' or an enum type.",
        Variable_declarations_of_a_for_statement_cannot_use_a_type_annotation: "Variable declarations of a 'for' statement cannot use a type annotation.",
        Variable_declarations_of_a_for_statement_must_be_of_types_string_or_any: "Variable declarations of a 'for' statement must be of types 'string' or 'any'.",
        The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter.",
        The_left_hand_side_of_an_in_expression_must_be_of_types_any_string_or_number: "The left-hand side of an 'in' expression must be of types 'any', 'string' or 'number'.",
        The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter.",
        The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.",
        The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type: "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type.",
        Setters_cannot_return_a_value: "Setters cannot return a value.",
        Tried_to_query_type_of_uninitialized_module_0: "Tried to query type of uninitialized module '{0}'.",
        Tried_to_set_variable_type_to_uninitialized_module_type_0: "Tried to set variable type to uninitialized module type '{0}'.",
        Type_0_is_not_generic: "Type '{0}' is not generic.",
        Getters_must_return_a_value: "Getters must return a value.",
        Getter_and_setter_accessors_do_not_agree_in_visibility: "Getter and setter accessors do not agree in visibility.",
        Invalid_left_hand_side_of_assignment_expression: "Invalid left-hand side of assignment expression.",
        Function_declared_a_non_void_return_type_but_has_no_return_expression: "Function declared a non-void return type, but has no return expression.",
        Cannot_resolve_return_type_reference: "Cannot resolve return type reference.",
        Constructors_cannot_have_a_return_type_of_void: "Constructors cannot have a return type of 'void'.",
        Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2: "Subsequent variable declarations must have the same type.  Variable '{0}' must be of type '{1}', but here has type '{2}'.",
        All_symbols_within_a_with_block_will_be_resolved_to_any: "All symbols within a with block will be resolved to 'any'.",
        Import_declarations_in_an_internal_module_cannot_reference_an_external_module: "Import declarations in an internal module cannot reference an external module.",
        Class_0_declares_interface_1_but_does_not_implement_it_NL_2: "Class {0} declares interface {1} but does not implement it:{NL}{2}",
        Class_0_declares_class_1_as_an_interface_but_does_not_implement_it_NL_2: "Class {0} declares class {1} as an interface but does not implement it:{NL}{2}",
        The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: "The operand of an increment or decrement operator must be a variable, property or indexer.",
        this_cannot_be_referenced_in_a_static_property_initializer: "'this' cannot be referenced in a static property initializer.",
        Class_0_cannot_extend_class_1_NL_2: "Class '{0}' cannot extend class '{1}':{NL}{2}",
        Interface_0_cannot_extend_class_1_NL_2: "Interface '{0}' cannot extend class '{1}':{NL}{2}",
        Interface_0_cannot_extend_interface_1_NL_2: "Interface '{0}' cannot extend interface '{1}':{NL}{2}",
        Overload_signature_is_not_compatible_with_function_definition: "Overload signature is not compatible with function definition.",
        Overload_signature_is_not_compatible_with_function_definition_NL_0: "Overload signature is not compatible with function definition:{NL}{0}",
        Overload_signatures_must_all_be_public_or_private: "Overload signatures must all be public or private.",
        Overload_signatures_must_all_be_exported_or_not_exported: "Overload signatures must all be exported or not exported.",
        Overload_signatures_must_all_be_ambient_or_non_ambient: "Overload signatures must all be ambient or non-ambient.",
        Overload_signatures_must_all_be_optional_or_required: "Overload signatures must all be optional or required.",
        Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature: "Specialized overload signature is not assignable to any non-specialized signature.",
        this_cannot_be_referenced_in_constructor_arguments: "'this' cannot be referenced in constructor arguments.",
        Instance_member_cannot_be_accessed_off_a_class: "Instance member cannot be accessed off a class.",
        Untyped_function_calls_may_not_accept_type_arguments: "Untyped function calls may not accept type arguments.",
        Non_generic_functions_may_not_accept_type_arguments: "Non-generic functions may not accept type arguments.",
        A_generic_type_may_not_reference_itself_with_a_wrapped_form_of_its_own_type_parameters: "A generic type may not reference itself with a wrapped form of its own type parameters.",
        A_rest_parameter_must_be_of_an_array_type: "A rest parameter must be of an array type.",
        Overload_signature_implementation_cannot_use_specialized_type: "Overload signature implementation cannot use specialized type.",
        Export_assignments_may_only_be_used_at_the_top_level_of_external_modules: "Export assignments may only be used at the top-level of external modules.",
        Export_assignments_may_only_be_made_with_variables_functions_classes_interfaces_enums_and_internal_modules: "Export assignments may only be made with variables, functions, classes, interfaces, enums and internal modules.",
        Only_public_methods_of_the_base_class_are_accessible_via_the_super_keyword: "Only public methods of the base class are accessible via the 'super' keyword.",
        Numeric_indexer_type_0_must_be_assignable_to_string_indexer_type_1: "Numeric indexer type '{0}' must be assignable to string indexer type '{1}'.",
        Numeric_indexer_type_0_must_be_assignable_to_string_indexer_type_1_NL_2: "Numeric indexer type '{0}' must be assignable to string indexer type '{1}':{NL}{2}",
        All_numerically_named_properties_must_be_assignable_to_numeric_indexer_type_0: "All numerically named properties must be assignable to numeric indexer type '{0}'.",
        All_numerically_named_properties_must_be_assignable_to_numeric_indexer_type_0_NL_1: "All numerically named properties must be assignable to numeric indexer type '{0}':{NL}{1}",
        All_named_properties_must_be_assignable_to_string_indexer_type_0: "All named properties must be assignable to string indexer type '{0}'.",
        All_named_properties_must_be_assignable_to_string_indexer_type_0_NL_1: "All named properties must be assignable to string indexer type '{0}':{NL}{1}",
        A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation: "A parameter initializer is only allowed in a function or constructor implementation.",
        Function_expression_declared_a_non_void_return_type_but_has_no_return_expression: "Function expression declared a non-void return type, but has no return expression.",
        Import_declaration_referencing_identifier_from_internal_module_can_only_be_made_with_variables_functions_classes_interfaces_enums_and_internal_modules: "Import declaration referencing identifier from internal module can only be made with variables, functions, classes, interfaces, enums and internal modules.",
        Module_0_has_no_exported_member_1: "Module '{0}' has no exported member '{1}'.",
        Unable_to_resolve_module_reference_0: "Unable to resolve module reference '{0}'.",
        Could_not_find_module_0_in_module_1: "Could not find module '{0}' in module '{1}'.",
        Exported_import_declaration_0_is_assigned_value_with_type_that_has_or_is_using_private_type_1: "Exported import declaration '{0}' is assigned value with type that has or is using private type '{1}'.",
        Exported_import_declaration_0_is_assigned_value_with_type_that_is_using_inaccessible_module_1: "Exported import declaration '{0}' is assigned value with type that is using inaccessible module '{1}'.",
        Exported_import_declaration_0_is_assigned_type_that_has_or_is_using_private_type_1: "Exported import declaration '{0}' is assigned type that has or is using private type '{1}'.",
        Exported_import_declaration_0_is_assigned_type_that_is_using_inaccessible_module_1: "Exported import declaration '{0}' is assigned type that is using inaccessible module '{1}'.",
        Exported_import_declaration_0_is_assigned_container_that_is_or_is_using_inaccessible_module_1: "Exported import declaration '{0}' is assigned container that is or is using inaccessible module '{1}'.",
        Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_1: "Type name '{0}' in extends clause does not reference constructor function for '{1}'.",
        Internal_module_reference_0_in_import_declaration_does_not_reference_module_instance_for_1: "Internal module reference '{0}' in import declaration does not reference module instance for '{1}'.",
        Module_0_cannot_merge_with_previous_declaration_of_1_in_a_different_file_2: "Module '{0}' cannot merge with previous declaration of '{1}' in a different file '{2}'.",
        Interface_0_cannot_simultaneously_extend_types_1_and_2_NL_3: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}':{NL}{3}",
        Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it: "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it.",
        Ambient_external_module_declaration_cannot_be_reopened: "Ambient external module declaration cannot be reopened.",
        All_declarations_of_merged_declaration_0_must_be_exported_or_not_exported: "All declarations of merged declaration '{0}' must be exported or not exported.",
        super_cannot_be_referenced_in_constructor_arguments: "'super' cannot be referenced in constructor arguments.",
        Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: "Return type of constructor signature must be assignable to the instance type of the class.",
        Ambient_external_module_declaration_must_be_defined_in_global_context: "Ambient external module declaration must be defined in global context.",
        Ambient_external_module_declaration_cannot_specify_relative_module_name: "Ambient external module declaration cannot specify relative module name.",
        Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: "Import declaration in an ambient external module declaration cannot reference external module through relative external module name.",
        No_best_common_type_exists_among_return_expressions: "No best common type exists among return expressions.",
        Import_declaration_cannot_refer_to_external_module_reference_when_noResolve_option_is_set: "Import declaration cannot refer to external module reference when --noResolve option is set.",
        Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference: "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.",
        Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference: "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference.",
        Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference: "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference.",
        Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference: "Expression resolves to '_super' that compiler uses to capture base class reference.",
        TypeParameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_type_1: "TypeParameter '{0}' of constructor signature from exported interface has or is using private type '{1}'.",
        TypeParameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_type_1: "TypeParameter '{0}' of call signature from exported interface has or is using private type '{1}'.",
        TypeParameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_type_1: "TypeParameter '{0}' of public static method from exported class has or is using private type '{1}'.",
        TypeParameter_0_of_public_method_from_exported_class_has_or_is_using_private_type_1: "TypeParameter '{0}' of public method from exported class has or is using private type '{1}'.",
        TypeParameter_0_of_method_from_exported_interface_has_or_is_using_private_type_1: "TypeParameter '{0}' of method from exported interface has or is using private type '{1}'.",
        TypeParameter_0_of_exported_function_has_or_is_using_private_type_1: "TypeParameter '{0}' of exported function has or is using private type '{1}'.",
        TypeParameter_0_of_constructor_signature_from_exported_interface_is_using_inaccessible_module_1: "TypeParameter '{0}' of constructor signature from exported interface is using inaccessible module {1}.",
        TypeParameter_0_of_call_signature_from_exported_interface_is_using_inaccessible_module_1: "TypeParameter '{0}' of call signature from exported interface is using inaccessible module {1}",
        TypeParameter_0_of_public_static_method_from_exported_class_is_using_inaccessible_module_1: "TypeParameter '{0}' of public static method from exported class is using inaccessible module {1}.",
        TypeParameter_0_of_public_method_from_exported_class_is_using_inaccessible_module_1: "TypeParameter '{0}' of public method from exported class is using inaccessible module {1}.",
        TypeParameter_0_of_method_from_exported_interface_is_using_inaccessible_module_1: "TypeParameter '{0}' of method from exported interface is using inaccessible module {1}.",
        TypeParameter_0_of_exported_function_is_using_inaccessible_module_1: "TypeParameter '{0}' of exported function is using inaccessible module {1}.",
        TypeParameter_0_of_exported_class_has_or_is_using_private_type_1: "TypeParameter '{0}' of exported class has or is using private type '{1}'.",
        TypeParameter_0_of_exported_interface_has_or_is_using_private_type_1: "TypeParameter '{0}' of exported interface has or is using private type '{1}'.",
        TypeParameter_0_of_exported_class_is_using_inaccessible_module_1: "TypeParameter '{0}' of exported class is using inaccessible module {1}.",
        TypeParameter_0_of_exported_interface_is_using_inaccessible_module_1: "TypeParameter '{0}' of exported interface is using inaccessible module {1}.",
        Duplicate_identifier_i_Compiler_uses_i_to_initialize_rest_parameter: "Duplicate identifier '_i'. Compiler uses '_i' to initialize rest parameter.",
        Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters: "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters.",
        No_best_common_type_exists_between_0_and_1: "No best common type exists between '{0}' and '{1}'.",
        No_best_common_type_exists_between_0_1_and_2: "No best common type exists between '{0}', '{1}', and '{2}'.",
        Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module: "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module.",
        Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list: "Constraint of a type parameter cannot reference any type parameter from the same type parameter list.",
        Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor.",
        Parameter_0_cannot_be_referenced_in_its_initializer: "Parameter '{0}' cannot be referenced in its initializer.",
        Duplicate_string_index_signature: "Duplicate string index signature.",
        Duplicate_number_index_signature: "Duplicate number index signature.",
        All_declarations_of_an_interface_must_have_identical_type_parameters: "All declarations of an interface must have identical type parameters.",
        Expression_resolves_to_variable_declaration_i_that_compiler_uses_to_initialize_rest_parameter: "Expression resolves to variable declaration '_i' that compiler uses to initialize rest parameter.",
        Neither_type_0_nor_type_1_is_assignable_to_the_other: "Neither type '{0}' nor type '{1}' is assignable to the other.",
        Neither_type_0_nor_type_1_is_assignable_to_the_other_NL_2: "Neither type '{0}' nor type '{1}' is assignable to the other:{NL}{2}",
        Duplicate_function_implementation: "Duplicate function implementation.",
        Function_implementation_expected: "Function implementation expected.",
        Function_overload_name_must_be_0: "Function overload name must be '{0}'.",
        Constructor_implementation_expected: "Constructor implementation expected.",
        Class_name_cannot_be_0: "Class name cannot be '{0}'.",
        Interface_name_cannot_be_0: "Interface name cannot be '{0}'.",
        Enum_name_cannot_be_0: "Enum name cannot be '{0}'.",
        A_module_cannot_have_multiple_export_assignments: "A module cannot have multiple export assignments.",
        Export_assignment_not_allowed_in_module_with_exported_element: "Export assignment not allowed in module with exported element.",
        A_parameter_property_is_only_allowed_in_a_constructor_implementation: "A parameter property is only allowed in a constructor implementation.",
        Function_overload_must_be_static: "Function overload must be static.",
        Function_overload_must_not_be_static: "Function overload must not be static.",
        Type_0_is_missing_property_1_from_type_2: "Type '{0}' is missing property '{1}' from type '{2}'.",
        Types_of_property_0_of_types_1_and_2_are_incompatible: "Types of property '{0}' of types '{1}' and '{2}' are incompatible.",
        Types_of_property_0_of_types_1_and_2_are_incompatible_NL_3: "Types of property '{0}' of types '{1}' and '{2}' are incompatible:{NL}{3}",
        Property_0_defined_as_private_in_type_1_is_defined_as_public_in_type_2: "Property '{0}' defined as private in type '{1}' is defined as public in type '{2}'.",
        Property_0_defined_as_public_in_type_1_is_defined_as_private_in_type_2: "Property '{0}' defined as public in type '{1}' is defined as private in type '{2}'.",
        Types_0_and_1_define_property_2_as_private: "Types '{0}' and '{1}' define property '{2}' as private.",
        Call_signatures_of_types_0_and_1_are_incompatible: "Call signatures of types '{0}' and '{1}' are incompatible.",
        Call_signatures_of_types_0_and_1_are_incompatible_NL_2: "Call signatures of types '{0}' and '{1}' are incompatible:{NL}{2}",
        Type_0_requires_a_call_signature_but_type_1_lacks_one: "Type '{0}' requires a call signature, but type '{1}' lacks one.",
        Construct_signatures_of_types_0_and_1_are_incompatible: "Construct signatures of types '{0}' and '{1}' are incompatible.",
        Construct_signatures_of_types_0_and_1_are_incompatible_NL_2: "Construct signatures of types '{0}' and '{1}' are incompatible:{NL}{2}",
        Type_0_requires_a_construct_signature_but_type_1_lacks_one: "Type '{0}' requires a construct signature, but type '{1}' lacks one.",
        Index_signatures_of_types_0_and_1_are_incompatible: "Index signatures of types '{0}' and '{1}' are incompatible.",
        Index_signatures_of_types_0_and_1_are_incompatible_NL_2: "Index signatures of types '{0}' and '{1}' are incompatible:{NL}{2}",
        Call_signature_expects_0_or_fewer_parameters: "Call signature expects {0} or fewer parameters.",
        Could_not_apply_type_0_to_argument_1_which_is_of_type_2: "Could not apply type '{0}' to argument {1} which is of type '{2}'.",
        Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function: "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function.",
        Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function: "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member function.",
        Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor.",
        Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property.",
        Types_of_static_property_0_of_class_1_and_class_2_are_incompatible: "Types of static property '{0}' of class '{1}' and class '{2}' are incompatible.",
        Types_of_static_property_0_of_class_1_and_class_2_are_incompatible_NL_3: "Types of static property '{0}' of class '{1}' and class '{2}' are incompatible:{NL}{3}",
        Type_reference_cannot_refer_to_container_0: "Type reference cannot refer to container '{0}'.",
        Type_reference_must_refer_to_type: "Type reference must refer to type.",
        In_enums_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_the_first_enum_element: "In enums with multiple declarations only one declaration can omit an initializer for the first enum element.",
        _0_overload_s: " (+ {0} overload(s))",
        Variable_declaration_cannot_have_the_same_name_as_an_import_declaration: "Variable declaration cannot have the same name as an import declaration.",
        Signature_expected_0_type_arguments_got_1_instead: "Signature expected {0} type arguments, got {1} instead.",
        Property_0_defined_as_optional_in_type_1_but_is_required_in_type_2: "Property '{0}' defined as optional in type '{1}', but is required in type '{2}'.",
        Types_0_and_1_originating_in_infinitely_expanding_type_reference_do_not_refer_to_same_named_type: "Types '{0}' and '{1}' originating in infinitely expanding type reference do not refer to same named type.",
        Types_0_and_1_originating_in_infinitely_expanding_type_reference_have_incompatible_type_arguments: "Types '{0}' and '{1}' originating in infinitely expanding type reference have incompatible type arguments.",
        Types_0_and_1_originating_in_infinitely_expanding_type_reference_have_incompatible_type_arguments_NL_2: "Types '{0}' and '{1}' originating in infinitely expanding type reference have incompatible type arguments:{NL}{2}",
        Named_properties_0_of_types_1_and_2_are_not_identical: "Named properties '{0}' of types '{1}' and '{2}' are not identical.",
        Types_of_string_indexer_of_types_0_and_1_are_not_identical: "Types of string indexer of types '{0}' and '{1}' are not identical.",
        Types_of_number_indexer_of_types_0_and_1_are_not_identical: "Types of number indexer of types '{0}' and '{1}' are not identical.",
        Type_of_number_indexer_in_type_0_is_not_assignable_to_string_indexer_type_in_type_1_NL_2: "Type of number indexer in type '{0}' is not assignable to string indexer type in type '{1}'.{NL}{2}",
        Type_of_property_0_in_type_1_is_not_assignable_to_string_indexer_type_in_type_2_NL_3: "Type of property '{0}' in type '{1}' is not assignable to string indexer type in type '{2}'.{NL}{3}",
        Type_of_property_0_in_type_1_is_not_assignable_to_number_indexer_type_in_type_2_NL_3: "Type of property '{0}' in type '{1}' is not assignable to number indexer type in type '{2}'.{NL}{3}",
        Static_property_0_defined_as_private_in_type_1_is_defined_as_public_in_type_2: "Static property '{0}' defined as private in type '{1}' is defined as public in type '{2}'.",
        Static_property_0_defined_as_public_in_type_1_is_defined_as_private_in_type_2: "Static property '{0}' defined as public in type '{1}' is defined as private in type '{2}'.",
        Types_0_and_1_define_static_property_2_as_private: "Types '{0}' and '{1}' define static property '{2}' as private.",
        Current_host_does_not_support_0_option: "Current host does not support '{0}' option.",
        ECMAScript_target_version_0_not_supported_Specify_a_valid_target_version_1_default_or_2: "ECMAScript target version '{0}' not supported.  Specify a valid target version: '{1}' (default), or '{2}'",
        Argument_for_0_option_must_be_1_or_2: "Argument for '{0}' option must be '{1}' or '{2}'",
        Could_not_find_file_0: "Could not find file: '{0}'.",
        A_file_cannot_have_a_reference_to_itself: "A file cannot have a reference to itself.",
        Cannot_resolve_referenced_file_0: "Cannot resolve referenced file: '{0}'.",
        Cannot_find_the_common_subdirectory_path_for_the_input_files: "Cannot find the common subdirectory path for the input files.",
        Emit_Error_0: "Emit Error: {0}.",
        Cannot_read_file_0_1: "Cannot read file '{0}': {1}",
        Unsupported_file_encoding: "Unsupported file encoding.",
        Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1: "Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'.",
        Unsupported_locale_0: "Unsupported locale: '{0}'.",
        Execution_Failed_NL: "Execution Failed.{NL}",
        Invalid_call_to_up: "Invalid call to 'up'",
        Invalid_call_to_down: "Invalid call to 'down'",
        Base64_value_0_finished_with_a_continuation_bit: "Base64 value '{0}' finished with a continuation bit.",
        Unknown_compiler_option_0: "Unknown compiler option '{0}'",
        Expected_0_arguments_to_message_got_1_instead: "Expected {0} arguments to message, got {1} instead.",
        Expected_the_message_0_to_have_1_arguments_but_it_had_2: "Expected the message '{0}' to have {1} arguments, but it had {2}",
        Could_not_delete_file_0: "Could not delete file '{0}'",
        Could_not_create_directory_0: "Could not create directory '{0}'",
        Error_while_executing_file_0: "Error while executing file '{0}': ",
        Cannot_compile_external_modules_unless_the_module_flag_is_provided: "Cannot compile external modules unless the '--module' flag is provided.",
        Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option: "Option mapRoot cannot be specified without specifying sourcemap option.",
        Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: "Option sourceRoot cannot be specified without specifying sourcemap option.",
        Options_mapRoot_and_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: "Options mapRoot and sourceRoot cannot be specified without specifying sourcemap option.",
        Option_0_specified_without_1: "Option '{0}' specified without '{1}'",
        codepage_option_not_supported_on_current_platform: "'codepage' option not supported on current platform.",
        Concatenate_and_emit_output_to_single_file: "Concatenate and emit output to single file.",
        Generates_corresponding_0_file: "Generates corresponding {0} file.",
        Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: "Specifies the location where debugger should locate map files instead of generated locations.",
        Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations: "Specifies the location where debugger should locate TypeScript files instead of source locations.",
        Watch_input_files: "Watch input files.",
        Redirect_output_structure_to_the_directory: "Redirect output structure to the directory.",
        Do_not_emit_comments_to_output: "Do not emit comments to output.",
        Skip_resolution_and_preprocessing: "Skip resolution and preprocessing.",
        Specify_ECMAScript_target_version_0_default_or_1: "Specify ECMAScript target version: '{0}' (default), or '{1}'",
        Specify_module_code_generation_0_or_1: "Specify module code generation: '{0}' or '{1}'",
        Print_this_message: "Print this message.",
        Print_the_compiler_s_version_0: "Print the compiler's version: {0}",
        Allow_use_of_deprecated_0_keyword_when_referencing_an_external_module: "Allow use of deprecated '{0}' keyword when referencing an external module.",
        Specify_locale_for_errors_and_messages_For_example_0_or_1: "Specify locale for errors and messages. For example '{0}' or '{1}'",
        Syntax_0: "Syntax:   {0}",
        options: "options",
        file1: "file",
        Examples: "Examples:",
        Options: "Options:",
        Insert_command_line_options_and_files_from_a_file: "Insert command line options and files from a file.",
        Version_0: "Version {0}",
        Use_the_0_flag_to_see_options: "Use the '{0}' flag to see options.",
        NL_Recompiling_0: "{NL}Recompiling ({0}):",
        STRING: "STRING",
        KIND: "KIND",
        file2: "FILE",
        VERSION: "VERSION",
        LOCATION: "LOCATION",
        DIRECTORY: "DIRECTORY",
        NUMBER: "NUMBER",
        Specify_the_codepage_to_use_when_opening_source_files: "Specify the codepage to use when opening source files.",
        Additional_locations: "Additional locations:",
        This_version_of_the_Javascript_runtime_does_not_support_the_0_function: "This version of the Javascript runtime does not support the '{0}' function.",
        Unknown_rule: "Unknown rule.",
        Invalid_line_number_0: "Invalid line number ({0})",
        Warn_on_expressions_and_declarations_with_an_implied_any_type: "Warn on expressions and declarations with an implied 'any' type.",
        Variable_0_implicitly_has_an_any_type: "Variable '{0}' implicitly has an 'any' type.",
        Parameter_0_of_1_implicitly_has_an_any_type: "Parameter '{0}' of '{1}' implicitly has an 'any' type.",
        Parameter_0_of_function_type_implicitly_has_an_any_type: "Parameter '{0}' of function type implicitly has an 'any' type.",
        Member_0_of_object_type_implicitly_has_an_any_type: "Member '{0}' of object type implicitly has an 'any' type.",
        new_expression_which_lacks_a_constructor_signature_implicitly_has_an_any_type: "'new' expression, which lacks a constructor signature, implicitly has an 'any' type.",
        _0_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: "'{0}', which lacks return-type annotation, implicitly has an 'any' return type.",
        Function_expression_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: "Function expression, which lacks return-type annotation, implicitly has an 'any' return type.",
        Parameter_0_of_lambda_function_implicitly_has_an_any_type: "Parameter '{0}' of lambda function implicitly has an 'any' type.",
        Constructor_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: "Constructor signature, which lacks return-type annotation, implicitly has an 'any' return type.",
        Lambda_Function_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: "Lambda Function, which lacks return-type annotation, implicitly has an 'any' return type.",
        Array_Literal_implicitly_has_an_any_type_from_widening: "Array Literal implicitly has an 'any' type from widening.",
        _0_which_lacks_get_accessor_and_parameter_type_annotation_on_set_accessor_implicitly_has_an_any_type: "'{0}', which lacks 'get' accessor and parameter type annotation on 'set' accessor, implicitly has an 'any' type.",
        Index_signature_of_object_type_implicitly_has_an_any_type: "Index signature of object type implicitly has an 'any' type.",
        Object_literal_s_property_0_implicitly_has_an_any_type_from_widening: "Object literal's property '{0}' implicitly has an 'any' type from widening."
    };
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (DiagnosticCategory) {
        DiagnosticCategory[DiagnosticCategory["Warning"] = 0] = "Warning";
        DiagnosticCategory[DiagnosticCategory["Error"] = 1] = "Error";
        DiagnosticCategory[DiagnosticCategory["Message"] = 2] = "Message";
        DiagnosticCategory[DiagnosticCategory["NoPrefix"] = 3] = "NoPrefix";
    })(TypeScript.DiagnosticCategory || (TypeScript.DiagnosticCategory = {}));
    var DiagnosticCategory = TypeScript.DiagnosticCategory;
})(TypeScript || (TypeScript = {}));
// <auto-generated />
/// <reference path="..\core\diagnosticCategory.ts" />
var TypeScript;
(function (TypeScript) {
    TypeScript.diagnosticInformationMap = {
        "error TS{0}: {1}": { "code": 0, "category": 3 /* NoPrefix */ },
        "warning TS{0}: {1}": { "code": 1, "category": 3 /* NoPrefix */ },
        "Unrecognized escape sequence.": { "code": 1000, "category": 1 /* Error */ },
        "Unexpected character {0}.": { "code": 1001, "category": 1 /* Error */ },
        "Missing close quote character.": { "code": 1002, "category": 1 /* Error */ },
        "Identifier expected.": { "code": 1003, "category": 1 /* Error */ },
        "'{0}' keyword expected.": { "code": 1004, "category": 1 /* Error */ },
        "'{0}' expected.": { "code": 1005, "category": 1 /* Error */ },
        "Identifier expected; '{0}' is a keyword.": { "code": 1006, "category": 1 /* Error */ },
        "Automatic semicolon insertion not allowed.": { "code": 1007, "category": 1 /* Error */ },
        "Unexpected token; '{0}' expected.": { "code": 1008, "category": 1 /* Error */ },
        "Trailing separator not allowed.": { "code": 1009, "category": 1 /* Error */ },
        "'*/' expected.": { "code": 1010, "category": 1 /* Error */ },
        "'public' or 'private' modifier must precede 'static'.": { "code": 1011, "category": 1 /* Error */ },
        "Unexpected token.": { "code": 1012, "category": 1 /* Error */ },
        "Catch clause parameter cannot have a type annotation.": { "code": 1013, "category": 1 /* Error */ },
        "A rest parameter must be last in a parameter list.": { "code": 1014, "category": 1 /* Error */ },
        "Parameter cannot have question mark and initializer.": { "code": 1015, "category": 1 /* Error */ },
        "A required parameter cannot follow an optional parameter.": { "code": 1016, "category": 1 /* Error */ },
        "Index signatures cannot have rest parameters.": { "code": 1017, "category": 1 /* Error */ },
        "Index signature parameter cannot have accessibility modifiers.": { "code": 1018, "category": 1 /* Error */ },
        "Index signature parameter cannot have a question mark.": { "code": 1019, "category": 1 /* Error */ },
        "Index signature parameter cannot have an initializer.": { "code": 1020, "category": 1 /* Error */ },
        "Index signature must have a type annotation.": { "code": 1021, "category": 1 /* Error */ },
        "Index signature parameter must have a type annotation.": { "code": 1022, "category": 1 /* Error */ },
        "Index signature parameter type must be 'string' or 'number'.": { "code": 1023, "category": 1 /* Error */ },
        "'extends' clause already seen.": { "code": 1024, "category": 1 /* Error */ },
        "'extends' clause must precede 'implements' clause.": { "code": 1025, "category": 1 /* Error */ },
        "Classes can only extend a single class.": { "code": 1026, "category": 1 /* Error */ },
        "'implements' clause already seen.": { "code": 1027, "category": 1 /* Error */ },
        "Accessibility modifier already seen.": { "code": 1028, "category": 1 /* Error */ },
        "'{0}' modifier must precede '{1}' modifier.": { "code": 1029, "category": 1 /* Error */ },
        "'{0}' modifier already seen.": { "code": 1030, "category": 1 /* Error */ },
        "'{0}' modifier cannot appear on a class element.": { "code": 1031, "category": 1 /* Error */ },
        "Interface declaration cannot have 'implements' clause.": { "code": 1032, "category": 1 /* Error */ },
        "'super' invocation cannot have type arguments.": { "code": 1034, "category": 1 /* Error */ },
        "Only ambient modules can use quoted names.": { "code": 1035, "category": 1 /* Error */ },
        "Statements are not allowed in ambient contexts.": { "code": 1036, "category": 1 /* Error */ },
        "A function implementation cannot be declared in an ambient context.": { "code": 1037, "category": 1 /* Error */ },
        "A 'declare' modifier cannot be used in an already ambient context.": { "code": 1038, "category": 1 /* Error */ },
        "Initializers are not allowed in ambient contexts.": { "code": 1039, "category": 1 /* Error */ },
        "'{0}' modifier cannot appear on a module element.": { "code": 1044, "category": 1 /* Error */ },
        "A 'declare' modifier cannot be used with an interface declaration.": { "code": 1045, "category": 1 /* Error */ },
        "A 'declare' modifier is required for a top level declaration in a .d.ts file.": { "code": 1046, "category": 1 /* Error */ },
        "A rest parameter cannot be optional.": { "code": 1047, "category": 1 /* Error */ },
        "A rest parameter cannot have an initializer.": { "code": 1048, "category": 1 /* Error */ },
        "'set' accessor must have exactly one parameter.": { "code": 1049, "category": 1 /* Error */ },
        "'set' accessor parameter cannot be optional.": { "code": 1051, "category": 1 /* Error */ },
        "'set' accessor parameter cannot have an initializer.": { "code": 1052, "category": 1 /* Error */ },
        "'set' accessor cannot have rest parameter.": { "code": 1053, "category": 1 /* Error */ },
        "'get' accessor cannot have parameters.": { "code": 1054, "category": 1 /* Error */ },
        "Modifiers cannot appear here.": { "code": 1055, "category": 1 /* Error */ },
        "Accessors are only available when targeting ECMAScript 5 and higher.": { "code": 1056, "category": 1 /* Error */ },
        "Enum member must have initializer.": { "code": 1061, "category": 1 /* Error */ },
        "Export assignment cannot be used in internal modules.": { "code": 1063, "category": 1 /* Error */ },
        "Ambient enum elements can only have integer literal initializers.": { "code": 1066, "category": 1 /* Error */ },
        "module, class, interface, enum, import or statement": { "code": 1067, "category": 3 /* NoPrefix */ },
        "constructor, function, accessor or variable": { "code": 1068, "category": 3 /* NoPrefix */ },
        "statement": { "code": 1069, "category": 3 /* NoPrefix */ },
        "case or default clause": { "code": 1070, "category": 3 /* NoPrefix */ },
        "identifier": { "code": 1071, "category": 3 /* NoPrefix */ },
        "call, construct, index, property or function signature": { "code": 1072, "category": 3 /* NoPrefix */ },
        "expression": { "code": 1073, "category": 3 /* NoPrefix */ },
        "type name": { "code": 1074, "category": 3 /* NoPrefix */ },
        "property or accessor": { "code": 1075, "category": 3 /* NoPrefix */ },
        "parameter": { "code": 1076, "category": 3 /* NoPrefix */ },
        "type": { "code": 1077, "category": 3 /* NoPrefix */ },
        "type parameter": { "code": 1078, "category": 3 /* NoPrefix */ },
        "A 'declare' modifier cannot be used with an import declaration.": { "code": 1079, "category": 1 /* Error */ },
        "Invalid 'reference' directive syntax.": { "code": 1084, "category": 1 /* Error */ },
        "Octal literals are not available when targeting ECMAScript 5 and higher.": { "code": 1085, "category": 1 /* Error */ },
        "Accessors are not allowed in ambient contexts.": { "code": 1086, "category": 1 /* Error */ },
        "'{0}' modifier cannot appear on a constructor declaration.": { "code": 1089, "category": 1 /* Error */ },
        "'{0}' modifier cannot appear on a parameter.": { "code": 1090, "category": 1 /* Error */ },
        "Only a single variable declaration is allowed in a 'for...in' statement.": { "code": 1091, "category": 1 /* Error */ },
        "Type parameters cannot appear on a constructor declaration.": { "code": 1092, "category": 1 /* Error */ },
        "Type annotation cannot appear on a constructor declaration.": { "code": 1093, "category": 1 /* Error */ },
        "Type parameters cannot appear on an accessor.": { "code": 1094, "category": 1 /* Error */ },
        "Type annotation cannot appear on a 'set' accessor.": { "code": 1095, "category": 1 /* Error */ },
        "Index signature must have exactly one parameter.": { "code": 1096, "category": 1 /* Error */ },
        "'{0}' list cannot be empty.": { "code": 1097, "category": 1 /* Error */ },
        "variable declaration": { "code": 1098, "category": 3 /* NoPrefix */ },
        "type argument": { "code": 1099, "category": 3 /* NoPrefix */ },
        "Invalid use of '{0}' in strict mode.": { "code": 1100, "category": 1 /* Error */ },
        "'with' statements are not allowed in strict mode.": { "code": 1101, "category": 1 /* Error */ },
        "'delete' cannot be called on an identifier in strict mode.": { "code": 1102, "category": 1 /* Error */ },
        "Invalid left-hand side in 'for...in' statement.": { "code": 1103, "category": 1 /* Error */ },
        "'continue' statement can only be used within an enclosing iteration statement.": { "code": 1104, "category": 1 /* Error */ },
        "'break' statement can only be used within an enclosing iteration or switch statement.": { "code": 1105, "category": 1 /* Error */ },
        "Jump target not found.": { "code": 1106, "category": 1 /* Error */ },
        "Jump target cannot cross function boundary.": { "code": 1107, "category": 1 /* Error */ },
        "'return' statement must be contained within a function body.": { "code": 1108, "category": 1 /* Error */ },
        "Expression expected.": { "code": 1109, "category": 1 /* Error */ },
        "Type expected.": { "code": 1110, "category": 1 /* Error */ },
        "Duplicate identifier '{0}'.": { "code": 2000, "category": 1 /* Error */ },
        "The name '{0}' does not exist in the current scope.": { "code": 2001, "category": 1 /* Error */ },
        "The name '{0}' does not refer to a value.": { "code": 2002, "category": 1 /* Error */ },
        "'super' can only be used inside a class instance method.": { "code": 2003, "category": 1 /* Error */ },
        "The left-hand side of an assignment expression must be a variable, property or indexer.": { "code": 2004, "category": 1 /* Error */ },
        "Value of type '{0}' is not callable. Did you mean to include 'new'?": { "code": 2161, "category": 1 /* Error */ },
        "Value of type '{0}' is not callable.": { "code": 2006, "category": 1 /* Error */ },
        "Value of type '{0}' is not newable.": { "code": 2007, "category": 1 /* Error */ },
        "An index expression argument must be 'string', 'number', or 'any'.": { "code": 2008, "category": 1 /* Error */ },
        "Operator '{0}' cannot be applied to types '{1}' and '{2}'.": { "code": 2009, "category": 1 /* Error */ },
        "Type '{0}' is not assignable to type '{1}'.": { "code": 2011, "category": 1 /* Error */ },
        "Type '{0}' is not assignable to type '{1}':{NL}{2}": { "code": 2012, "category": 1 /* Error */ },
        "Expected var, class, interface, or module.": { "code": 2013, "category": 1 /* Error */ },
        "Getter '{0}' already declared.": { "code": 2015, "category": 1 /* Error */ },
        "Setter '{0}' already declared.": { "code": 2016, "category": 1 /* Error */ },
        "Exported class '{0}' extends private class '{1}'.": { "code": 2018, "category": 1 /* Error */ },
        "Exported class '{0}' implements private interface '{1}'.": { "code": 2019, "category": 1 /* Error */ },
        "Exported interface '{0}' extends private interface '{1}'.": { "code": 2020, "category": 1 /* Error */ },
        "Exported class '{0}' extends class from inaccessible module {1}.": { "code": 2021, "category": 1 /* Error */ },
        "Exported class '{0}' implements interface from inaccessible module {1}.": { "code": 2022, "category": 1 /* Error */ },
        "Exported interface '{0}' extends interface from inaccessible module {1}.": { "code": 2023, "category": 1 /* Error */ },
        "Public static property '{0}' of exported class has or is using private type '{1}'.": { "code": 2024, "category": 1 /* Error */ },
        "Public property '{0}' of exported class has or is using private type '{1}'.": { "code": 2025, "category": 1 /* Error */ },
        "Property '{0}' of exported interface has or is using private type '{1}'.": { "code": 2026, "category": 1 /* Error */ },
        "Exported variable '{0}' has or is using private type '{1}'.": { "code": 2027, "category": 1 /* Error */ },
        "Public static property '{0}' of exported class is using inaccessible module {1}.": { "code": 2028, "category": 1 /* Error */ },
        "Public property '{0}' of exported class is using inaccessible module {1}.": { "code": 2029, "category": 1 /* Error */ },
        "Property '{0}' of exported interface is using inaccessible module {1}.": { "code": 2030, "category": 1 /* Error */ },
        "Exported variable '{0}' is using inaccessible module {1}.": { "code": 2031, "category": 1 /* Error */ },
        "Parameter '{0}' of constructor from exported class has or is using private type '{1}'.": { "code": 2032, "category": 1 /* Error */ },
        "Parameter '{0}' of public static property setter from exported class has or is using private type '{1}'.": { "code": 2033, "category": 1 /* Error */ },
        "Parameter '{0}' of public property setter from exported class has or is using private type '{1}'.": { "code": 2034, "category": 1 /* Error */ },
        "Parameter '{0}' of constructor signature from exported interface has or is using private type '{1}'.": { "code": 2035, "category": 1 /* Error */ },
        "Parameter '{0}' of call signature from exported interface has or is using private type '{1}'.": { "code": 2036, "category": 1 /* Error */ },
        "Parameter '{0}' of public static method from exported class has or is using private type '{1}'.": { "code": 2037, "category": 1 /* Error */ },
        "Parameter '{0}' of public method from exported class has or is using private type '{1}'.": { "code": 2038, "category": 1 /* Error */ },
        "Parameter '{0}' of method from exported interface has or is using private type '{1}'.": { "code": 2039, "category": 1 /* Error */ },
        "Parameter '{0}' of exported function has or is using private type '{1}'.": { "code": 2040, "category": 1 /* Error */ },
        "Parameter '{0}' of constructor from exported class is using inaccessible module {1}.": { "code": 2041, "category": 1 /* Error */ },
        "Parameter '{0}' of public static property setter from exported class is using inaccessible module {1}.": { "code": 2042, "category": 1 /* Error */ },
        "Parameter '{0}' of public property setter from exported class is using inaccessible module {1}.": { "code": 2043, "category": 1 /* Error */ },
        "Parameter '{0}' of constructor signature from exported interface is using inaccessible module {1}.": { "code": 2044, "category": 1 /* Error */ },
        "Parameter '{0}' of call signature from exported interface is using inaccessible module {1}": { "code": 2045, "category": 1 /* Error */ },
        "Parameter '{0}' of public static method from exported class is using inaccessible module {1}.": { "code": 2046, "category": 1 /* Error */ },
        "Parameter '{0}' of public method from exported class is using inaccessible module {1}.": { "code": 2047, "category": 1 /* Error */ },
        "Parameter '{0}' of method from exported interface is using inaccessible module {1}.": { "code": 2048, "category": 1 /* Error */ },
        "Parameter '{0}' of exported function is using inaccessible module {1}.": { "code": 2049, "category": 1 /* Error */ },
        "Return type of public static property getter from exported class has or is using private type '{0}'.": { "code": 2050, "category": 1 /* Error */ },
        "Return type of public property getter from exported class has or is using private type '{0}'.": { "code": 2051, "category": 1 /* Error */ },
        "Return type of constructor signature from exported interface has or is using private type '{0}'.": { "code": 2052, "category": 1 /* Error */ },
        "Return type of call signature from exported interface has or is using private type '{0}'.": { "code": 2053, "category": 1 /* Error */ },
        "Return type of index signature from exported interface has or is using private type '{0}'.": { "code": 2054, "category": 1 /* Error */ },
        "Return type of public static method from exported class has or is using private type '{0}'.": { "code": 2055, "category": 1 /* Error */ },
        "Return type of public method from exported class has or is using private type '{0}'.": { "code": 2056, "category": 1 /* Error */ },
        "Return type of method from exported interface has or is using private type '{0}'.": { "code": 2057, "category": 1 /* Error */ },
        "Return type of exported function has or is using private type '{0}'.": { "code": 2058, "category": 1 /* Error */ },
        "Return type of public static property getter from exported class is using inaccessible module {0}.": { "code": 2059, "category": 1 /* Error */ },
        "Return type of public property getter from exported class is using inaccessible module {0}.": { "code": 2060, "category": 1 /* Error */ },
        "Return type of constructor signature from exported interface is using inaccessible module {0}.": { "code": 2061, "category": 1 /* Error */ },
        "Return type of call signature from exported interface is using inaccessible module {0}.": { "code": 2062, "category": 1 /* Error */ },
        "Return type of index signature from exported interface is using inaccessible module {0}.": { "code": 2063, "category": 1 /* Error */ },
        "Return type of public static method from exported class is using inaccessible module {0}.": { "code": 2064, "category": 1 /* Error */ },
        "Return type of public method from exported class is using inaccessible module {0}.": { "code": 2065, "category": 1 /* Error */ },
        "Return type of method from exported interface is using inaccessible module {0}.": { "code": 2066, "category": 1 /* Error */ },
        "Return type of exported function is using inaccessible module {0}.": { "code": 2067, "category": 1 /* Error */ },
        "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead.": { "code": 2068, "category": 1 /* Error */ },
        "A parameter list must follow a generic type argument list. '(' expected.": { "code": 2069, "category": 1 /* Error */ },
        "Multiple constructor implementations are not allowed.": { "code": 2070, "category": 1 /* Error */ },
        "Cannot find external module '{0}'.": { "code": 2071, "category": 1 /* Error */ },
        "Module cannot be aliased to a non-module type.": { "code": 2072, "category": 1 /* Error */ },
        "A class may only extend another class.": { "code": 2073, "category": 1 /* Error */ },
        "A class may only implement another class or interface.": { "code": 2074, "category": 1 /* Error */ },
        "An interface may only extend a class or another interface.": { "code": 2075, "category": 1 /* Error */ },
        "Unable to resolve type.": { "code": 2077, "category": 1 /* Error */ },
        "Unable to resolve type of '{0}'.": { "code": 2078, "category": 1 /* Error */ },
        "Unable to resolve type parameter constraint.": { "code": 2079, "category": 1 /* Error */ },
        "Type parameter constraint cannot be a primitive type.": { "code": 2080, "category": 1 /* Error */ },
        "Supplied parameters do not match any signature of call target.": { "code": 2081, "category": 1 /* Error */ },
        "Supplied parameters do not match any signature of call target:{NL}{0}": { "code": 2082, "category": 1 /* Error */ },
        "Cannot use 'new' with an expression whose type lacks a signature.": { "code": 2083, "category": 1 /* Error */ },
        "Only a void function can be called with the 'new' keyword.": { "code": 2084, "category": 1 /* Error */ },
        "Could not select overload for 'new' expression.": { "code": 2085, "category": 1 /* Error */ },
        "Type '{0}' does not satisfy the constraint '{1}'.": { "code": 2086, "category": 1 /* Error */ },
        "Could not select overload for 'call' expression.": { "code": 2087, "category": 1 /* Error */ },
        "Cannot invoke an expression whose type lacks a call signature.": { "code": 2088, "category": 1 /* Error */ },
        "Calls to 'super' are only valid inside a class.": { "code": 2089, "category": 1 /* Error */ },
        "Generic type '{0}' requires {1} type argument(s).": { "code": 2090, "category": 1 /* Error */ },
        "Type of array literal cannot be determined. Best common type could not be found for array elements.": { "code": 2092, "category": 1 /* Error */ },
        "Could not find enclosing symbol for dotted name '{0}'.": { "code": 2093, "category": 1 /* Error */ },
        "Property '{0}' does not exist on value of type '{1}'.": { "code": 2094, "category": 1 /* Error */ },
        "Cannot find name '{0}'.": { "code": 2095, "category": 1 /* Error */ },
        "'get' and 'set' accessor must have the same type.": { "code": 2096, "category": 1 /* Error */ },
        "'this' cannot be referenced in current location.": { "code": 2097, "category": 1 /* Error */ },
        "Static members cannot reference class type parameters.": { "code": 2099, "category": 1 /* Error */ },
        "Type '{0}' recursively references itself as a base type.": { "code": 2100, "category": 1 /* Error */ },
        "'super' property access is permitted only in a constructor, member function, or member accessor of a derived class.": { "code": 2102, "category": 1 /* Error */ },
        "'super' can only be referenced in a derived class.": { "code": 2103, "category": 1 /* Error */ },
        "A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.": { "code": 2104, "category": 1 /* Error */ },
        "Constructors for derived classes must contain a 'super' call.": { "code": 2105, "category": 1 /* Error */ },
        "Super calls are not permitted outside constructors or in nested functions inside constructors.": { "code": 2106, "category": 1 /* Error */ },
        "'{0}.{1}' is inaccessible.": { "code": 2107, "category": 1 /* Error */ },
        "'this' cannot be referenced in a module body.": { "code": 2108, "category": 1 /* Error */ },
        "Invalid '+' expression - types not known to support the addition operator.": { "code": 2111, "category": 1 /* Error */ },
        "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.": { "code": 2112, "category": 1 /* Error */ },
        "The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.": { "code": 2113, "category": 1 /* Error */ },
        "An arithmetic operand must be of type 'any', 'number' or an enum type.": { "code": 2114, "category": 1 /* Error */ },
        "Variable declarations of a 'for' statement cannot use a type annotation.": { "code": 2115, "category": 1 /* Error */ },
        "Variable declarations of a 'for' statement must be of types 'string' or 'any'.": { "code": 2116, "category": 1 /* Error */ },
        "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter.": { "code": 2117, "category": 1 /* Error */ },
        "The left-hand side of an 'in' expression must be of types 'any', 'string' or 'number'.": { "code": 2118, "category": 1 /* Error */ },
        "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter.": { "code": 2119, "category": 1 /* Error */ },
        "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.": { "code": 2120, "category": 1 /* Error */ },
        "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type.": { "code": 2121, "category": 1 /* Error */ },
        "Setters cannot return a value.": { "code": 2122, "category": 1 /* Error */ },
        "Tried to query type of uninitialized module '{0}'.": { "code": 2123, "category": 1 /* Error */ },
        "Tried to set variable type to uninitialized module type '{0}'.": { "code": 2124, "category": 1 /* Error */ },
        "Type '{0}' is not generic.": { "code": 2125, "category": 1 /* Error */ },
        "Getters must return a value.": { "code": 2126, "category": 1 /* Error */ },
        "Getter and setter accessors do not agree in visibility.": { "code": 2127, "category": 1 /* Error */ },
        "Invalid left-hand side of assignment expression.": { "code": 2130, "category": 1 /* Error */ },
        "Function declared a non-void return type, but has no return expression.": { "code": 2131, "category": 1 /* Error */ },
        "Cannot resolve return type reference.": { "code": 2132, "category": 1 /* Error */ },
        "Constructors cannot have a return type of 'void'.": { "code": 2133, "category": 1 /* Error */ },
        "Subsequent variable declarations must have the same type.  Variable '{0}' must be of type '{1}', but here has type '{2}'.": { "code": 2134, "category": 1 /* Error */ },
        "All symbols within a with block will be resolved to 'any'.": { "code": 2135, "category": 1 /* Error */ },
        "Import declarations in an internal module cannot reference an external module.": { "code": 2136, "category": 1 /* Error */ },
        "Class {0} declares interface {1} but does not implement it:{NL}{2}": { "code": 2137, "category": 1 /* Error */ },
        "Class {0} declares class {1} as an interface but does not implement it:{NL}{2}": { "code": 2138, "category": 1 /* Error */ },
        "The operand of an increment or decrement operator must be a variable, property or indexer.": { "code": 2139, "category": 1 /* Error */ },
        "'this' cannot be referenced in a static property initializer.": { "code": 2140, "category": 1 /* Error */ },
        "Class '{0}' cannot extend class '{1}':{NL}{2}": { "code": 2141, "category": 1 /* Error */ },
        "Interface '{0}' cannot extend class '{1}':{NL}{2}": { "code": 2142, "category": 1 /* Error */ },
        "Interface '{0}' cannot extend interface '{1}':{NL}{2}": { "code": 2143, "category": 1 /* Error */ },
        "Overload signature is not compatible with function definition.": { "code": 2148, "category": 1 /* Error */ },
        "Overload signature is not compatible with function definition:{NL}{0}": { "code": 2149, "category": 1 /* Error */ },
        "Overload signatures must all be public or private.": { "code": 2150, "category": 1 /* Error */ },
        "Overload signatures must all be exported or not exported.": { "code": 2151, "category": 1 /* Error */ },
        "Overload signatures must all be ambient or non-ambient.": { "code": 2152, "category": 1 /* Error */ },
        "Overload signatures must all be optional or required.": { "code": 2153, "category": 1 /* Error */ },
        "Specialized overload signature is not assignable to any non-specialized signature.": { "code": 2154, "category": 1 /* Error */ },
        "'this' cannot be referenced in constructor arguments.": { "code": 2155, "category": 1 /* Error */ },
        "Instance member cannot be accessed off a class.": { "code": 2157, "category": 1 /* Error */ },
        "Untyped function calls may not accept type arguments.": { "code": 2158, "category": 1 /* Error */ },
        "Non-generic functions may not accept type arguments.": { "code": 2159, "category": 1 /* Error */ },
        "A generic type may not reference itself with a wrapped form of its own type parameters.": { "code": 2160, "category": 1 /* Error */ },
        "A rest parameter must be of an array type.": { "code": 2162, "category": 1 /* Error */ },
        "Overload signature implementation cannot use specialized type.": { "code": 2163, "category": 1 /* Error */ },
        "Export assignments may only be used at the top-level of external modules.": { "code": 2164, "category": 1 /* Error */ },
        "Export assignments may only be made with variables, functions, classes, interfaces, enums and internal modules.": { "code": 2165, "category": 1 /* Error */ },
        "Only public methods of the base class are accessible via the 'super' keyword.": { "code": 2166, "category": 1 /* Error */ },
        "Numeric indexer type '{0}' must be assignable to string indexer type '{1}'.": { "code": 2167, "category": 1 /* Error */ },
        "Numeric indexer type '{0}' must be assignable to string indexer type '{1}':{NL}{2}": { "code": 2168, "category": 1 /* Error */ },
        "All numerically named properties must be assignable to numeric indexer type '{0}'.": { "code": 2169, "category": 1 /* Error */ },
        "All numerically named properties must be assignable to numeric indexer type '{0}':{NL}{1}": { "code": 2170, "category": 1 /* Error */ },
        "All named properties must be assignable to string indexer type '{0}'.": { "code": 2171, "category": 1 /* Error */ },
        "All named properties must be assignable to string indexer type '{0}':{NL}{1}": { "code": 2172, "category": 1 /* Error */ },
        "A parameter initializer is only allowed in a function or constructor implementation.": { "code": 2174, "category": 1 /* Error */ },
        "Function expression declared a non-void return type, but has no return expression.": { "code": 2176, "category": 1 /* Error */ },
        "Import declaration referencing identifier from internal module can only be made with variables, functions, classes, interfaces, enums and internal modules.": { "code": 2177, "category": 1 /* Error */ },
        "Module '{0}' has no exported member '{1}'.": { "code": 2178, "category": 1 /* Error */ },
        "Unable to resolve module reference '{0}'.": { "code": 2179, "category": 1 /* Error */ },
        "Could not find module '{0}' in module '{1}'.": { "code": 2180, "category": 1 /* Error */ },
        "Exported import declaration '{0}' is assigned value with type that has or is using private type '{1}'.": { "code": 2181, "category": 1 /* Error */ },
        "Exported import declaration '{0}' is assigned value with type that is using inaccessible module '{1}'.": { "code": 2182, "category": 1 /* Error */ },
        "Exported import declaration '{0}' is assigned type that has or is using private type '{1}'.": { "code": 2183, "category": 1 /* Error */ },
        "Exported import declaration '{0}' is assigned type that is using inaccessible module '{1}'.": { "code": 2184, "category": 1 /* Error */ },
        "Exported import declaration '{0}' is assigned container that is or is using inaccessible module '{1}'.": { "code": 2185, "category": 1 /* Error */ },
        "Type name '{0}' in extends clause does not reference constructor function for '{1}'.": { "code": 2186, "category": 1 /* Error */ },
        "Internal module reference '{0}' in import declaration does not reference module instance for '{1}'.": { "code": 2187, "category": 1 /* Error */ },
        "Module '{0}' cannot merge with previous declaration of '{1}' in a different file '{2}'.": { "code": 2188, "category": 1 /* Error */ },
        "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}':{NL}{3}": { "code": 2189, "category": 1 /* Error */ },
        "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it.": { "code": 2190, "category": 1 /* Error */ },
        "Ambient external module declaration cannot be reopened.": { "code": 2191, "category": 1 /* Error */ },
        "All declarations of merged declaration '{0}' must be exported or not exported.": { "code": 2192, "category": 1 /* Error */ },
        "'super' cannot be referenced in constructor arguments.": { "code": 2193, "category": 1 /* Error */ },
        "Return type of constructor signature must be assignable to the instance type of the class.": { "code": 2194, "category": 1 /* Error */ },
        "Ambient external module declaration must be defined in global context.": { "code": 2195, "category": 1 /* Error */ },
        "Ambient external module declaration cannot specify relative module name.": { "code": 2196, "category": 1 /* Error */ },
        "Import declaration in an ambient external module declaration cannot reference external module through relative external module name.": { "code": 2197, "category": 1 /* Error */ },
        "No best common type exists among return expressions.": { "code": 2198, "category": 1 /* Error */ },
        "Import declaration cannot refer to external module reference when --noResolve option is set.": { "code": 2199, "category": 1 /* Error */ },
        "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.": { "code": 2200, "category": 1 /* Error */ },
        "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference.": { "code": 2205, "category": 1 /* Error */ },
        "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference.": { "code": 2206, "category": 1 /* Error */ },
        "Expression resolves to '_super' that compiler uses to capture base class reference.": { "code": 2207, "category": 1 /* Error */ },
        "TypeParameter '{0}' of constructor signature from exported interface has or is using private type '{1}'.": { "code": 2208, "category": 1 /* Error */ },
        "TypeParameter '{0}' of call signature from exported interface has or is using private type '{1}'.": { "code": 2209, "category": 1 /* Error */ },
        "TypeParameter '{0}' of public static method from exported class has or is using private type '{1}'.": { "code": 2210, "category": 1 /* Error */ },
        "TypeParameter '{0}' of public method from exported class has or is using private type '{1}'.": { "code": 2211, "category": 1 /* Error */ },
        "TypeParameter '{0}' of method from exported interface has or is using private type '{1}'.": { "code": 2212, "category": 1 /* Error */ },
        "TypeParameter '{0}' of exported function has or is using private type '{1}'.": { "code": 2213, "category": 1 /* Error */ },
        "TypeParameter '{0}' of constructor signature from exported interface is using inaccessible module {1}.": { "code": 2214, "category": 1 /* Error */ },
        "TypeParameter '{0}' of call signature from exported interface is using inaccessible module {1}": { "code": 2215, "category": 1 /* Error */ },
        "TypeParameter '{0}' of public static method from exported class is using inaccessible module {1}.": { "code": 2216, "category": 1 /* Error */ },
        "TypeParameter '{0}' of public method from exported class is using inaccessible module {1}.": { "code": 2217, "category": 1 /* Error */ },
        "TypeParameter '{0}' of method from exported interface is using inaccessible module {1}.": { "code": 2218, "category": 1 /* Error */ },
        "TypeParameter '{0}' of exported function is using inaccessible module {1}.": { "code": 2219, "category": 1 /* Error */ },
        "TypeParameter '{0}' of exported class has or is using private type '{1}'.": { "code": 2220, "category": 1 /* Error */ },
        "TypeParameter '{0}' of exported interface has or is using private type '{1}'.": { "code": 2221, "category": 1 /* Error */ },
        "TypeParameter '{0}' of exported class is using inaccessible module {1}.": { "code": 2222, "category": 1 /* Error */ },
        "TypeParameter '{0}' of exported interface is using inaccessible module {1}.": { "code": 2223, "category": 1 /* Error */ },
        "Duplicate identifier '_i'. Compiler uses '_i' to initialize rest parameter.": { "code": 2224, "category": 1 /* Error */ },
        "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters.": { "code": 2225, "category": 1 /* Error */ },
        "No best common type exists between '{0}' and '{1}'.": { "code": 2226, "category": 1 /* Error */ },
        "No best common type exists between '{0}', '{1}', and '{2}'.": { "code": 2227, "category": 1 /* Error */ },
        "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module.": { "code": 2228, "category": 1 /* Error */ },
        "Constraint of a type parameter cannot reference any type parameter from the same type parameter list.": { "code": 2229, "category": 1 /* Error */ },
        "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor.": { "code": 2230, "category": 1 /* Error */ },
        "Parameter '{0}' cannot be referenced in its initializer.": { "code": 2231, "category": 1 /* Error */ },
        "Duplicate string index signature.": { "code": 2232, "category": 1 /* Error */ },
        "Duplicate number index signature.": { "code": 2233, "category": 1 /* Error */ },
        "All declarations of an interface must have identical type parameters.": { "code": 2234, "category": 1 /* Error */ },
        "Expression resolves to variable declaration '_i' that compiler uses to initialize rest parameter.": { "code": 2235, "category": 1 /* Error */ },
        "Neither type '{0}' nor type '{1}' is assignable to the other.": { "code": 2236, "category": 1 /* Error */ },
        "Neither type '{0}' nor type '{1}' is assignable to the other:{NL}{2}": { "code": 2237, "category": 1 /* Error */ },
        "Duplicate function implementation.": { "code": 2237, "category": 1 /* Error */ },
        "Function implementation expected.": { "code": 2238, "category": 1 /* Error */ },
        "Function overload name must be '{0}'.": { "code": 2239, "category": 1 /* Error */ },
        "Constructor implementation expected.": { "code": 2240, "category": 1 /* Error */ },
        "Class name cannot be '{0}'.": { "code": 2241, "category": 1 /* Error */ },
        "Interface name cannot be '{0}'.": { "code": 2242, "category": 1 /* Error */ },
        "Enum name cannot be '{0}'.": { "code": 2243, "category": 1 /* Error */ },
        "A module cannot have multiple export assignments.": { "code": 2244, "category": 1 /* Error */ },
        "Export assignment not allowed in module with exported element.": { "code": 2245, "category": 1 /* Error */ },
        "A parameter property is only allowed in a constructor implementation.": { "code": 2246, "category": 1 /* Error */ },
        "Function overload must be static.": { "code": 2247, "category": 1 /* Error */ },
        "Function overload must not be static.": { "code": 2248, "category": 1 /* Error */ },
        "Type '{0}' is missing property '{1}' from type '{2}'.": { "code": 4000, "category": 3 /* NoPrefix */ },
        "Types of property '{0}' of types '{1}' and '{2}' are incompatible.": { "code": 4001, "category": 3 /* NoPrefix */ },
        "Types of property '{0}' of types '{1}' and '{2}' are incompatible:{NL}{3}": { "code": 4002, "category": 3 /* NoPrefix */ },
        "Property '{0}' defined as private in type '{1}' is defined as public in type '{2}'.": { "code": 4003, "category": 3 /* NoPrefix */ },
        "Property '{0}' defined as public in type '{1}' is defined as private in type '{2}'.": { "code": 4004, "category": 3 /* NoPrefix */ },
        "Types '{0}' and '{1}' define property '{2}' as private.": { "code": 4005, "category": 3 /* NoPrefix */ },
        "Call signatures of types '{0}' and '{1}' are incompatible.": { "code": 4006, "category": 3 /* NoPrefix */ },
        "Call signatures of types '{0}' and '{1}' are incompatible:{NL}{2}": { "code": 4007, "category": 3 /* NoPrefix */ },
        "Type '{0}' requires a call signature, but type '{1}' lacks one.": { "code": 4008, "category": 3 /* NoPrefix */ },
        "Construct signatures of types '{0}' and '{1}' are incompatible.": { "code": 4009, "category": 3 /* NoPrefix */ },
        "Construct signatures of types '{0}' and '{1}' are incompatible:{NL}{2}": { "code": 4010, "category": 3 /* NoPrefix */ },
        "Type '{0}' requires a construct signature, but type '{1}' lacks one.": { "code": 4011, "category": 3 /* NoPrefix */ },
        "Index signatures of types '{0}' and '{1}' are incompatible.": { "code": 4012, "category": 3 /* NoPrefix */ },
        "Index signatures of types '{0}' and '{1}' are incompatible:{NL}{2}": { "code": 4013, "category": 3 /* NoPrefix */ },
        "Call signature expects {0} or fewer parameters.": { "code": 4014, "category": 3 /* NoPrefix */ },
        "Could not apply type '{0}' to argument {1} which is of type '{2}'.": { "code": 4015, "category": 3 /* NoPrefix */ },
        "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function.": { "code": 4016, "category": 3 /* NoPrefix */ },
        "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member function.": { "code": 4017, "category": 3 /* NoPrefix */ },
        "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor.": { "code": 4018, "category": 3 /* NoPrefix */ },
        "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property.": { "code": 4019, "category": 3 /* NoPrefix */ },
        "Types of static property '{0}' of class '{1}' and class '{2}' are incompatible.": { "code": 4020, "category": 3 /* NoPrefix */ },
        "Types of static property '{0}' of class '{1}' and class '{2}' are incompatible:{NL}{3}": { "code": 4021, "category": 3 /* NoPrefix */ },
        "Type reference cannot refer to container '{0}'.": { "code": 4022, "category": 1 /* Error */ },
        "Type reference must refer to type.": { "code": 4023, "category": 1 /* Error */ },
        "In enums with multiple declarations only one declaration can omit an initializer for the first enum element.": { "code": 4024, "category": 1 /* Error */ },
        " (+ {0} overload(s))": { "code": 4025, "category": 2 /* Message */ },
        "Variable declaration cannot have the same name as an import declaration.": { "code": 4026, "category": 1 /* Error */ },
        "Signature expected {0} type arguments, got {1} instead.": { "code": 4027, "category": 1 /* Error */ },
        "Property '{0}' defined as optional in type '{1}', but is required in type '{2}'.": { "code": 4028, "category": 3 /* NoPrefix */ },
        "Types '{0}' and '{1}' originating in infinitely expanding type reference do not refer to same named type.": { "code": 4029, "category": 3 /* NoPrefix */ },
        "Types '{0}' and '{1}' originating in infinitely expanding type reference have incompatible type arguments.": { "code": 4030, "category": 3 /* NoPrefix */ },
        "Types '{0}' and '{1}' originating in infinitely expanding type reference have incompatible type arguments:{NL}{2}": { "code": 4031, "category": 3 /* NoPrefix */ },
        "Named properties '{0}' of types '{1}' and '{2}' are not identical.": { "code": 4032, "category": 3 /* NoPrefix */ },
        "Types of string indexer of types '{0}' and '{1}' are not identical.": { "code": 4033, "category": 3 /* NoPrefix */ },
        "Types of number indexer of types '{0}' and '{1}' are not identical.": { "code": 4034, "category": 3 /* NoPrefix */ },
        "Type of number indexer in type '{0}' is not assignable to string indexer type in type '{1}'.{NL}{2}": { "code": 4035, "category": 3 /* NoPrefix */ },
        "Type of property '{0}' in type '{1}' is not assignable to string indexer type in type '{2}'.{NL}{3}": { "code": 4036, "category": 3 /* NoPrefix */ },
        "Type of property '{0}' in type '{1}' is not assignable to number indexer type in type '{2}'.{NL}{3}": { "code": 4037, "category": 3 /* NoPrefix */ },
        "Static property '{0}' defined as private in type '{1}' is defined as public in type '{2}'.": { "code": 4038, "category": 3 /* NoPrefix */ },
        "Static property '{0}' defined as public in type '{1}' is defined as private in type '{2}'.": { "code": 4039, "category": 3 /* NoPrefix */ },
        "Types '{0}' and '{1}' define static property '{2}' as private.": { "code": 4040, "category": 3 /* NoPrefix */ },
        "Current host does not support '{0}' option.": { "code": 5001, "category": 1 /* Error */ },
        "ECMAScript target version '{0}' not supported.  Specify a valid target version: '{1}' (default), or '{2}'": { "code": 5002, "category": 1 /* Error */ },
        "Argument for '{0}' option must be '{1}' or '{2}'": { "code": 5003, "category": 1 /* Error */ },
        "Could not find file: '{0}'.": { "code": 5004, "category": 1 /* Error */ },
        "A file cannot have a reference to itself.": { "code": 5006, "category": 1 /* Error */ },
        "Cannot resolve referenced file: '{0}'.": { "code": 5007, "category": 1 /* Error */ },
        "Cannot find the common subdirectory path for the input files.": { "code": 5009, "category": 1 /* Error */ },
        "Emit Error: {0}.": { "code": 5011, "category": 1 /* Error */ },
        "Cannot read file '{0}': {1}": { "code": 5012, "category": 1 /* Error */ },
        "Unsupported file encoding.": { "code": 5013, "category": 3 /* NoPrefix */ },
        "Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'.": { "code": 5014, "category": 1 /* Error */ },
        "Unsupported locale: '{0}'.": { "code": 5015, "category": 1 /* Error */ },
        "Execution Failed.{NL}": { "code": 5016, "category": 1 /* Error */ },
        "Invalid call to 'up'": { "code": 5019, "category": 1 /* Error */ },
        "Invalid call to 'down'": { "code": 5020, "category": 1 /* Error */ },
        "Base64 value '{0}' finished with a continuation bit.": { "code": 5021, "category": 1 /* Error */ },
        "Unknown compiler option '{0}'": { "code": 5023, "category": 1 /* Error */ },
        "Expected {0} arguments to message, got {1} instead.": { "code": 5024, "category": 1 /* Error */ },
        "Expected the message '{0}' to have {1} arguments, but it had {2}": { "code": 5025, "category": 1 /* Error */ },
        "Could not delete file '{0}'": { "code": 5034, "category": 1 /* Error */ },
        "Could not create directory '{0}'": { "code": 5035, "category": 1 /* Error */ },
        "Error while executing file '{0}': ": { "code": 5036, "category": 1 /* Error */ },
        "Cannot compile external modules unless the '--module' flag is provided.": { "code": 5037, "category": 1 /* Error */ },
        "Option mapRoot cannot be specified without specifying sourcemap option.": { "code": 5038, "category": 1 /* Error */ },
        "Option sourceRoot cannot be specified without specifying sourcemap option.": { "code": 5039, "category": 1 /* Error */ },
        "Options mapRoot and sourceRoot cannot be specified without specifying sourcemap option.": { "code": 5040, "category": 1 /* Error */ },
        "Option '{0}' specified without '{1}'": { "code": 5041, "category": 1 /* Error */ },
        "'codepage' option not supported on current platform.": { "code": 5042, "category": 1 /* Error */ },
        "Concatenate and emit output to single file.": { "code": 6001, "category": 2 /* Message */ },
        "Generates corresponding {0} file.": { "code": 6002, "category": 2 /* Message */ },
        "Specifies the location where debugger should locate map files instead of generated locations.": { "code": 6003, "category": 2 /* Message */ },
        "Specifies the location where debugger should locate TypeScript files instead of source locations.": { "code": 6004, "category": 2 /* Message */ },
        "Watch input files.": { "code": 6005, "category": 2 /* Message */ },
        "Redirect output structure to the directory.": { "code": 6006, "category": 2 /* Message */ },
        "Do not emit comments to output.": { "code": 6009, "category": 2 /* Message */ },
        "Skip resolution and preprocessing.": { "code": 6010, "category": 2 /* Message */ },
        "Specify ECMAScript target version: '{0}' (default), or '{1}'": { "code": 6015, "category": 2 /* Message */ },
        "Specify module code generation: '{0}' or '{1}'": { "code": 6016, "category": 2 /* Message */ },
        "Print this message.": { "code": 6017, "category": 2 /* Message */ },
        "Print the compiler's version: {0}": { "code": 6019, "category": 2 /* Message */ },
        "Allow use of deprecated '{0}' keyword when referencing an external module.": { "code": 6021, "category": 2 /* Message */ },
        "Specify locale for errors and messages. For example '{0}' or '{1}'": { "code": 6022, "category": 2 /* Message */ },
        "Syntax:   {0}": { "code": 6023, "category": 2 /* Message */ },
        "options": { "code": 6024, "category": 2 /* Message */ },
        "file1": { "code": 6025, "category": 2 /* Message */ },
        "Examples:": { "code": 6026, "category": 2 /* Message */ },
        "Options:": { "code": 6027, "category": 2 /* Message */ },
        "Insert command line options and files from a file.": { "code": 6030, "category": 2 /* Message */ },
        "Version {0}": { "code": 6029, "category": 2 /* Message */ },
        "Use the '{0}' flag to see options.": { "code": 6031, "category": 2 /* Message */ },
        "{NL}Recompiling ({0}):": { "code": 6032, "category": 2 /* Message */ },
        "STRING": { "code": 6033, "category": 2 /* Message */ },
        "KIND": { "code": 6034, "category": 2 /* Message */ },
        "file2": { "code": 6035, "category": 2 /* Message */ },
        "VERSION": { "code": 6036, "category": 2 /* Message */ },
        "LOCATION": { "code": 6037, "category": 2 /* Message */ },
        "DIRECTORY": { "code": 6038, "category": 2 /* Message */ },
        "NUMBER": { "code": 6039, "category": 2 /* Message */ },
        "Specify the codepage to use when opening source files.": { "code": 6040, "category": 2 /* Message */ },
        "Additional locations:": { "code": 6041, "category": 2 /* Message */ },
        "This version of the Javascript runtime does not support the '{0}' function.": { "code": 7000, "category": 1 /* Error */ },
        "Unknown rule.": { "code": 7002, "category": 1 /* Error */ },
        "Invalid line number ({0})": { "code": 7003, "category": 1 /* Error */ },
        "Warn on expressions and declarations with an implied 'any' type.": { "code": 7004, "category": 2 /* Message */ },
        "Variable '{0}' implicitly has an 'any' type.": { "code": 7005, "category": 1 /* Error */ },
        "Parameter '{0}' of '{1}' implicitly has an 'any' type.": { "code": 7006, "category": 1 /* Error */ },
        "Parameter '{0}' of function type implicitly has an 'any' type.": { "code": 7007, "category": 1 /* Error */ },
        "Member '{0}' of object type implicitly has an 'any' type.": { "code": 7008, "category": 1 /* Error */ },
        "'new' expression, which lacks a constructor signature, implicitly has an 'any' type.": { "code": 7009, "category": 1 /* Error */ },
        "'{0}', which lacks return-type annotation, implicitly has an 'any' return type.": { "code": 7010, "category": 1 /* Error */ },
        "Function expression, which lacks return-type annotation, implicitly has an 'any' return type.": { "code": 7011, "category": 1 /* Error */ },
        "Parameter '{0}' of lambda function implicitly has an 'any' type.": { "code": 7012, "category": 1 /* Error */ },
        "Constructor signature, which lacks return-type annotation, implicitly has an 'any' return type.": { "code": 7013, "category": 1 /* Error */ },
        "Lambda Function, which lacks return-type annotation, implicitly has an 'any' return type.": { "code": 7014, "category": 1 /* Error */ },
        "Array Literal implicitly has an 'any' type from widening.": { "code": 7015, "category": 1 /* Error */ },
        "'{0}', which lacks 'get' accessor and parameter type annotation on 'set' accessor, implicitly has an 'any' type.": { "code": 7016, "category": 1 /* Error */ },
        "Index signature of object type implicitly has an 'any' type.": { "code": 7017, "category": 1 /* Error */ },
        "Object literal's property '{0}' implicitly has an 'any' type from widening.": { "code": 7018, "category": 1 /* Error */ }
    };
})(TypeScript || (TypeScript = {}));
/// <reference path='diagnosticCode.generated.ts' />
/// <reference path='diagnosticInformationMap.generated.ts' />
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var ArrayUtilities = (function () {
        function ArrayUtilities() {
        }
        ArrayUtilities.sequenceEquals = function (array1, array2, equals) {
            if (array1 === array2) {
                return true;
            }

            if (array1 === null || array2 === null) {
                return false;
            }

            if (array1.length !== array2.length) {
                return false;
            }

            for (var i = 0, n = array1.length; i < n; i++) {
                if (!equals(array1[i], array2[i])) {
                    return false;
                }
            }

            return true;
        };

        ArrayUtilities.contains = function (array, value) {
            for (var i = 0; i < array.length; i++) {
                if (array[i] === value) {
                    return true;
                }
            }

            return false;
        };

        // Gets unique element array
        ArrayUtilities.distinct = function (array, equalsFn) {
            var result = [];

            for (var i = 0, n = array.length; i < n; i++) {
                var current = array[i];
                for (var j = 0; j < result.length; j++) {
                    if (equalsFn(result[j], current)) {
                        break;
                    }
                }

                if (j === result.length) {
                    result.push(current);
                }
            }

            return result;
        };

        ArrayUtilities.last = function (array) {
            if (array.length === 0) {
                throw TypeScript.Errors.argumentOutOfRange('array');
            }

            return array[array.length - 1];
        };

        ArrayUtilities.lastOrDefault = function (array, predicate) {
            for (var i = array.length - 1; i >= 0; i--) {
                var v = array[i];
                if (predicate(v, i)) {
                    return v;
                }
            }

            return null;
        };

        ArrayUtilities.firstOrDefault = function (array, func) {
            for (var i = 0, n = array.length; i < n; i++) {
                var value = array[i];
                if (func(value, i)) {
                    return value;
                }
            }

            return null;
        };

        ArrayUtilities.first = function (array, func) {
            for (var i = 0, n = array.length; i < n; i++) {
                var value = array[i];
                if (!func || func(value, i)) {
                    return value;
                }
            }

            throw TypeScript.Errors.invalidOperation();
        };

        ArrayUtilities.sum = function (array, func) {
            var result = 0;

            for (var i = 0, n = array.length; i < n; i++) {
                result += func(array[i]);
            }

            return result;
        };

        ArrayUtilities.select = function (values, func) {
            var result = new Array(values.length);

            for (var i = 0; i < values.length; i++) {
                result[i] = func(values[i]);
            }

            return result;
        };

        ArrayUtilities.where = function (values, func) {
            var result = new Array();

            for (var i = 0; i < values.length; i++) {
                if (func(values[i])) {
                    result.push(values[i]);
                }
            }

            return result;
        };

        ArrayUtilities.any = function (array, func) {
            for (var i = 0, n = array.length; i < n; i++) {
                if (func(array[i])) {
                    return true;
                }
            }

            return false;
        };

        ArrayUtilities.all = function (array, func) {
            for (var i = 0, n = array.length; i < n; i++) {
                if (!func(array[i])) {
                    return false;
                }
            }

            return true;
        };

        ArrayUtilities.binarySearch = function (array, value) {
            var low = 0;
            var high = array.length - 1;

            while (low <= high) {
                var middle = low + ((high - low) >> 1);
                var midValue = array[middle];

                if (midValue === value) {
                    return middle;
                } else if (midValue > value) {
                    high = middle - 1;
                } else {
                    low = middle + 1;
                }
            }

            return ~low;
        };

        ArrayUtilities.createArray = function (length, defaultValue) {
            var result = new Array(length);
            for (var i = 0; i < length; i++) {
                result[i] = defaultValue;
            }

            return result;
        };

        ArrayUtilities.grow = function (array, length, defaultValue) {
            var count = length - array.length;
            for (var i = 0; i < count; i++) {
                array.push(defaultValue);
            }
        };

        ArrayUtilities.copy = function (sourceArray, sourceIndex, destinationArray, destinationIndex, length) {
            for (var i = 0; i < length; i++) {
                destinationArray[destinationIndex + i] = sourceArray[sourceIndex + i];
            }
        };

        ArrayUtilities.indexOf = function (array, predicate) {
            for (var i = 0, n = array.length; i < n; i++) {
                if (predicate(array[i])) {
                    return i;
                }
            }

            return -1;
        };
        return ArrayUtilities;
    })();
    TypeScript.ArrayUtilities = ArrayUtilities;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts'/>
var TypeScript;
(function (TypeScript) {
    (function (BitVector) {
        var pool = [];
        var Constants;
        (function (Constants) {
            // We only use up to 30 bits in a number.  That way the encoded value can always fit
            // within an int so that the underlying engine doesn't use a 64bit float here.
            Constants[Constants["MaxBitsPerEncodedNumber"] = 30] = "MaxBitsPerEncodedNumber";
            Constants[Constants["BitsPerEncodedBiStateValue"] = 1] = "BitsPerEncodedBiStateValue";

            // For a tri state vector we need 2 bits per encoded value.  00 for 'undefined',
            // '01' for 'false' and '10' for true.
            Constants[Constants["BitsPerEncodedTriStateValue"] = 2] = "BitsPerEncodedTriStateValue";

            Constants[Constants["BiStateEncodedTrue"] = 1] = "BiStateEncodedTrue";
            Constants[Constants["BiStateClearBitsMask"] = 1] = "BiStateClearBitsMask";

            Constants[Constants["TriStateEncodedFalse"] = 1] = "TriStateEncodedFalse";
            Constants[Constants["TriStateEncodedTrue"] = 2] = "TriStateEncodedTrue";
            Constants[Constants["TriStateClearBitsMask"] = 3] = "TriStateClearBitsMask";
        })(Constants || (Constants = {}));

        var BitVectorImpl = (function () {
            function BitVectorImpl(allowUndefinedValues) {
                this.allowUndefinedValues = allowUndefinedValues;
                this.isReleased = false;
                this.bits = [];
            }
            BitVectorImpl.prototype.computeTriStateArrayIndex = function (index) {
                // The number of values that can be encoded in a single number.
                var encodedValuesPerNumber = 30 /* MaxBitsPerEncodedNumber */ / 2 /* BitsPerEncodedTriStateValue */;

                return (index / encodedValuesPerNumber) >>> 0;
            };

            BitVectorImpl.prototype.computeBiStateArrayIndex = function (index) {
                // The number of values that can be encoded in a single number.
                var encodedValuesPerNumber = 30 /* MaxBitsPerEncodedNumber */ / 1 /* BitsPerEncodedBiStateValue */;

                return (index / encodedValuesPerNumber) >>> 0;
            };

            BitVectorImpl.prototype.computeTriStateEncodedValueIndex = function (index) {
                // The number of values that can be encoded in a single number.
                var encodedValuesPerNumber = 30 /* MaxBitsPerEncodedNumber */ / 2 /* BitsPerEncodedTriStateValue */;

                return (index % encodedValuesPerNumber) * 2 /* BitsPerEncodedTriStateValue */;
            };

            BitVectorImpl.prototype.computeBiStateEncodedValueIndex = function (index) {
                // The number of values that can be encoded in a single number.
                var encodedValuesPerNumber = 30 /* MaxBitsPerEncodedNumber */ / 1 /* BitsPerEncodedBiStateValue */;

                return (index % encodedValuesPerNumber) * 1 /* BitsPerEncodedBiStateValue */;
            };

            BitVectorImpl.prototype.valueAt = function (index) {
                TypeScript.Debug.assert(!this.isReleased, "Should not use a released bitvector");
                if (this.allowUndefinedValues) {
                    // tri-state bit vector.  2 bits per value.
                    var arrayIndex = this.computeTriStateArrayIndex(index);
                    var encoded = this.bits[arrayIndex];
                    if (encoded === undefined) {
                        // We don't even have an encoded value at this array position.  That's
                        // equivalent to 'undefined' for a tri-state vector.
                        return undefined;
                    }

                    var bitIndex = this.computeTriStateEncodedValueIndex(index);
                    if (encoded & (2 /* TriStateEncodedTrue */ << bitIndex)) {
                        return true;
                    } else if (encoded & (1 /* TriStateEncodedFalse */ << bitIndex)) {
                        return false;
                    } else {
                        return undefined;
                    }
                } else {
                    // Normal bitvector.  One bit per value stored.
                    var arrayIndex = this.computeBiStateArrayIndex(index);
                    var encoded = this.bits[arrayIndex];
                    if (encoded === undefined) {
                        // We don't even have an encoded value at this array position.  That's
                        // equivalent to 'false' for a bi-state vector.
                        return false;
                    }

                    // If we don't support undefined values, then we use one bit per value. Just
                    // index to that bit and see if it's set or not.
                    var bitIndex = this.computeBiStateEncodedValueIndex(index);
                    if (encoded & (1 /* BiStateEncodedTrue */ << bitIndex)) {
                        return true;
                    } else {
                        return false;
                    }
                }
            };

            BitVectorImpl.prototype.setValueAt = function (index, value) {
                TypeScript.Debug.assert(!this.isReleased, "Should not use a released bitvector");
                if (this.allowUndefinedValues) {
                    TypeScript.Debug.assert(value === true || value === false || value === undefined, "value must only be true, false or undefined.");

                    var arrayIndex = this.computeTriStateArrayIndex(index);
                    var encoded = this.bits[arrayIndex];
                    if (encoded === undefined) {
                        if (value === undefined) {
                            // They're trying to set a bit to undefined that we don't even have an entry
                            // for.  We can bail out quickly here.
                            return;
                        }

                        encoded = 0;
                    }

                    // First, we clear out any bits set at the appropriate index.
                    var bitIndex = this.computeTriStateEncodedValueIndex(index);

                    // Create a mask similar to: 11111111100111111
                    // i.e. all 1's except for 2 zeroes in the appropriate place.
                    var clearMask = ~(3 /* TriStateClearBitsMask */ << bitIndex);
                    encoded = encoded & clearMask;

                    if (value === true) {
                        encoded = encoded | (2 /* TriStateEncodedTrue */ << bitIndex);
                    } else if (value === false) {
                        encoded = encoded | (1 /* TriStateEncodedFalse */ << bitIndex);
                    }

                    // else {
                    //   They're setting the value to 'undefined'.  We already cleared the value
                    //   so there's nothing we need to do here.
                    // }
                    this.bits[arrayIndex] = encoded;
                } else {
                    TypeScript.Debug.assert(value === true || value === false, "value must only be true or false.");

                    var arrayIndex = this.computeBiStateArrayIndex(index);
                    var encoded = this.bits[arrayIndex];
                    if (encoded === undefined) {
                        if (value === false) {
                            // They're trying to set a bit to false that we don't even have an entry
                            // for.  We can bail out quickly here.
                            return;
                        }

                        encoded = 0;
                    }

                    var bitIndex = this.computeBiStateEncodedValueIndex(index);

                    // First, clear out the bit at this location.
                    encoded = encoded & ~(1 /* BiStateClearBitsMask */ << bitIndex);

                    if (value) {
                        encoded = encoded | (1 /* BiStateEncodedTrue */ << bitIndex);
                    }

                    // else {
                    //   They're setting the value to 'false'.  We already cleared the value
                    //   so there's nothing we need to do here.
                    // }
                    this.bits[arrayIndex] = encoded;
                }
            };

            BitVectorImpl.prototype.release = function () {
                TypeScript.Debug.assert(!this.isReleased, "Should not use a released bitvector");
                this.isReleased = true;
                this.bits.length = 0;
                pool.push(this);
            };
            return BitVectorImpl;
        })();

        function getBitVector(allowUndefinedValues) {
            if (pool.length === 0) {
                return new BitVectorImpl(allowUndefinedValues);
            }

            var vector = pool.pop();
            vector.isReleased = false;
            vector.allowUndefinedValues = allowUndefinedValues;

            return vector;
        }
        BitVector.getBitVector = getBitVector;
    })(TypeScript.BitVector || (TypeScript.BitVector = {}));
    var BitVector = TypeScript.BitVector;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (BitMatrix) {
        var pool = [];

        var BitMatrixImpl = (function () {
            function BitMatrixImpl(allowUndefinedValues) {
                this.allowUndefinedValues = allowUndefinedValues;
                this.isReleased = false;
                this.vectors = [];
            }
            BitMatrixImpl.prototype.valueAt = function (x, y) {
                TypeScript.Debug.assert(!this.isReleased, "Should not use a released bitvector");
                var vector = this.vectors[x];
                if (!vector) {
                    return this.allowUndefinedValues ? undefined : false;
                }

                return vector.valueAt(y);
            };

            BitMatrixImpl.prototype.setValueAt = function (x, y, value) {
                TypeScript.Debug.assert(!this.isReleased, "Should not use a released bitvector");
                var vector = this.vectors[x];
                if (!vector) {
                    if (value === undefined) {
                        // If they're storing an undefined value, and we don't even have a vector,
                        // then we can short circuit early here.
                        return;
                    }

                    vector = TypeScript.BitVector.getBitVector(this.allowUndefinedValues);
                    this.vectors[x] = vector;
                }

                vector.setValueAt(y, value);
            };

            BitMatrixImpl.prototype.release = function () {
                TypeScript.Debug.assert(!this.isReleased, "Should not use a released bitvector");
                this.isReleased = true;

                for (var name in this.vectors) {
                    if (this.vectors.hasOwnProperty(name)) {
                        var vector = this.vectors[name];
                        vector.release();
                    }
                }

                this.vectors.length = 0;
                pool.push(this);
            };
            return BitMatrixImpl;
        })();

        function getBitMatrix(allowUndefinedValues) {
            if (pool.length === 0) {
                return new BitMatrixImpl(allowUndefinedValues);
            }

            var matrix = pool.pop();
            matrix.isReleased = false;
            matrix.allowUndefinedValues = allowUndefinedValues;

            return matrix;
        }
        BitMatrix.getBitMatrix = getBitMatrix;
    })(TypeScript.BitMatrix || (TypeScript.BitMatrix = {}));
    var BitMatrix = TypeScript.BitMatrix;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (Constants) {
        // 2^30-1
        Constants[Constants["Max31BitInteger"] = 1073741823] = "Max31BitInteger";
        Constants[Constants["Min31BitInteger"] = -1073741824] = "Min31BitInteger";
    })(TypeScript.Constants || (TypeScript.Constants = {}));
    var Constants = TypeScript.Constants;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (AssertionLevel) {
        AssertionLevel[AssertionLevel["None"] = 0] = "None";
        AssertionLevel[AssertionLevel["Normal"] = 1] = "Normal";
        AssertionLevel[AssertionLevel["Aggressive"] = 2] = "Aggressive";
        AssertionLevel[AssertionLevel["VeryAggressive"] = 3] = "VeryAggressive";
    })(TypeScript.AssertionLevel || (TypeScript.AssertionLevel = {}));
    var AssertionLevel = TypeScript.AssertionLevel;

    var Debug = (function () {
        function Debug() {
        }
        Debug.shouldAssert = function (level) {
            return this.currentAssertionLevel >= level;
        };

        Debug.assert = function (expression, message, verboseDebugInfo) {
            if (typeof message === "undefined") { message = ""; }
            if (typeof verboseDebugInfo === "undefined") { verboseDebugInfo = null; }
            if (!expression) {
                var verboseDebugString = "";
                if (verboseDebugInfo) {
                    verboseDebugString = "\r\nVerbose Debug Information:" + verboseDebugInfo();
                }

                throw new Error("Debug Failure. False expression: " + message + verboseDebugString);
            }
        };

        Debug.fail = function (message) {
            Debug.assert(false, message);
        };
        Debug.currentAssertionLevel = 0 /* None */;
        return Debug;
    })();
    TypeScript.Debug = Debug;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var TypeScript;
(function (TypeScript) {
    TypeScript.LocalizedDiagnosticMessages = null;

    var Location = (function () {
        function Location(fileName, lineMap, start, length) {
            this._fileName = fileName;
            this._lineMap = lineMap;
            this._start = start;
            this._length = length;
        }
        Location.prototype.fileName = function () {
            return this._fileName;
        };

        Location.prototype.lineMap = function () {
            return this._lineMap;
        };

        Location.prototype.line = function () {
            return this._lineMap ? this._lineMap.getLineNumberFromPosition(this.start()) : 0;
        };

        Location.prototype.character = function () {
            return this._lineMap ? this._lineMap.getLineAndCharacterFromPosition(this.start()).character() : 0;
        };

        Location.prototype.start = function () {
            return this._start;
        };

        Location.prototype.length = function () {
            return this._length;
        };

        Location.equals = function (location1, location2) {
            return location1._fileName === location2._fileName && location1._start === location2._start && location1._length === location2._length;
        };
        return Location;
    })();
    TypeScript.Location = Location;

    var Diagnostic = (function (_super) {
        __extends(Diagnostic, _super);
        function Diagnostic(fileName, lineMap, start, length, diagnosticKey, _arguments, additionalLocations) {
            if (typeof _arguments === "undefined") { _arguments = null; }
            if (typeof additionalLocations === "undefined") { additionalLocations = null; }
            _super.call(this, fileName, lineMap, start, length);
            this._diagnosticKey = diagnosticKey;
            this._arguments = (_arguments && _arguments.length > 0) ? _arguments : null;
            this._additionalLocations = (additionalLocations && additionalLocations.length > 0) ? additionalLocations : null;
        }
        Diagnostic.prototype.toJSON = function (key) {
            var result = {};
            result.start = this.start();
            result.length = this.length();

            result.diagnosticCode = this._diagnosticKey;

            var _arguments = this.arguments();
            if (_arguments && _arguments.length > 0) {
                result.arguments = _arguments;
            }

            return result;
        };

        Diagnostic.prototype.diagnosticKey = function () {
            return this._diagnosticKey;
        };

        Diagnostic.prototype.arguments = function () {
            return this._arguments;
        };

        /**
        * Get the text of the message in the given language.
        */
        Diagnostic.prototype.text = function () {
            return TypeScript.getLocalizedText(this._diagnosticKey, this._arguments);
        };

        /**
        * Get the text of the message including the error code in the given language.
        */
        Diagnostic.prototype.message = function () {
            return TypeScript.getDiagnosticMessage(this._diagnosticKey, this._arguments);
        };

        /**
        * If a derived class has additional information about other referenced symbols, it can
        * expose the locations of those symbols in a general way, so they can be reported along
        * with the error.
        */
        Diagnostic.prototype.additionalLocations = function () {
            return this._additionalLocations || [];
        };

        Diagnostic.equals = function (diagnostic1, diagnostic2) {
            return Location.equals(diagnostic1, diagnostic2) && diagnostic1._diagnosticKey === diagnostic2._diagnosticKey && TypeScript.ArrayUtilities.sequenceEquals(diagnostic1._arguments, diagnostic2._arguments, function (v1, v2) {
                return v1 === v2;
            });
        };

        Diagnostic.prototype.info = function () {
            return getDiagnosticInfoFromKey(this.diagnosticKey());
        };
        return Diagnostic;
    })(Location);
    TypeScript.Diagnostic = Diagnostic;

    function newLine() {
        // TODO: We need to expose an extensibility point on our hosts to have them tell us what
        // they want the newline string to be.  That way we can get the correct result regardless
        // of which host we use
        return TypeScript.Environment ? TypeScript.Environment.newLine : "\r\n";
    }
    TypeScript.newLine = newLine;

    function getLargestIndex(diagnostic) {
        var largest = -1;
        var regex = /\{(\d+)\}/g;

        var match;
        while (match = regex.exec(diagnostic)) {
            var val = parseInt(match[1]);
            if (!isNaN(val) && val > largest) {
                largest = val;
            }
        }

        return largest;
    }

    function getDiagnosticInfoFromKey(diagnosticKey) {
        var result = TypeScript.diagnosticInformationMap[diagnosticKey];
        TypeScript.Debug.assert(result);
        return result;
    }

    function getLocalizedText(diagnosticKey, args) {
        if (TypeScript.LocalizedDiagnosticMessages) {
            //Debug.assert(LocalizedDiagnosticMessages.hasOwnProperty(diagnosticKey));
        }

        var diagnosticMessageText = TypeScript.LocalizedDiagnosticMessages ? TypeScript.LocalizedDiagnosticMessages[diagnosticKey] : diagnosticKey;
        TypeScript.Debug.assert(diagnosticMessageText !== undefined && diagnosticMessageText !== null);

        var actualCount = args ? args.length : 0;

        // We have a string like "foo_0_bar_1".  We want to find the largest integer there.
        // (i.e.'1').  We then need one more arg than that to be correct.
        var expectedCount = 1 + getLargestIndex(diagnosticKey);

        if (expectedCount !== actualCount) {
            throw new Error(getLocalizedText(TypeScript.DiagnosticCode.Expected_0_arguments_to_message_got_1_instead, [expectedCount, actualCount]));
        }

        // This should also be the same number of arguments as the message text
        var valueCount = 1 + getLargestIndex(diagnosticMessageText);
        if (valueCount !== expectedCount) {
            throw new Error(getLocalizedText(TypeScript.DiagnosticCode.Expected_the_message_0_to_have_1_arguments_but_it_had_2, [diagnosticMessageText, expectedCount, valueCount]));
        }

        diagnosticMessageText = diagnosticMessageText.replace(/{(\d+)}/g, function (match, num) {
            return typeof args[num] !== 'undefined' ? args[num] : match;
        });

        diagnosticMessageText = diagnosticMessageText.replace(/{(NL)}/g, function (match) {
            return TypeScript.newLine();
        });

        return diagnosticMessageText;
    }
    TypeScript.getLocalizedText = getLocalizedText;

    function getDiagnosticMessage(diagnosticKey, args) {
        var diagnostic = getDiagnosticInfoFromKey(diagnosticKey);
        var diagnosticMessageText = getLocalizedText(diagnosticKey, args);

        var message;
        if (diagnostic.category === 1 /* Error */) {
            message = getLocalizedText(TypeScript.DiagnosticCode.error_TS_0_1, [diagnostic.code, diagnosticMessageText]);
        } else if (diagnostic.category === 0 /* Warning */) {
            message = getLocalizedText(TypeScript.DiagnosticCode.warning_TS_0_1, [diagnostic.code, diagnosticMessageText]);
        } else {
            message = diagnosticMessageText;
        }

        return message;
    }
    TypeScript.getDiagnosticMessage = getDiagnosticMessage;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var Errors = (function () {
        function Errors() {
        }
        Errors.argument = function (argument, message) {
            return new Error("Invalid argument: " + argument + ". " + message);
        };

        Errors.argumentOutOfRange = function (argument) {
            return new Error("Argument out of range: " + argument);
        };

        Errors.argumentNull = function (argument) {
            return new Error("Argument null: " + argument);
        };

        Errors.abstract = function () {
            return new Error("Operation not implemented properly by subclass.");
        };

        Errors.notYetImplemented = function () {
            return new Error("Not yet implemented.");
        };

        Errors.invalidOperation = function (message) {
            return new Error("Invalid operation: " + message);
        };
        return Errors;
    })();
    TypeScript.Errors = Errors;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var Hash = (function () {
        function Hash() {
        }
        Hash.computeFnv1aCharArrayHashCode = function (text, start, len) {
            var hashCode = Hash.FNV_BASE;
            var end = start + len;

            for (var i = start; i < end; i++) {
                hashCode = TypeScript.IntegerUtilities.integerMultiplyLow32Bits(hashCode ^ text[i], Hash.FNV_PRIME);
            }

            return hashCode;
        };

        Hash.computeSimple31BitCharArrayHashCode = function (key, start, len) {
            // Start with an int.
            var hash = 0;

            for (var i = 0; i < len; i++) {
                var ch = key[start + i];

                // Left shift keeps things as a 32bit int.  And we're only doing two adds.  Chakra and
                // V8 recognize this as not needing to go past the 53 bits needed for the float
                // mantissa.  Or'ing with 0 keeps this 32 bits.
                hash = ((((hash << 5) - hash) | 0) + ch) | 0;
            }

            // Ensure we fit in 31 bits.  That way if/when this gets stored, it won't require any heap
            // allocation.
            return hash & 0x7FFFFFFF;
        };

        Hash.computeSimple31BitStringHashCode = function (key) {
            // Start with an int.
            var hash = 0;

            var start = 0;
            var len = key.length;

            for (var i = 0; i < len; i++) {
                var ch = key.charCodeAt(start + i);

                // Left shift keeps things as a 32bit int.  And we're only doing two adds.  Chakra and
                // V8 recognize this as not needing to go past the 53 bits needed for the float
                // mantissa.  Or'ing with 0 keeps this 32 bits.
                hash = ((((hash << 5) - hash) | 0) + ch) | 0;
            }

            // Ensure we fit in 31 bits.  That way if/when this gets stored, it won't require any heap
            // allocation.
            return hash & 0x7FFFFFFF;
        };

        Hash.computeMurmur2StringHashCode = function (key, seed) {
            // 'm' and 'r' are mixing constants generated offline.
            // They're not really 'magic', they just happen to work well.
            var m = 0x5bd1e995;
            var r = 24;

            // Initialize the hash to a 'random' value
            var numberOfCharsLeft = key.length;
            var h = Math.abs(seed ^ numberOfCharsLeft);

            // Mix 4 bytes at a time into the hash.  NOTE: 4 bytes is two chars, so we iterate
            // through the string two chars at a time.
            var index = 0;
            while (numberOfCharsLeft >= 2) {
                var c1 = key.charCodeAt(index);
                var c2 = key.charCodeAt(index + 1);

                var k = Math.abs(c1 | (c2 << 16));

                k = TypeScript.IntegerUtilities.integerMultiplyLow32Bits(k, m);
                k ^= k >> r;
                k = TypeScript.IntegerUtilities.integerMultiplyLow32Bits(k, m);

                h = TypeScript.IntegerUtilities.integerMultiplyLow32Bits(h, m);
                h ^= k;

                index += 2;
                numberOfCharsLeft -= 2;
            }

            // Handle the last char (or 2 bytes) if they exist.  This happens if the original string had
            // odd length.
            if (numberOfCharsLeft === 1) {
                h ^= key.charCodeAt(index);
                h = TypeScript.IntegerUtilities.integerMultiplyLow32Bits(h, m);
            }

            // Do a few final mixes of the hash to ensure the last few bytes are well-incorporated.
            h ^= h >> 13;
            h = TypeScript.IntegerUtilities.integerMultiplyLow32Bits(h, m);
            h ^= h >> 15;

            return h;
        };

        Hash.combine = function (value, currentHash) {
            // Ensure we stay within 31 bits.
            return (((currentHash << 5) + currentHash) + value) & 0x7FFFFFFF;
        };
        // This table uses FNV1a as a string hash
        Hash.FNV_BASE = 2166136261;
        Hash.FNV_PRIME = 16777619;
        return Hash;
    })();
    TypeScript.Hash = Hash;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
///<reference path='..\enumerator.ts' />
///<reference path='..\process.ts' />

var TypeScript;
(function (TypeScript) {
    TypeScript.nodeMakeDirectoryTime = 0;
    TypeScript.nodeCreateBufferTime = 0;
    TypeScript.nodeWriteFileSyncTime = 0;

    (function (ByteOrderMark) {
        ByteOrderMark[ByteOrderMark["None"] = 0] = "None";
        ByteOrderMark[ByteOrderMark["Utf8"] = 1] = "Utf8";
        ByteOrderMark[ByteOrderMark["Utf16BigEndian"] = 2] = "Utf16BigEndian";
        ByteOrderMark[ByteOrderMark["Utf16LittleEndian"] = 3] = "Utf16LittleEndian";
    })(TypeScript.ByteOrderMark || (TypeScript.ByteOrderMark = {}));
    var ByteOrderMark = TypeScript.ByteOrderMark;

    var FileInformation = (function () {
        function FileInformation(contents, byteOrderMark) {
            this.contents = contents;
            this.byteOrderMark = byteOrderMark;
        }
        return FileInformation;
    })();
    TypeScript.FileInformation = FileInformation;

    function throwIOError(message, error) {
        var errorMessage = message;
        if (error && error.message) {
            errorMessage += (" " + error.message);
        }
        throw new Error(errorMessage);
    }

    TypeScript.Environment = (function () {
        // Create an IO object for use inside WindowsScriptHost hosts
        // Depends on WSCript and FileSystemObject
        function getWindowsScriptHostEnvironment() {
            try  {
                var fso = new ActiveXObject("Scripting.FileSystemObject");
            } catch (e) {
                return null;
            }

            var streamObjectPool = [];

            function getStreamObject() {
                if (streamObjectPool.length > 0) {
                    return streamObjectPool.pop();
                } else {
                    return new ActiveXObject("ADODB.Stream");
                }
            }

            function releaseStreamObject(obj) {
                streamObjectPool.push(obj);
            }

            var args = [];
            for (var i = 0; i < WScript.Arguments.length; i++) {
                args[i] = WScript.Arguments.Item(i);
            }

            return {
                // On windows, the newline sequence is always "\r\n";
                newLine: "\r\n",
                currentDirectory: function () {
                    return WScript.CreateObject("WScript.Shell").CurrentDirectory;
                },
                supportsCodePage: function () {
                    return WScript.ReadFile;
                },
                absolutePath: function (path) {
                    return fso.GetAbsolutePathName(path);
                },
                readFile: function (path, codepage) {
                    try  {
                        // If a codepage is requested, defer to our host to do the reading.  If it
                        // fails, fall back to our normal BOM/utf8 logic.
                        if (codepage !== null && this.supportsCodePage()) {
                            try  {
                                var contents = WScript.ReadFile(path, codepage);
                                return new FileInformation(contents, 0 /* None */);
                            } catch (e) {
                                // We couldn't read it with that code page.  Fall back to the normal
                                // BOM/utf8 logic below.
                            }
                        }

                        // Initially just read the first two bytes of the file to see if there's a bom.
                        var streamObj = getStreamObject();
                        streamObj.Open();
                        streamObj.Type = 2; // Text data

                        // Start reading individual chars without any interpretation.  That way we can check for a bom.
                        streamObj.Charset = 'x-ansi';

                        streamObj.LoadFromFile(path);
                        var bomChar = streamObj.ReadText(2);

                        // Position has to be at 0 before changing the encoding
                        streamObj.Position = 0;

                        var byteOrderMark = 0 /* None */;

                        if (bomChar.charCodeAt(0) === 0xFE && bomChar.charCodeAt(1) === 0xFF) {
                            streamObj.Charset = 'unicode';
                            byteOrderMark = 2 /* Utf16BigEndian */;
                        } else if (bomChar.charCodeAt(0) === 0xFF && bomChar.charCodeAt(1) === 0xFE) {
                            streamObj.Charset = 'unicode';
                            byteOrderMark = 3 /* Utf16LittleEndian */;
                        } else if (bomChar.charCodeAt(0) === 0xEF && bomChar.charCodeAt(1) === 0xBB) {
                            streamObj.Charset = 'utf-8';
                            byteOrderMark = 1 /* Utf8 */;
                        } else {
                            // Always read a file as utf8 if it has no bom.
                            streamObj.Charset = 'utf-8';
                        }

                        // Read the whole file
                        var contents = streamObj.ReadText(-1);
                        streamObj.Close();
                        releaseStreamObject(streamObj);
                        return new FileInformation(contents, byteOrderMark);
                    } catch (err) {
                        // -2147024809 is the javascript value for 0x80070057 which is the HRESULT for
                        // "the parameter is incorrect".
                        var message;
                        if (err.number === -2147024809) {
                            message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Unsupported_file_encoding, null);
                        } else {
                            message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Cannot_read_file_0_1, [path, err.message]);
                        }

                        throw new Error(message);
                    }
                },
                writeFile: function (path, contents, writeByteOrderMark) {
                    // First, convert the text contents passed in to binary in UTF8 format.
                    var textStream = getStreamObject();
                    textStream.Charset = 'utf-8';
                    textStream.Open();
                    textStream.WriteText(contents, 0);

                    // If they don't want the BOM, then skip it (it will be added automatically
                    // when we write the utf8 bytes out above).
                    if (!writeByteOrderMark) {
                        textStream.Position = 3;
                    } else {
                        textStream.Position = 0;
                    }

                    // Now, write all those bytes out to a file.
                    var fileStream = getStreamObject();
                    fileStream.Type = 1; //binary data.
                    fileStream.Open();

                    textStream.CopyTo(fileStream);

                    // Flush and save the file.
                    fileStream.Flush();
                    fileStream.SaveToFile(path, 2);
                    fileStream.Close();

                    textStream.Flush();
                    textStream.Close();
                },
                fileExists: function (path) {
                    return fso.FileExists(path);
                },
                deleteFile: function (path) {
                    if (fso.FileExists(path)) {
                        fso.DeleteFile(path, true); // true: delete read-only files
                    }
                },
                directoryExists: function (path) {
                    return fso.FolderExists(path);
                },
                directoryName: function (path) {
                    return fso.GetParentFolderName(path);
                },
                createDirectory: function (path) {
                    try  {
                        if (!this.directoryExists(path)) {
                            fso.CreateFolder(path);
                        }
                    } catch (e) {
                        throwIOError(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Could_not_create_directory_0, [path]), e);
                    }
                },
                listFiles: function (path, spec, options) {
                    options = options || {};
                    function filesInFolder(folder, root) {
                        var paths = [];
                        var fc;

                        if (options.recursive) {
                            fc = new Enumerator(folder.subfolders);

                            for (; !fc.atEnd(); fc.moveNext()) {
                                paths = paths.concat(filesInFolder(fc.item(), root + "\\" + fc.item().Name));
                            }
                        }

                        fc = new Enumerator(folder.files);

                        for (; !fc.atEnd(); fc.moveNext()) {
                            if (!spec || fc.item().Name.match(spec)) {
                                paths.push(root + "\\" + fc.item().Name);
                            }
                        }

                        return paths;
                    }

                    var folder = fso.GetFolder(path);
                    var paths = [];

                    return filesInFolder(folder, path);
                },
                arguments: args,
                standardOut: WScript.StdOut,
                standardError: WScript.StdErr,
                executingFilePath: function () {
                    return WScript.ScriptFullName;
                },
                quit: function (exitCode) {
                    if (typeof exitCode === "undefined") { exitCode = 0; }
                    try  {
                        WScript.Quit(exitCode);
                    } catch (e) {
                    }
                },
                watchFile: null
            };
        }
        ;

        function getNodeEnvironment() {
            var _fs = require('fs');
            var _path = require('path');
            var _module = require('module');
            var _os = require('os');

            return {
                // On node pick up the newline character from the OS
                newLine: _os.EOL,
                currentDirectory: function () {
                    return process.cwd();
                },
                supportsCodePage: function () {
                    return false;
                },
                absolutePath: function (path) {
                    return _path.resolve(path);
                },
                readFile: function (file, codepage) {
                    if (codepage !== null) {
                        throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.codepage_option_not_supported_on_current_platform, null));
                    }

                    var buffer = _fs.readFileSync(file);
                    switch (buffer[0]) {
                        case 0xFE:
                            if (buffer[1] === 0xFF) {
                                // utf16-be. Reading the buffer as big endian is not supported, so convert it to
                                // Little Endian first
                                var i = 0;
                                while ((i + 1) < buffer.length) {
                                    var temp = buffer[i];
                                    buffer[i] = buffer[i + 1];
                                    buffer[i + 1] = temp;
                                    i += 2;
                                }
                                return new FileInformation(buffer.toString("ucs2", 2), 2 /* Utf16BigEndian */);
                            }
                            break;
                        case 0xFF:
                            if (buffer[1] === 0xFE) {
                                // utf16-le
                                return new FileInformation(buffer.toString("ucs2", 2), 3 /* Utf16LittleEndian */);
                            }
                            break;
                        case 0xEF:
                            if (buffer[1] === 0xBB) {
                                // utf-8
                                return new FileInformation(buffer.toString("utf8", 3), 1 /* Utf8 */);
                            }
                    }

                    // Default behaviour
                    return new FileInformation(buffer.toString("utf8", 0), 0 /* None */);
                },
                writeFile: function (path, contents, writeByteOrderMark) {
                    function mkdirRecursiveSync(path) {
                        var stats = _fs.statSync(path);
                        if (stats.isFile()) {
                            throw "\"" + path + "\" exists but isn't a directory.";
                        } else if (stats.isDirectory()) {
                            return;
                        } else {
                            mkdirRecursiveSync(_path.dirname(path));
                            _fs.mkdirSync(path, 509);
                        }
                    }
                    var start = new Date().getTime();
                    mkdirRecursiveSync(_path.dirname(path));
                    TypeScript.nodeMakeDirectoryTime += new Date().getTime() - start;

                    if (writeByteOrderMark) {
                        contents = '\uFEFF' + contents;
                    }

                    var start = new Date().getTime();

                    var chunkLength = 4 * 1024;
                    var fileDescriptor = _fs.openSync(path, "w");
                    try  {
                        for (var index = 0; index < contents.length; index += chunkLength) {
                            var bufferStart = new Date().getTime();
                            var buffer = new Buffer(contents.substr(index, chunkLength), "utf8");
                            TypeScript.nodeCreateBufferTime += new Date().getTime() - bufferStart;

                            _fs.writeSync(fileDescriptor, buffer, 0, buffer.length, null);
                        }
                    } finally {
                        _fs.closeSync(fileDescriptor);
                    }

                    TypeScript.nodeWriteFileSyncTime += new Date().getTime() - start;
                },
                fileExists: function (path) {
                    return _fs.existsSync(path);
                },
                deleteFile: function (path) {
                    try  {
                        _fs.unlinkSync(path);
                    } catch (e) {
                    }
                },
                directoryExists: function (path) {
                    return _fs.existsSync(path) && _fs.statSync(path).isDirectory();
                },
                directoryName: function (path) {
                    var dirPath = _path.dirname(path);

                    // Node will just continue to repeat the root path, rather than return null
                    if (dirPath === path) {
                        dirPath = null;
                    }

                    return dirPath;
                },
                createDirectory: function (path) {
                    try  {
                        if (!this.directoryExists(path)) {
                            _fs.mkdirSync(path);
                        }
                    } catch (e) {
                        throwIOError(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Could_not_create_directory_0, [path]), e);
                    }
                },
                listFiles: function (path, spec, options) {
                    options = options || {};

                    function filesInFolder(folder) {
                        var paths = [];

                        var files = _fs.readdirSync(folder);
                        for (var i = 0; i < files.length; i++) {
                            var pathToFile = _path.join(folder, files[i]);
                            var stat = _fs.statSync(pathToFile);
                            if (options.recursive && stat.isDirectory()) {
                                paths = paths.concat(filesInFolder(pathToFile));
                            } else if (stat.isFile() && (!spec || files[i].match(spec))) {
                                paths.push(pathToFile);
                            }
                        }

                        return paths;
                    }

                    return filesInFolder(path);
                },
                arguments: process.argv.slice(2),
                standardOut: {
                    Write: function (str) {
                        return process.stdout.write(str);
                    },
                    WriteLine: function (str) {
                        return process.stdout.write(str + '\n');
                    },
                    Close: function () {
                    }
                },
                standardError: {
                    Write: function (str) {
                        return process.stderr.write(str);
                    },
                    WriteLine: function (str) {
                        return process.stderr.write(str + '\n');
                    },
                    Close: function () {
                    }
                },
                executingFilePath: function () {
                    return process.mainModule.filename;
                },
                quit: function (code) {
                    var stderrFlushed = process.stderr.write('');
                    var stdoutFlushed = process.stdout.write('');
                    process.stderr.on('drain', function () {
                        stderrFlushed = true;
                        if (stdoutFlushed) {
                            process.exit(code);
                        }
                    });
                    process.stdout.on('drain', function () {
                        stdoutFlushed = true;
                        if (stderrFlushed) {
                            process.exit(code);
                        }
                    });
                    setTimeout(function () {
                        process.exit(code);
                    }, 5);
                },
                watchFile: function (fileName, callback) {
                    var firstRun = true;
                    var processingChange = false;

                    var fileChanged = function (curr, prev) {
                        if (!firstRun) {
                            if (curr.mtime < prev.mtime) {
                                return;
                            }

                            _fs.unwatchFile(fileName, fileChanged);
                            if (!processingChange) {
                                processingChange = true;
                                callback(fileName);
                                setTimeout(function () {
                                    processingChange = false;
                                }, 100);
                            }
                        }
                        firstRun = false;
                        _fs.watchFile(fileName, { persistent: true, interval: 500 }, fileChanged);
                    };

                    fileChanged();
                    return {
                        fileName: fileName,
                        close: function () {
                            _fs.unwatchFile(fileName, fileChanged);
                        }
                    };
                }
            };
        }
        ;

        if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
            return getWindowsScriptHostEnvironment();
        } else if (typeof module !== 'undefined' && module.exports) {
            return getNodeEnvironment();
        } else {
            return null;
        }
    })();
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts'/>
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (IntegerUtilities) {
        function integerDivide(numerator, denominator) {
            return (numerator / denominator) >> 0;
        }
        IntegerUtilities.integerDivide = integerDivide;

        function integerMultiplyLow32Bits(n1, n2) {
            var n1Low16 = n1 & 0x0000ffff;
            var n1High16 = n1 >>> 16;

            var n2Low16 = n2 & 0x0000ffff;
            var n2High16 = n2 >>> 16;

            var resultLow32 = (((n1 & 0xffff0000) * n2) >>> 0) + (((n1 & 0x0000ffff) * n2) >>> 0) >>> 0;
            return resultLow32;
        }
        IntegerUtilities.integerMultiplyLow32Bits = integerMultiplyLow32Bits;

        function isInteger(text) {
            return /^[0-9]+$/.test(text);
        }
        IntegerUtilities.isInteger = isInteger;

        function isHexInteger(text) {
            return /^0(x|X)[0-9a-fA-F]+$/.test(text);
        }
        IntegerUtilities.isHexInteger = isHexInteger;
    })(TypeScript.IntegerUtilities || (TypeScript.IntegerUtilities = {}));
    var IntegerUtilities = TypeScript.IntegerUtilities;
})(TypeScript || (TypeScript = {}));
/// <reference path='references.ts' />
///<reference path='references.ts' />
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var LineMap = (function () {
        function LineMap(_computeLineStarts, length) {
            this._computeLineStarts = _computeLineStarts;
            this.length = length;
            this._lineStarts = null;
        }
        LineMap.prototype.toJSON = function (key) {
            return { lineStarts: this.lineStarts(), length: this.length };
        };

        LineMap.prototype.equals = function (other) {
            return this.length === other.length && TypeScript.ArrayUtilities.sequenceEquals(this.lineStarts(), other.lineStarts(), function (v1, v2) {
                return v1 === v2;
            });
        };

        LineMap.prototype.lineStarts = function () {
            if (this._lineStarts === null) {
                this._lineStarts = this._computeLineStarts();
            }

            return this._lineStarts;
        };

        LineMap.prototype.lineCount = function () {
            return this.lineStarts().length;
        };

        LineMap.prototype.getPosition = function (line, character) {
            return this.lineStarts()[line] + character;
        };

        LineMap.prototype.getLineNumberFromPosition = function (position) {
            if (position < 0 || position > this.length) {
                throw TypeScript.Errors.argumentOutOfRange("position");
            }

            if (position === this.length) {
                // this can happen when the user tried to get the line of items
                // that are at the absolute end of this text (i.e. the EndOfLine
                // token, or missing tokens that are at the end of the text).
                // In this case, we want the last line in the text.
                return this.lineCount() - 1;
            }

            // Binary search to find the right line
            var lineNumber = TypeScript.ArrayUtilities.binarySearch(this.lineStarts(), position);
            if (lineNumber < 0) {
                lineNumber = (~lineNumber) - 1;
            }

            return lineNumber;
        };

        LineMap.prototype.getLineStartPosition = function (lineNumber) {
            return this.lineStarts()[lineNumber];
        };

        LineMap.prototype.fillLineAndCharacterFromPosition = function (position, lineAndCharacter) {
            if (position < 0 || position > this.length) {
                throw TypeScript.Errors.argumentOutOfRange("position");
            }

            var lineNumber = this.getLineNumberFromPosition(position);
            lineAndCharacter.line = lineNumber;
            lineAndCharacter.character = position - this.lineStarts()[lineNumber];
        };

        LineMap.prototype.getLineAndCharacterFromPosition = function (position) {
            if (position < 0 || position > this.length) {
                throw TypeScript.Errors.argumentOutOfRange("position");
            }

            var lineNumber = this.getLineNumberFromPosition(position);

            return new TypeScript.LineAndCharacter(lineNumber, position - this.lineStarts()[lineNumber]);
        };
        LineMap.empty = new LineMap(function () {
            return [0];
        }, 0);
        return LineMap;
    })();
    TypeScript.LineMap = LineMap;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var LineAndCharacter = (function () {
        /**
        * Initializes a new instance of a LinePosition with the given line and character. ArgumentOutOfRangeException if "line" or "character" is less than zero.
        * @param line The line of the line position. The first line in a file is defined as line 0 (zero based line numbering).
        * @param character The character position in the line.
        */
        function LineAndCharacter(line, character) {
            this._line = 0;
            this._character = 0;
            if (line < 0) {
                throw TypeScript.Errors.argumentOutOfRange("line");
            }

            if (character < 0) {
                throw TypeScript.Errors.argumentOutOfRange("character");
            }

            this._line = line;
            this._character = character;
        }
        LineAndCharacter.prototype.line = function () {
            return this._line;
        };

        LineAndCharacter.prototype.character = function () {
            return this._character;
        };
        return LineAndCharacter;
    })();
    TypeScript.LineAndCharacter = LineAndCharacter;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var StringUtilities = (function () {
        function StringUtilities() {
        }
        StringUtilities.isString = function (value) {
            return Object.prototype.toString.apply(value, []) === '[object String]';
        };

        StringUtilities.endsWith = function (string, value) {
            return string.substring(string.length - value.length, string.length) === value;
        };

        StringUtilities.startsWith = function (string, value) {
            return string.substr(0, value.length) === value;
        };

        StringUtilities.repeat = function (value, count) {
            return Array(count + 1).join(value);
        };
        return StringUtilities;
    })();
    TypeScript.StringUtilities = StringUtilities;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var global = Function("return this").call(null);

var TypeScript;
(function (TypeScript) {
    var Clock;
    (function (Clock) {
        Clock.now;
        Clock.resolution;

        if (typeof WScript !== "undefined" && typeof global['WScript'].InitializeProjection !== "undefined") {
            // Running in JSHost.
            global['WScript'].InitializeProjection();

            Clock.now = function () {
                return TestUtilities.QueryPerformanceCounter();
            };

            Clock.resolution = TestUtilities.QueryPerformanceFrequency();
        } else {
            Clock.now = function () {
                return Date.now();
            };

            Clock.resolution = 1000;
        }
    })(Clock || (Clock = {}));

    var Timer = (function () {
        function Timer() {
            this.time = 0;
        }
        Timer.prototype.start = function () {
            this.time = 0;
            this.startTime = Clock.now();
        };

        Timer.prototype.end = function () {
            // Set time to MS.
            this.time = (Clock.now() - this.startTime);
        };
        return Timer;
    })();
    TypeScript.Timer = Timer;
})(TypeScript || (TypeScript = {}));
///<reference path='require.ts' />
///<reference path='..\resources\references.ts' />
///<reference path='arrayUtilities.ts' />
///<reference path='bitVector.ts' />
///<reference path='bitMatrix.ts' />
///<reference path='constants.ts' />
///<reference path='debug.ts' />
///<reference path='diagnosticCategory.ts' />
///<reference path='diagnosticCore.ts' />
///<reference path='diagnosticInfo.ts' />
///<reference path='errors.ts' />
///<reference path='hash.ts' />
///<reference path='environment.ts' />
///<reference path='indexable.ts' />
///<reference path='integerUtilities.ts' />
///<reference path='iterator.ts' />
///<reference path='lineAndCharacter.ts' />
///<reference path='lineMap.ts' />
///<reference path='linePosition.ts' />
// ///<reference path='stringTable.ts' />
///<reference path='stringUtilities.ts' />
///<reference path='timer.ts' />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='enumerator.ts' />
///<reference path='process.ts' />
///<reference path='core\references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (IOUtils) {
        // Creates the directory including its parent if not already present
        function createDirectoryStructure(ioHost, dirName) {
            if (ioHost.directoryExists(dirName)) {
                return;
            }

            var parentDirectory = ioHost.directoryName(dirName);
            if (parentDirectory != "") {
                createDirectoryStructure(ioHost, parentDirectory);
            }
            ioHost.createDirectory(dirName);
        }

        // Creates a file including its directory structure if not already present
        function writeFileAndFolderStructure(ioHost, fileName, contents, writeByteOrderMark) {
            var start = new Date().getTime();
            var path = ioHost.absolutePath(fileName);
            TypeScript.ioHostResolvePathTime += new Date().getTime() - start;

            var start = new Date().getTime();
            var dirName = ioHost.directoryName(path);
            TypeScript.ioHostDirectoryNameTime += new Date().getTime() - start;

            var start = new Date().getTime();
            createDirectoryStructure(ioHost, dirName);
            TypeScript.ioHostCreateDirectoryStructureTime += new Date().getTime() - start;

            var start = new Date().getTime();
            ioHost.writeFile(path, contents, writeByteOrderMark);
            TypeScript.ioHostWriteFileTime += new Date().getTime() - start;
        }
        IOUtils.writeFileAndFolderStructure = writeFileAndFolderStructure;

        function combine(prefix, suffix) {
            return prefix + "/" + suffix;
        }
        IOUtils.combine = combine;
    })(TypeScript.IOUtils || (TypeScript.IOUtils = {}));
    var IOUtils = TypeScript.IOUtils;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (CharacterCodes) {
        CharacterCodes[CharacterCodes["nullCharacter"] = 0] = "nullCharacter";
        CharacterCodes[CharacterCodes["maxAsciiCharacter"] = 127] = "maxAsciiCharacter";

        CharacterCodes[CharacterCodes["lineFeed"] = 10] = "lineFeed";
        CharacterCodes[CharacterCodes["carriageReturn"] = 13] = "carriageReturn";
        CharacterCodes[CharacterCodes["lineSeparator"] = 0x2028] = "lineSeparator";
        CharacterCodes[CharacterCodes["paragraphSeparator"] = 0x2029] = "paragraphSeparator";

        // REVIEW: do we need to support this?  The scanner doesn't, but our IText does.  This seems
        // like an odd disparity?  (Or maybe it's completely fine for them to be different).
        CharacterCodes[CharacterCodes["nextLine"] = 0x0085] = "nextLine";

        // Unicode 3.0 space characters
        CharacterCodes[CharacterCodes["space"] = 0x0020] = "space";
        CharacterCodes[CharacterCodes["nonBreakingSpace"] = 0x00A0] = "nonBreakingSpace";
        CharacterCodes[CharacterCodes["enQuad"] = 0x2000] = "enQuad";
        CharacterCodes[CharacterCodes["emQuad"] = 0x2001] = "emQuad";
        CharacterCodes[CharacterCodes["enSpace"] = 0x2002] = "enSpace";
        CharacterCodes[CharacterCodes["emSpace"] = 0x2003] = "emSpace";
        CharacterCodes[CharacterCodes["threePerEmSpace"] = 0x2004] = "threePerEmSpace";
        CharacterCodes[CharacterCodes["fourPerEmSpace"] = 0x2005] = "fourPerEmSpace";
        CharacterCodes[CharacterCodes["sixPerEmSpace"] = 0x2006] = "sixPerEmSpace";
        CharacterCodes[CharacterCodes["figureSpace"] = 0x2007] = "figureSpace";
        CharacterCodes[CharacterCodes["punctuationSpace"] = 0x2008] = "punctuationSpace";
        CharacterCodes[CharacterCodes["thinSpace"] = 0x2009] = "thinSpace";
        CharacterCodes[CharacterCodes["hairSpace"] = 0x200A] = "hairSpace";
        CharacterCodes[CharacterCodes["zeroWidthSpace"] = 0x200B] = "zeroWidthSpace";
        CharacterCodes[CharacterCodes["narrowNoBreakSpace"] = 0x202F] = "narrowNoBreakSpace";
        CharacterCodes[CharacterCodes["ideographicSpace"] = 0x3000] = "ideographicSpace";

        CharacterCodes[CharacterCodes["_"] = 95] = "_";
        CharacterCodes[CharacterCodes["$"] = 36] = "$";

        CharacterCodes[CharacterCodes["_0"] = 48] = "_0";
        CharacterCodes[CharacterCodes["_1"] = 49] = "_1";
        CharacterCodes[CharacterCodes["_2"] = 50] = "_2";
        CharacterCodes[CharacterCodes["_3"] = 51] = "_3";
        CharacterCodes[CharacterCodes["_4"] = 52] = "_4";
        CharacterCodes[CharacterCodes["_5"] = 53] = "_5";
        CharacterCodes[CharacterCodes["_6"] = 54] = "_6";
        CharacterCodes[CharacterCodes["_7"] = 55] = "_7";
        CharacterCodes[CharacterCodes["_8"] = 56] = "_8";
        CharacterCodes[CharacterCodes["_9"] = 57] = "_9";

        CharacterCodes[CharacterCodes["a"] = 97] = "a";
        CharacterCodes[CharacterCodes["b"] = 98] = "b";
        CharacterCodes[CharacterCodes["c"] = 99] = "c";
        CharacterCodes[CharacterCodes["d"] = 100] = "d";
        CharacterCodes[CharacterCodes["e"] = 101] = "e";
        CharacterCodes[CharacterCodes["f"] = 102] = "f";
        CharacterCodes[CharacterCodes["g"] = 103] = "g";
        CharacterCodes[CharacterCodes["h"] = 104] = "h";
        CharacterCodes[CharacterCodes["i"] = 105] = "i";
        CharacterCodes[CharacterCodes["j"] = 106] = "j";
        CharacterCodes[CharacterCodes["k"] = 107] = "k";
        CharacterCodes[CharacterCodes["l"] = 108] = "l";
        CharacterCodes[CharacterCodes["m"] = 109] = "m";
        CharacterCodes[CharacterCodes["n"] = 110] = "n";
        CharacterCodes[CharacterCodes["o"] = 111] = "o";
        CharacterCodes[CharacterCodes["p"] = 112] = "p";
        CharacterCodes[CharacterCodes["q"] = 113] = "q";
        CharacterCodes[CharacterCodes["r"] = 114] = "r";
        CharacterCodes[CharacterCodes["s"] = 115] = "s";
        CharacterCodes[CharacterCodes["t"] = 116] = "t";
        CharacterCodes[CharacterCodes["u"] = 117] = "u";
        CharacterCodes[CharacterCodes["v"] = 118] = "v";
        CharacterCodes[CharacterCodes["w"] = 119] = "w";
        CharacterCodes[CharacterCodes["x"] = 120] = "x";
        CharacterCodes[CharacterCodes["y"] = 121] = "y";
        CharacterCodes[CharacterCodes["z"] = 122] = "z";

        CharacterCodes[CharacterCodes["A"] = 65] = "A";
        CharacterCodes[CharacterCodes["B"] = 66] = "B";
        CharacterCodes[CharacterCodes["C"] = 67] = "C";
        CharacterCodes[CharacterCodes["D"] = 68] = "D";
        CharacterCodes[CharacterCodes["E"] = 69] = "E";
        CharacterCodes[CharacterCodes["F"] = 70] = "F";
        CharacterCodes[CharacterCodes["G"] = 71] = "G";
        CharacterCodes[CharacterCodes["H"] = 72] = "H";
        CharacterCodes[CharacterCodes["I"] = 73] = "I";
        CharacterCodes[CharacterCodes["J"] = 74] = "J";
        CharacterCodes[CharacterCodes["K"] = 75] = "K";
        CharacterCodes[CharacterCodes["L"] = 76] = "L";
        CharacterCodes[CharacterCodes["M"] = 77] = "M";
        CharacterCodes[CharacterCodes["N"] = 78] = "N";
        CharacterCodes[CharacterCodes["O"] = 79] = "O";
        CharacterCodes[CharacterCodes["P"] = 80] = "P";
        CharacterCodes[CharacterCodes["Q"] = 81] = "Q";
        CharacterCodes[CharacterCodes["R"] = 82] = "R";
        CharacterCodes[CharacterCodes["S"] = 83] = "S";
        CharacterCodes[CharacterCodes["T"] = 84] = "T";
        CharacterCodes[CharacterCodes["U"] = 85] = "U";
        CharacterCodes[CharacterCodes["V"] = 86] = "V";
        CharacterCodes[CharacterCodes["W"] = 87] = "W";
        CharacterCodes[CharacterCodes["X"] = 88] = "X";
        CharacterCodes[CharacterCodes["Y"] = 89] = "Y";
        CharacterCodes[CharacterCodes["Z"] = 90] = "Z";

        CharacterCodes[CharacterCodes["ampersand"] = 38] = "ampersand";
        CharacterCodes[CharacterCodes["asterisk"] = 42] = "asterisk";
        CharacterCodes[CharacterCodes["at"] = 64] = "at";
        CharacterCodes[CharacterCodes["backslash"] = 92] = "backslash";
        CharacterCodes[CharacterCodes["bar"] = 124] = "bar";
        CharacterCodes[CharacterCodes["caret"] = 94] = "caret";
        CharacterCodes[CharacterCodes["closeBrace"] = 125] = "closeBrace";
        CharacterCodes[CharacterCodes["closeBracket"] = 93] = "closeBracket";
        CharacterCodes[CharacterCodes["closeParen"] = 41] = "closeParen";
        CharacterCodes[CharacterCodes["colon"] = 58] = "colon";
        CharacterCodes[CharacterCodes["comma"] = 44] = "comma";
        CharacterCodes[CharacterCodes["dot"] = 46] = "dot";
        CharacterCodes[CharacterCodes["doubleQuote"] = 34] = "doubleQuote";
        CharacterCodes[CharacterCodes["equals"] = 61] = "equals";
        CharacterCodes[CharacterCodes["exclamation"] = 33] = "exclamation";
        CharacterCodes[CharacterCodes["greaterThan"] = 62] = "greaterThan";
        CharacterCodes[CharacterCodes["lessThan"] = 60] = "lessThan";
        CharacterCodes[CharacterCodes["minus"] = 45] = "minus";
        CharacterCodes[CharacterCodes["openBrace"] = 123] = "openBrace";
        CharacterCodes[CharacterCodes["openBracket"] = 91] = "openBracket";
        CharacterCodes[CharacterCodes["openParen"] = 40] = "openParen";
        CharacterCodes[CharacterCodes["percent"] = 37] = "percent";
        CharacterCodes[CharacterCodes["plus"] = 43] = "plus";
        CharacterCodes[CharacterCodes["question"] = 63] = "question";
        CharacterCodes[CharacterCodes["semicolon"] = 59] = "semicolon";
        CharacterCodes[CharacterCodes["singleQuote"] = 39] = "singleQuote";
        CharacterCodes[CharacterCodes["slash"] = 47] = "slash";
        CharacterCodes[CharacterCodes["tilde"] = 126] = "tilde";

        CharacterCodes[CharacterCodes["backspace"] = 8] = "backspace";
        CharacterCodes[CharacterCodes["formFeed"] = 12] = "formFeed";
        CharacterCodes[CharacterCodes["byteOrderMark"] = 0xFEFF] = "byteOrderMark";
        CharacterCodes[CharacterCodes["tab"] = 9] = "tab";
        CharacterCodes[CharacterCodes["verticalTab"] = 11] = "verticalTab";
    })(TypeScript.CharacterCodes || (TypeScript.CharacterCodes = {}));
    var CharacterCodes = TypeScript.CharacterCodes;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    

    (function (ScriptSnapshot) {
        var StringScriptSnapshot = (function () {
            function StringScriptSnapshot(text) {
                this.text = text;
                this._lineStartPositions = null;
            }
            StringScriptSnapshot.prototype.getText = function (start, end) {
                return this.text.substring(start, end);
            };

            StringScriptSnapshot.prototype.getLength = function () {
                return this.text.length;
            };

            StringScriptSnapshot.prototype.getLineStartPositions = function () {
                if (!this._lineStartPositions) {
                    this._lineStartPositions = TypeScript.TextUtilities.parseLineStarts(this.text);
                }

                return this._lineStartPositions;
            };

            StringScriptSnapshot.prototype.getTextChangeRangeSinceVersion = function (scriptVersion) {
                throw TypeScript.Errors.notYetImplemented();
            };
            return StringScriptSnapshot;
        })();

        function fromString(text) {
            return new StringScriptSnapshot(text);
        }
        ScriptSnapshot.fromString = fromString;
    })(TypeScript.ScriptSnapshot || (TypeScript.ScriptSnapshot = {}));
    var ScriptSnapshot = TypeScript.ScriptSnapshot;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (LineMap1) {
        function fromSimpleText(text) {
            return new TypeScript.LineMap(function () {
                return TypeScript.TextUtilities.parseLineStarts({ charCodeAt: function (index) {
                        return text.charCodeAt(index);
                    }, length: text.length() });
            }, text.length());
        }
        LineMap1.fromSimpleText = fromSimpleText;

        function fromScriptSnapshot(scriptSnapshot) {
            return new TypeScript.LineMap(function () {
                return scriptSnapshot.getLineStartPositions();
            }, scriptSnapshot.getLength());
        }
        LineMap1.fromScriptSnapshot = fromScriptSnapshot;

        function fromString(text) {
            return new TypeScript.LineMap(function () {
                return TypeScript.TextUtilities.parseLineStarts(text);
            }, text.length);
        }
        LineMap1.fromString = fromString;
    })(TypeScript.LineMap1 || (TypeScript.LineMap1 = {}));
    var LineMap1 = TypeScript.LineMap1;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (SimpleText) {
        var SimpleStringText = (function () {
            function SimpleStringText(value) {
                this.value = value;
                this._lineMap = null;
            }
            SimpleStringText.prototype.length = function () {
                return this.value.length;
            };

            SimpleStringText.prototype.substr = function (start, length) {
                return this.value.substr(start, length);
            };

            SimpleStringText.prototype.charCodeAt = function (index) {
                return this.value.charCodeAt(index);
            };

            SimpleStringText.prototype.lineMap = function () {
                if (!this._lineMap) {
                    this._lineMap = TypeScript.LineMap1.fromString(this.value);
                }

                return this._lineMap;
            };
            return SimpleStringText;
        })();

        // Class which wraps a host IScriptSnapshot and exposes an ISimpleText for newer compiler code.
        var SimpleScriptSnapshotText = (function () {
            function SimpleScriptSnapshotText(scriptSnapshot) {
                this.scriptSnapshot = scriptSnapshot;
                this._lineMap = null;
            }
            SimpleScriptSnapshotText.prototype.charCodeAt = function (index) {
                return this.scriptSnapshot.getText(index, index + 1).charCodeAt(0);
            };

            SimpleScriptSnapshotText.prototype.length = function () {
                return this.scriptSnapshot.getLength();
            };

            SimpleScriptSnapshotText.prototype.substr = function (start, length) {
                return this.scriptSnapshot.getText(start, start + length);
            };

            SimpleScriptSnapshotText.prototype.lineMap = function () {
                var _this = this;
                if (this._lineMap === null) {
                    this._lineMap = new TypeScript.LineMap(function () {
                        return _this.scriptSnapshot.getLineStartPositions();
                    }, this.length());
                }

                return this._lineMap;
            };
            return SimpleScriptSnapshotText;
        })();

        function fromString(value) {
            return new SimpleStringText(value);
        }
        SimpleText.fromString = fromString;

        function fromScriptSnapshot(scriptSnapshot) {
            return new SimpleScriptSnapshotText(scriptSnapshot);
        }
        SimpleText.fromScriptSnapshot = fromScriptSnapshot;
    })(TypeScript.SimpleText || (TypeScript.SimpleText = {}));
    var SimpleText = TypeScript.SimpleText;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (TextUtilities) {
        function parseLineStarts(text) {
            var length = text.length;

            // Corner case check
            if (0 === length) {
                var result = new Array();
                result.push(0);
                return result;
            }

            var position = 0;
            var index = 0;
            var arrayBuilder = new Array();
            var lineNumber = 0;

            while (index < length) {
                var c = text.charCodeAt(index);
                var lineBreakLength;

                // common case - ASCII & not a line break
                if (c > 13 /* carriageReturn */ && c <= 127) {
                    index++;
                    continue;
                } else if (c === 13 /* carriageReturn */ && index + 1 < length && text.charCodeAt(index + 1) === 10 /* lineFeed */) {
                    lineBreakLength = 2;
                } else if (c === 10 /* lineFeed */) {
                    lineBreakLength = 1;
                } else {
                    lineBreakLength = TextUtilities.getLengthOfLineBreak(text, index);
                }

                if (0 === lineBreakLength) {
                    index++;
                } else {
                    arrayBuilder.push(position);
                    index += lineBreakLength;
                    position = index;
                    lineNumber++;
                }
            }

            // Create a start for the final line.
            arrayBuilder.push(position);

            return arrayBuilder;
        }
        TextUtilities.parseLineStarts = parseLineStarts;

        function getLengthOfLineBreakSlow(text, index, c) {
            if (c === 13 /* carriageReturn */) {
                var next = index + 1;
                return (next < text.length) && 10 /* lineFeed */ === text.charCodeAt(next) ? 2 : 1;
            } else if (isAnyLineBreakCharacter(c)) {
                return 1;
            } else {
                return 0;
            }
        }
        TextUtilities.getLengthOfLineBreakSlow = getLengthOfLineBreakSlow;

        function getLengthOfLineBreak(text, index) {
            var c = text.charCodeAt(index);

            // common case - ASCII & not a line break
            if (c > 13 /* carriageReturn */ && c <= 127) {
                return 0;
            }

            return getLengthOfLineBreakSlow(text, index, c);
        }
        TextUtilities.getLengthOfLineBreak = getLengthOfLineBreak;

        function isAnyLineBreakCharacter(c) {
            return c === 10 /* lineFeed */ || c === 13 /* carriageReturn */ || c === 133 /* nextLine */ || c === 8232 /* lineSeparator */ || c === 8233 /* paragraphSeparator */;
        }
        TextUtilities.isAnyLineBreakCharacter = isAnyLineBreakCharacter;
    })(TypeScript.TextUtilities || (TypeScript.TextUtilities = {}));
    var TextUtilities = TypeScript.TextUtilities;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var TextSpan = (function () {
        /**
        * Creates a TextSpan instance beginning with the position Start and having the Length
        * specified with length.
        */
        function TextSpan(start, length) {
            if (start < 0) {
                TypeScript.Errors.argument("start");
            }

            if (length < 0) {
                TypeScript.Errors.argument("length");
            }

            this._start = start;
            this._length = length;
        }
        TextSpan.prototype.start = function () {
            return this._start;
        };

        TextSpan.prototype.length = function () {
            return this._length;
        };

        TextSpan.prototype.end = function () {
            return this._start + this._length;
        };

        TextSpan.prototype.isEmpty = function () {
            return this._length === 0;
        };

        /**
        * Determines whether the position lies within the span. Returns true if the position is greater than or equal to Start and strictly less
        * than End, otherwise false.
        * @param position The position to check.
        */
        TextSpan.prototype.containsPosition = function (position) {
            return position >= this._start && position < this.end();
        };

        /**
        * Determines whether span falls completely within this span. Returns true if the specified span falls completely within this span, otherwise false.
        * @param span The span to check.
        */
        TextSpan.prototype.containsTextSpan = function (span) {
            return span._start >= this._start && span.end() <= this.end();
        };

        /**
        * Determines whether the given span overlaps this span. Two spans are considered to overlap
        * if they have positions in common and neither is empty. Empty spans do not overlap with any
        * other span. Returns true if the spans overlap, false otherwise.
        * @param span The span to check.
        */
        TextSpan.prototype.overlapsWith = function (span) {
            var overlapStart = Math.max(this._start, span._start);
            var overlapEnd = Math.min(this.end(), span.end());

            return overlapStart < overlapEnd;
        };

        /**
        * Returns the overlap with the given span, or null if there is no overlap.
        * @param span The span to check.
        */
        TextSpan.prototype.overlap = function (span) {
            var overlapStart = Math.max(this._start, span._start);
            var overlapEnd = Math.min(this.end(), span.end());

            if (overlapStart < overlapEnd) {
                return TextSpan.fromBounds(overlapStart, overlapEnd);
            }

            return null;
        };

        /**
        * Determines whether span intersects this span. Two spans are considered to
        * intersect if they have positions in common or the end of one span
        * coincides with the start of the other span. Returns true if the spans intersect, false otherwise.
        * @param The span to check.
        */
        TextSpan.prototype.intersectsWithTextSpan = function (span) {
            return span._start <= this.end() && span.end() >= this._start;
        };

        TextSpan.prototype.intersectsWith = function (start, length) {
            var end = start + length;
            return start <= this.end() && end >= this._start;
        };

        /**
        * Determines whether the given position intersects this span.
        * A position is considered to intersect if it is between the start and
        * end positions (inclusive) of this span. Returns true if the position intersects, false otherwise.
        * @param position The position to check.
        */
        TextSpan.prototype.intersectsWithPosition = function (position) {
            return position <= this.end() && position >= this._start;
        };

        /**
        * Returns the intersection with the given span, or null if there is no intersection.
        * @param span The span to check.
        */
        TextSpan.prototype.intersection = function (span) {
            var intersectStart = Math.max(this._start, span._start);
            var intersectEnd = Math.min(this.end(), span.end());

            if (intersectStart <= intersectEnd) {
                return TextSpan.fromBounds(intersectStart, intersectEnd);
            }

            return null;
        };

        /**
        * Creates a new TextSpan from the given start and end positions
        * as opposed to a position and length.
        */
        TextSpan.fromBounds = function (start, end) {
            TypeScript.Debug.assert(start >= 0);
            TypeScript.Debug.assert(end - start >= 0);
            return new TextSpan(start, end - start);
        };
        return TextSpan;
    })();
    TypeScript.TextSpan = TextSpan;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var TextChangeRange = (function () {
        /**
        * Initializes a new instance of TextChangeRange.
        */
        function TextChangeRange(span, newLength) {
            if (newLength < 0) {
                throw TypeScript.Errors.argumentOutOfRange("newLength");
            }

            this._span = span;
            this._newLength = newLength;
        }
        /**
        * The span of text before the edit which is being changed
        */
        TextChangeRange.prototype.span = function () {
            return this._span;
        };

        /**
        * Width of the span after the edit.  A 0 here would represent a delete
        */
        TextChangeRange.prototype.newLength = function () {
            return this._newLength;
        };

        TextChangeRange.prototype.newSpan = function () {
            return new TypeScript.TextSpan(this.span().start(), this.newLength());
        };

        TextChangeRange.prototype.isUnchanged = function () {
            return this.span().isEmpty() && this.newLength() === 0;
        };

        /**
        * Called to merge all the changes that occurred across several versions of a script snapshot
        * into a single change.  i.e. if a user keeps making successive edits to a script we will
        * have a text change from V1 to V2, V2 to V3, ..., Vn.
        *
        * This function will then merge those changes into a single change range valid between V1 and
        * Vn.
        */
        TextChangeRange.collapseChangesAcrossMultipleVersions = function (changes) {
            if (changes.length === 0) {
                return TextChangeRange.unchanged;
            }

            if (changes.length === 1) {
                return changes[0];
            }

            // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd }
            // as it makes things much easier to reason about.
            var change0 = changes[0];

            var oldStartN = change0.span().start();
            var oldEndN = change0.span().end();
            var newEndN = oldStartN + change0.newLength();

            for (var i = 1; i < changes.length; i++) {
                var nextChange = changes[i];

                // Consider the following case:
                // i.e. two edits.  The first represents the text change range { { 10, 50 }, 30 }.  i.e. The span starting
                // at 10, with length 50 is reduced to length 30.  The second represents the text change range { { 30, 30 }, 40 }.
                // i.e. the span starting at 30 with length 30 is increased to length 40.
                //
                //      0         10        20        30        40        50        60        70        80        90        100
                //      -------------------------------------------------------------------------------------------------------
                //                |                                                 /
                //                |                                            /----
                //  T1            |                                       /----
                //                |                                  /----
                //                |                             /----
                //      -------------------------------------------------------------------------------------------------------
                //                                     |                            \
                //                                     |                               \
                //   T2                                |                                 \
                //                                     |                                   \
                //                                     |                                      \
                //      -------------------------------------------------------------------------------------------------------
                //
                // Merging these turns out to not be too difficult.  First, determining the new start of the change is trivial
                // it's just the min of the old and new starts.  i.e.:
                //
                //      0         10        20        30        40        50        60        70        80        90        100
                //      ------------------------------------------------------------*------------------------------------------
                //                |                                                 /
                //                |                                            /----
                //  T1            |                                       /----
                //                |                                  /----
                //                |                             /----
                //      ----------------------------------------$-------------------$------------------------------------------
                //                .                    |                            \
                //                .                    |                               \
                //   T2           .                    |                                 \
                //                .                    |                                   \
                //                .                    |                                      \
                //      ----------------------------------------------------------------------*--------------------------------
                //
                // (Note the dots represent the newly inferrred start.
                // Determining the new and old end is also pretty simple.  Basically it boils down to paying attention to the
                // absolute positions at the asterixes, and the relative change between the dollar signs. Basically, we see
                // which if the two $'s precedes the other, and we move that one forward until they line up.  in this case that
                // means:
                //
                //      0         10        20        30        40        50        60        70        80        90        100
                //      --------------------------------------------------------------------------------*----------------------
                //                |                                                                     /
                //                |                                                                /----
                //  T1            |                                                           /----
                //                |                                                      /----
                //                |                                                 /----
                //      ------------------------------------------------------------$------------------------------------------
                //                .                    |                            \
                //                .                    |                               \
                //   T2           .                    |                                 \
                //                .                    |                                   \
                //                .                    |                                      \
                //      ----------------------------------------------------------------------*--------------------------------
                //
                // In other words (in this case), we're recognizing that the second edit happened after where the first edit
                // ended with a delta of 20 characters (60 - 40).  Thus, if we go back in time to where the first edit started
                // that's the same as if we started at char 80 instead of 60.
                //
                // As it so happens, the same logic applies if the second edit precedes the first edit.  In that case rahter
                // than pusing the first edit forward to match the second, we'll push the second edit forward to match the
                // first.
                //
                // In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange
                // semantics: { { start: 10, length: 70 }, newLength: 60 }
                //
                // The math then works out as follows.
                // If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the
                // final result like so:
                //
                // {
                //      oldStart3: Min(oldStart1, oldStart2),
                //      oldEnd3  : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)),
                //      newEnd3  : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
                // }
                var oldStart1 = oldStartN;
                var oldEnd1 = oldEndN;
                var newEnd1 = newEndN;

                var oldStart2 = nextChange.span().start();
                var oldEnd2 = nextChange.span().end();
                var newEnd2 = oldStart2 + nextChange.newLength();

                oldStartN = Math.min(oldStart1, oldStart2);
                oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));
                newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2));
            }

            return new TextChangeRange(TypeScript.TextSpan.fromBounds(oldStartN, oldEndN), newEndN - oldStartN);
        };
        TextChangeRange.unchanged = new TextChangeRange(new TypeScript.TextSpan(0, 0), 0);
        return TextChangeRange;
    })();
    TypeScript.TextChangeRange = TextChangeRange;
})(TypeScript || (TypeScript = {}));
///<reference path='..\core\references.ts' />
///<reference path='characterCodes.ts' />
///<reference path='scriptSnapshot.ts' />
///<reference path='text.ts' />
///<reference path='lineMap.ts' />
///<reference path='textFactory.ts' />
///<reference path='textUtilities.ts' />
///<reference path='textSpan.ts' />
// TextChangeRange depends on TextSpan.
///<reference path='textChangeRange.ts' />
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (CharacterInfo) {
        function isDecimalDigit(c) {
            return c >= 48 /* _0 */ && c <= 57 /* _9 */;
        }
        CharacterInfo.isDecimalDigit = isDecimalDigit;

        function isOctalDigit(c) {
            return c >= 48 /* _0 */ && c <= 55 /* _7 */;
        }
        CharacterInfo.isOctalDigit = isOctalDigit;

        function isHexDigit(c) {
            return CharacterInfo.isDecimalDigit(c) || (c >= 65 /* A */ && c <= 70 /* F */) || (c >= 97 /* a */ && c <= 102 /* f */);
        }
        CharacterInfo.isHexDigit = isHexDigit;

        function hexValue(c) {
            // Debug.assert(isHexDigit(c));
            return CharacterInfo.isDecimalDigit(c) ? (c - 48 /* _0 */) : (c >= 65 /* A */ && c <= 70 /* F */) ? c - 65 /* A */ + 10 : c - 97 /* a */ + 10;
        }
        CharacterInfo.hexValue = hexValue;

        function isWhitespace(ch) {
            switch (ch) {
                case 32 /* space */:
                case 160 /* nonBreakingSpace */:
                case 8192 /* enQuad */:
                case 8193 /* emQuad */:
                case 8194 /* enSpace */:
                case 8195 /* emSpace */:
                case 8196 /* threePerEmSpace */:
                case 8197 /* fourPerEmSpace */:
                case 8198 /* sixPerEmSpace */:
                case 8199 /* figureSpace */:
                case 8200 /* punctuationSpace */:
                case 8201 /* thinSpace */:
                case 8202 /* hairSpace */:
                case 8203 /* zeroWidthSpace */:
                case 8239 /* narrowNoBreakSpace */:
                case 12288 /* ideographicSpace */:

                case 9 /* tab */:
                case 11 /* verticalTab */:
                case 12 /* formFeed */:
                case 65279 /* byteOrderMark */:
                    return true;
            }

            return false;
        }
        CharacterInfo.isWhitespace = isWhitespace;

        function isLineTerminator(ch) {
            switch (ch) {
                case 13 /* carriageReturn */:
                case 10 /* lineFeed */:
                case 8233 /* paragraphSeparator */:
                case 8232 /* lineSeparator */:
                    return true;
            }

            return false;
        }
        CharacterInfo.isLineTerminator = isLineTerminator;
    })(TypeScript.CharacterInfo || (TypeScript.CharacterInfo = {}));
    var CharacterInfo = TypeScript.CharacterInfo;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (SyntaxConstants) {
        SyntaxConstants[SyntaxConstants["None"] = 0] = "None";

        // Masks that we use to place information about a node into a single int.  The first bit tells
        // us if we've computed the data for a node.
        //
        // The second bit tells us if the node is incrementally reusable if it does not
        // containe any skipped tokens, zero width tokens, regex tokens in it ("/", "/=" or "/.../"),
        // and contains no tokens that were parser generated.
        //
        // The next bit lets us know if the nodes was parsed in a strict context or node.  A node can
        // only be used by the incremental parser if it is parsed in the same strict context as before.
        // last masks off the part of the int
        //
        // The width of the node is stored in the remainder of the int.  This allows us up to 512MB
        // for a node by using all 29 bits.  However, in the common case, we'll use less than 29 bits
        // for the width.  Thus, the info will be stored in a single int in chakra.
        SyntaxConstants[SyntaxConstants["NodeDataComputed"] = 0x00000001] = "NodeDataComputed";
        SyntaxConstants[SyntaxConstants["NodeIncrementallyUnusableMask"] = 0x00000002] = "NodeIncrementallyUnusableMask";
        SyntaxConstants[SyntaxConstants["NodeParsedInStrictModeMask"] = 0x00000004] = "NodeParsedInStrictModeMask";
        SyntaxConstants[SyntaxConstants["NodeFullWidthShift"] = 3] = "NodeFullWidthShift";
    })(TypeScript.SyntaxConstants || (TypeScript.SyntaxConstants = {}));
    var SyntaxConstants = TypeScript.SyntaxConstants;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var FormattingOptions = (function () {
        function FormattingOptions(useTabs, spacesPerTab, indentSpaces, newLineCharacter) {
            this.useTabs = useTabs;
            this.spacesPerTab = spacesPerTab;
            this.indentSpaces = indentSpaces;
            this.newLineCharacter = newLineCharacter;
        }
        FormattingOptions.defaultOptions = new FormattingOptions(false, 4, 4, "\r\n");
        return FormattingOptions;
    })();
    TypeScript.FormattingOptions = FormattingOptions;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (LanguageVersion) {
        LanguageVersion[LanguageVersion["EcmaScript3"] = 0] = "EcmaScript3";
        LanguageVersion[LanguageVersion["EcmaScript5"] = 1] = "EcmaScript5";
    })(TypeScript.LanguageVersion || (TypeScript.LanguageVersion = {}));
    var LanguageVersion = TypeScript.LanguageVersion;
})(TypeScript || (TypeScript = {}));
// If you change anything in this enum, make sure you run SyntaxGenerator again!
var TypeScript;
(function (TypeScript) {
    (function (SyntaxKind) {
        // Variable width tokens, trivia and lists.
        SyntaxKind[SyntaxKind["None"] = 0] = "None";
        SyntaxKind[SyntaxKind["List"] = 1] = "List";
        SyntaxKind[SyntaxKind["SeparatedList"] = 2] = "SeparatedList";
        SyntaxKind[SyntaxKind["TriviaList"] = 3] = "TriviaList";

        // Trivia
        SyntaxKind[SyntaxKind["WhitespaceTrivia"] = 4] = "WhitespaceTrivia";
        SyntaxKind[SyntaxKind["NewLineTrivia"] = 5] = "NewLineTrivia";
        SyntaxKind[SyntaxKind["MultiLineCommentTrivia"] = 6] = "MultiLineCommentTrivia";
        SyntaxKind[SyntaxKind["SingleLineCommentTrivia"] = 7] = "SingleLineCommentTrivia";
        SyntaxKind[SyntaxKind["SkippedTokenTrivia"] = 8] = "SkippedTokenTrivia";

        // Note: all variable width tokens must come before all fixed width tokens.
        SyntaxKind[SyntaxKind["ErrorToken"] = 9] = "ErrorToken";
        SyntaxKind[SyntaxKind["EndOfFileToken"] = 10] = "EndOfFileToken";

        // Tokens
        SyntaxKind[SyntaxKind["IdentifierName"] = 11] = "IdentifierName";

        // LiteralTokens
        SyntaxKind[SyntaxKind["RegularExpressionLiteral"] = 12] = "RegularExpressionLiteral";
        SyntaxKind[SyntaxKind["NumericLiteral"] = 13] = "NumericLiteral";
        SyntaxKind[SyntaxKind["StringLiteral"] = 14] = "StringLiteral";

        // All fixed width tokens follow.
        // Keywords
        SyntaxKind[SyntaxKind["BreakKeyword"] = 15] = "BreakKeyword";
        SyntaxKind[SyntaxKind["CaseKeyword"] = 16] = "CaseKeyword";
        SyntaxKind[SyntaxKind["CatchKeyword"] = 17] = "CatchKeyword";
        SyntaxKind[SyntaxKind["ContinueKeyword"] = 18] = "ContinueKeyword";
        SyntaxKind[SyntaxKind["DebuggerKeyword"] = 19] = "DebuggerKeyword";
        SyntaxKind[SyntaxKind["DefaultKeyword"] = 20] = "DefaultKeyword";
        SyntaxKind[SyntaxKind["DeleteKeyword"] = 21] = "DeleteKeyword";
        SyntaxKind[SyntaxKind["DoKeyword"] = 22] = "DoKeyword";
        SyntaxKind[SyntaxKind["ElseKeyword"] = 23] = "ElseKeyword";
        SyntaxKind[SyntaxKind["FalseKeyword"] = 24] = "FalseKeyword";
        SyntaxKind[SyntaxKind["FinallyKeyword"] = 25] = "FinallyKeyword";
        SyntaxKind[SyntaxKind["ForKeyword"] = 26] = "ForKeyword";
        SyntaxKind[SyntaxKind["FunctionKeyword"] = 27] = "FunctionKeyword";
        SyntaxKind[SyntaxKind["IfKeyword"] = 28] = "IfKeyword";
        SyntaxKind[SyntaxKind["InKeyword"] = 29] = "InKeyword";
        SyntaxKind[SyntaxKind["InstanceOfKeyword"] = 30] = "InstanceOfKeyword";
        SyntaxKind[SyntaxKind["NewKeyword"] = 31] = "NewKeyword";
        SyntaxKind[SyntaxKind["NullKeyword"] = 32] = "NullKeyword";
        SyntaxKind[SyntaxKind["ReturnKeyword"] = 33] = "ReturnKeyword";
        SyntaxKind[SyntaxKind["SwitchKeyword"] = 34] = "SwitchKeyword";
        SyntaxKind[SyntaxKind["ThisKeyword"] = 35] = "ThisKeyword";
        SyntaxKind[SyntaxKind["ThrowKeyword"] = 36] = "ThrowKeyword";
        SyntaxKind[SyntaxKind["TrueKeyword"] = 37] = "TrueKeyword";
        SyntaxKind[SyntaxKind["TryKeyword"] = 38] = "TryKeyword";
        SyntaxKind[SyntaxKind["TypeOfKeyword"] = 39] = "TypeOfKeyword";
        SyntaxKind[SyntaxKind["VarKeyword"] = 40] = "VarKeyword";
        SyntaxKind[SyntaxKind["VoidKeyword"] = 41] = "VoidKeyword";
        SyntaxKind[SyntaxKind["WhileKeyword"] = 42] = "WhileKeyword";
        SyntaxKind[SyntaxKind["WithKeyword"] = 43] = "WithKeyword";

        // FutureReservedWords.
        SyntaxKind[SyntaxKind["ClassKeyword"] = 44] = "ClassKeyword";
        SyntaxKind[SyntaxKind["ConstKeyword"] = 45] = "ConstKeyword";
        SyntaxKind[SyntaxKind["EnumKeyword"] = 46] = "EnumKeyword";
        SyntaxKind[SyntaxKind["ExportKeyword"] = 47] = "ExportKeyword";
        SyntaxKind[SyntaxKind["ExtendsKeyword"] = 48] = "ExtendsKeyword";
        SyntaxKind[SyntaxKind["ImportKeyword"] = 49] = "ImportKeyword";
        SyntaxKind[SyntaxKind["SuperKeyword"] = 50] = "SuperKeyword";

        // FutureReservedStrictWords.
        SyntaxKind[SyntaxKind["ImplementsKeyword"] = 51] = "ImplementsKeyword";
        SyntaxKind[SyntaxKind["InterfaceKeyword"] = 52] = "InterfaceKeyword";
        SyntaxKind[SyntaxKind["LetKeyword"] = 53] = "LetKeyword";
        SyntaxKind[SyntaxKind["PackageKeyword"] = 54] = "PackageKeyword";
        SyntaxKind[SyntaxKind["PrivateKeyword"] = 55] = "PrivateKeyword";
        SyntaxKind[SyntaxKind["ProtectedKeyword"] = 56] = "ProtectedKeyword";
        SyntaxKind[SyntaxKind["PublicKeyword"] = 57] = "PublicKeyword";
        SyntaxKind[SyntaxKind["StaticKeyword"] = 58] = "StaticKeyword";
        SyntaxKind[SyntaxKind["YieldKeyword"] = 59] = "YieldKeyword";

        // TypeScript keywords.
        SyntaxKind[SyntaxKind["AnyKeyword"] = 60] = "AnyKeyword";
        SyntaxKind[SyntaxKind["BooleanKeyword"] = 61] = "BooleanKeyword";
        SyntaxKind[SyntaxKind["ConstructorKeyword"] = 62] = "ConstructorKeyword";
        SyntaxKind[SyntaxKind["DeclareKeyword"] = 63] = "DeclareKeyword";
        SyntaxKind[SyntaxKind["GetKeyword"] = 64] = "GetKeyword";
        SyntaxKind[SyntaxKind["ModuleKeyword"] = 65] = "ModuleKeyword";
        SyntaxKind[SyntaxKind["RequireKeyword"] = 66] = "RequireKeyword";
        SyntaxKind[SyntaxKind["NumberKeyword"] = 67] = "NumberKeyword";
        SyntaxKind[SyntaxKind["SetKeyword"] = 68] = "SetKeyword";
        SyntaxKind[SyntaxKind["StringKeyword"] = 69] = "StringKeyword";

        // Punctuators
        SyntaxKind[SyntaxKind["OpenBraceToken"] = 70] = "OpenBraceToken";
        SyntaxKind[SyntaxKind["CloseBraceToken"] = 71] = "CloseBraceToken";
        SyntaxKind[SyntaxKind["OpenParenToken"] = 72] = "OpenParenToken";
        SyntaxKind[SyntaxKind["CloseParenToken"] = 73] = "CloseParenToken";
        SyntaxKind[SyntaxKind["OpenBracketToken"] = 74] = "OpenBracketToken";
        SyntaxKind[SyntaxKind["CloseBracketToken"] = 75] = "CloseBracketToken";
        SyntaxKind[SyntaxKind["DotToken"] = 76] = "DotToken";
        SyntaxKind[SyntaxKind["DotDotDotToken"] = 77] = "DotDotDotToken";
        SyntaxKind[SyntaxKind["SemicolonToken"] = 78] = "SemicolonToken";
        SyntaxKind[SyntaxKind["CommaToken"] = 79] = "CommaToken";
        SyntaxKind[SyntaxKind["LessThanToken"] = 80] = "LessThanToken";
        SyntaxKind[SyntaxKind["GreaterThanToken"] = 81] = "GreaterThanToken";
        SyntaxKind[SyntaxKind["LessThanEqualsToken"] = 82] = "LessThanEqualsToken";
        SyntaxKind[SyntaxKind["GreaterThanEqualsToken"] = 83] = "GreaterThanEqualsToken";
        SyntaxKind[SyntaxKind["EqualsEqualsToken"] = 84] = "EqualsEqualsToken";
        SyntaxKind[SyntaxKind["EqualsGreaterThanToken"] = 85] = "EqualsGreaterThanToken";
        SyntaxKind[SyntaxKind["ExclamationEqualsToken"] = 86] = "ExclamationEqualsToken";
        SyntaxKind[SyntaxKind["EqualsEqualsEqualsToken"] = 87] = "EqualsEqualsEqualsToken";
        SyntaxKind[SyntaxKind["ExclamationEqualsEqualsToken"] = 88] = "ExclamationEqualsEqualsToken";
        SyntaxKind[SyntaxKind["PlusToken"] = 89] = "PlusToken";
        SyntaxKind[SyntaxKind["MinusToken"] = 90] = "MinusToken";
        SyntaxKind[SyntaxKind["AsteriskToken"] = 91] = "AsteriskToken";
        SyntaxKind[SyntaxKind["PercentToken"] = 92] = "PercentToken";
        SyntaxKind[SyntaxKind["PlusPlusToken"] = 93] = "PlusPlusToken";
        SyntaxKind[SyntaxKind["MinusMinusToken"] = 94] = "MinusMinusToken";
        SyntaxKind[SyntaxKind["LessThanLessThanToken"] = 95] = "LessThanLessThanToken";
        SyntaxKind[SyntaxKind["GreaterThanGreaterThanToken"] = 96] = "GreaterThanGreaterThanToken";
        SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanToken"] = 97] = "GreaterThanGreaterThanGreaterThanToken";
        SyntaxKind[SyntaxKind["AmpersandToken"] = 98] = "AmpersandToken";
        SyntaxKind[SyntaxKind["BarToken"] = 99] = "BarToken";
        SyntaxKind[SyntaxKind["CaretToken"] = 100] = "CaretToken";
        SyntaxKind[SyntaxKind["ExclamationToken"] = 101] = "ExclamationToken";
        SyntaxKind[SyntaxKind["TildeToken"] = 102] = "TildeToken";
        SyntaxKind[SyntaxKind["AmpersandAmpersandToken"] = 103] = "AmpersandAmpersandToken";
        SyntaxKind[SyntaxKind["BarBarToken"] = 104] = "BarBarToken";
        SyntaxKind[SyntaxKind["QuestionToken"] = 105] = "QuestionToken";
        SyntaxKind[SyntaxKind["ColonToken"] = 106] = "ColonToken";
        SyntaxKind[SyntaxKind["EqualsToken"] = 107] = "EqualsToken";
        SyntaxKind[SyntaxKind["PlusEqualsToken"] = 108] = "PlusEqualsToken";
        SyntaxKind[SyntaxKind["MinusEqualsToken"] = 109] = "MinusEqualsToken";
        SyntaxKind[SyntaxKind["AsteriskEqualsToken"] = 110] = "AsteriskEqualsToken";
        SyntaxKind[SyntaxKind["PercentEqualsToken"] = 111] = "PercentEqualsToken";
        SyntaxKind[SyntaxKind["LessThanLessThanEqualsToken"] = 112] = "LessThanLessThanEqualsToken";
        SyntaxKind[SyntaxKind["GreaterThanGreaterThanEqualsToken"] = 113] = "GreaterThanGreaterThanEqualsToken";
        SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanEqualsToken"] = 114] = "GreaterThanGreaterThanGreaterThanEqualsToken";
        SyntaxKind[SyntaxKind["AmpersandEqualsToken"] = 115] = "AmpersandEqualsToken";
        SyntaxKind[SyntaxKind["BarEqualsToken"] = 116] = "BarEqualsToken";
        SyntaxKind[SyntaxKind["CaretEqualsToken"] = 117] = "CaretEqualsToken";
        SyntaxKind[SyntaxKind["SlashToken"] = 118] = "SlashToken";
        SyntaxKind[SyntaxKind["SlashEqualsToken"] = 119] = "SlashEqualsToken";

        // SyntaxNodes
        SyntaxKind[SyntaxKind["SourceUnit"] = 120] = "SourceUnit";

        // Names
        SyntaxKind[SyntaxKind["QualifiedName"] = 121] = "QualifiedName";

        // Types
        SyntaxKind[SyntaxKind["ObjectType"] = 122] = "ObjectType";
        SyntaxKind[SyntaxKind["FunctionType"] = 123] = "FunctionType";
        SyntaxKind[SyntaxKind["ArrayType"] = 124] = "ArrayType";
        SyntaxKind[SyntaxKind["ConstructorType"] = 125] = "ConstructorType";
        SyntaxKind[SyntaxKind["GenericType"] = 126] = "GenericType";
        SyntaxKind[SyntaxKind["TypeQuery"] = 127] = "TypeQuery";

        // Module elements.
        SyntaxKind[SyntaxKind["InterfaceDeclaration"] = 128] = "InterfaceDeclaration";
        SyntaxKind[SyntaxKind["FunctionDeclaration"] = 129] = "FunctionDeclaration";
        SyntaxKind[SyntaxKind["ModuleDeclaration"] = 130] = "ModuleDeclaration";
        SyntaxKind[SyntaxKind["ClassDeclaration"] = 131] = "ClassDeclaration";
        SyntaxKind[SyntaxKind["EnumDeclaration"] = 132] = "EnumDeclaration";
        SyntaxKind[SyntaxKind["ImportDeclaration"] = 133] = "ImportDeclaration";
        SyntaxKind[SyntaxKind["ExportAssignment"] = 134] = "ExportAssignment";

        // ClassElements
        SyntaxKind[SyntaxKind["MemberFunctionDeclaration"] = 135] = "MemberFunctionDeclaration";
        SyntaxKind[SyntaxKind["MemberVariableDeclaration"] = 136] = "MemberVariableDeclaration";
        SyntaxKind[SyntaxKind["ConstructorDeclaration"] = 137] = "ConstructorDeclaration";
        SyntaxKind[SyntaxKind["IndexMemberDeclaration"] = 138] = "IndexMemberDeclaration";

        // ClassElement and PropertyAssignment
        SyntaxKind[SyntaxKind["GetAccessor"] = 139] = "GetAccessor";
        SyntaxKind[SyntaxKind["SetAccessor"] = 140] = "SetAccessor";

        // Type members.
        SyntaxKind[SyntaxKind["PropertySignature"] = 141] = "PropertySignature";
        SyntaxKind[SyntaxKind["CallSignature"] = 142] = "CallSignature";
        SyntaxKind[SyntaxKind["ConstructSignature"] = 143] = "ConstructSignature";
        SyntaxKind[SyntaxKind["IndexSignature"] = 144] = "IndexSignature";
        SyntaxKind[SyntaxKind["MethodSignature"] = 145] = "MethodSignature";

        // Statements
        SyntaxKind[SyntaxKind["Block"] = 146] = "Block";
        SyntaxKind[SyntaxKind["IfStatement"] = 147] = "IfStatement";
        SyntaxKind[SyntaxKind["VariableStatement"] = 148] = "VariableStatement";
        SyntaxKind[SyntaxKind["ExpressionStatement"] = 149] = "ExpressionStatement";
        SyntaxKind[SyntaxKind["ReturnStatement"] = 150] = "ReturnStatement";
        SyntaxKind[SyntaxKind["SwitchStatement"] = 151] = "SwitchStatement";
        SyntaxKind[SyntaxKind["BreakStatement"] = 152] = "BreakStatement";
        SyntaxKind[SyntaxKind["ContinueStatement"] = 153] = "ContinueStatement";
        SyntaxKind[SyntaxKind["ForStatement"] = 154] = "ForStatement";
        SyntaxKind[SyntaxKind["ForInStatement"] = 155] = "ForInStatement";
        SyntaxKind[SyntaxKind["EmptyStatement"] = 156] = "EmptyStatement";
        SyntaxKind[SyntaxKind["ThrowStatement"] = 157] = "ThrowStatement";
        SyntaxKind[SyntaxKind["WhileStatement"] = 158] = "WhileStatement";
        SyntaxKind[SyntaxKind["TryStatement"] = 159] = "TryStatement";
        SyntaxKind[SyntaxKind["LabeledStatement"] = 160] = "LabeledStatement";
        SyntaxKind[SyntaxKind["DoStatement"] = 161] = "DoStatement";
        SyntaxKind[SyntaxKind["DebuggerStatement"] = 162] = "DebuggerStatement";
        SyntaxKind[SyntaxKind["WithStatement"] = 163] = "WithStatement";

        // Expressions
        SyntaxKind[SyntaxKind["PlusExpression"] = 164] = "PlusExpression";
        SyntaxKind[SyntaxKind["NegateExpression"] = 165] = "NegateExpression";
        SyntaxKind[SyntaxKind["BitwiseNotExpression"] = 166] = "BitwiseNotExpression";
        SyntaxKind[SyntaxKind["LogicalNotExpression"] = 167] = "LogicalNotExpression";
        SyntaxKind[SyntaxKind["PreIncrementExpression"] = 168] = "PreIncrementExpression";
        SyntaxKind[SyntaxKind["PreDecrementExpression"] = 169] = "PreDecrementExpression";
        SyntaxKind[SyntaxKind["DeleteExpression"] = 170] = "DeleteExpression";
        SyntaxKind[SyntaxKind["TypeOfExpression"] = 171] = "TypeOfExpression";
        SyntaxKind[SyntaxKind["VoidExpression"] = 172] = "VoidExpression";
        SyntaxKind[SyntaxKind["CommaExpression"] = 173] = "CommaExpression";
        SyntaxKind[SyntaxKind["AssignmentExpression"] = 174] = "AssignmentExpression";
        SyntaxKind[SyntaxKind["AddAssignmentExpression"] = 175] = "AddAssignmentExpression";
        SyntaxKind[SyntaxKind["SubtractAssignmentExpression"] = 176] = "SubtractAssignmentExpression";
        SyntaxKind[SyntaxKind["MultiplyAssignmentExpression"] = 177] = "MultiplyAssignmentExpression";
        SyntaxKind[SyntaxKind["DivideAssignmentExpression"] = 178] = "DivideAssignmentExpression";
        SyntaxKind[SyntaxKind["ModuloAssignmentExpression"] = 179] = "ModuloAssignmentExpression";
        SyntaxKind[SyntaxKind["AndAssignmentExpression"] = 180] = "AndAssignmentExpression";
        SyntaxKind[SyntaxKind["ExclusiveOrAssignmentExpression"] = 181] = "ExclusiveOrAssignmentExpression";
        SyntaxKind[SyntaxKind["OrAssignmentExpression"] = 182] = "OrAssignmentExpression";
        SyntaxKind[SyntaxKind["LeftShiftAssignmentExpression"] = 183] = "LeftShiftAssignmentExpression";
        SyntaxKind[SyntaxKind["SignedRightShiftAssignmentExpression"] = 184] = "SignedRightShiftAssignmentExpression";
        SyntaxKind[SyntaxKind["UnsignedRightShiftAssignmentExpression"] = 185] = "UnsignedRightShiftAssignmentExpression";
        SyntaxKind[SyntaxKind["ConditionalExpression"] = 186] = "ConditionalExpression";
        SyntaxKind[SyntaxKind["LogicalOrExpression"] = 187] = "LogicalOrExpression";
        SyntaxKind[SyntaxKind["LogicalAndExpression"] = 188] = "LogicalAndExpression";
        SyntaxKind[SyntaxKind["BitwiseOrExpression"] = 189] = "BitwiseOrExpression";
        SyntaxKind[SyntaxKind["BitwiseExclusiveOrExpression"] = 190] = "BitwiseExclusiveOrExpression";
        SyntaxKind[SyntaxKind["BitwiseAndExpression"] = 191] = "BitwiseAndExpression";
        SyntaxKind[SyntaxKind["EqualsWithTypeConversionExpression"] = 192] = "EqualsWithTypeConversionExpression";
        SyntaxKind[SyntaxKind["NotEqualsWithTypeConversionExpression"] = 193] = "NotEqualsWithTypeConversionExpression";
        SyntaxKind[SyntaxKind["EqualsExpression"] = 194] = "EqualsExpression";
        SyntaxKind[SyntaxKind["NotEqualsExpression"] = 195] = "NotEqualsExpression";
        SyntaxKind[SyntaxKind["LessThanExpression"] = 196] = "LessThanExpression";
        SyntaxKind[SyntaxKind["GreaterThanExpression"] = 197] = "GreaterThanExpression";
        SyntaxKind[SyntaxKind["LessThanOrEqualExpression"] = 198] = "LessThanOrEqualExpression";
        SyntaxKind[SyntaxKind["GreaterThanOrEqualExpression"] = 199] = "GreaterThanOrEqualExpression";
        SyntaxKind[SyntaxKind["InstanceOfExpression"] = 200] = "InstanceOfExpression";
        SyntaxKind[SyntaxKind["InExpression"] = 201] = "InExpression";
        SyntaxKind[SyntaxKind["LeftShiftExpression"] = 202] = "LeftShiftExpression";
        SyntaxKind[SyntaxKind["SignedRightShiftExpression"] = 203] = "SignedRightShiftExpression";
        SyntaxKind[SyntaxKind["UnsignedRightShiftExpression"] = 204] = "UnsignedRightShiftExpression";
        SyntaxKind[SyntaxKind["MultiplyExpression"] = 205] = "MultiplyExpression";
        SyntaxKind[SyntaxKind["DivideExpression"] = 206] = "DivideExpression";
        SyntaxKind[SyntaxKind["ModuloExpression"] = 207] = "ModuloExpression";
        SyntaxKind[SyntaxKind["AddExpression"] = 208] = "AddExpression";
        SyntaxKind[SyntaxKind["SubtractExpression"] = 209] = "SubtractExpression";
        SyntaxKind[SyntaxKind["PostIncrementExpression"] = 210] = "PostIncrementExpression";
        SyntaxKind[SyntaxKind["PostDecrementExpression"] = 211] = "PostDecrementExpression";
        SyntaxKind[SyntaxKind["MemberAccessExpression"] = 212] = "MemberAccessExpression";
        SyntaxKind[SyntaxKind["InvocationExpression"] = 213] = "InvocationExpression";
        SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 214] = "ArrayLiteralExpression";
        SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 215] = "ObjectLiteralExpression";
        SyntaxKind[SyntaxKind["ObjectCreationExpression"] = 216] = "ObjectCreationExpression";
        SyntaxKind[SyntaxKind["ParenthesizedExpression"] = 217] = "ParenthesizedExpression";
        SyntaxKind[SyntaxKind["ParenthesizedArrowFunctionExpression"] = 218] = "ParenthesizedArrowFunctionExpression";
        SyntaxKind[SyntaxKind["SimpleArrowFunctionExpression"] = 219] = "SimpleArrowFunctionExpression";
        SyntaxKind[SyntaxKind["CastExpression"] = 220] = "CastExpression";
        SyntaxKind[SyntaxKind["ElementAccessExpression"] = 221] = "ElementAccessExpression";
        SyntaxKind[SyntaxKind["FunctionExpression"] = 222] = "FunctionExpression";
        SyntaxKind[SyntaxKind["OmittedExpression"] = 223] = "OmittedExpression";

        // Variable declarations
        SyntaxKind[SyntaxKind["VariableDeclaration"] = 224] = "VariableDeclaration";
        SyntaxKind[SyntaxKind["VariableDeclarator"] = 225] = "VariableDeclarator";

        // Lists
        SyntaxKind[SyntaxKind["ArgumentList"] = 226] = "ArgumentList";
        SyntaxKind[SyntaxKind["ParameterList"] = 227] = "ParameterList";
        SyntaxKind[SyntaxKind["TypeArgumentList"] = 228] = "TypeArgumentList";
        SyntaxKind[SyntaxKind["TypeParameterList"] = 229] = "TypeParameterList";

        // Clauses
        SyntaxKind[SyntaxKind["ExtendsHeritageClause"] = 230] = "ExtendsHeritageClause";
        SyntaxKind[SyntaxKind["ImplementsHeritageClause"] = 231] = "ImplementsHeritageClause";
        SyntaxKind[SyntaxKind["EqualsValueClause"] = 232] = "EqualsValueClause";
        SyntaxKind[SyntaxKind["CaseSwitchClause"] = 233] = "CaseSwitchClause";
        SyntaxKind[SyntaxKind["DefaultSwitchClause"] = 234] = "DefaultSwitchClause";
        SyntaxKind[SyntaxKind["ElseClause"] = 235] = "ElseClause";
        SyntaxKind[SyntaxKind["CatchClause"] = 236] = "CatchClause";
        SyntaxKind[SyntaxKind["FinallyClause"] = 237] = "FinallyClause";

        // Generics
        SyntaxKind[SyntaxKind["TypeParameter"] = 238] = "TypeParameter";
        SyntaxKind[SyntaxKind["Constraint"] = 239] = "Constraint";

        // Property Assignment
        SyntaxKind[SyntaxKind["SimplePropertyAssignment"] = 240] = "SimplePropertyAssignment";

        // GetAccessorPropertyAssignment,
        // SetAccessorPropertyAssignment,
        SyntaxKind[SyntaxKind["FunctionPropertyAssignment"] = 241] = "FunctionPropertyAssignment";

        // Misc.
        SyntaxKind[SyntaxKind["Parameter"] = 242] = "Parameter";
        SyntaxKind[SyntaxKind["EnumElement"] = 243] = "EnumElement";
        SyntaxKind[SyntaxKind["TypeAnnotation"] = 244] = "TypeAnnotation";
        SyntaxKind[SyntaxKind["ExternalModuleReference"] = 245] = "ExternalModuleReference";
        SyntaxKind[SyntaxKind["ModuleNameModuleReference"] = 246] = "ModuleNameModuleReference";

        SyntaxKind[SyntaxKind["FirstStandardKeyword"] = SyntaxKind.BreakKeyword] = "FirstStandardKeyword";
        SyntaxKind[SyntaxKind["LastStandardKeyword"] = SyntaxKind.WithKeyword] = "LastStandardKeyword";

        SyntaxKind[SyntaxKind["FirstFutureReservedKeyword"] = SyntaxKind.ClassKeyword] = "FirstFutureReservedKeyword";
        SyntaxKind[SyntaxKind["LastFutureReservedKeyword"] = SyntaxKind.SuperKeyword] = "LastFutureReservedKeyword";

        SyntaxKind[SyntaxKind["FirstFutureReservedStrictKeyword"] = SyntaxKind.ImplementsKeyword] = "FirstFutureReservedStrictKeyword";
        SyntaxKind[SyntaxKind["LastFutureReservedStrictKeyword"] = SyntaxKind.YieldKeyword] = "LastFutureReservedStrictKeyword";

        SyntaxKind[SyntaxKind["FirstTypeScriptKeyword"] = SyntaxKind.AnyKeyword] = "FirstTypeScriptKeyword";
        SyntaxKind[SyntaxKind["LastTypeScriptKeyword"] = SyntaxKind.StringKeyword] = "LastTypeScriptKeyword";

        SyntaxKind[SyntaxKind["FirstKeyword"] = SyntaxKind.FirstStandardKeyword] = "FirstKeyword";
        SyntaxKind[SyntaxKind["LastKeyword"] = SyntaxKind.LastTypeScriptKeyword] = "LastKeyword";

        SyntaxKind[SyntaxKind["FirstToken"] = SyntaxKind.ErrorToken] = "FirstToken";
        SyntaxKind[SyntaxKind["LastToken"] = SyntaxKind.SlashEqualsToken] = "LastToken";

        SyntaxKind[SyntaxKind["FirstPunctuation"] = SyntaxKind.OpenBraceToken] = "FirstPunctuation";
        SyntaxKind[SyntaxKind["LastPunctuation"] = SyntaxKind.SlashEqualsToken] = "LastPunctuation";

        SyntaxKind[SyntaxKind["FirstFixedWidth"] = SyntaxKind.FirstKeyword] = "FirstFixedWidth";
        SyntaxKind[SyntaxKind["LastFixedWidth"] = SyntaxKind.LastPunctuation] = "LastFixedWidth";

        SyntaxKind[SyntaxKind["FirstTrivia"] = SyntaxKind.WhitespaceTrivia] = "FirstTrivia";
        SyntaxKind[SyntaxKind["LastTrivia"] = SyntaxKind.SkippedTokenTrivia] = "LastTrivia";

        SyntaxKind[SyntaxKind["FirstNode"] = SyntaxKind.SourceUnit] = "FirstNode";
        SyntaxKind[SyntaxKind["LastNode"] = SyntaxKind.ModuleNameModuleReference] = "LastNode";
    })(TypeScript.SyntaxKind || (TypeScript.SyntaxKind = {}));
    var SyntaxKind = TypeScript.SyntaxKind;
})(TypeScript || (TypeScript = {}));
///<reference path='syntaxKind.ts' />
var TypeScript;
(function (TypeScript) {
    (function (SyntaxFacts) {
        var textToKeywordKind = {
            "any": 60 /* AnyKeyword */,
            "boolean": 61 /* BooleanKeyword */,
            "break": 15 /* BreakKeyword */,
            "case": 16 /* CaseKeyword */,
            "catch": 17 /* CatchKeyword */,
            "class": 44 /* ClassKeyword */,
            "continue": 18 /* ContinueKeyword */,
            "const": 45 /* ConstKeyword */,
            "constructor": 62 /* ConstructorKeyword */,
            "debugger": 19 /* DebuggerKeyword */,
            "declare": 63 /* DeclareKeyword */,
            "default": 20 /* DefaultKeyword */,
            "delete": 21 /* DeleteKeyword */,
            "do": 22 /* DoKeyword */,
            "else": 23 /* ElseKeyword */,
            "enum": 46 /* EnumKeyword */,
            "export": 47 /* ExportKeyword */,
            "extends": 48 /* ExtendsKeyword */,
            "false": 24 /* FalseKeyword */,
            "finally": 25 /* FinallyKeyword */,
            "for": 26 /* ForKeyword */,
            "function": 27 /* FunctionKeyword */,
            "get": 64 /* GetKeyword */,
            "if": 28 /* IfKeyword */,
            "implements": 51 /* ImplementsKeyword */,
            "import": 49 /* ImportKeyword */,
            "in": 29 /* InKeyword */,
            "instanceof": 30 /* InstanceOfKeyword */,
            "interface": 52 /* InterfaceKeyword */,
            "let": 53 /* LetKeyword */,
            "module": 65 /* ModuleKeyword */,
            "new": 31 /* NewKeyword */,
            "null": 32 /* NullKeyword */,
            "number": 67 /* NumberKeyword */,
            "package": 54 /* PackageKeyword */,
            "private": 55 /* PrivateKeyword */,
            "protected": 56 /* ProtectedKeyword */,
            "public": 57 /* PublicKeyword */,
            "require": 66 /* RequireKeyword */,
            "return": 33 /* ReturnKeyword */,
            "set": 68 /* SetKeyword */,
            "static": 58 /* StaticKeyword */,
            "string": 69 /* StringKeyword */,
            "super": 50 /* SuperKeyword */,
            "switch": 34 /* SwitchKeyword */,
            "this": 35 /* ThisKeyword */,
            "throw": 36 /* ThrowKeyword */,
            "true": 37 /* TrueKeyword */,
            "try": 38 /* TryKeyword */,
            "typeof": 39 /* TypeOfKeyword */,
            "var": 40 /* VarKeyword */,
            "void": 41 /* VoidKeyword */,
            "while": 42 /* WhileKeyword */,
            "with": 43 /* WithKeyword */,
            "yield": 59 /* YieldKeyword */,
            "{": 70 /* OpenBraceToken */,
            "}": 71 /* CloseBraceToken */,
            "(": 72 /* OpenParenToken */,
            ")": 73 /* CloseParenToken */,
            "[": 74 /* OpenBracketToken */,
            "]": 75 /* CloseBracketToken */,
            ".": 76 /* DotToken */,
            "...": 77 /* DotDotDotToken */,
            ";": 78 /* SemicolonToken */,
            ",": 79 /* CommaToken */,
            "<": 80 /* LessThanToken */,
            ">": 81 /* GreaterThanToken */,
            "<=": 82 /* LessThanEqualsToken */,
            ">=": 83 /* GreaterThanEqualsToken */,
            "==": 84 /* EqualsEqualsToken */,
            "=>": 85 /* EqualsGreaterThanToken */,
            "!=": 86 /* ExclamationEqualsToken */,
            "===": 87 /* EqualsEqualsEqualsToken */,
            "!==": 88 /* ExclamationEqualsEqualsToken */,
            "+": 89 /* PlusToken */,
            "-": 90 /* MinusToken */,
            "*": 91 /* AsteriskToken */,
            "%": 92 /* PercentToken */,
            "++": 93 /* PlusPlusToken */,
            "--": 94 /* MinusMinusToken */,
            "<<": 95 /* LessThanLessThanToken */,
            ">>": 96 /* GreaterThanGreaterThanToken */,
            ">>>": 97 /* GreaterThanGreaterThanGreaterThanToken */,
            "&": 98 /* AmpersandToken */,
            "|": 99 /* BarToken */,
            "^": 100 /* CaretToken */,
            "!": 101 /* ExclamationToken */,
            "~": 102 /* TildeToken */,
            "&&": 103 /* AmpersandAmpersandToken */,
            "||": 104 /* BarBarToken */,
            "?": 105 /* QuestionToken */,
            ":": 106 /* ColonToken */,
            "=": 107 /* EqualsToken */,
            "+=": 108 /* PlusEqualsToken */,
            "-=": 109 /* MinusEqualsToken */,
            "*=": 110 /* AsteriskEqualsToken */,
            "%=": 111 /* PercentEqualsToken */,
            "<<=": 112 /* LessThanLessThanEqualsToken */,
            ">>=": 113 /* GreaterThanGreaterThanEqualsToken */,
            ">>>=": 114 /* GreaterThanGreaterThanGreaterThanEqualsToken */,
            "&=": 115 /* AmpersandEqualsToken */,
            "|=": 116 /* BarEqualsToken */,
            "^=": 117 /* CaretEqualsToken */,
            "/": 118 /* SlashToken */,
            "/=": 119 /* SlashEqualsToken */
        };

        var kindToText = new Array();

        for (var name in textToKeywordKind) {
            if (textToKeywordKind.hasOwnProperty(name)) {
                // Debug.assert(kindToText[textToKeywordKind[name]] === undefined);
                kindToText[textToKeywordKind[name]] = name;
            }
        }

        // Manually work around a bug in the CScript 5.8 runtime where 'constructor' is not
        // listed when SyntaxFacts.textToKeywordKind is enumerated because it is the name of
        // the constructor function.
        kindToText[62 /* ConstructorKeyword */] = "constructor";

        function getTokenKind(text) {
            if (textToKeywordKind.hasOwnProperty(text)) {
                return textToKeywordKind[text];
            }

            return 0 /* None */;
        }
        SyntaxFacts.getTokenKind = getTokenKind;

        function getText(kind) {
            var result = kindToText[kind];
            return result !== undefined ? result : null;
        }
        SyntaxFacts.getText = getText;

        function isAnyKeyword(kind) {
            return kind >= TypeScript.SyntaxKind.FirstKeyword && kind <= TypeScript.SyntaxKind.LastKeyword;
        }
        SyntaxFacts.isAnyKeyword = isAnyKeyword;

        function isAnyPunctuation(kind) {
            return kind >= TypeScript.SyntaxKind.FirstPunctuation && kind <= TypeScript.SyntaxKind.LastPunctuation;
        }
        SyntaxFacts.isAnyPunctuation = isAnyPunctuation;

        function isPrefixUnaryExpressionOperatorToken(tokenKind) {
            return getPrefixUnaryExpressionFromOperatorToken(tokenKind) !== 0 /* None */;
        }
        SyntaxFacts.isPrefixUnaryExpressionOperatorToken = isPrefixUnaryExpressionOperatorToken;

        function isBinaryExpressionOperatorToken(tokenKind) {
            return getBinaryExpressionFromOperatorToken(tokenKind) !== 0 /* None */;
        }
        SyntaxFacts.isBinaryExpressionOperatorToken = isBinaryExpressionOperatorToken;

        function getPrefixUnaryExpressionFromOperatorToken(tokenKind) {
            switch (tokenKind) {
                case 89 /* PlusToken */: return 164 /* PlusExpression */;
                case 90 /* MinusToken */: return 165 /* NegateExpression */;
                case 102 /* TildeToken */: return 166 /* BitwiseNotExpression */;
                case 101 /* ExclamationToken */: return 167 /* LogicalNotExpression */;
                case 93 /* PlusPlusToken */: return 168 /* PreIncrementExpression */;
                case 94 /* MinusMinusToken */: return 169 /* PreDecrementExpression */;
                default: return 0 /* None */;
            }
        }
        SyntaxFacts.getPrefixUnaryExpressionFromOperatorToken = getPrefixUnaryExpressionFromOperatorToken;

        function getPostfixUnaryExpressionFromOperatorToken(tokenKind) {
            switch (tokenKind) {
                case 93 /* PlusPlusToken */: return 210 /* PostIncrementExpression */;
                case 94 /* MinusMinusToken */: return 211 /* PostDecrementExpression */;
                default: return 0 /* None */;
            }
        }
        SyntaxFacts.getPostfixUnaryExpressionFromOperatorToken = getPostfixUnaryExpressionFromOperatorToken;

        function getBinaryExpressionFromOperatorToken(tokenKind) {
            switch (tokenKind) {
                case 91 /* AsteriskToken */: return 205 /* MultiplyExpression */;
                case 118 /* SlashToken */: return 206 /* DivideExpression */;
                case 92 /* PercentToken */: return 207 /* ModuloExpression */;
                case 89 /* PlusToken */: return 208 /* AddExpression */;
                case 90 /* MinusToken */: return 209 /* SubtractExpression */;
                case 95 /* LessThanLessThanToken */: return 202 /* LeftShiftExpression */;
                case 96 /* GreaterThanGreaterThanToken */: return 203 /* SignedRightShiftExpression */;
                case 97 /* GreaterThanGreaterThanGreaterThanToken */: return 204 /* UnsignedRightShiftExpression */;
                case 80 /* LessThanToken */: return 196 /* LessThanExpression */;
                case 81 /* GreaterThanToken */: return 197 /* GreaterThanExpression */;
                case 82 /* LessThanEqualsToken */: return 198 /* LessThanOrEqualExpression */;
                case 83 /* GreaterThanEqualsToken */: return 199 /* GreaterThanOrEqualExpression */;
                case 30 /* InstanceOfKeyword */: return 200 /* InstanceOfExpression */;
                case 29 /* InKeyword */: return 201 /* InExpression */;
                case 84 /* EqualsEqualsToken */: return 192 /* EqualsWithTypeConversionExpression */;
                case 86 /* ExclamationEqualsToken */: return 193 /* NotEqualsWithTypeConversionExpression */;
                case 87 /* EqualsEqualsEqualsToken */: return 194 /* EqualsExpression */;
                case 88 /* ExclamationEqualsEqualsToken */: return 195 /* NotEqualsExpression */;
                case 98 /* AmpersandToken */: return 191 /* BitwiseAndExpression */;
                case 100 /* CaretToken */: return 190 /* BitwiseExclusiveOrExpression */;
                case 99 /* BarToken */: return 189 /* BitwiseOrExpression */;
                case 103 /* AmpersandAmpersandToken */: return 188 /* LogicalAndExpression */;
                case 104 /* BarBarToken */: return 187 /* LogicalOrExpression */;
                case 116 /* BarEqualsToken */: return 182 /* OrAssignmentExpression */;
                case 115 /* AmpersandEqualsToken */: return 180 /* AndAssignmentExpression */;
                case 117 /* CaretEqualsToken */: return 181 /* ExclusiveOrAssignmentExpression */;
                case 112 /* LessThanLessThanEqualsToken */: return 183 /* LeftShiftAssignmentExpression */;
                case 113 /* GreaterThanGreaterThanEqualsToken */: return 184 /* SignedRightShiftAssignmentExpression */;
                case 114 /* GreaterThanGreaterThanGreaterThanEqualsToken */: return 185 /* UnsignedRightShiftAssignmentExpression */;
                case 108 /* PlusEqualsToken */: return 175 /* AddAssignmentExpression */;
                case 109 /* MinusEqualsToken */: return 176 /* SubtractAssignmentExpression */;
                case 110 /* AsteriskEqualsToken */: return 177 /* MultiplyAssignmentExpression */;
                case 119 /* SlashEqualsToken */: return 178 /* DivideAssignmentExpression */;
                case 111 /* PercentEqualsToken */: return 179 /* ModuloAssignmentExpression */;
                case 107 /* EqualsToken */: return 174 /* AssignmentExpression */;
                case 79 /* CommaToken */: return 173 /* CommaExpression */;
                default: return 0 /* None */;
            }
        }
        SyntaxFacts.getBinaryExpressionFromOperatorToken = getBinaryExpressionFromOperatorToken;

        function getOperatorTokenFromBinaryExpression(tokenKind) {
            switch (tokenKind) {
                case 205 /* MultiplyExpression */: return 91 /* AsteriskToken */;
                case 206 /* DivideExpression */: return 118 /* SlashToken */;
                case 207 /* ModuloExpression */: return 92 /* PercentToken */;
                case 208 /* AddExpression */: return 89 /* PlusToken */;
                case 209 /* SubtractExpression */: return 90 /* MinusToken */;
                case 202 /* LeftShiftExpression */: return 95 /* LessThanLessThanToken */;
                case 203 /* SignedRightShiftExpression */: return 96 /* GreaterThanGreaterThanToken */;
                case 204 /* UnsignedRightShiftExpression */: return 97 /* GreaterThanGreaterThanGreaterThanToken */;
                case 196 /* LessThanExpression */: return 80 /* LessThanToken */;
                case 197 /* GreaterThanExpression */: return 81 /* GreaterThanToken */;
                case 198 /* LessThanOrEqualExpression */: return 82 /* LessThanEqualsToken */;
                case 199 /* GreaterThanOrEqualExpression */: return 83 /* GreaterThanEqualsToken */;
                case 200 /* InstanceOfExpression */: return 30 /* InstanceOfKeyword */;
                case 201 /* InExpression */: return 29 /* InKeyword */;
                case 192 /* EqualsWithTypeConversionExpression */: return 84 /* EqualsEqualsToken */;
                case 193 /* NotEqualsWithTypeConversionExpression */: return 86 /* ExclamationEqualsToken */;
                case 194 /* EqualsExpression */: return 87 /* EqualsEqualsEqualsToken */;
                case 195 /* NotEqualsExpression */: return 88 /* ExclamationEqualsEqualsToken */;
                case 191 /* BitwiseAndExpression */: return 98 /* AmpersandToken */;
                case 190 /* BitwiseExclusiveOrExpression */: return 100 /* CaretToken */;
                case 189 /* BitwiseOrExpression */: return 99 /* BarToken */;
                case 188 /* LogicalAndExpression */: return 103 /* AmpersandAmpersandToken */;
                case 187 /* LogicalOrExpression */: return 104 /* BarBarToken */;
                case 182 /* OrAssignmentExpression */: return 116 /* BarEqualsToken */;
                case 180 /* AndAssignmentExpression */: return 115 /* AmpersandEqualsToken */;
                case 181 /* ExclusiveOrAssignmentExpression */: return 117 /* CaretEqualsToken */;
                case 183 /* LeftShiftAssignmentExpression */: return 112 /* LessThanLessThanEqualsToken */;
                case 184 /* SignedRightShiftAssignmentExpression */: return 113 /* GreaterThanGreaterThanEqualsToken */;
                case 185 /* UnsignedRightShiftAssignmentExpression */: return 114 /* GreaterThanGreaterThanGreaterThanEqualsToken */;
                case 175 /* AddAssignmentExpression */: return 108 /* PlusEqualsToken */;
                case 176 /* SubtractAssignmentExpression */: return 109 /* MinusEqualsToken */;
                case 177 /* MultiplyAssignmentExpression */: return 110 /* AsteriskEqualsToken */;
                case 178 /* DivideAssignmentExpression */: return 119 /* SlashEqualsToken */;
                case 179 /* ModuloAssignmentExpression */: return 111 /* PercentEqualsToken */;
                case 174 /* AssignmentExpression */: return 107 /* EqualsToken */;
                case 173 /* CommaExpression */: return 79 /* CommaToken */;
                default: return 0 /* None */;
            }
        }
        SyntaxFacts.getOperatorTokenFromBinaryExpression = getOperatorTokenFromBinaryExpression;

        function isAssignmentOperatorToken(tokenKind) {
            switch (tokenKind) {
                case 116 /* BarEqualsToken */:
                case 115 /* AmpersandEqualsToken */:
                case 117 /* CaretEqualsToken */:
                case 112 /* LessThanLessThanEqualsToken */:
                case 113 /* GreaterThanGreaterThanEqualsToken */:
                case 114 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
                case 108 /* PlusEqualsToken */:
                case 109 /* MinusEqualsToken */:
                case 110 /* AsteriskEqualsToken */:
                case 119 /* SlashEqualsToken */:
                case 111 /* PercentEqualsToken */:
                case 107 /* EqualsToken */:
                    return true;

                default:
                    return false;
            }
        }
        SyntaxFacts.isAssignmentOperatorToken = isAssignmentOperatorToken;
    })(TypeScript.SyntaxFacts || (TypeScript.SyntaxFacts = {}));
    var SyntaxFacts = TypeScript.SyntaxFacts;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (Scanner) {
        // Make sure we can encode a token's kind in 7 bits.
        TypeScript.Debug.assert(TypeScript.SyntaxKind.LastToken <= 127);

        // Fixed width tokens (keywords and punctuation) that have no trivia generally make up 30% of
        // all the tokens in a program.  We heavily optimize for that case with a token instance that
        // just needs a parent pointer and a single 30bit int like so:
        //
        // 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0xxx xxxx    <-- kind
        // 0000 0000 0000 0000 0000 0000 0000 0000 00xx xxxx xxxx xxxx xxxx xxxx x000 0000    <-- full start
        // ^                                         ^                                   ^
        // |                                         |                                   |
        // Bit 64                                    Bit 30                              Bit 1
        //
        // This gives us 23 bits for the start of the token.  We don't need to store the width as it
        // can be inferred from the 'kind' for a fixed width token.
        //
        // For small tokens, we encode the data in one 30bit int like so:
        //
        // 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0xxx xxxx    <-- kind
        // 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 xxxx x000 0000    <-- full width
        // 0000 0000 0000 0000 0000 0000 0000 0000 00xx xxxx xxxx xxxx xxxx 0000 0000 0000    <-- full start
        // ^                                         ^                                   ^
        // |                                         |                                   |
        // Bit 64                                    Bit 30                              Bit 1
        //
        // This allows for 5bits for teh width.  i.e. tokens up to 31 chars in width.  And 18 bits for
        // the full start.  This allows for tokens starting up to and including position 262,143.
        //
        // In practice, for codebases we have measured, these values are sufficient to cover ~85% of
        // all tokens.  If a token won't fit within those limits, we make a large token for it.
        //
        //
        // For large tokens, we encode data with two 30 bit ints like so:
        //
        //   _packedFullStartAndInfo:
        //
        // 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000x    <-- has leading trivia
        // 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 00x0    <-- has trailing trivia
        // 0000 0000 0000 0000 0000 0000 0000 0000 00xx xxxx xxxx xxxx xxxx xxxx xxxx xx00    <-- full start
        // ^                                         ^                                   ^
        // |                                         |                                   |
        // Bit 64                                    Bit 30                              Bit 1
        //
        // This gives us 28 bits for the start of the token.  At 256MB That's more than enough for
        // any codebase.
        //
        //   _packedFullWidthAndKind:
        //
        // 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0xxx xxxx    <-- kind
        // 0000 0000 0000 0000 0000 0000 0000 0000 00xx xxxx xxxx xxxx xxxx xxxx x000 0000    <-- full width
        // ^                                         ^                                   ^
        // |                                         |                                   |
        // Bit 64                                    Bit 30                              Bit 1
        //
        // This gives us 23bit for width (or 8MB of width which should be enough for any codebase).
        var ScannerConstants;
        (function (ScannerConstants) {
            ScannerConstants[ScannerConstants["LargeTokenFullStartShift"] = 2] = "LargeTokenFullStartShift";
            ScannerConstants[ScannerConstants["LargeTokenFullWidthShift"] = 7] = "LargeTokenFullWidthShift";

            ScannerConstants[ScannerConstants["FixedWidthTokenFullStartShift"] = 7] = "FixedWidthTokenFullStartShift";

            ScannerConstants[ScannerConstants["SmallTokenFullWidthShift"] = 7] = "SmallTokenFullWidthShift";
            ScannerConstants[ScannerConstants["SmallTokenFullStartShift"] = 12] = "SmallTokenFullStartShift";

            ScannerConstants[ScannerConstants["KindMask"] = 0x7F] = "KindMask";
            ScannerConstants[ScannerConstants["IsVariableWidthMask"] = 0x80] = "IsVariableWidthMask";

            ScannerConstants[ScannerConstants["LargeTokenLeadingTriviaBitMask"] = 0x01] = "LargeTokenLeadingTriviaBitMask";
            ScannerConstants[ScannerConstants["LargeTokenTrailingTriviaBitMask"] = 0x02] = "LargeTokenTrailingTriviaBitMask";

            ScannerConstants[ScannerConstants["SmallTokenFullWidthMask"] = 0x1F] = "SmallTokenFullWidthMask";

            ScannerConstants[ScannerConstants["FixedWidthTokenMaxFullStart"] = 0x7FFFFF] = "FixedWidthTokenMaxFullStart";
            ScannerConstants[ScannerConstants["SmallTokenMaxFullStart"] = 0x3FFFF] = "SmallTokenMaxFullStart";
            ScannerConstants[ScannerConstants["SmallTokenMaxFullWidth"] = 0x1F] = "SmallTokenMaxFullWidth";
        })(ScannerConstants || (ScannerConstants = {}));

        // Make sure our math works for packing/unpacking large fullStarts.
        TypeScript.Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(1 << 28, 1, 1)) === (1 << 28));
        TypeScript.Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(3 << 27, 0, 1)) === (3 << 27));
        TypeScript.Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(10 << 25, 1, 0)) === (10 << 25));

        function fixedWidthTokenPackData(fullStart, kind) {
            return (fullStart << 7 /* FixedWidthTokenFullStartShift */) | kind;
        }

        function fixedWidthTokenUnpackFullStart(packedData) {
            return packedData >> 7 /* FixedWidthTokenFullStartShift */;
        }

        function smallTokenPackData(fullStart, fullWidth, kind) {
            return (fullStart << 12 /* SmallTokenFullStartShift */) | (fullWidth << 7 /* SmallTokenFullWidthShift */) | kind;
        }

        function smallTokenUnpackFullWidth(packedData) {
            return (packedData >> 7 /* SmallTokenFullWidthShift */) & 31 /* SmallTokenFullWidthMask */;
        }

        function smallTokenUnpackFullStart(packedData) {
            return packedData >> 12 /* SmallTokenFullStartShift */;
        }

        function largeTokenPackFullStartAndInfo(fullStart, hasLeadingTriviaInfo, hasTrailingTriviaInfo) {
            return (fullStart << 2 /* LargeTokenFullStartShift */) | hasLeadingTriviaInfo | hasTrailingTriviaInfo;
        }

        function largeTokenUnpackFullWidth(packedFullWidthAndKind) {
            return packedFullWidthAndKind >> 7 /* LargeTokenFullWidthShift */;
        }

        function largeTokenUnpackFullStart(packedFullStartAndInfo) {
            return packedFullStartAndInfo >> 2 /* LargeTokenFullStartShift */;
        }

        function largeTokenUnpackHasLeadingTriviaInfo(packed) {
            return packed & 1 /* LargeTokenLeadingTriviaBitMask */;
        }

        function largeTokenUnpackHasTrailingTriviaInfo(packed) {
            return packed & 2 /* LargeTokenTrailingTriviaBitMask */;
        }

        var isKeywordStartCharacter = TypeScript.ArrayUtilities.createArray(127 /* maxAsciiCharacter */, 0);
        var isIdentifierStartCharacter = TypeScript.ArrayUtilities.createArray(127 /* maxAsciiCharacter */, false);
        var isIdentifierPartCharacter = TypeScript.ArrayUtilities.createArray(127 /* maxAsciiCharacter */, false);

        for (var character = 0; character < 127 /* maxAsciiCharacter */; character++) {
            if ((character >= 97 /* a */ && character <= 122 /* z */) || (character >= 65 /* A */ && character <= 90 /* Z */) || character === 95 /* _ */ || character === 36 /* $ */) {
                isIdentifierStartCharacter[character] = true;
                isIdentifierPartCharacter[character] = true;
            } else if (character >= 48 /* _0 */ && character <= 57 /* _9 */) {
                isIdentifierPartCharacter[character] = true;
            }
        }

        for (var keywordKind = TypeScript.SyntaxKind.FirstKeyword; keywordKind <= TypeScript.SyntaxKind.LastKeyword; keywordKind++) {
            var keyword = TypeScript.SyntaxFacts.getText(keywordKind);
            isKeywordStartCharacter[keyword.charCodeAt(0)] = 1;
        }

        function isContextualToken(token) {
            switch (token.kind()) {
                case 12 /* RegularExpressionLiteral */:

                case 96 /* GreaterThanGreaterThanToken */:
                case 97 /* GreaterThanGreaterThanGreaterThanToken */:
                case 83 /* GreaterThanEqualsToken */:
                case 113 /* GreaterThanGreaterThanEqualsToken */:
                case 114 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
                    return true;

                default:
                    return token.isKeywordConvertedToIdentifier();
            }
        }
        Scanner.isContextualToken = isContextualToken;

        var lastTokenInfo = { leadingTriviaWidth: -1, width: -1 };
        var lastTokenInfoTokenID = -1;

        var triviaScanner = createScannerInternal(1 /* EcmaScript5 */, TypeScript.SimpleText.fromString(""), function () {
        });

        function fillSizeInfo(token, text) {
            if (lastTokenInfoTokenID !== TypeScript.syntaxID(token)) {
                triviaScanner.fillTokenInfo(token, text, lastTokenInfo);
                lastTokenInfoTokenID = TypeScript.syntaxID(token);
            }
        }

        function fullText(token, text) {
            return text.substr(token.fullStart(), token.fullWidth());
        }

        function leadingTrivia(token, text) {
            if (!token.hasLeadingTrivia()) {
                return TypeScript.Syntax.emptyTriviaList;
            }

            return triviaScanner.scanTrivia(token, text, false);
        }

        function trailingTrivia(token, text) {
            if (!token.hasTrailingTrivia()) {
                return TypeScript.Syntax.emptyTriviaList;
            }

            return triviaScanner.scanTrivia(token, text, true);
        }

        function leadingTriviaWidth(token, text) {
            if (!token.hasLeadingTrivia()) {
                return 0;
            }

            fillSizeInfo(token, text);
            return lastTokenInfo.leadingTriviaWidth;
        }

        function trailingTriviaWidth(token, text) {
            if (!token.hasTrailingTrivia()) {
                return 0;
            }

            fillSizeInfo(token, text);
            return token.fullWidth() - lastTokenInfo.leadingTriviaWidth - lastTokenInfo.width;
        }

        function tokenIsIncrementallyUnusable(token) {
            // No scanner tokens make their *containing node* incrementally unusable.
            // Note: several scanner tokens may themselves be unusable.  i.e. if the parser asks
            // for a full node, then that ndoe can be returned even if it contains parser generated
            // tokens (like regexs and merged operator tokens). However, if the parser asks for a
            // for a token, then those contextual tokens will not be reusable.
            return false;
        }

        var FixedWidthTokenWithNoTrivia = (function () {
            function FixedWidthTokenWithNoTrivia(_packedData) {
                this._packedData = _packedData;
            }
            FixedWidthTokenWithNoTrivia.prototype.setFullStart = function (fullStart) {
                this._packedData = fixedWidthTokenPackData(fullStart, this.kind());
            };

            FixedWidthTokenWithNoTrivia.prototype.isIncrementallyUnusable = function () {
                return false;
            };
            FixedWidthTokenWithNoTrivia.prototype.isKeywordConvertedToIdentifier = function () {
                return false;
            };
            FixedWidthTokenWithNoTrivia.prototype.hasSkippedToken = function () {
                return false;
            };
            FixedWidthTokenWithNoTrivia.prototype.fullText = function () {
                return TypeScript.SyntaxFacts.getText(this.kind());
            };
            FixedWidthTokenWithNoTrivia.prototype.text = function () {
                return this.fullText();
            };
            FixedWidthTokenWithNoTrivia.prototype.leadingTrivia = function () {
                return TypeScript.Syntax.emptyTriviaList;
            };
            FixedWidthTokenWithNoTrivia.prototype.trailingTrivia = function () {
                return TypeScript.Syntax.emptyTriviaList;
            };
            FixedWidthTokenWithNoTrivia.prototype.leadingTriviaWidth = function () {
                return 0;
            };
            FixedWidthTokenWithNoTrivia.prototype.trailingTriviaWidth = function () {
                return 0;
            };

            FixedWidthTokenWithNoTrivia.prototype.kind = function () {
                return this._packedData & 127 /* KindMask */;
            };
            FixedWidthTokenWithNoTrivia.prototype.fullWidth = function () {
                return this.fullText().length;
            };
            FixedWidthTokenWithNoTrivia.prototype.fullStart = function () {
                return fixedWidthTokenUnpackFullStart(this._packedData);
            };
            FixedWidthTokenWithNoTrivia.prototype.hasLeadingTrivia = function () {
                return false;
            };
            FixedWidthTokenWithNoTrivia.prototype.hasTrailingTrivia = function () {
                return false;
            };
            FixedWidthTokenWithNoTrivia.prototype.clone = function () {
                return new FixedWidthTokenWithNoTrivia(this._packedData);
            };
            return FixedWidthTokenWithNoTrivia;
        })();

        var LargeScannerToken = (function () {
            function LargeScannerToken(_packedFullStartAndInfo, _packedFullWidthAndKind, cachedText) {
                this._packedFullStartAndInfo = _packedFullStartAndInfo;
                this._packedFullWidthAndKind = _packedFullWidthAndKind;
                if (cachedText !== undefined) {
                    this.cachedText = cachedText;
                }
            }
            LargeScannerToken.prototype.setFullStart = function (fullStart) {
                this._packedFullStartAndInfo = largeTokenPackFullStartAndInfo(fullStart, largeTokenUnpackHasLeadingTriviaInfo(this._packedFullStartAndInfo), largeTokenUnpackHasTrailingTriviaInfo(this._packedFullStartAndInfo));
            };

            LargeScannerToken.prototype.syntaxTreeText = function (text) {
                var result = text || TypeScript.syntaxTree(this).text;
                TypeScript.Debug.assert(result);
                return result;
            };

            LargeScannerToken.prototype.isIncrementallyUnusable = function () {
                return tokenIsIncrementallyUnusable(this);
            };
            LargeScannerToken.prototype.isKeywordConvertedToIdentifier = function () {
                return false;
            };
            LargeScannerToken.prototype.hasSkippedToken = function () {
                return false;
            };

            LargeScannerToken.prototype.fullText = function (text) {
                return fullText(this, this.syntaxTreeText(text));
            };

            LargeScannerToken.prototype.text = function () {
                var cachedText = this.cachedText;
                return cachedText !== undefined ? cachedText : TypeScript.SyntaxFacts.getText(this.kind());
            };

            LargeScannerToken.prototype.leadingTrivia = function (text) {
                return leadingTrivia(this, this.syntaxTreeText(text));
            };
            LargeScannerToken.prototype.trailingTrivia = function (text) {
                return trailingTrivia(this, this.syntaxTreeText(text));
            };

            LargeScannerToken.prototype.leadingTriviaWidth = function (text) {
                return leadingTriviaWidth(this, this.syntaxTreeText(text));
            };

            LargeScannerToken.prototype.trailingTriviaWidth = function (text) {
                return trailingTriviaWidth(this, this.syntaxTreeText(text));
            };

            LargeScannerToken.prototype.kind = function () {
                return this._packedFullWidthAndKind & 127 /* KindMask */;
            };
            LargeScannerToken.prototype.fullWidth = function () {
                return largeTokenUnpackFullWidth(this._packedFullWidthAndKind);
            };
            LargeScannerToken.prototype.fullStart = function () {
                return largeTokenUnpackFullStart(this._packedFullStartAndInfo);
            };
            LargeScannerToken.prototype.hasLeadingTrivia = function () {
                return largeTokenUnpackHasLeadingTriviaInfo(this._packedFullStartAndInfo) !== 0;
            };
            LargeScannerToken.prototype.hasTrailingTrivia = function () {
                return largeTokenUnpackHasTrailingTriviaInfo(this._packedFullStartAndInfo) !== 0;
            };
            LargeScannerToken.prototype.clone = function () {
                return new LargeScannerToken(this._packedFullStartAndInfo, this._packedFullWidthAndKind, this.cachedText);
            };
            return LargeScannerToken;
        })();

        function createScanner(languageVersion, text, reportDiagnostic) {
            var scanner = createScannerInternal(languageVersion, text, reportDiagnostic);
            return {
                setIndex: scanner.setIndex,
                scan: scanner.scan
            };
        }
        Scanner.createScanner = createScanner;

        function createScannerInternal(languageVersion, text, reportDiagnostic) {
            var str;
            var index;
            var start;
            var end;

            function setIndex(_index) {
                index = _index;
            }

            function reset(_text, _start, _end) {
                TypeScript.Debug.assert(_start <= _text.length());
                TypeScript.Debug.assert(_end <= _text.length());

                if (!str || text !== _text) {
                    text = _text;
                    str = _text.substr(0, _text.length());
                }

                start = _start;
                end = _end;
                index = _start;
            }

            function scan(allowContextualToken) {
                var fullStart = index;
                var leadingTriviaInfo = scanTriviaInfo(false);

                var start = index;
                var kindAndIsVariableWidth = scanSyntaxKind(allowContextualToken);

                var end = index;
                var trailingTriviaInfo = scanTriviaInfo(true);

                var fullWidth = index - fullStart;

                // If we have no trivia, and we are a fixed width token kind, and our size isn't too
                // large, and we're a real fixed width token (and not something like "\u0076ar").
                var kind = kindAndIsVariableWidth & 127 /* KindMask */;
                var isFixedWidth = kind >= TypeScript.SyntaxKind.FirstFixedWidth && kind <= TypeScript.SyntaxKind.LastFixedWidth && ((kindAndIsVariableWidth & 128 /* IsVariableWidthMask */) === 0);

                if (isFixedWidth && leadingTriviaInfo === 0 && trailingTriviaInfo === 0 && fullStart <= 8388607 /* FixedWidthTokenMaxFullStart */ && (kindAndIsVariableWidth & 128 /* IsVariableWidthMask */) === 0) {
                    return new FixedWidthTokenWithNoTrivia((fullStart << 7 /* FixedWidthTokenFullStartShift */) | kind);
                } else {
                    // inline the packing logic for perf.
                    var packedFullStartAndTriviaInfo = (fullStart << 2 /* LargeTokenFullStartShift */) | leadingTriviaInfo | (trailingTriviaInfo << 1);

                    var packedFullWidthAndKind = (fullWidth << 7 /* LargeTokenFullWidthShift */) | kind;
                    var cachedText = isFixedWidth ? undefined : text.substr(start, end - start);
                    return new LargeScannerToken(packedFullStartAndTriviaInfo, packedFullWidthAndKind, cachedText);
                }
            }

            function scanTrivia(parent, text, isTrailing) {
                var tokenFullStart = parent.fullStart();
                var tokenStart = tokenFullStart + leadingTriviaWidth(parent, text);

                if (isTrailing) {
                    reset(text, tokenStart + parent.text().length, tokenFullStart + parent.fullWidth());
                } else {
                    reset(text, tokenFullStart, tokenStart);
                }

                // Debug.assert(length > 0);
                // Keep this exactly in sync with scanTriviaInfo
                var trivia = [];

                while (true) {
                    if (index < end) {
                        var ch = str.charCodeAt(index);
                        switch (ch) {
                            case 32 /* space */:
                            case 160 /* nonBreakingSpace */:
                            case 8192 /* enQuad */:
                            case 8193 /* emQuad */:
                            case 8194 /* enSpace */:
                            case 8195 /* emSpace */:
                            case 8196 /* threePerEmSpace */:
                            case 8197 /* fourPerEmSpace */:
                            case 8198 /* sixPerEmSpace */:
                            case 8199 /* figureSpace */:
                            case 8200 /* punctuationSpace */:
                            case 8201 /* thinSpace */:
                            case 8202 /* hairSpace */:
                            case 8203 /* zeroWidthSpace */:
                            case 8239 /* narrowNoBreakSpace */:
                            case 12288 /* ideographicSpace */:

                            case 9 /* tab */:
                            case 11 /* verticalTab */:
                            case 12 /* formFeed */:
                            case 65279 /* byteOrderMark */:
                                // Normal whitespace.  Consume and continue.
                                trivia.push(scanWhitespaceTrivia());
                                continue;

                            case 47 /* slash */:
                                // Potential comment.  Consume if so.  Otherwise, break out and return.
                                var ch2 = str.charCodeAt(index + 1);
                                if (ch2 === 47 /* slash */) {
                                    trivia.push(scanSingleLineCommentTrivia());
                                    continue;
                                }

                                if (ch2 === 42 /* asterisk */) {
                                    trivia.push(scanMultiLineCommentTrivia());
                                    continue;
                                }

                                throw TypeScript.Errors.invalidOperation();

                            case 13 /* carriageReturn */:
                            case 10 /* lineFeed */:
                            case 8233 /* paragraphSeparator */:
                            case 8232 /* lineSeparator */:
                                trivia.push(scanLineTerminatorSequenceTrivia(ch));

                                // If we're consuming leading trivia, then we will continue consuming more
                                // trivia (including newlines) up to the first token we see.  If we're
                                // consuming trailing trivia, then we break after the first newline we see.
                                if (!isTrailing) {
                                    continue;
                                }

                                break;

                            default:
                                throw TypeScript.Errors.invalidOperation();
                        }
                    }

                    // Debug.assert(trivia.length > 0);
                    var triviaList = TypeScript.Syntax.triviaList(trivia);
                    triviaList.parent = parent;

                    return triviaList;
                }
            }

            // Returns 0 if there was no trivia, or 1 if there was trivia.  Returned as an int instead
            // of a boolean because we'll need a numerical value later on to store in our tokens.
            function scanTriviaInfo(isTrailing) {
                // Keep this exactly in sync with scanTrivia
                var result = 0;
                var _end = end;

                while (index < _end) {
                    var ch = str.charCodeAt(index);

                    switch (ch) {
                        case 9 /* tab */:
                        case 32 /* space */:
                        case 11 /* verticalTab */:
                        case 12 /* formFeed */:
                            index++;
                            result = 1;
                            continue;

                        case 13 /* carriageReturn */:
                            if ((index + 1) < end && str.charCodeAt(index + 1) === 10 /* lineFeed */) {
                                index++;
                            }

                        case 10 /* lineFeed */:
                            index++;

                            // If we're consuming leading trivia, then we will continue consuming more
                            // trivia (including newlines) up to the first token we see.  If we're
                            // consuming trailing trivia, then we break after the first newline we see.
                            if (isTrailing) {
                                return 1;
                            }

                            result = 1;
                            continue;

                        case 47 /* slash */:
                            if ((index + 1) < _end) {
                                var ch2 = str.charCodeAt(index + 1);
                                if (ch2 === 47 /* slash */) {
                                    result = 1;
                                    skipSingleLineCommentTrivia();
                                    continue;
                                }

                                if (ch2 === 42 /* asterisk */) {
                                    result = 1;
                                    skipMultiLineCommentTrivia();
                                    continue;
                                }
                            }

                            // Not a comment.  Don't consume.
                            return result;

                        default:
                            if (ch > 127 /* maxAsciiCharacter */ && slowScanTriviaInfo(ch)) {
                                result = 1;
                                continue;
                            }

                            return result;
                    }
                }

                return result;
            }

            function slowScanTriviaInfo(ch) {
                switch (ch) {
                    case 160 /* nonBreakingSpace */:
                    case 8192 /* enQuad */:
                    case 8193 /* emQuad */:
                    case 8194 /* enSpace */:
                    case 8195 /* emSpace */:
                    case 8196 /* threePerEmSpace */:
                    case 8197 /* fourPerEmSpace */:
                    case 8198 /* sixPerEmSpace */:
                    case 8199 /* figureSpace */:
                    case 8200 /* punctuationSpace */:
                    case 8201 /* thinSpace */:
                    case 8202 /* hairSpace */:
                    case 8203 /* zeroWidthSpace */:
                    case 8239 /* narrowNoBreakSpace */:
                    case 12288 /* ideographicSpace */:
                    case 65279 /* byteOrderMark */:
                    case 8233 /* paragraphSeparator */:
                    case 8232 /* lineSeparator */:
                        index++;
                        return true;

                    default:
                        return false;
                }
            }

            function isNewLineCharacter(ch) {
                switch (ch) {
                    case 13 /* carriageReturn */:
                    case 10 /* lineFeed */:
                    case 8233 /* paragraphSeparator */:
                    case 8232 /* lineSeparator */:
                        return true;
                    default:
                        return false;
                }
            }

            function scanWhitespaceTrivia() {
                // We're going to be extracting text out of sliding window.  Make sure it can't move past
                // this point.
                var absoluteStartIndex = index;

                while (true) {
                    var ch = str.charCodeAt(index);

                    switch (ch) {
                        case 32 /* space */:
                        case 160 /* nonBreakingSpace */:
                        case 8192 /* enQuad */:
                        case 8193 /* emQuad */:
                        case 8194 /* enSpace */:
                        case 8195 /* emSpace */:
                        case 8196 /* threePerEmSpace */:
                        case 8197 /* fourPerEmSpace */:
                        case 8198 /* sixPerEmSpace */:
                        case 8199 /* figureSpace */:
                        case 8200 /* punctuationSpace */:
                        case 8201 /* thinSpace */:
                        case 8202 /* hairSpace */:
                        case 8203 /* zeroWidthSpace */:
                        case 8239 /* narrowNoBreakSpace */:
                        case 12288 /* ideographicSpace */:

                        case 9 /* tab */:
                        case 11 /* verticalTab */:
                        case 12 /* formFeed */:
                        case 65279 /* byteOrderMark */:
                            // Normal whitespace.  Consume and continue.
                            index++;
                            continue;
                    }

                    break;
                }

                return createTrivia(4 /* WhitespaceTrivia */, absoluteStartIndex);
            }

            function createTrivia(kind, absoluteStartIndex) {
                var fullWidth = index - absoluteStartIndex;
                return TypeScript.Syntax.deferredTrivia(kind, text, absoluteStartIndex, fullWidth);
            }

            function scanSingleLineCommentTrivia() {
                var absoluteStartIndex = index;
                skipSingleLineCommentTrivia();

                return createTrivia(7 /* SingleLineCommentTrivia */, absoluteStartIndex);
            }

            function skipSingleLineCommentTrivia() {
                index += 2;

                while (index < end) {
                    if (isNewLineCharacter(str.charCodeAt(index))) {
                        return;
                    }

                    index++;
                }
            }

            function scanMultiLineCommentTrivia() {
                var absoluteStartIndex = index;
                skipMultiLineCommentTrivia();

                return createTrivia(6 /* MultiLineCommentTrivia */, absoluteStartIndex);
            }

            function skipMultiLineCommentTrivia() {
                // The '2' is for the "/*" we consumed.
                index += 2;

                while (true) {
                    if (index === end) {
                        reportDiagnostic(end, 0, TypeScript.DiagnosticCode.AsteriskSlash_expected, null);
                        return;
                    }

                    if ((index + 1) < end && str.charCodeAt(index) === 42 /* asterisk */ && str.charCodeAt(index + 1) === 47 /* slash */) {
                        index += 2;
                        return;
                    }

                    index++;
                }
            }

            function scanLineTerminatorSequenceTrivia(ch) {
                var absoluteStartIndex = index;
                skipLineTerminatorSequence(ch);

                return createTrivia(5 /* NewLineTrivia */, absoluteStartIndex);
            }

            function skipLineTerminatorSequence(ch) {
                // Consume the first of the line terminator we saw.
                index++;

                // If it happened to be a \r and there's a following \n, then consume both.
                if (ch === 13 /* carriageReturn */ && str.charCodeAt(index) === 10 /* lineFeed */) {
                    index++;
                }
            }

            function scanSyntaxKind(allowContextualToken) {
                if (index >= end) {
                    return 10 /* EndOfFileToken */;
                }

                var character = str.charCodeAt(index);
                index++;

                switch (character) {
                    case 33 /* exclamation */: return scanExclamationToken();
                    case 34 /* doubleQuote */: return scanStringLiteral(character);
                    case 37 /* percent */: return scanPercentToken();
                    case 38 /* ampersand */: return scanAmpersandToken();
                    case 39 /* singleQuote */: return scanStringLiteral(character);
                    case 40 /* openParen */: return 72 /* OpenParenToken */;
                    case 41 /* closeParen */: return 73 /* CloseParenToken */;
                    case 42 /* asterisk */: return scanAsteriskToken();
                    case 43 /* plus */: return scanPlusToken();
                    case 44 /* comma */: return 79 /* CommaToken */;
                    case 45 /* minus */: return scanMinusToken();
                    case 46 /* dot */: return scanDotToken();
                    case 47 /* slash */: return scanSlashToken(allowContextualToken);

                    case 48 /* _0 */:
                    case 49 /* _1 */:
                    case 50 /* _2 */:
                    case 51 /* _3 */:
                    case 52 /* _4 */:
                    case 53 /* _5 */:
                    case 54 /* _6 */:
                    case 55 /* _7 */:
                    case 56 /* _8 */:
                    case 57 /* _9 */:
                        return scanNumericLiteral(character);

                    case 58 /* colon */: return 106 /* ColonToken */;
                    case 59 /* semicolon */: return 78 /* SemicolonToken */;
                    case 60 /* lessThan */: return scanLessThanToken();
                    case 61 /* equals */: return scanEqualsToken();
                    case 62 /* greaterThan */: return scanGreaterThanToken(allowContextualToken);
                    case 63 /* question */: return 105 /* QuestionToken */;

                    case 91 /* openBracket */: return 74 /* OpenBracketToken */;
                    case 93 /* closeBracket */: return 75 /* CloseBracketToken */;
                    case 94 /* caret */: return scanCaretToken();

                    case 123 /* openBrace */: return 70 /* OpenBraceToken */;
                    case 124 /* bar */: return scanBarToken();
                    case 125 /* closeBrace */: return 71 /* CloseBraceToken */;
                    case 126 /* tilde */: return 102 /* TildeToken */;
                }

                // We run into so many identifiers (and keywords) when scanning, that we want the code to
                // be as fast as possible.  To that end, we have an extremely fast path for scanning that
                // handles the 99.9% case of no-unicode characters and no unicode escapes.
                if (isIdentifierStartCharacter[character]) {
                    var result = tryFastScanIdentifierOrKeyword(character);
                    if (result !== 0 /* None */) {
                        return result;
                    }
                }

                // Move the index back one and try the slow path.
                index--;
                if (isIdentifierStart(peekCharOrUnicodeEscape())) {
                    return slowScanIdentifierOrKeyword();
                }

                // Was nothing that we could understand.  Report the issue and keep moving on.
                var text = String.fromCharCode(character);
                var messageText = getErrorMessageText(text);
                reportDiagnostic(index, 1, TypeScript.DiagnosticCode.Unexpected_character_0, [messageText]);

                index++;

                return 9 /* ErrorToken */;
            }

            function isIdentifierStart(interpretedChar) {
                if (isIdentifierStartCharacter[interpretedChar]) {
                    return true;
                }

                return interpretedChar > 127 /* maxAsciiCharacter */ && TypeScript.Unicode.isIdentifierStart(interpretedChar, languageVersion);
            }

            function isIdentifierPart(interpretedChar) {
                if (isIdentifierPartCharacter[interpretedChar]) {
                    return true;
                }

                return interpretedChar > 127 /* maxAsciiCharacter */ && TypeScript.Unicode.isIdentifierPart(interpretedChar, languageVersion);
            }

            function tryFastScanIdentifierOrKeyword(firstCharacter) {
                var startIndex = index;
                var character = firstCharacter;

                while (index < end) {
                    character = str.charCodeAt(index);
                    if (!isIdentifierPartCharacter[character]) {
                        break;
                    }

                    index++;
                }

                if (index < end && (character === 92 /* backslash */ || character > 127 /* maxAsciiCharacter */)) {
                    // We saw a \ (which could start a unicode escape), or we saw a unicode character.
                    // This can't be scanned quickly.  Don't update the window position and just bail out
                    // to the slow path.
                    index = startIndex;
                    return 0 /* None */;
                } else {
                    // Saw an ascii character that wasn't a backslash and wasn't an identifier
                    // character.  Or we hit the end of the file  This identifier is done.
                    // Also check if it a keyword if it started with a keyword start char.
                    if (isKeywordStartCharacter[firstCharacter]) {
                        return TypeScript.ScannerUtilities.identifierKind(str, startIndex - 1, index - startIndex + 1);
                    } else {
                        return 11 /* IdentifierName */;
                    }
                }
            }

            // A slow path for scanning identifiers.  Called when we run into a unicode character or
            // escape sequence while processing the fast path.
            function slowScanIdentifierOrKeyword() {
                var startIndex = index;

                do {
                    scanCharOrUnicodeEscape();
                } while(isIdentifierPart(peekCharOrUnicodeEscape()));

                // From ES6 specification.
                // The ReservedWord definitions are specified as literal sequences of Unicode
                // characters.However, any Unicode character in a ReservedWord can also be
                // expressed by a \ UnicodeEscapeSequence that expresses that same Unicode
                // character's code point.Use of such escape sequences does not change the meaning
                // of the ReservedWord.
                //
                // i.e. "\u0076ar" is the keyword 'var'.  Check for that here.
                var length = index - startIndex;
                var text = str.substr(startIndex, length);
                var valueText = TypeScript.massageEscapes(text);

                var keywordKind = TypeScript.SyntaxFacts.getTokenKind(valueText);
                if (keywordKind >= TypeScript.SyntaxKind.FirstKeyword && keywordKind <= TypeScript.SyntaxKind.LastKeyword) {
                    // We have a keyword, but it is also variable width.  We can't put represent this
                    // width a fixed width token.
                    return keywordKind | 128 /* IsVariableWidthMask */;
                }

                return 11 /* IdentifierName */;
            }

            function scanNumericLiteral(ch) {
                if (isHexNumericLiteral(ch)) {
                    scanHexNumericLiteral();
                } else if (isOctalNumericLiteral(ch)) {
                    scanOctalNumericLiteral();
                } else {
                    scanDecimalNumericLiteral();
                }

                return 13 /* NumericLiteral */;
            }

            function isOctalNumericLiteral(ch) {
                return ch === 48 /* _0 */ && TypeScript.CharacterInfo.isOctalDigit(str.charCodeAt(index));
            }

            function scanOctalNumericLiteral() {
                var start = index - 1;

                while (TypeScript.CharacterInfo.isOctalDigit(str.charCodeAt(index))) {
                    index++;
                }

                if (languageVersion >= 1 /* EcmaScript5 */) {
                    reportDiagnostic(start, index - start, TypeScript.DiagnosticCode.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher, null);
                }
            }

            function scanDecimalDigits() {
                while (TypeScript.CharacterInfo.isDecimalDigit(str.charCodeAt(index))) {
                    index++;
                }
            }

            function scanDecimalNumericLiteral() {
                scanDecimalDigits();

                if (str.charCodeAt(index) === 46 /* dot */) {
                    index++;
                }

                scanDecimalNumericLiteralAfterDot();
            }

            function scanDecimalNumericLiteralAfterDot() {
                scanDecimalDigits();

                // If we see an 'e' or 'E' we should only consume it if its of the form:
                // e<number> or E<number>
                // e+<number>   E+<number>
                // e-<number>   E-<number>
                var ch = str.charCodeAt(index);
                if (ch === 101 /* e */ || ch === 69 /* E */) {
                    // Ok, we've got 'e' or 'E'.  Make sure it's followed correctly.
                    var nextChar1 = str.charCodeAt(index + 1);

                    if (TypeScript.CharacterInfo.isDecimalDigit(nextChar1)) {
                        // e<number> or E<number>
                        // Consume 'e' or 'E' and the number portion.
                        index++;
                        scanDecimalDigits();
                    } else if (nextChar1 === 45 /* minus */ || nextChar1 === 43 /* plus */) {
                        // e+ or E+ or e- or E-
                        var nextChar2 = str.charCodeAt(index + 2);
                        if (TypeScript.CharacterInfo.isDecimalDigit(nextChar2)) {
                            // e+<number> or E+<number> or e-<number> or E-<number>
                            // Consume first two characters and the number portion.
                            index += 2;
                            scanDecimalDigits();
                        }
                    }
                }
            }

            function scanHexNumericLiteral() {
                // Move past the x.
                index++;

                while (TypeScript.CharacterInfo.isHexDigit(str.charCodeAt(index))) {
                    index++;
                }
            }

            function isHexNumericLiteral(ch) {
                if (ch === 48 /* _0 */) {
                    var ch = str.charCodeAt(index);

                    if (ch === 120 /* x */ || ch === 88 /* X */) {
                        return TypeScript.CharacterInfo.isHexDigit(str.charCodeAt(index + 1));
                    }
                }

                return false;
            }

            function scanLessThanToken() {
                var ch0 = str.charCodeAt(index);
                if (ch0 === 61 /* equals */) {
                    index++;
                    return 82 /* LessThanEqualsToken */;
                } else if (ch0 === 60 /* lessThan */) {
                    index++;
                    if (str.charCodeAt(index) === 61 /* equals */) {
                        index++;
                        return 112 /* LessThanLessThanEqualsToken */;
                    } else {
                        return 95 /* LessThanLessThanToken */;
                    }
                } else {
                    return 80 /* LessThanToken */;
                }
            }

            function scanGreaterThanToken(allowContextualToken) {
                if (allowContextualToken) {
                    var ch0 = str.charCodeAt(index);
                    if (ch0 === 62 /* greaterThan */) {
                        // >>
                        index++;
                        var ch1 = str.charCodeAt(index);
                        if (ch1 === 62 /* greaterThan */) {
                            // >>>
                            index++;
                            var ch2 = str.charCodeAt(index);
                            if (ch2 === 61 /* equals */) {
                                // >>>=
                                index++;
                                return 114 /* GreaterThanGreaterThanGreaterThanEqualsToken */;
                            } else {
                                return 97 /* GreaterThanGreaterThanGreaterThanToken */;
                            }
                        } else if (ch1 === 61 /* equals */) {
                            // >>=
                            index++;
                            return 113 /* GreaterThanGreaterThanEqualsToken */;
                        } else {
                            return 96 /* GreaterThanGreaterThanToken */;
                        }
                    } else if (ch0 === 61 /* equals */) {
                        // >=
                        index++;
                        return 83 /* GreaterThanEqualsToken */;
                    }
                }

                return 81 /* GreaterThanToken */;
            }

            function scanBarToken() {
                var ch = str.charCodeAt(index);
                if (ch === 61 /* equals */) {
                    index++;
                    return 116 /* BarEqualsToken */;
                } else if (ch === 124 /* bar */) {
                    index++;
                    return 104 /* BarBarToken */;
                } else {
                    return 99 /* BarToken */;
                }
            }

            function scanCaretToken() {
                if (str.charCodeAt(index) === 61 /* equals */) {
                    index++;
                    return 117 /* CaretEqualsToken */;
                } else {
                    return 100 /* CaretToken */;
                }
            }

            function scanAmpersandToken() {
                var character = str.charCodeAt(index);
                if (character === 61 /* equals */) {
                    index++;
                    return 115 /* AmpersandEqualsToken */;
                } else if (character === 38 /* ampersand */) {
                    index++;
                    return 103 /* AmpersandAmpersandToken */;
                } else {
                    return 98 /* AmpersandToken */;
                }
            }

            function scanPercentToken() {
                if (str.charCodeAt(index) === 61 /* equals */) {
                    index++;
                    return 111 /* PercentEqualsToken */;
                } else {
                    return 92 /* PercentToken */;
                }
            }

            function scanMinusToken() {
                var character = str.charCodeAt(index);

                if (character === 61 /* equals */) {
                    index++;
                    return 109 /* MinusEqualsToken */;
                } else if (character === 45 /* minus */) {
                    index++;
                    return 94 /* MinusMinusToken */;
                } else {
                    return 90 /* MinusToken */;
                }
            }

            function scanPlusToken() {
                var character = str.charCodeAt(index);
                if (character === 61 /* equals */) {
                    index++;
                    return 108 /* PlusEqualsToken */;
                } else if (character === 43 /* plus */) {
                    index++;
                    return 93 /* PlusPlusToken */;
                } else {
                    return 89 /* PlusToken */;
                }
            }

            function scanAsteriskToken() {
                if (str.charCodeAt(index) === 61 /* equals */) {
                    index++;
                    return 110 /* AsteriskEqualsToken */;
                } else {
                    return 91 /* AsteriskToken */;
                }
            }

            function scanEqualsToken() {
                var character = str.charCodeAt(index);
                if (character === 61 /* equals */) {
                    index++;

                    if (str.charCodeAt(index) === 61 /* equals */) {
                        index++;

                        return 87 /* EqualsEqualsEqualsToken */;
                    } else {
                        return 84 /* EqualsEqualsToken */;
                    }
                } else if (character === 62 /* greaterThan */) {
                    index++;
                    return 85 /* EqualsGreaterThanToken */;
                } else {
                    return 107 /* EqualsToken */;
                }
            }

            function scanDotToken() {
                var nextChar = str.charCodeAt(index);
                if (TypeScript.CharacterInfo.isDecimalDigit(nextChar)) {
                    scanDecimalNumericLiteralAfterDot();
                    return 13 /* NumericLiteral */;
                }

                if (nextChar === 46 /* dot */ && str.charCodeAt(index + 1) === 46 /* dot */) {
                    index += 2;
                    return 77 /* DotDotDotToken */;
                } else {
                    return 76 /* DotToken */;
                }
            }

            function scanSlashToken(allowContextualToken) {
                // NOTE: By default, we do not try scanning a / as a regexp here.  We instead consider it a
                // div or div-assign.  Later on, if the parser runs into a situation where it would like a
                // term, and it sees one of these then it may restart us asking specifically if we could
                // scan out a regex.
                if (allowContextualToken) {
                    var result = tryScanRegularExpressionToken();
                    if (result !== 0 /* None */) {
                        return result;
                    }
                }

                if (str.charCodeAt(index) === 61 /* equals */) {
                    index++;
                    return 119 /* SlashEqualsToken */;
                } else {
                    return 118 /* SlashToken */;
                }
            }

            function tryScanRegularExpressionToken() {
                var startIndex = index;

                var inEscape = false;
                var inCharacterClass = false;
                while (true) {
                    var ch = str.charCodeAt(index);

                    if (isNaN(ch) || isNewLineCharacter(ch)) {
                        index = startIndex;
                        return 0 /* None */;
                    }

                    index++;
                    if (inEscape) {
                        inEscape = false;
                        continue;
                    }

                    switch (ch) {
                        case 92 /* backslash */:
                            // We're now in an escape.  Consume the next character we see (unless it's
                            // a newline or null.
                            inEscape = true;
                            continue;

                        case 91 /* openBracket */:
                            // If we see a [ then we're starting an character class.  Note: it's ok if
                            // we then hit another [ inside a character class.  We'll just set the value
                            // to true again and that's ok.
                            inCharacterClass = true;
                            continue;

                        case 93 /* closeBracket */:
                            // If we ever hit a cloe bracket then we're now no longer in a character
                            // class.  If we weren't in a character class to begin with, then this has
                            // no effect.
                            inCharacterClass = false;
                            continue;

                        case 47 /* slash */:
                            // If we see a slash, and we're in a character class, then ignore it.
                            if (inCharacterClass) {
                                continue;
                            }

                            break;

                        default:
                            continue;
                    }

                    break;
                }

                while (isIdentifierPartCharacter[str.charCodeAt(index)]) {
                    index++;
                }

                return 12 /* RegularExpressionLiteral */;
            }

            function scanExclamationToken() {
                if (str.charCodeAt(index) === 61 /* equals */) {
                    index++;

                    if (str.charCodeAt(index) === 61 /* equals */) {
                        index++;

                        return 88 /* ExclamationEqualsEqualsToken */;
                    } else {
                        return 86 /* ExclamationEqualsToken */;
                    }
                } else {
                    return 101 /* ExclamationToken */;
                }
            }

            // Convert text into a printable form usable for an error message.  This will both quote the
            // string, and ensure all characters printable (i.e. by using unicode escapes when they're not).
            function getErrorMessageText(text) {
                // For just a simple backslash, we return it as is.  The default behavior of JSON.stringify
                // is not what we want here.
                if (text === "\\") {
                    return '"\\"';
                }

                return JSON.stringify(text);
            }

            function skipEscapeSequence() {
                var rewindPoint = index;

                // Consume the backslash.
                index++;

                // Get the char after the backslash
                var ch = str.charCodeAt(index);
                if (isNaN(ch)) {
                    // if we're at teh end of the file, just return, the string scanning code will
                    // report an appropriate error.
                    return;
                }

                index++;
                switch (ch) {
                    case 120 /* x */:
                    case 117 /* u */:
                        index = rewindPoint;
                        var value = scanUnicodeOrHexEscape(true);
                        break;

                    case 13 /* carriageReturn */:
                        // If it's \r\n then consume both characters.
                        if (str.charCodeAt(index) === 10 /* lineFeed */) {
                            index++;
                        }
                        break;

                    default:
                        break;
                }
            }

            function scanStringLiteral(quoteCharacter) {
                while (true) {
                    var ch = str.charCodeAt(index);
                    if (ch === 92 /* backslash */) {
                        skipEscapeSequence();
                    } else if (ch === quoteCharacter) {
                        index++;
                        break;
                    } else if (isNaN(ch) || isNewLineCharacter(ch)) {
                        reportDiagnostic(Math.min(index, end), 1, TypeScript.DiagnosticCode.Missing_close_quote_character, null);
                        break;
                    } else {
                        index++;
                    }
                }

                return 14 /* StringLiteral */;
            }

            function isUnicodeEscape(character) {
                return character === 92 /* backslash */ && str.charCodeAt(index + 1) === 117 /* u */;
            }

            function peekCharOrUnicodeEscape() {
                var character = str.charCodeAt(index);
                if (isUnicodeEscape(character)) {
                    return peekUnicodeOrHexEscape();
                } else {
                    return character;
                }
            }

            function peekUnicodeOrHexEscape() {
                var startIndex = index;

                // if we're peeking, then we don't want to change the position
                var ch = scanUnicodeOrHexEscape(false);

                index = startIndex;

                return ch;
            }

            // Returns true if this was a unicode escape.
            function scanCharOrUnicodeEscape() {
                if (str.charCodeAt(index) === 92 /* backslash */ && str.charCodeAt(index + 1) === 117 /* u */) {
                    scanUnicodeOrHexEscape(true);
                } else {
                    index++;
                }
            }

            function scanUnicodeOrHexEscape(report) {
                var start = index;
                var character = str.charCodeAt(index);

                // Debug.assert(character === CharacterCodes.backslash);
                index++;

                character = str.charCodeAt(index);

                // Debug.assert(character === CharacterCodes.u || character === CharacterCodes.x);
                var intChar = 0;
                index++;

                var count = character === 117 /* u */ ? 4 : 2;

                for (var i = 0; i < count; i++) {
                    var ch2 = str.charCodeAt(index);
                    if (!TypeScript.CharacterInfo.isHexDigit(ch2)) {
                        if (report) {
                            reportDiagnostic(start, index - start, TypeScript.DiagnosticCode.Unrecognized_escape_sequence, null);
                        }

                        break;
                    }

                    intChar = (intChar << 4) + TypeScript.CharacterInfo.hexValue(ch2);
                    index++;
                }

                return intChar;
            }

            function fillTokenInfo(token, text, tokenInfo) {
                var fullStart = token.fullStart();
                var fullEnd = fullStart + token.fullWidth();
                reset(text, fullStart, fullEnd);

                var leadingTriviaInfo = scanTriviaInfo(false);

                var start = index;
                scanSyntaxKind(isContextualToken(token));
                var end = index;

                tokenInfo.leadingTriviaWidth = start - fullStart;
                tokenInfo.width = end - start;
            }

            reset(text, 0, text.length());

            return {
                setIndex: setIndex,
                scan: scan,
                fillTokenInfo: fillTokenInfo,
                scanTrivia: scanTrivia
            };
        }

        function isValidIdentifier(text, languageVersion) {
            var hadError = false;
            var scanner = createScanner(languageVersion, text, function () {
                return hadError = true;
            });

            var token = scanner.scan(false);

            return !hadError && TypeScript.SyntaxFacts.isIdentifierNameOrAnyKeyword(token) && TypeScript.width(token) === text.length();
        }
        Scanner.isValidIdentifier = isValidIdentifier;

        

        // Parser source used in batch scenarios.  Directly calls into an underlying text scanner and
        // supports none of the functionality to reuse nodes.  Good for when you just want want to do
        // a single parse of a file.
        function createParserSource(fileName, text, languageVersion) {
            // The absolute position we're at in the text we're reading from.
            var _absolutePosition = 0;

            // The diagnostics we get while scanning.  Note: this never gets rewound when we do a normal
            // rewind.  That's because rewinding doesn't affect the tokens created.  It only affects where
            // in the token stream we're pointing at.  However, it will get modified if we we decide to
            // reparse a / or /= as a regular expression.
            var _tokenDiagnostics = [];

            // Pool of rewind points we give out if the parser needs one.
            var rewindPointPool = [];
            var rewindPointPoolCount = 0;

            var lastDiagnostic = null;
            var reportDiagnostic = function (position, fullWidth, diagnosticKey, args) {
                lastDiagnostic = new TypeScript.Diagnostic(fileName, text.lineMap(), position, fullWidth, diagnosticKey, args);
            };

            // The sliding window that we store tokens in.
            var slidingWindow = new TypeScript.SlidingWindow(fetchNextItem, TypeScript.ArrayUtilities.createArray(1024, null), null);

            // The scanner we're pulling tokens from.
            var scanner = createScanner(languageVersion, text, reportDiagnostic);

            function release() {
                slidingWindow = null;
                scanner = null;
                _tokenDiagnostics = [];
                rewindPointPool = [];
                lastDiagnostic = null;
                reportDiagnostic = null;
            }

            function currentNode() {
                // The normal parser source never returns nodes.  They're only returned by the
                // incremental parser source.
                return null;
            }

            function consumeNode(node) {
                throw TypeScript.Errors.invalidOperation();
            }

            function absolutePosition() {
                return _absolutePosition;
            }

            function tokenDiagnostics() {
                return _tokenDiagnostics;
            }

            function getOrCreateRewindPoint() {
                if (rewindPointPoolCount === 0) {
                    return {};
                }

                rewindPointPoolCount--;
                var result = rewindPointPool[rewindPointPoolCount];
                rewindPointPool[rewindPointPoolCount] = null;
                return result;
            }

            function getRewindPoint() {
                var slidingWindowIndex = slidingWindow.getAndPinAbsoluteIndex();

                var rewindPoint = getOrCreateRewindPoint();

                rewindPoint.slidingWindowIndex = slidingWindowIndex;
                rewindPoint.absolutePosition = _absolutePosition;

                // rewindPoint.pinCount = slidingWindow.pinCount();
                return rewindPoint;
            }

            function rewind(rewindPoint) {
                slidingWindow.rewindToPinnedIndex(rewindPoint.slidingWindowIndex);

                _absolutePosition = rewindPoint.absolutePosition;
            }

            function releaseRewindPoint(rewindPoint) {
                // Debug.assert(slidingWindow.pinCount() === rewindPoint.pinCount);
                slidingWindow.releaseAndUnpinAbsoluteIndex(rewindPoint.absoluteIndex);

                rewindPointPool[rewindPointPoolCount] = rewindPoint;
                rewindPointPoolCount++;
            }

            function fetchNextItem(allowContextualToken) {
                // Assert disabled because it is actually expensive enugh to affect perf.
                // Debug.assert(spaceAvailable > 0);
                var token = scanner.scan(allowContextualToken);

                if (lastDiagnostic === null) {
                    return token;
                }

                // If we produced any diagnostics while creating this token, then realize the token so
                // it won't be reused in incremental scenarios.
                _tokenDiagnostics.push(lastDiagnostic);
                lastDiagnostic = null;
                return TypeScript.Syntax.realizeToken(token, text);
            }

            function peekToken(n) {
                return slidingWindow.peekItemN(n);
            }

            function consumeToken(token) {
                // Debug.assert(currentToken() === token);
                _absolutePosition += token.fullWidth();

                slidingWindow.moveToNextItem();
            }

            function currentToken() {
                return slidingWindow.currentItem(false);
            }

            function removeDiagnosticsOnOrAfterPosition(position) {
                // walk backwards, removing any diagnostics that came after the the current token's
                // full start position.
                var tokenDiagnosticsLength = _tokenDiagnostics.length;
                while (tokenDiagnosticsLength > 0) {
                    var diagnostic = _tokenDiagnostics[tokenDiagnosticsLength - 1];
                    if (diagnostic.start() >= position) {
                        tokenDiagnosticsLength--;
                    } else {
                        break;
                    }
                }

                _tokenDiagnostics.length = tokenDiagnosticsLength;
            }

            function resetToPosition(absolutePosition) {
                _absolutePosition = absolutePosition;

                // First, remove any diagnostics that came after this position.
                removeDiagnosticsOnOrAfterPosition(absolutePosition);

                // Now, tell our sliding window to throw away all tokens after this position as well.
                slidingWindow.disgardAllItemsFromCurrentIndexOnwards();

                // Now tell the scanner to reset its position to this position as well.  That way
                // when we try to scan the next item, we'll be at the right location.
                scanner.setIndex(absolutePosition);
            }

            function currentContextualToken() {
                // We better be on a / or > token right now.
                // Debug.assert(SyntaxFacts.isAnyDivideToken(currentToken().kind()));
                // First, we're going to rewind all our data to the point where this / or /= token started.
                // That's because if it does turn out to be a regular expression, then any tokens or token
                // diagnostics we produced after the original / may no longer be valid.  This would actually
                // be a  fairly expected case.  For example, if you had:  / ... gibberish ... /, we may have
                // produced several diagnostics in the process of scanning the tokens after the first / as
                // they may not have been legal javascript okens.
                //
                // We also need to remove all the tokens we've gotten from the slash and onwards.  They may
                // not have been what the scanner would have produced if it decides that this is actually
                // a regular expresion.
                resetToPosition(_absolutePosition);

                // Now actually fetch the token again from the scanner. This time let it know that it
                // can scan it as a regex token if it wants to.
                var token = slidingWindow.currentItem(true);

                // We have better gotten some sort of regex token.  Otherwise, something *very* wrong has
                // occurred.
                // Debug.assert(SyntaxFacts.isAnyDivideOrRegularExpressionToken(token.kind()));
                return token;
            }

            return {
                text: text,
                fileName: fileName,
                languageVersion: languageVersion,
                currentNode: currentNode,
                currentToken: currentToken,
                currentContextualToken: currentContextualToken,
                peekToken: peekToken,
                consumeNode: consumeNode,
                consumeToken: consumeToken,
                getRewindPoint: getRewindPoint,
                rewind: rewind,
                releaseRewindPoint: releaseRewindPoint,
                tokenDiagnostics: tokenDiagnostics,
                release: release,
                absolutePosition: absolutePosition,
                resetToPosition: resetToPosition
            };
        }
        Scanner.createParserSource = createParserSource;
    })(TypeScript.Scanner || (TypeScript.Scanner = {}));
    var Scanner = TypeScript.Scanner;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var ScannerUtilities = (function () {
        function ScannerUtilities() {
        }
        ScannerUtilities.identifierKind = function (str, start, length) {
            switch (length) {
                case 2:
                    switch (str.charCodeAt(start)) {
                        case 100 /* d */: return (str.charCodeAt(start + 1) === 111 /* o */) ? 22 /* DoKeyword */ : 11 /* IdentifierName */;
                        case 105 /* i */:
                            switch (str.charCodeAt(start + 1)) {
                                case 102 /* f */: return 28 /* IfKeyword */;
                                case 110 /* n */: return 29 /* InKeyword */;
                                default: return 11 /* IdentifierName */;
                            }
                        default: return 11 /* IdentifierName */;
                    }
                case 3:
                    switch (str.charCodeAt(start)) {
                        case 97 /* a */: return (str.charCodeAt(start + 1) === 110 /* n */ && str.charCodeAt(start + 2) === 121 /* y */) ? 60 /* AnyKeyword */ : 11 /* IdentifierName */;
                        case 102 /* f */: return (str.charCodeAt(start + 1) === 111 /* o */ && str.charCodeAt(start + 2) === 114 /* r */) ? 26 /* ForKeyword */ : 11 /* IdentifierName */;
                        case 103 /* g */: return (str.charCodeAt(start + 1) === 101 /* e */ && str.charCodeAt(start + 2) === 116 /* t */) ? 64 /* GetKeyword */ : 11 /* IdentifierName */;
                        case 108 /* l */: return (str.charCodeAt(start + 1) === 101 /* e */ && str.charCodeAt(start + 2) === 116 /* t */) ? 53 /* LetKeyword */ : 11 /* IdentifierName */;
                        case 110 /* n */: return (str.charCodeAt(start + 1) === 101 /* e */ && str.charCodeAt(start + 2) === 119 /* w */) ? 31 /* NewKeyword */ : 11 /* IdentifierName */;
                        case 115 /* s */: return (str.charCodeAt(start + 1) === 101 /* e */ && str.charCodeAt(start + 2) === 116 /* t */) ? 68 /* SetKeyword */ : 11 /* IdentifierName */;
                        case 116 /* t */: return (str.charCodeAt(start + 1) === 114 /* r */ && str.charCodeAt(start + 2) === 121 /* y */) ? 38 /* TryKeyword */ : 11 /* IdentifierName */;
                        case 118 /* v */: return (str.charCodeAt(start + 1) === 97 /* a */ && str.charCodeAt(start + 2) === 114 /* r */) ? 40 /* VarKeyword */ : 11 /* IdentifierName */;
                        default: return 11 /* IdentifierName */;
                    }
                case 4:
                    switch (str.charCodeAt(start)) {
                        case 99 /* c */: return (str.charCodeAt(start + 1) === 97 /* a */ && str.charCodeAt(start + 2) === 115 /* s */ && str.charCodeAt(start + 3) === 101 /* e */) ? 16 /* CaseKeyword */ : 11 /* IdentifierName */;
                        case 101 /* e */:
                            switch (str.charCodeAt(start + 1)) {
                                case 108 /* l */: return (str.charCodeAt(start + 2) === 115 /* s */ && str.charCodeAt(start + 3) === 101 /* e */) ? 23 /* ElseKeyword */ : 11 /* IdentifierName */;
                                case 110 /* n */: return (str.charCodeAt(start + 2) === 117 /* u */ && str.charCodeAt(start + 3) === 109 /* m */) ? 46 /* EnumKeyword */ : 11 /* IdentifierName */;
                                default: return 11 /* IdentifierName */;
                            }
                        case 110 /* n */: return (str.charCodeAt(start + 1) === 117 /* u */ && str.charCodeAt(start + 2) === 108 /* l */ && str.charCodeAt(start + 3) === 108 /* l */) ? 32 /* NullKeyword */ : 11 /* IdentifierName */;
                        case 116 /* t */:
                            switch (str.charCodeAt(start + 1)) {
                                case 104 /* h */: return (str.charCodeAt(start + 2) === 105 /* i */ && str.charCodeAt(start + 3) === 115 /* s */) ? 35 /* ThisKeyword */ : 11 /* IdentifierName */;
                                case 114 /* r */: return (str.charCodeAt(start + 2) === 117 /* u */ && str.charCodeAt(start + 3) === 101 /* e */) ? 37 /* TrueKeyword */ : 11 /* IdentifierName */;
                                default: return 11 /* IdentifierName */;
                            }
                        case 118 /* v */: return (str.charCodeAt(start + 1) === 111 /* o */ && str.charCodeAt(start + 2) === 105 /* i */ && str.charCodeAt(start + 3) === 100 /* d */) ? 41 /* VoidKeyword */ : 11 /* IdentifierName */;
                        case 119 /* w */: return (str.charCodeAt(start + 1) === 105 /* i */ && str.charCodeAt(start + 2) === 116 /* t */ && str.charCodeAt(start + 3) === 104 /* h */) ? 43 /* WithKeyword */ : 11 /* IdentifierName */;
                        default: return 11 /* IdentifierName */;
                    }
                case 5:
                    switch (str.charCodeAt(start)) {
                        case 98 /* b */: return (str.charCodeAt(start + 1) === 114 /* r */ && str.charCodeAt(start + 2) === 101 /* e */ && str.charCodeAt(start + 3) === 97 /* a */ && str.charCodeAt(start + 4) === 107 /* k */) ? 15 /* BreakKeyword */ : 11 /* IdentifierName */;
                        case 99 /* c */:
                            switch (str.charCodeAt(start + 1)) {
                                case 97 /* a */: return (str.charCodeAt(start + 2) === 116 /* t */ && str.charCodeAt(start + 3) === 99 /* c */ && str.charCodeAt(start + 4) === 104 /* h */) ? 17 /* CatchKeyword */ : 11 /* IdentifierName */;
                                case 108 /* l */: return (str.charCodeAt(start + 2) === 97 /* a */ && str.charCodeAt(start + 3) === 115 /* s */ && str.charCodeAt(start + 4) === 115 /* s */) ? 44 /* ClassKeyword */ : 11 /* IdentifierName */;
                                case 111 /* o */: return (str.charCodeAt(start + 2) === 110 /* n */ && str.charCodeAt(start + 3) === 115 /* s */ && str.charCodeAt(start + 4) === 116 /* t */) ? 45 /* ConstKeyword */ : 11 /* IdentifierName */;
                                default: return 11 /* IdentifierName */;
                            }
                        case 102 /* f */: return (str.charCodeAt(start + 1) === 97 /* a */ && str.charCodeAt(start + 2) === 108 /* l */ && str.charCodeAt(start + 3) === 115 /* s */ && str.charCodeAt(start + 4) === 101 /* e */) ? 24 /* FalseKeyword */ : 11 /* IdentifierName */;
                        case 115 /* s */: return (str.charCodeAt(start + 1) === 117 /* u */ && str.charCodeAt(start + 2) === 112 /* p */ && str.charCodeAt(start + 3) === 101 /* e */ && str.charCodeAt(start + 4) === 114 /* r */) ? 50 /* SuperKeyword */ : 11 /* IdentifierName */;
                        case 116 /* t */: return (str.charCodeAt(start + 1) === 104 /* h */ && str.charCodeAt(start + 2) === 114 /* r */ && str.charCodeAt(start + 3) === 111 /* o */ && str.charCodeAt(start + 4) === 119 /* w */) ? 36 /* ThrowKeyword */ : 11 /* IdentifierName */;
                        case 119 /* w */: return (str.charCodeAt(start + 1) === 104 /* h */ && str.charCodeAt(start + 2) === 105 /* i */ && str.charCodeAt(start + 3) === 108 /* l */ && str.charCodeAt(start + 4) === 101 /* e */) ? 42 /* WhileKeyword */ : 11 /* IdentifierName */;
                        case 121 /* y */: return (str.charCodeAt(start + 1) === 105 /* i */ && str.charCodeAt(start + 2) === 101 /* e */ && str.charCodeAt(start + 3) === 108 /* l */ && str.charCodeAt(start + 4) === 100 /* d */) ? 59 /* YieldKeyword */ : 11 /* IdentifierName */;
                        default: return 11 /* IdentifierName */;
                    }
                case 6:
                    switch (str.charCodeAt(start)) {
                        case 100 /* d */: return (str.charCodeAt(start + 1) === 101 /* e */ && str.charCodeAt(start + 2) === 108 /* l */ && str.charCodeAt(start + 3) === 101 /* e */ && str.charCodeAt(start + 4) === 116 /* t */ && str.charCodeAt(start + 5) === 101 /* e */) ? 21 /* DeleteKeyword */ : 11 /* IdentifierName */;
                        case 101 /* e */: return (str.charCodeAt(start + 1) === 120 /* x */ && str.charCodeAt(start + 2) === 112 /* p */ && str.charCodeAt(start + 3) === 111 /* o */ && str.charCodeAt(start + 4) === 114 /* r */ && str.charCodeAt(start + 5) === 116 /* t */) ? 47 /* ExportKeyword */ : 11 /* IdentifierName */;
                        case 105 /* i */: return (str.charCodeAt(start + 1) === 109 /* m */ && str.charCodeAt(start + 2) === 112 /* p */ && str.charCodeAt(start + 3) === 111 /* o */ && str.charCodeAt(start + 4) === 114 /* r */ && str.charCodeAt(start + 5) === 116 /* t */) ? 49 /* ImportKeyword */ : 11 /* IdentifierName */;
                        case 109 /* m */: return (str.charCodeAt(start + 1) === 111 /* o */ && str.charCodeAt(start + 2) === 100 /* d */ && str.charCodeAt(start + 3) === 117 /* u */ && str.charCodeAt(start + 4) === 108 /* l */ && str.charCodeAt(start + 5) === 101 /* e */) ? 65 /* ModuleKeyword */ : 11 /* IdentifierName */;
                        case 110 /* n */: return (str.charCodeAt(start + 1) === 117 /* u */ && str.charCodeAt(start + 2) === 109 /* m */ && str.charCodeAt(start + 3) === 98 /* b */ && str.charCodeAt(start + 4) === 101 /* e */ && str.charCodeAt(start + 5) === 114 /* r */) ? 67 /* NumberKeyword */ : 11 /* IdentifierName */;
                        case 112 /* p */: return (str.charCodeAt(start + 1) === 117 /* u */ && str.charCodeAt(start + 2) === 98 /* b */ && str.charCodeAt(start + 3) === 108 /* l */ && str.charCodeAt(start + 4) === 105 /* i */ && str.charCodeAt(start + 5) === 99 /* c */) ? 57 /* PublicKeyword */ : 11 /* IdentifierName */;
                        case 114 /* r */: return (str.charCodeAt(start + 1) === 101 /* e */ && str.charCodeAt(start + 2) === 116 /* t */ && str.charCodeAt(start + 3) === 117 /* u */ && str.charCodeAt(start + 4) === 114 /* r */ && str.charCodeAt(start + 5) === 110 /* n */) ? 33 /* ReturnKeyword */ : 11 /* IdentifierName */;
                        case 115 /* s */:
                            switch (str.charCodeAt(start + 1)) {
                                case 116 /* t */:
                                    switch (str.charCodeAt(start + 2)) {
                                        case 97 /* a */: return (str.charCodeAt(start + 3) === 116 /* t */ && str.charCodeAt(start + 4) === 105 /* i */ && str.charCodeAt(start + 5) === 99 /* c */) ? 58 /* StaticKeyword */ : 11 /* IdentifierName */;
                                        case 114 /* r */: return (str.charCodeAt(start + 3) === 105 /* i */ && str.charCodeAt(start + 4) === 110 /* n */ && str.charCodeAt(start + 5) === 103 /* g */) ? 69 /* StringKeyword */ : 11 /* IdentifierName */;
                                        default: return 11 /* IdentifierName */;
                                    }
                                case 119 /* w */: return (str.charCodeAt(start + 2) === 105 /* i */ && str.charCodeAt(start + 3) === 116 /* t */ && str.charCodeAt(start + 4) === 99 /* c */ && str.charCodeAt(start + 5) === 104 /* h */) ? 34 /* SwitchKeyword */ : 11 /* IdentifierName */;
                                default: return 11 /* IdentifierName */;
                            }
                        case 116 /* t */: return (str.charCodeAt(start + 1) === 121 /* y */ && str.charCodeAt(start + 2) === 112 /* p */ && str.charCodeAt(start + 3) === 101 /* e */ && str.charCodeAt(start + 4) === 111 /* o */ && str.charCodeAt(start + 5) === 102 /* f */) ? 39 /* TypeOfKeyword */ : 11 /* IdentifierName */;
                        default: return 11 /* IdentifierName */;
                    }
                case 7:
                    switch (str.charCodeAt(start)) {
                        case 98 /* b */: return (str.charCodeAt(start + 1) === 111 /* o */ && str.charCodeAt(start + 2) === 111 /* o */ && str.charCodeAt(start + 3) === 108 /* l */ && str.charCodeAt(start + 4) === 101 /* e */ && str.charCodeAt(start + 5) === 97 /* a */ && str.charCodeAt(start + 6) === 110 /* n */) ? 61 /* BooleanKeyword */ : 11 /* IdentifierName */;
                        case 100 /* d */:
                            switch (str.charCodeAt(start + 1)) {
                                case 101 /* e */:
                                    switch (str.charCodeAt(start + 2)) {
                                        case 99 /* c */: return (str.charCodeAt(start + 3) === 108 /* l */ && str.charCodeAt(start + 4) === 97 /* a */ && str.charCodeAt(start + 5) === 114 /* r */ && str.charCodeAt(start + 6) === 101 /* e */) ? 63 /* DeclareKeyword */ : 11 /* IdentifierName */;
                                        case 102 /* f */: return (str.charCodeAt(start + 3) === 97 /* a */ && str.charCodeAt(start + 4) === 117 /* u */ && str.charCodeAt(start + 5) === 108 /* l */ && str.charCodeAt(start + 6) === 116 /* t */) ? 20 /* DefaultKeyword */ : 11 /* IdentifierName */;
                                        default: return 11 /* IdentifierName */;
                                    }
                                default: return 11 /* IdentifierName */;
                            }
                        case 101 /* e */: return (str.charCodeAt(start + 1) === 120 /* x */ && str.charCodeAt(start + 2) === 116 /* t */ && str.charCodeAt(start + 3) === 101 /* e */ && str.charCodeAt(start + 4) === 110 /* n */ && str.charCodeAt(start + 5) === 100 /* d */ && str.charCodeAt(start + 6) === 115 /* s */) ? 48 /* ExtendsKeyword */ : 11 /* IdentifierName */;
                        case 102 /* f */: return (str.charCodeAt(start + 1) === 105 /* i */ && str.charCodeAt(start + 2) === 110 /* n */ && str.charCodeAt(start + 3) === 97 /* a */ && str.charCodeAt(start + 4) === 108 /* l */ && str.charCodeAt(start + 5) === 108 /* l */ && str.charCodeAt(start + 6) === 121 /* y */) ? 25 /* FinallyKeyword */ : 11 /* IdentifierName */;
                        case 112 /* p */:
                            switch (str.charCodeAt(start + 1)) {
                                case 97 /* a */: return (str.charCodeAt(start + 2) === 99 /* c */ && str.charCodeAt(start + 3) === 107 /* k */ && str.charCodeAt(start + 4) === 97 /* a */ && str.charCodeAt(start + 5) === 103 /* g */ && str.charCodeAt(start + 6) === 101 /* e */) ? 54 /* PackageKeyword */ : 11 /* IdentifierName */;
                                case 114 /* r */: return (str.charCodeAt(start + 2) === 105 /* i */ && str.charCodeAt(start + 3) === 118 /* v */ && str.charCodeAt(start + 4) === 97 /* a */ && str.charCodeAt(start + 5) === 116 /* t */ && str.charCodeAt(start + 6) === 101 /* e */) ? 55 /* PrivateKeyword */ : 11 /* IdentifierName */;
                                default: return 11 /* IdentifierName */;
                            }
                        case 114 /* r */: return (str.charCodeAt(start + 1) === 101 /* e */ && str.charCodeAt(start + 2) === 113 /* q */ && str.charCodeAt(start + 3) === 117 /* u */ && str.charCodeAt(start + 4) === 105 /* i */ && str.charCodeAt(start + 5) === 114 /* r */ && str.charCodeAt(start + 6) === 101 /* e */) ? 66 /* RequireKeyword */ : 11 /* IdentifierName */;
                        default: return 11 /* IdentifierName */;
                    }
                case 8:
                    switch (str.charCodeAt(start)) {
                        case 99 /* c */: return (str.charCodeAt(start + 1) === 111 /* o */ && str.charCodeAt(start + 2) === 110 /* n */ && str.charCodeAt(start + 3) === 116 /* t */ && str.charCodeAt(start + 4) === 105 /* i */ && str.charCodeAt(start + 5) === 110 /* n */ && str.charCodeAt(start + 6) === 117 /* u */ && str.charCodeAt(start + 7) === 101 /* e */) ? 18 /* ContinueKeyword */ : 11 /* IdentifierName */;
                        case 100 /* d */: return (str.charCodeAt(start + 1) === 101 /* e */ && str.charCodeAt(start + 2) === 98 /* b */ && str.charCodeAt(start + 3) === 117 /* u */ && str.charCodeAt(start + 4) === 103 /* g */ && str.charCodeAt(start + 5) === 103 /* g */ && str.charCodeAt(start + 6) === 101 /* e */ && str.charCodeAt(start + 7) === 114 /* r */) ? 19 /* DebuggerKeyword */ : 11 /* IdentifierName */;
                        case 102 /* f */: return (str.charCodeAt(start + 1) === 117 /* u */ && str.charCodeAt(start + 2) === 110 /* n */ && str.charCodeAt(start + 3) === 99 /* c */ && str.charCodeAt(start + 4) === 116 /* t */ && str.charCodeAt(start + 5) === 105 /* i */ && str.charCodeAt(start + 6) === 111 /* o */ && str.charCodeAt(start + 7) === 110 /* n */) ? 27 /* FunctionKeyword */ : 11 /* IdentifierName */;
                        default: return 11 /* IdentifierName */;
                    }
                case 9:
                    switch (str.charCodeAt(start)) {
                        case 105 /* i */: return (str.charCodeAt(start + 1) === 110 /* n */ && str.charCodeAt(start + 2) === 116 /* t */ && str.charCodeAt(start + 3) === 101 /* e */ && str.charCodeAt(start + 4) === 114 /* r */ && str.charCodeAt(start + 5) === 102 /* f */ && str.charCodeAt(start + 6) === 97 /* a */ && str.charCodeAt(start + 7) === 99 /* c */ && str.charCodeAt(start + 8) === 101 /* e */) ? 52 /* InterfaceKeyword */ : 11 /* IdentifierName */;
                        case 112 /* p */: return (str.charCodeAt(start + 1) === 114 /* r */ && str.charCodeAt(start + 2) === 111 /* o */ && str.charCodeAt(start + 3) === 116 /* t */ && str.charCodeAt(start + 4) === 101 /* e */ && str.charCodeAt(start + 5) === 99 /* c */ && str.charCodeAt(start + 6) === 116 /* t */ && str.charCodeAt(start + 7) === 101 /* e */ && str.charCodeAt(start + 8) === 100 /* d */) ? 56 /* ProtectedKeyword */ : 11 /* IdentifierName */;
                        default: return 11 /* IdentifierName */;
                    }
                case 10:
                    switch (str.charCodeAt(start)) {
                        case 105 /* i */:
                            switch (str.charCodeAt(start + 1)) {
                                case 109 /* m */: return (str.charCodeAt(start + 2) === 112 /* p */ && str.charCodeAt(start + 3) === 108 /* l */ && str.charCodeAt(start + 4) === 101 /* e */ && str.charCodeAt(start + 5) === 109 /* m */ && str.charCodeAt(start + 6) === 101 /* e */ && str.charCodeAt(start + 7) === 110 /* n */ && str.charCodeAt(start + 8) === 116 /* t */ && str.charCodeAt(start + 9) === 115 /* s */) ? 51 /* ImplementsKeyword */ : 11 /* IdentifierName */;
                                case 110 /* n */: return (str.charCodeAt(start + 2) === 115 /* s */ && str.charCodeAt(start + 3) === 116 /* t */ && str.charCodeAt(start + 4) === 97 /* a */ && str.charCodeAt(start + 5) === 110 /* n */ && str.charCodeAt(start + 6) === 99 /* c */ && str.charCodeAt(start + 7) === 101 /* e */ && str.charCodeAt(start + 8) === 111 /* o */ && str.charCodeAt(start + 9) === 102 /* f */) ? 30 /* InstanceOfKeyword */ : 11 /* IdentifierName */;
                                default: return 11 /* IdentifierName */;
                            }
                        default: return 11 /* IdentifierName */;
                    }
                case 11: return (str.charCodeAt(start) === 99 /* c */ && str.charCodeAt(start + 1) === 111 /* o */ && str.charCodeAt(start + 2) === 110 /* n */ && str.charCodeAt(start + 3) === 115 /* s */ && str.charCodeAt(start + 4) === 116 /* t */ && str.charCodeAt(start + 5) === 114 /* r */ && str.charCodeAt(start + 6) === 117 /* u */ && str.charCodeAt(start + 7) === 99 /* c */ && str.charCodeAt(start + 8) === 116 /* t */ && str.charCodeAt(start + 9) === 111 /* o */ && str.charCodeAt(start + 10) === 114 /* r */) ? 62 /* ConstructorKeyword */ : 11 /* IdentifierName */;
                default: return 11 /* IdentifierName */;
            }
        };
        return ScannerUtilities;
    })();
    TypeScript.ScannerUtilities = ScannerUtilities;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var SlidingWindow = (function () {
        function SlidingWindow(// Underlying source that we retrieve items from.
fetchNextItem, // A window of items that has been read in from the underlying source.
        window, // The default value to return when there are no more items left in the window.
        defaultValue, // The length of the source we're reading from if we know it up front.  -1 if we do not.
        sourceLength) {
            if (typeof sourceLength === "undefined") { sourceLength = -1; }
            this.fetchNextItem = fetchNextItem;
            this.window = window;
            this.defaultValue = defaultValue;
            this.sourceLength = sourceLength;
            // The number of valid items in window.
            this.windowCount = 0;
            // The *absolute* index in the *full* array of items the *window* array starts at.  i.e.
            // if there were 100 items, and window contains tokens [70, 80), then this value would be
            // 70.
            this.windowAbsoluteStartIndex = 0;
            // The index in the window array that we're at. i.e. if there 100 items and
            // window contains tokens [70, 80), and we're on item 75, then this value would be '5'.
            // Note: it is not absolute.  It is relative to the start of the window.
            this.currentRelativeItemIndex = 0;
            // The number of pinned points there are.  As long as there is at least one  pinned point, we
            // will not advance the start of the window array past the item marked by that pin point.
            this._pinCount = 0;
            // If there are any outstanding rewind points, this is index in the full array of items
            // that the first rewind point points to.  If this is not -1, then we will not shift the
            // start of the items array past this point.
            this.firstPinnedAbsoluteIndex = -1;
        }
        SlidingWindow.prototype.addMoreItemsToWindow = function (argument) {
            var sourceLength = this.sourceLength;
            if (sourceLength >= 0 && this.absoluteIndex() >= sourceLength) {
                return false;
            }

            // First, make room for the new items if we're out of room.
            if (this.windowCount >= this.window.length) {
                this.tryShiftOrGrowWindow();
            }

            var item = this.fetchNextItem(argument);

            this.window[this.windowCount] = item;

            // Assert disabled because it is actually expensive enugh to affect perf.
            this.windowCount++;
            return true;
        };

        SlidingWindow.prototype.tryShiftOrGrowWindow = function () {
            // We want to shift if our current item is past the halfway point of the current item window.
            var currentIndexIsPastWindowHalfwayPoint = this.currentRelativeItemIndex > (this.window.length >>> 1);

            // However, we can only shift if we have no outstanding rewind points.  Or, if we have an
            // outstanding rewind point, that it points to some point after the start of the window.
            var isAllowedToShift = this.firstPinnedAbsoluteIndex === -1 || this.firstPinnedAbsoluteIndex > this.windowAbsoluteStartIndex;

            if (currentIndexIsPastWindowHalfwayPoint && isAllowedToShift) {
                // Figure out where we're going to start shifting from. If we have no oustanding rewind
                // points, then we'll start shifting over all the items starting from the current
                // token we're point out.  Otherwise, we'll shift starting from the first item that
                // the rewind point is pointing at.
                //
                // We'll call that point 'N' from now on.
                var shiftStartIndex = this.firstPinnedAbsoluteIndex === -1 ? this.currentRelativeItemIndex : this.firstPinnedAbsoluteIndex - this.windowAbsoluteStartIndex;

                // We have to shift the number of elements between the start index and the number of
                // items in the window.
                var shiftCount = this.windowCount - shiftStartIndex;

                // Debug.assert(shiftStartIndex > 0);
                if (shiftCount > 0) {
                    TypeScript.ArrayUtilities.copy(this.window, shiftStartIndex, this.window, 0, shiftCount);
                }

                // The window has now moved over to the right by N.
                this.windowAbsoluteStartIndex += shiftStartIndex;

                // The number of valid items in the window has now decreased by N.
                this.windowCount -= shiftStartIndex;

                // The current item now starts further to the left in the window.
                this.currentRelativeItemIndex -= shiftStartIndex;
            } else {
                // Grow the exisitng array.
                // this.window[this.window.length * 2 - 1] = this.defaultValue;
                TypeScript.ArrayUtilities.grow(this.window, this.window.length * 2, this.defaultValue);
            }
        };

        SlidingWindow.prototype.absoluteIndex = function () {
            return this.windowAbsoluteStartIndex + this.currentRelativeItemIndex;
        };

        SlidingWindow.prototype.isAtEndOfSource = function () {
            return this.absoluteIndex() >= this.sourceLength;
        };

        SlidingWindow.prototype.getAndPinAbsoluteIndex = function () {
            // Find the absolute index of this pin point.  i.e. it's the index as if we had an
            // array containing *all* tokens.
            var absoluteIndex = this.absoluteIndex();
            var pinCount = this._pinCount++;
            if (pinCount === 0) {
                // If this is the first pinned point, then store off this index.  We will ensure that
                // we never shift the window past this point.
                this.firstPinnedAbsoluteIndex = absoluteIndex;
            }

            return absoluteIndex;
        };

        SlidingWindow.prototype.releaseAndUnpinAbsoluteIndex = function (absoluteIndex) {
            this._pinCount--;
            if (this._pinCount === 0) {
                // If we just released the last outstanding pin, then we no longer need to 'fix' the
                // token window so it can't move forward.  Set the index to -1 so that we can shift
                // things over the next time we read past the end of the array.
                this.firstPinnedAbsoluteIndex = -1;
            }
        };

        SlidingWindow.prototype.rewindToPinnedIndex = function (absoluteIndex) {
            // The rewind point shows which absolute item we want to rewind to.  Get the relative
            // index in the actual array that we want to point to.
            var relativeIndex = absoluteIndex - this.windowAbsoluteStartIndex;

            // Make sure we haven't screwed anything up.
            // Debug.assert(relativeIndex >= 0 && relativeIndex < this.windowCount);
            // Set ourselves back to that point.
            this.currentRelativeItemIndex = relativeIndex;
        };

        SlidingWindow.prototype.currentItem = function (argument) {
            if (this.currentRelativeItemIndex >= this.windowCount) {
                if (!this.addMoreItemsToWindow(argument)) {
                    return this.defaultValue;
                }
            }

            return this.window[this.currentRelativeItemIndex];
        };

        SlidingWindow.prototype.peekItemN = function (n) {
            while (this.currentRelativeItemIndex + n >= this.windowCount) {
                if (!this.addMoreItemsToWindow(null)) {
                    return this.defaultValue;
                }
            }

            return this.window[this.currentRelativeItemIndex + n];
        };

        SlidingWindow.prototype.moveToNextItem = function () {
            this.currentRelativeItemIndex++;
        };

        SlidingWindow.prototype.disgardAllItemsFromCurrentIndexOnwards = function () {
            // By setting the window count to the current relative offset, we are effectively making
            // any items we added to the window from the current offset onwards unusable.  When we
            // try to get the next item, we'll be forced to refetch them from the underlying source.
            this.windowCount = this.currentRelativeItemIndex;
        };
        return SlidingWindow;
    })();
    TypeScript.SlidingWindow = SlidingWindow;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (Syntax) {
        Syntax._nextSyntaxID = 1;

        function childIndex(parent, child) {
            for (var i = 0, n = TypeScript.childCount(parent); i < n; i++) {
                var current = TypeScript.childAt(parent, i);
                if (current === child) {
                    return i;
                }
            }

            throw TypeScript.Errors.invalidOperation();
        }
        Syntax.childIndex = childIndex;

        function nodeHasSkippedOrMissingTokens(node) {
            for (var i = 0; i < TypeScript.childCount(node); i++) {
                var child = TypeScript.childAt(node, i);
                if (TypeScript.isToken(child)) {
                    var token = child;

                    // If a token is skipped, return true. Or if it is a missing token. The only empty token that is not missing is EOF
                    if (token.hasSkippedToken() || (TypeScript.width(token) === 0 && token.kind() !== 10 /* EndOfFileToken */)) {
                        return true;
                    }
                }
            }

            return false;
        }
        Syntax.nodeHasSkippedOrMissingTokens = nodeHasSkippedOrMissingTokens;

        function isUnterminatedStringLiteral(token) {
            if (token && token.kind() === 14 /* StringLiteral */) {
                var text = token.text();
                return text.length < 2 || text.charCodeAt(text.length - 1) !== text.charCodeAt(0);
            }

            return false;
        }
        Syntax.isUnterminatedStringLiteral = isUnterminatedStringLiteral;

        function isUnterminatedMultilineCommentTrivia(trivia) {
            if (trivia && trivia.kind() === 6 /* MultiLineCommentTrivia */) {
                var text = trivia.fullText();
                return text.length < 4 || text.substring(text.length - 2) !== "*/";
            }
            return false;
        }
        Syntax.isUnterminatedMultilineCommentTrivia = isUnterminatedMultilineCommentTrivia;

        function isEntirelyInsideCommentTrivia(trivia, fullStart, position) {
            if (trivia && trivia.isComment() && position > fullStart) {
                var end = fullStart + trivia.fullWidth();
                if (position < end) {
                    return true;
                } else if (position === end) {
                    return trivia.kind() === 7 /* SingleLineCommentTrivia */ || isUnterminatedMultilineCommentTrivia(trivia);
                }
            }

            return false;
        }
        Syntax.isEntirelyInsideCommentTrivia = isEntirelyInsideCommentTrivia;

        function isEntirelyInsideComment(sourceUnit, position) {
            var positionedToken = TypeScript.findToken(sourceUnit, position);
            var fullStart = positionedToken.fullStart();
            var triviaList = null;
            var lastTriviaBeforeToken = null;

            if (positionedToken.kind() === 10 /* EndOfFileToken */) {
                // Check if the trivia is leading on the EndOfFile token
                if (positionedToken.hasLeadingTrivia()) {
                    triviaList = positionedToken.leadingTrivia();
                } else {
                    positionedToken = TypeScript.previousToken(positionedToken);
                    if (positionedToken) {
                        if (positionedToken && positionedToken.hasTrailingTrivia()) {
                            triviaList = positionedToken.trailingTrivia();
                            fullStart = TypeScript.end(positionedToken);
                        }
                    }
                }
            } else {
                if (position <= (fullStart + positionedToken.leadingTriviaWidth())) {
                    triviaList = positionedToken.leadingTrivia();
                } else if (position >= (fullStart + TypeScript.width(positionedToken))) {
                    triviaList = positionedToken.trailingTrivia();
                    fullStart = TypeScript.end(positionedToken);
                }
            }

            if (triviaList) {
                for (var i = 0, n = triviaList.count(); i < n; i++) {
                    var trivia = triviaList.syntaxTriviaAt(i);
                    if (position <= fullStart) {
                        break;
                    } else if (position <= fullStart + trivia.fullWidth() && trivia.isComment()) {
                        // Found the comment trivia we were looking for
                        lastTriviaBeforeToken = trivia;
                        break;
                    }

                    fullStart += trivia.fullWidth();
                }
            }

            return lastTriviaBeforeToken && isEntirelyInsideCommentTrivia(lastTriviaBeforeToken, fullStart, position);
        }
        Syntax.isEntirelyInsideComment = isEntirelyInsideComment;

        function isEntirelyInStringOrRegularExpressionLiteral(sourceUnit, position) {
            var positionedToken = TypeScript.findToken(sourceUnit, position);

            if (positionedToken) {
                if (positionedToken.kind() === 10 /* EndOfFileToken */) {
                    // EndOfFile token, enusre it did not follow an unterminated string literal
                    positionedToken = TypeScript.previousToken(positionedToken);
                    return positionedToken && positionedToken.trailingTriviaWidth() === 0 && isUnterminatedStringLiteral(positionedToken);
                } else if (position > TypeScript.start(positionedToken)) {
                    // Ensure position falls enterily within the literal if it is terminated, or the line if it is not
                    return (position < TypeScript.end(positionedToken) && (positionedToken.kind() === 14 /* StringLiteral */ || positionedToken.kind() === 12 /* RegularExpressionLiteral */)) || (position <= TypeScript.end(positionedToken) && isUnterminatedStringLiteral(positionedToken));
                }
            }

            return false;
        }
        Syntax.isEntirelyInStringOrRegularExpressionLiteral = isEntirelyInStringOrRegularExpressionLiteral;

        function findSkippedTokenOnLeftInTriviaList(positionedToken, position, lookInLeadingTriviaList) {
            var triviaList = null;
            var fullEnd;

            if (lookInLeadingTriviaList) {
                triviaList = positionedToken.leadingTrivia();
                fullEnd = positionedToken.fullStart() + triviaList.fullWidth();
            } else {
                triviaList = positionedToken.trailingTrivia();
                fullEnd = TypeScript.fullEnd(positionedToken);
            }

            if (triviaList && triviaList.hasSkippedToken()) {
                for (var i = triviaList.count() - 1; i >= 0; i--) {
                    var trivia = triviaList.syntaxTriviaAt(i);
                    var triviaWidth = trivia.fullWidth();

                    if (trivia.isSkippedToken() && position >= fullEnd) {
                        return trivia.skippedToken();
                    }

                    fullEnd -= triviaWidth;
                }
            }

            return null;
        }

        function findSkippedTokenOnLeft(positionedToken, position) {
            var positionInLeadingTriviaList = (position < TypeScript.start(positionedToken));
            return findSkippedTokenOnLeftInTriviaList(positionedToken, position, positionInLeadingTriviaList);
        }
        Syntax.findSkippedTokenOnLeft = findSkippedTokenOnLeft;

        function getAncestorOfKind(positionedToken, kind) {
            while (positionedToken && positionedToken.parent) {
                if (positionedToken.parent.kind() === kind) {
                    return positionedToken.parent;
                }

                positionedToken = positionedToken.parent;
            }

            return null;
        }
        Syntax.getAncestorOfKind = getAncestorOfKind;

        function hasAncestorOfKind(positionedToken, kind) {
            return getAncestorOfKind(positionedToken, kind) !== null;
        }
        Syntax.hasAncestorOfKind = hasAncestorOfKind;

        function isIntegerLiteral(expression) {
            if (expression) {
                switch (expression.kind()) {
                    case 164 /* PlusExpression */:
                    case 165 /* NegateExpression */:
                        // Note: if there is a + or - sign, we can only allow a normal integer following
                        // (and not a hex integer).  i.e. -0xA is a legal expression, but it is not a
                        // *literal*.
                        expression = expression.operand;
                        return TypeScript.isToken(expression) && TypeScript.IntegerUtilities.isInteger(expression.text());

                    case 13 /* NumericLiteral */:
                        // If it doesn't have a + or -, then either an integer literal or a hex literal
                        // is acceptable.
                        var text = expression.text();
                        return TypeScript.IntegerUtilities.isInteger(text) || TypeScript.IntegerUtilities.isHexInteger(text);
                }
            }

            return false;
        }
        Syntax.isIntegerLiteral = isIntegerLiteral;

        function containingNode(element) {
            var current = element.parent;

            while (current !== null && !TypeScript.isNode(current)) {
                current = current.parent;
            }

            return current;
        }
        Syntax.containingNode = containingNode;

        function findTokenOnLeft(element, position, includeSkippedTokens) {
            if (typeof includeSkippedTokens === "undefined") { includeSkippedTokens = false; }
            var positionedToken = TypeScript.findToken(element, position, false);
            var _start = TypeScript.start(positionedToken);

            // Position better fall within this token.
            // Debug.assert(position >= positionedToken.fullStart());
            // Debug.assert(position < positionedToken.fullEnd() || positionedToken.token().tokenKind === SyntaxKind.EndOfFileToken);
            if (includeSkippedTokens) {
                positionedToken = findSkippedTokenOnLeft(positionedToken, position) || positionedToken;
            }

            // if position is after the start of the token, then this token is the token on the left.
            if (position > _start) {
                return positionedToken;
            }

            // we're in the trivia before the start of the token.  Need to return the previous token.
            if (positionedToken.fullStart() === 0) {
                // Already on the first token.  Nothing before us.
                return null;
            }

            return TypeScript.previousToken(positionedToken, includeSkippedTokens);
        }
        Syntax.findTokenOnLeft = findTokenOnLeft;

        function findCompleteTokenOnLeft(element, position, includeSkippedTokens) {
            if (typeof includeSkippedTokens === "undefined") { includeSkippedTokens = false; }
            var positionedToken = TypeScript.findToken(element, position, false);

            // Position better fall within this token.
            // Debug.assert(position >= positionedToken.fullStart());
            // Debug.assert(position < positionedToken.fullEnd() || positionedToken.token().tokenKind === SyntaxKind.EndOfFileToken);
            if (includeSkippedTokens) {
                positionedToken = findSkippedTokenOnLeft(positionedToken, position) || positionedToken;
            }

            // if position is after the end of the token, then this token is the token on the left.
            if (TypeScript.width(positionedToken) > 0 && position >= TypeScript.end(positionedToken)) {
                return positionedToken;
            }

            return TypeScript.previousToken(positionedToken, includeSkippedTokens);
        }
        Syntax.findCompleteTokenOnLeft = findCompleteTokenOnLeft;

        function firstTokenInLineContainingPosition(syntaxTree, position) {
            var current = TypeScript.findToken(syntaxTree.sourceUnit(), position);
            while (true) {
                if (isFirstTokenInLine(current, syntaxTree.lineMap())) {
                    break;
                }

                current = TypeScript.previousToken(current);
            }

            return current;
        }
        Syntax.firstTokenInLineContainingPosition = firstTokenInLineContainingPosition;

        function isFirstTokenInLine(token, lineMap) {
            var _previousToken = TypeScript.previousToken(token);
            if (_previousToken === null) {
                return true;
            }

            return lineMap.getLineNumberFromPosition(TypeScript.end(_previousToken)) !== lineMap.getLineNumberFromPosition(TypeScript.start(token));
        }
    })(TypeScript.Syntax || (TypeScript.Syntax = {}));
    var Syntax = TypeScript.Syntax;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    // True if there is only a single instance of this element (and thus can be reused in many
    // places in a syntax tree).  Examples of this include our empty lists.  Because empty
    // lists can be found all over the tree, we want to save on memory by using this single
    // instance instead of creating new objects for each case.  Note: because of this, shared
    // nodes don't have positions or parents.
    function isShared(element) {
        var kind = element.kind();
        return (kind === 1 /* List */ || kind === 2 /* SeparatedList */) && element.length === 0;
    }
    TypeScript.isShared = isShared;

    function childCount(element) {
        var kind = element.kind();
        if (kind === 1 /* List */) {
            return element.length;
        } else if (kind === 2 /* SeparatedList */) {
            return element.length + element.separators.length;
        } else if (kind >= TypeScript.SyntaxKind.FirstToken && kind <= TypeScript.SyntaxKind.LastToken) {
            return 0;
        } else {
            return TypeScript.nodeMetadata[kind].length;
        }
    }
    TypeScript.childCount = childCount;

    function childAt(element, index) {
        var kind = element.kind();
        if (kind === 1 /* List */) {
            return element[index];
        } else if (kind === 2 /* SeparatedList */) {
            return (index % 2 === 0) ? element[index / 2] : element.separators[(index - 1) / 2];
        } else {
            // Debug.assert(isNode(element));
            return element[TypeScript.nodeMetadata[element.kind()][index]];
        }
    }
    TypeScript.childAt = childAt;

    function syntaxTree(element) {
        if (element) {
            TypeScript.Debug.assert(!isShared(element));

            while (element) {
                if (element.kind() === 120 /* SourceUnit */) {
                    return element.syntaxTree;
                }

                element = element.parent;
            }
        }

        return null;
    }
    TypeScript.syntaxTree = syntaxTree;

    function parsedInStrictMode(node) {
        var info = node.data;
        if (info === undefined) {
            return false;
        }

        return (info & 4 /* NodeParsedInStrictModeMask */) !== 0;
    }
    TypeScript.parsedInStrictMode = parsedInStrictMode;

    function previousToken(token, includeSkippedTokens) {
        if (typeof includeSkippedTokens === "undefined") { includeSkippedTokens = false; }
        if (includeSkippedTokens) {
            var triviaList = token.leadingTrivia();
            if (triviaList && triviaList.hasSkippedToken()) {
                var currentTriviaEndPosition = TypeScript.start(token);
                for (var i = triviaList.count() - 1; i >= 0; i--) {
                    var trivia = triviaList.syntaxTriviaAt(i);
                    if (trivia.isSkippedToken()) {
                        return trivia.skippedToken();
                    }

                    currentTriviaEndPosition -= trivia.fullWidth();
                }
            }
        }

        var start = token.fullStart();
        if (start === 0) {
            return null;
        }

        return findToken(syntaxTree(token).sourceUnit(), start - 1, includeSkippedTokens);
    }
    TypeScript.previousToken = previousToken;

    /**
    * Finds a token according to the following rules:
    * 1) If position matches the End of the node/s FullSpan and the node is SourceUnitSyntax,
    *    then the EOF token is returned.
    *
    *  2) If node.FullSpan.Contains(position) then the token that contains given position is
    *     returned.
    *
    *  3) Otherwise an ArgumentOutOfRangeException is thrown
    *
    * Note: findToken will always return a non-missing token with width greater than or equal to
    * 1 (except for EOF).  Empty tokens synthesized by the parser are never returned.
    */
    function findToken(element, position, includeSkippedTokens) {
        if (typeof includeSkippedTokens === "undefined") { includeSkippedTokens = false; }
        var endOfFileToken = tryGetEndOfFileAt(element, position);
        if (endOfFileToken !== null) {
            return endOfFileToken;
        }

        if (position < 0 || position >= fullWidth(element)) {
            throw TypeScript.Errors.argumentOutOfRange("position");
        }

        var positionedToken = findTokenWorker(element, position);

        if (includeSkippedTokens) {
            return findSkippedTokenInPositionedToken(positionedToken, position) || positionedToken;
        }

        // Could not find a better match
        return positionedToken;
    }
    TypeScript.findToken = findToken;

    function findSkippedTokenInPositionedToken(positionedToken, position) {
        var positionInLeadingTriviaList = (position < start(positionedToken));
        return findSkippedTokenInTriviaList(positionedToken, position, positionInLeadingTriviaList);
    }
    TypeScript.findSkippedTokenInPositionedToken = findSkippedTokenInPositionedToken;

    function findSkippedTokenInLeadingTriviaList(positionedToken, position) {
        return findSkippedTokenInTriviaList(positionedToken, position, true);
    }
    TypeScript.findSkippedTokenInLeadingTriviaList = findSkippedTokenInLeadingTriviaList;

    function findSkippedTokenInTrailingTriviaList(positionedToken, position) {
        return findSkippedTokenInTriviaList(positionedToken, position, false);
    }
    TypeScript.findSkippedTokenInTrailingTriviaList = findSkippedTokenInTrailingTriviaList;

    function findSkippedTokenInTriviaList(positionedToken, position, lookInLeadingTriviaList) {
        var triviaList = null;
        var fullStart;

        if (lookInLeadingTriviaList) {
            triviaList = positionedToken.leadingTrivia();
            fullStart = positionedToken.fullStart();
        } else {
            triviaList = positionedToken.trailingTrivia();
            fullStart = end(positionedToken);
        }

        if (triviaList && triviaList.hasSkippedToken()) {
            for (var i = 0, n = triviaList.count(); i < n; i++) {
                var trivia = triviaList.syntaxTriviaAt(i);
                var triviaWidth = trivia.fullWidth();

                if (trivia.isSkippedToken() && position >= fullStart && position <= fullStart + triviaWidth) {
                    return trivia.skippedToken();
                }

                fullStart += triviaWidth;
            }
        }

        return null;
    }

    function findTokenWorker(element, position) {
        // Debug.assert(position >= 0 && position < this.fullWidth());
        if (isToken(element)) {
            TypeScript.Debug.assert(fullWidth(element) > 0);
            return element;
        }

        if (isShared(element)) {
            throw TypeScript.Errors.invalidOperation();
        }

        for (var i = 0, n = childCount(element); i < n; i++) {
            var child = childAt(element, i);

            if (child !== null) {
                var childFullWidth = fullWidth(child);
                if (childFullWidth > 0) {
                    var childFullStart = fullStart(child);

                    if (position >= childFullStart) {
                        var childFullEnd = childFullStart + childFullWidth;

                        if (position < childFullEnd) {
                            return findTokenWorker(child, position);
                        }
                    }
                }
            }
        }

        throw TypeScript.Errors.invalidOperation();
    }

    function tryGetEndOfFileAt(element, position) {
        if (element.kind() === 120 /* SourceUnit */ && position === fullWidth(element)) {
            var sourceUnit = element;
            return sourceUnit.endOfFileToken;
        }

        return null;
    }

    function nextToken(token, text, includeSkippedTokens) {
        if (typeof includeSkippedTokens === "undefined") { includeSkippedTokens = false; }
        if (token.kind() === 10 /* EndOfFileToken */) {
            return null;
        }

        if (includeSkippedTokens) {
            var triviaList = token.trailingTrivia(text);
            if (triviaList && triviaList.hasSkippedToken()) {
                for (var i = 0, n = triviaList.count(); i < n; i++) {
                    var trivia = triviaList.syntaxTriviaAt(i);
                    if (trivia.isSkippedToken()) {
                        return trivia.skippedToken();
                    }
                }
            }
        }

        return findToken(syntaxTree(token).sourceUnit(), fullEnd(token), includeSkippedTokens);
    }
    TypeScript.nextToken = nextToken;

    function isNode(element) {
        if (element !== null) {
            var kind = element.kind();
            return kind >= TypeScript.SyntaxKind.FirstNode && kind <= TypeScript.SyntaxKind.LastNode;
        }

        return false;
    }
    TypeScript.isNode = isNode;

    function isTokenKind(kind) {
        return kind >= TypeScript.SyntaxKind.FirstToken && kind <= TypeScript.SyntaxKind.LastToken;
    }

    function isToken(element) {
        if (element !== null) {
            return isTokenKind(element.kind());
        }

        return false;
    }
    TypeScript.isToken = isToken;

    function isList(element) {
        return element !== null && element.kind() === 1 /* List */;
    }
    TypeScript.isList = isList;

    function isSeparatedList(element) {
        return element !== null && element.kind() === 2 /* SeparatedList */;
    }
    TypeScript.isSeparatedList = isSeparatedList;

    function syntaxID(element) {
        if (isShared(element)) {
            throw TypeScript.Errors.invalidOperation("Should not use shared syntax element as a key.");
        }

        var obj = element;
        if (obj._syntaxID === undefined) {
            obj._syntaxID = TypeScript.Syntax._nextSyntaxID++;
        }

        return obj._syntaxID;
    }
    TypeScript.syntaxID = syntaxID;

    function collectTextElements(element, elements, text) {
        if (element) {
            if (isToken(element)) {
                elements.push(element.fullText(text));
            } else {
                for (var i = 0, n = childCount(element); i < n; i++) {
                    collectTextElements(childAt(element, i), elements, text);
                }
            }
        }
    }

    function fullText(element, text) {
        if (isToken(element)) {
            return element.fullText(text);
        }

        var elements = [];
        collectTextElements(element, elements, text);

        return elements.join("");
    }
    TypeScript.fullText = fullText;

    function leadingTriviaWidth(element, text) {
        var token = firstToken(element);
        return token ? token.leadingTriviaWidth(text) : 0;
    }
    TypeScript.leadingTriviaWidth = leadingTriviaWidth;

    function trailingTriviaWidth(element, text) {
        var token = lastToken(element);
        return token ? token.trailingTriviaWidth(text) : 0;
    }
    TypeScript.trailingTriviaWidth = trailingTriviaWidth;

    function firstToken(element) {
        if (element) {
            var kind = element.kind();

            if (isTokenKind(kind)) {
                return fullWidth(element) > 0 || element.kind() === 10 /* EndOfFileToken */ ? element : null;
            }

            if (kind === 1 /* List */) {
                var array = element;
                for (var i = 0, n = array.length; i < n; i++) {
                    var token = firstToken(array[i]);
                    if (token) {
                        return token;
                    }
                }
            } else if (kind === 2 /* SeparatedList */) {
                var array = element;
                var separators = array.separators;
                for (var i = 0, n = array.length + separators.length; i < n; i++) {
                    var token = firstToken(i % 2 === 0 ? array[i / 2] : separators[(i - 1) / 2]);
                    if (token) {
                        return token;
                    }
                }
            } else {
                var metadata = TypeScript.nodeMetadata[kind];
                for (var i = 0, n = metadata.length; i < n; i++) {
                    var child = element[metadata[i]];
                    var token = firstToken(child);
                    if (token) {
                        return token;
                    }
                }

                if (element.kind() === 120 /* SourceUnit */) {
                    return element.endOfFileToken;
                }
            }
        }

        return null;
    }
    TypeScript.firstToken = firstToken;

    function lastToken(element) {
        if (isToken(element)) {
            return fullWidth(element) > 0 || element.kind() === 10 /* EndOfFileToken */ ? element : null;
        }

        if (element.kind() === 120 /* SourceUnit */) {
            return element.endOfFileToken;
        }

        for (var i = childCount(element) - 1; i >= 0; i--) {
            var child = childAt(element, i);
            if (child !== null) {
                var token = lastToken(child);
                if (token) {
                    return token;
                }
            }
        }

        return null;
    }
    TypeScript.lastToken = lastToken;

    function fullStart(element) {
        TypeScript.Debug.assert(!isShared(element));
        var token = isToken(element) ? element : firstToken(element);
        return token ? token.fullStart() : -1;
    }
    TypeScript.fullStart = fullStart;

    function fullWidth(element) {
        if (isToken(element)) {
            return element.fullWidth();
        }

        if (isShared(element)) {
            return 0;
        }

        var info = data(element);
        return info >>> 3 /* NodeFullWidthShift */;
    }
    TypeScript.fullWidth = fullWidth;

    function isIncrementallyUnusable(element) {
        if (isToken(element)) {
            return element.isIncrementallyUnusable();
        }

        if (isShared(element)) {
            // All shared lists are reusable.
            return false;
        }

        return (data(element) & 2 /* NodeIncrementallyUnusableMask */) !== 0;
    }
    TypeScript.isIncrementallyUnusable = isIncrementallyUnusable;

    function data(element) {
        TypeScript.Debug.assert(isNode(element) || isList(element) || isSeparatedList(element));

        // Lists and nodes all have a 'data' element.
        var dataElement = element;

        var info = dataElement.data;
        if (info === undefined) {
            info = 0;
        }

        if ((info & 1 /* NodeDataComputed */) === 0) {
            info |= computeData(element);
            dataElement.data = info;
        }

        return info;
    }

    function computeData(element) {
        var slotCount = childCount(element);

        var fullWidth = 0;

        // If we have no children (like an OmmittedExpressionSyntax), we're automatically not reusable.
        var isIncrementallyUnusable = slotCount === 0;

        for (var i = 0, n = slotCount; i < n; i++) {
            var child = childAt(element, i);

            if (child) {
                fullWidth += TypeScript.fullWidth(child);

                isIncrementallyUnusable = isIncrementallyUnusable || TypeScript.isIncrementallyUnusable(child);
            }
        }

        return (fullWidth << 3 /* NodeFullWidthShift */) | (isIncrementallyUnusable ? 2 /* NodeIncrementallyUnusableMask */ : 0) | 1 /* NodeDataComputed */;
    }

    function start(element, text) {
        var token = isToken(element) ? element : firstToken(element);
        return token ? token.fullStart() + token.leadingTriviaWidth(text) : -1;
    }
    TypeScript.start = start;

    function end(element, text) {
        var token = isToken(element) ? element : lastToken(element);
        return token ? fullEnd(token) - token.trailingTriviaWidth(text) : -1;
    }
    TypeScript.end = end;

    function width(element, text) {
        if (isToken(element)) {
            return element.text().length;
        }
        return fullWidth(element) - leadingTriviaWidth(element, text) - trailingTriviaWidth(element, text);
    }
    TypeScript.width = width;

    function fullEnd(element) {
        return fullStart(element) + fullWidth(element);
    }
    TypeScript.fullEnd = fullEnd;

    function existsNewLineBetweenTokens(token1, token2, text) {
        if (token1 === token2) {
            return false;
        }

        if (token1 === null || token2 === null) {
            return true;
        }

        var lineMap = text.lineMap();
        return lineMap.getLineNumberFromPosition(end(token1, text)) !== lineMap.getLineNumberFromPosition(start(token2, text));
    }
    TypeScript.existsNewLineBetweenTokens = existsNewLineBetweenTokens;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (SyntaxFacts) {
        function isDirectivePrologueElement(node) {
            if (node.kind() === 149 /* ExpressionStatement */) {
                var expressionStatement = node;
                var expression = expressionStatement.expression;

                if (expression.kind() === 14 /* StringLiteral */) {
                    return true;
                }
            }

            return false;
        }
        SyntaxFacts.isDirectivePrologueElement = isDirectivePrologueElement;

        function isUseStrictDirective(node) {
            var expressionStatement = node;
            var stringLiteral = expressionStatement.expression;

            var text = stringLiteral.text();
            return text === '"use strict"' || text === "'use strict'";
        }
        SyntaxFacts.isUseStrictDirective = isUseStrictDirective;

        function isIdentifierNameOrAnyKeyword(token) {
            var tokenKind = token.kind();
            return tokenKind === 11 /* IdentifierName */ || SyntaxFacts.isAnyKeyword(tokenKind);
        }
        SyntaxFacts.isIdentifierNameOrAnyKeyword = isIdentifierNameOrAnyKeyword;
    })(TypeScript.SyntaxFacts || (TypeScript.SyntaxFacts = {}));
    var SyntaxFacts = TypeScript.SyntaxFacts;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />

var TypeScript;
(function (TypeScript) {
    (function (Syntax) {
        var _emptyList = [];

        var _emptySeparatedList = [];
        var _emptySeparators = [];

        _emptySeparatedList.separators = _emptySeparators;

        function assertEmptyLists() {
            // Debug.assert(_emptyList.length === 0);
            // var separators = _emptySeparatedList.separators;
            // Debug.assert(!separators || separators.length === 0);
        }

        Array.prototype.kind = function () {
            return this.separators === undefined ? 1 /* List */ : 2 /* SeparatedList */;
        };

        Array.prototype.separatorCount = function () {
            assertEmptyLists();

            // Debug.assert(this.kind === SyntaxKind.SeparatedList);
            return this.separators.length;
        };

        Array.prototype.separatorAt = function (index) {
            assertEmptyLists();

            // Debug.assert(this.kind === SyntaxKind.SeparatedList);
            // Debug.assert(index >= 0 && index < this.separators.length);
            return this.separators[index];
        };

        function emptyList() {
            return _emptyList;
        }
        Syntax.emptyList = emptyList;

        function emptySeparatedList() {
            return _emptySeparatedList;
        }
        Syntax.emptySeparatedList = emptySeparatedList;

        function list(nodes) {
            if (nodes === undefined || nodes === null || nodes.length === 0) {
                return emptyList();
            }

            for (var i = 0, n = nodes.length; i < n; i++) {
                nodes[i].parent = nodes;
            }

            return nodes;
        }
        Syntax.list = list;

        function separatedList(nodes, separators) {
            if (nodes === undefined || nodes === null || nodes.length === 0) {
                return emptySeparatedList();
            }

            for (var i = 0, n = nodes.length; i < n; i++) {
                nodes[i].parent = nodes;
            }

            for (var i = 0, n = separators.length; i < n; i++) {
                separators[i].parent = nodes;
            }

            nodes.separators = separators.length === 0 ? _emptySeparators : separators;

            return nodes;
        }
        Syntax.separatedList = separatedList;

        function nonSeparatorIndexOf(list, ast) {
            for (var i = 0, n = list.length; i < n; i++) {
                if (list[i] === ast) {
                    return i;
                }
            }

            return -1;
        }
        Syntax.nonSeparatorIndexOf = nonSeparatorIndexOf;
    })(TypeScript.Syntax || (TypeScript.Syntax = {}));
    var Syntax = TypeScript.Syntax;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var SyntaxNode = (function () {
        function SyntaxNode(data) {
            if (data) {
                this.data = data;
            }
        }
        SyntaxNode.prototype.kind = function () {
            return this.__kind;
        };
        return SyntaxNode;
    })();
    TypeScript.SyntaxNode = SyntaxNode;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    TypeScript.nodeMetadata = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], ["moduleElements", "endOfFileToken"], ["left", "dotToken", "right"], ["openBraceToken", "typeMembers", "closeBraceToken"], ["typeParameterList", "parameterList", "equalsGreaterThanToken", "type"], ["type", "openBracketToken", "closeBracketToken"], ["newKeyword", "typeParameterList", "parameterList", "equalsGreaterThanToken", "type"], ["name", "typeArgumentList"], ["typeOfKeyword", "name"], ["modifiers", "interfaceKeyword", "identifier", "typeParameterList", "heritageClauses", "body"], ["modifiers", "functionKeyword", "identifier", "callSignature", "block", "semicolonToken"], ["modifiers", "moduleKeyword", "name", "stringLiteral", "openBraceToken", "moduleElements", "closeBraceToken"], ["modifiers", "classKeyword", "identifier", "typeParameterList", "heritageClauses", "openBraceToken", "classElements", "closeBraceToken"], ["modifiers", "enumKeyword", "identifier", "openBraceToken", "enumElements", "closeBraceToken"], ["modifiers", "importKeyword", "identifier", "equalsToken", "moduleReference", "semicolonToken"], ["exportKeyword", "equalsToken", "identifier", "semicolonToken"], ["modifiers", "propertyName", "callSignature", "block", "semicolonToken"], ["modifiers", "variableDeclarator", "semicolonToken"], ["modifiers", "constructorKeyword", "callSignature", "block", "semicolonToken"], ["modifiers", "indexSignature", "semicolonToken"], ["modifiers", "getKeyword", "propertyName", "callSignature", "block"], ["modifiers", "setKeyword", "propertyName", "callSignature", "block"], ["propertyName", "questionToken", "typeAnnotation"], ["typeParameterList", "parameterList", "typeAnnotation"], ["newKeyword", "callSignature"], ["openBracketToken", "parameters", "closeBracketToken", "typeAnnotation"], ["propertyName", "questionToken", "callSignature"], ["openBraceToken", "statements", "closeBraceToken"], ["ifKeyword", "openParenToken", "condition", "closeParenToken", "statement", "elseClause"], ["modifiers", "variableDeclaration", "semicolonToken"], ["expression", "semicolonToken"], ["returnKeyword", "expression", "semicolonToken"], ["switchKeyword", "openParenToken", "expression", "closeParenToken", "openBraceToken", "switchClauses", "closeBraceToken"], ["breakKeyword", "identifier", "semicolonToken"], ["continueKeyword", "identifier", "semicolonToken"], ["forKeyword", "openParenToken", "variableDeclaration", "initializer", "firstSemicolonToken", "condition", "secondSemicolonToken", "incrementor", "closeParenToken", "statement"], ["forKeyword", "openParenToken", "variableDeclaration", "left", "inKeyword", "expression", "closeParenToken", "statement"], ["semicolonToken"], ["throwKeyword", "expression", "semicolonToken"], ["whileKeyword", "openParenToken", "condition", "closeParenToken", "statement"], ["tryKeyword", "block", "catchClause", "finallyClause"], ["identifier", "colonToken", "statement"], ["doKeyword", "statement", "whileKeyword", "openParenToken", "condition", "closeParenToken", "semicolonToken"], ["debuggerKeyword", "semicolonToken"], ["withKeyword", "openParenToken", "condition", "closeParenToken", "statement"], ["operatorToken", "operand"], ["operatorToken", "operand"], ["operatorToken", "operand"], ["operatorToken", "operand"], ["operatorToken", "operand"], ["operatorToken", "operand"], ["deleteKeyword", "expression"], ["typeOfKeyword", "expression"], ["voidKeyword", "expression"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["condition", "questionToken", "whenTrue", "colonToken", "whenFalse"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["left", "operatorToken", "right"], ["operand", "operatorToken"], ["operand", "operatorToken"], ["expression", "dotToken", "name"], ["expression", "argumentList"], ["openBracketToken", "expressions", "closeBracketToken"], ["openBraceToken", "propertyAssignments", "closeBraceToken"], ["newKeyword", "expression", "argumentList"], ["openParenToken", "expression", "closeParenToken"], ["callSignature", "equalsGreaterThanToken", "block", "expression"], ["parameter", "equalsGreaterThanToken", "block", "expression"], ["lessThanToken", "type", "greaterThanToken", "expression"], ["expression", "openBracketToken", "argumentExpression", "closeBracketToken"], ["functionKeyword", "identifier", "callSignature", "block"], [], ["varKeyword", "variableDeclarators"], ["propertyName", "typeAnnotation", "equalsValueClause"], ["typeArgumentList", "openParenToken", "arguments", "closeParenToken"], ["openParenToken", "parameters", "closeParenToken"], ["lessThanToken", "typeArguments", "greaterThanToken"], ["lessThanToken", "typeParameters", "greaterThanToken"], ["extendsOrImplementsKeyword", "typeNames"], ["extendsOrImplementsKeyword", "typeNames"], ["equalsToken", "value"], ["caseKeyword", "expression", "colonToken", "statements"], ["defaultKeyword", "colonToken", "statements"], ["elseKeyword", "statement"], ["catchKeyword", "openParenToken", "identifier", "typeAnnotation", "closeParenToken", "block"], ["finallyKeyword", "block"], ["identifier", "constraint"], ["extendsKeyword", "type"], ["propertyName", "colonToken", "expression"], ["propertyName", "callSignature", "block"], ["dotDotDotToken", "modifiers", "identifier", "questionToken", "typeAnnotation", "equalsValueClause"], ["propertyName", "equalsValueClause"], ["colonToken", "type"], ["requireKeyword", "openParenToken", "stringLiteral", "closeParenToken"], ["moduleName"]];
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />

var TypeScript;
(function (TypeScript) {
    function tokenValue(token) {
        if (token.fullWidth() === 0) {
            return null;
        }

        var kind = token.kind();
        var text = token.text();

        if (kind === 11 /* IdentifierName */) {
            return massageEscapes(text);
        }

        switch (kind) {
            case 37 /* TrueKeyword */:
                return true;
            case 24 /* FalseKeyword */:
                return false;
            case 32 /* NullKeyword */:
                return null;
        }

        if (TypeScript.SyntaxFacts.isAnyKeyword(kind) || TypeScript.SyntaxFacts.isAnyPunctuation(kind)) {
            return TypeScript.SyntaxFacts.getText(kind);
        }

        if (kind === 13 /* NumericLiteral */) {
            return TypeScript.IntegerUtilities.isHexInteger(text) ? parseInt(text, 16) : parseFloat(text);
        } else if (kind === 14 /* StringLiteral */) {
            if (text.length > 1 && text.charCodeAt(text.length - 1) === text.charCodeAt(0)) {
                // Properly terminated.  Remove the quotes, and massage any escape characters we see.
                return massageEscapes(text.substr(1, text.length - 2));
            } else {
                // Not property terminated.  Remove the first quote and massage any escape characters we see.
                return massageEscapes(text.substr(1));
            }
        } else if (kind === 12 /* RegularExpressionLiteral */) {
            return regularExpressionValue(text);
        } else if (kind === 10 /* EndOfFileToken */ || kind === 9 /* ErrorToken */) {
            return null;
        } else {
            throw TypeScript.Errors.invalidOperation();
        }
    }
    TypeScript.tokenValue = tokenValue;

    function tokenValueText(token) {
        var value = tokenValue(token);
        return value === null ? "" : massageDisallowedIdentifiers(value.toString());
    }
    TypeScript.tokenValueText = tokenValueText;

    function massageEscapes(text) {
        return text.indexOf("\\") >= 0 ? convertEscapes(text) : text;
    }
    TypeScript.massageEscapes = massageEscapes;

    function regularExpressionValue(text) {
        try  {
            var lastSlash = text.lastIndexOf("/");
            var body = text.substring(1, lastSlash);
            var flags = text.substring(lastSlash + 1);
            return new RegExp(body, flags);
        } catch (e) {
            return null;
        }
    }

    function massageDisallowedIdentifiers(text) {
        // We routinely store the 'valueText' for a token as keys in dictionaries.  However, as those
        // dictionaries are usually just a javascript object, we run into issues when teh keys collide
        // with certain predefined keys they depend on (like __proto__).  To workaround this
        // we ensure that the valueText of any token is not __proto__ but is instead ___proto__.
        //
        // We also prepend a _ to any identifier starting with two __ .  That allows us to carve
        // out the entire namespace of identifiers starting with __ for ourselves.
        if (text.charCodeAt(0) === 95 /* _ */ && text.charCodeAt(1) === 95 /* _ */) {
            return "_" + text;
        }

        return text;
    }

    var characterArray = [];

    function convertEscapes(text) {
        characterArray.length = 0;
        var result = "";

        for (var i = 0, n = text.length; i < n; i++) {
            var ch = text.charCodeAt(i);

            if (ch === 92 /* backslash */) {
                i++;
                if (i < n) {
                    ch = text.charCodeAt(i);
                    switch (ch) {
                        case 48 /* _0 */:
                            characterArray.push(0 /* nullCharacter */);
                            continue;

                        case 98 /* b */:
                            characterArray.push(8 /* backspace */);
                            continue;

                        case 102 /* f */:
                            characterArray.push(12 /* formFeed */);
                            continue;

                        case 110 /* n */:
                            characterArray.push(10 /* lineFeed */);
                            continue;

                        case 114 /* r */:
                            characterArray.push(13 /* carriageReturn */);
                            continue;

                        case 116 /* t */:
                            characterArray.push(9 /* tab */);
                            continue;

                        case 118 /* v */:
                            characterArray.push(11 /* verticalTab */);
                            continue;

                        case 120 /* x */:
                            characterArray.push(hexValue(text, i + 1, 2));
                            i += 2;
                            continue;

                        case 117 /* u */:
                            characterArray.push(hexValue(text, i + 1, 4));
                            i += 4;
                            continue;

                        case 13 /* carriageReturn */:
                            var nextIndex = i + 1;
                            if (nextIndex < text.length && text.charCodeAt(nextIndex) === 10 /* lineFeed */) {
                                // Skip the entire \r\n sequence.
                                i++;
                            }
                            continue;

                        case 10 /* lineFeed */:
                        case 8233 /* paragraphSeparator */:
                        case 8232 /* lineSeparator */:
                            continue;

                        default:
                    }
                }
            }

            characterArray.push(ch);

            if (i && !(i % 1024)) {
                result = result.concat(String.fromCharCode.apply(null, characterArray));
                characterArray.length = 0;
            }
        }

        if (characterArray.length) {
            result = result.concat(String.fromCharCode.apply(null, characterArray));
        }

        return result;
    }

    function hexValue(text, start, length) {
        var intChar = 0;
        for (var i = 0; i < length; i++) {
            var ch2 = text.charCodeAt(start + i);
            if (!TypeScript.CharacterInfo.isHexDigit(ch2)) {
                break;
            }

            intChar = (intChar << 4) + TypeScript.CharacterInfo.hexValue(ch2);
        }

        return intChar;
    }
})(TypeScript || (TypeScript = {}));

var TypeScript;
(function (TypeScript) {
    (function (Syntax) {
        function realizeToken(token, text) {
            return new RealizedToken(token.fullStart(), token.kind(), token.isKeywordConvertedToIdentifier(), token.leadingTrivia(text), token.text(), token.trailingTrivia(text));
        }
        Syntax.realizeToken = realizeToken;

        function convertKeywordToIdentifier(token) {
            return new ConvertedKeywordToken(token);
        }
        Syntax.convertKeywordToIdentifier = convertKeywordToIdentifier;

        function withLeadingTrivia(token, leadingTrivia, text) {
            return new RealizedToken(token.fullStart(), token.kind(), token.isKeywordConvertedToIdentifier(), leadingTrivia, token.text(), token.trailingTrivia(text));
        }
        Syntax.withLeadingTrivia = withLeadingTrivia;

        function withTrailingTrivia(token, trailingTrivia, text) {
            return new RealizedToken(token.fullStart(), token.kind(), token.isKeywordConvertedToIdentifier(), token.leadingTrivia(text), token.text(), trailingTrivia);
        }
        Syntax.withTrailingTrivia = withTrailingTrivia;

        function emptyToken(kind) {
            return new EmptyToken(kind);
        }
        Syntax.emptyToken = emptyToken;

        var EmptyToken = (function () {
            function EmptyToken(_kind) {
                this._kind = _kind;
            }
            EmptyToken.prototype.setFullStart = function (fullStart) {
                // An empty token is always at the -1 position.
            };

            EmptyToken.prototype.kind = function () {
                return this._kind;
            };

            EmptyToken.prototype.clone = function () {
                return new EmptyToken(this.kind());
            };

            // Empty tokens are never incrementally reusable.
            EmptyToken.prototype.isIncrementallyUnusable = function () {
                return true;
            };

            EmptyToken.prototype.isKeywordConvertedToIdentifier = function () {
                return false;
            };

            EmptyToken.prototype.fullWidth = function () {
                return 0;
            };

            EmptyToken.prototype.position = function () {
                // It's hard for us to tell the position of an empty token at the eact time we create
                // it.  For example, we may have:
                //
                //      a / finally
                //
                // There will be a missing token detected after the forward slash, so it would be
                // tempting to set its position as the full-end of hte slash token. However,
                // immediately after that, the 'finally' token will be skipped and will be attached
                // as skipped text to the forward slash.  This means the 'full-end' of the forward
                // slash will change, and thus the empty token will now appear to be embedded inside
                // another token.  This violates are rule that all tokens must only touch at the end,
                // and makes enforcing invariants much harder.
                //
                // To address this we create the empty token with no known position, and then we
                // determine what it's position should be based on where it lies in the tree.
                // Specifically, we find the previous non-zero-width syntax element, and we consider
                // the full-start of this token to be at the full-end of that element.
                var previousElement = this.previousNonZeroWidthElement();
                return previousElement === null ? 0 : TypeScript.fullStart(previousElement) + TypeScript.fullWidth(previousElement);
            };

            EmptyToken.prototype.previousNonZeroWidthElement = function () {
                var current = this;
                while (true) {
                    var parent = current.parent;
                    if (parent === null) {
                        TypeScript.Debug.assert(current.kind() === 120 /* SourceUnit */, "We had a node without a parent that was not the root node!");

                        // We walked all the way to the top, and never found a previous element.  This
                        // can happen with code like:
                        //
                        //      / b;
                        //
                        // We will have an empty identifier token as the first token in the tree.  In
                        // this case, return null so that the position of the empty token will be
                        // considered to be 0.
                        return null;
                    }

                    for (var i = 0, n = TypeScript.childCount(parent); i < n; i++) {
                        if (TypeScript.childAt(parent, i) === current) {
                            break;
                        }
                    }

                    TypeScript.Debug.assert(i !== n, "Could not find current element in parent's child list!");

                    for (var j = i - 1; j >= 0; j--) {
                        var sibling = TypeScript.childAt(parent, j);
                        if (sibling && TypeScript.fullWidth(sibling) > 0) {
                            return sibling;
                        }
                    }

                    // We couldn't find a non-zero-width sibling.  We were either the first element, or
                    // all preceding elements are empty.  So, move up to our parent so we we can find
                    // its preceding sibling.
                    current = current.parent;
                }
            };

            EmptyToken.prototype.fullStart = function () {
                return this.position();
            };

            EmptyToken.prototype.text = function () {
                return "";
            };
            EmptyToken.prototype.fullText = function () {
                return "";
            };

            EmptyToken.prototype.hasLeadingTrivia = function () {
                return false;
            };
            EmptyToken.prototype.leadingTriviaWidth = function () {
                return 0;
            };
            EmptyToken.prototype.hasTrailingTrivia = function () {
                return false;
            };
            EmptyToken.prototype.hasSkippedToken = function () {
                return false;
            };

            EmptyToken.prototype.trailingTriviaWidth = function () {
                return 0;
            };
            EmptyToken.prototype.leadingTrivia = function () {
                return Syntax.emptyTriviaList;
            };
            EmptyToken.prototype.trailingTrivia = function () {
                return Syntax.emptyTriviaList;
            };
            return EmptyToken;
        })();

        var RealizedToken = (function () {
            function RealizedToken(fullStart, kind, isKeywordConvertedToIdentifier, leadingTrivia, text, trailingTrivia) {
                this._fullStart = fullStart;
                this._kind = kind;
                this._isKeywordConvertedToIdentifier = isKeywordConvertedToIdentifier;
                this._text = text;

                this._leadingTrivia = leadingTrivia.clone();
                this._trailingTrivia = trailingTrivia.clone();

                if (!this._leadingTrivia.isShared()) {
                    this._leadingTrivia.parent = this;
                }

                if (!this._trailingTrivia.isShared()) {
                    this._trailingTrivia.parent = this;
                }
            }
            RealizedToken.prototype.setFullStart = function (fullStart) {
                this._fullStart = fullStart;
            };

            RealizedToken.prototype.kind = function () {
                return this._kind;
            };

            RealizedToken.prototype.clone = function () {
                return new RealizedToken(this._fullStart, this.kind(), this._isKeywordConvertedToIdentifier, this._leadingTrivia, this._text, this._trailingTrivia);
            };

            // Realized tokens are created from the parser.  They are *never* incrementally reusable.
            RealizedToken.prototype.isIncrementallyUnusable = function () {
                return true;
            };

            RealizedToken.prototype.isKeywordConvertedToIdentifier = function () {
                return this._isKeywordConvertedToIdentifier;
            };

            RealizedToken.prototype.fullStart = function () {
                return this._fullStart;
            };
            RealizedToken.prototype.fullWidth = function () {
                return this._leadingTrivia.fullWidth() + this._text.length + this._trailingTrivia.fullWidth();
            };

            RealizedToken.prototype.text = function () {
                return this._text;
            };
            RealizedToken.prototype.fullText = function () {
                return this._leadingTrivia.fullText() + this.text() + this._trailingTrivia.fullText();
            };

            RealizedToken.prototype.hasLeadingTrivia = function () {
                return this._leadingTrivia.count() > 0;
            };
            RealizedToken.prototype.hasTrailingTrivia = function () {
                return this._trailingTrivia.count() > 0;
            };

            RealizedToken.prototype.leadingTriviaWidth = function () {
                return this._leadingTrivia.fullWidth();
            };
            RealizedToken.prototype.trailingTriviaWidth = function () {
                return this._trailingTrivia.fullWidth();
            };

            RealizedToken.prototype.hasSkippedToken = function () {
                return this._leadingTrivia.hasSkippedToken() || this._trailingTrivia.hasSkippedToken();
            };

            RealizedToken.prototype.leadingTrivia = function () {
                return this._leadingTrivia;
            };
            RealizedToken.prototype.trailingTrivia = function () {
                return this._trailingTrivia;
            };
            return RealizedToken;
        })();

        var ConvertedKeywordToken = (function () {
            function ConvertedKeywordToken(underlyingToken) {
                this.underlyingToken = underlyingToken;
            }
            ConvertedKeywordToken.prototype.kind = function () {
                return 11 /* IdentifierName */;
            };

            ConvertedKeywordToken.prototype.setFullStart = function (fullStart) {
                this.underlyingToken.setFullStart(fullStart);
            };

            ConvertedKeywordToken.prototype.fullStart = function () {
                return this.underlyingToken.fullStart();
            };

            ConvertedKeywordToken.prototype.fullWidth = function () {
                return this.underlyingToken.fullWidth();
            };

            ConvertedKeywordToken.prototype.text = function () {
                return this.underlyingToken.text();
            };

            ConvertedKeywordToken.prototype.syntaxTreeText = function (text) {
                var result = text || TypeScript.syntaxTree(this).text;
                TypeScript.Debug.assert(result);
                return result;
            };

            ConvertedKeywordToken.prototype.fullText = function (text) {
                return this.underlyingToken.fullText(this.syntaxTreeText(text));
            };

            ConvertedKeywordToken.prototype.hasLeadingTrivia = function () {
                return this.underlyingToken.hasLeadingTrivia();
            };

            ConvertedKeywordToken.prototype.hasTrailingTrivia = function () {
                return this.underlyingToken.hasTrailingTrivia();
            };

            ConvertedKeywordToken.prototype.hasSkippedToken = function () {
                return this.underlyingToken.hasSkippedToken();
            };

            ConvertedKeywordToken.prototype.leadingTrivia = function (text) {
                var result = this.underlyingToken.leadingTrivia(this.syntaxTreeText(text));
                result.parent = this;
                return result;
            };

            ConvertedKeywordToken.prototype.trailingTrivia = function (text) {
                var result = this.underlyingToken.trailingTrivia(this.syntaxTreeText(text));
                result.parent = this;
                return result;
            };

            ConvertedKeywordToken.prototype.leadingTriviaWidth = function (text) {
                return this.underlyingToken.leadingTriviaWidth(this.syntaxTreeText(text));
            };

            ConvertedKeywordToken.prototype.trailingTriviaWidth = function (text) {
                return this.underlyingToken.trailingTriviaWidth(this.syntaxTreeText(text));
            };

            ConvertedKeywordToken.prototype.isKeywordConvertedToIdentifier = function () {
                return true;
            };

            ConvertedKeywordToken.prototype.isIncrementallyUnusable = function () {
                // We're incrementally unusable if our underlying token is unusable.
                // For example, we may have: this.public \
                // In this case we will keyword converted to an identifier that is still unusable because
                // it has a trailing skipped token.
                return this.underlyingToken.isIncrementallyUnusable();
            };

            ConvertedKeywordToken.prototype.clone = function () {
                return new ConvertedKeywordToken(this.underlyingToken);
            };
            return ConvertedKeywordToken;
        })();
    })(TypeScript.Syntax || (TypeScript.Syntax = {}));
    var Syntax = TypeScript.Syntax;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />

var TypeScript;
(function (TypeScript) {
    (function (Syntax) {
        var AbstractTrivia = (function () {
            function AbstractTrivia(_kind) {
                this._kind = _kind;
            }
            AbstractTrivia.prototype.kind = function () {
                return this._kind;
            };

            AbstractTrivia.prototype.clone = function () {
                throw TypeScript.Errors.abstract();
            };

            AbstractTrivia.prototype.fullStart = function () {
                throw TypeScript.Errors.abstract();
            };

            AbstractTrivia.prototype.fullWidth = function () {
                throw TypeScript.Errors.abstract();
            };

            AbstractTrivia.prototype.fullText = function () {
                throw TypeScript.Errors.abstract();
            };

            AbstractTrivia.prototype.skippedToken = function () {
                throw TypeScript.Errors.abstract();
            };

            AbstractTrivia.prototype.isWhitespace = function () {
                return this.kind() === 4 /* WhitespaceTrivia */;
            };

            AbstractTrivia.prototype.isComment = function () {
                return this.kind() === 7 /* SingleLineCommentTrivia */ || this.kind() === 6 /* MultiLineCommentTrivia */;
            };

            AbstractTrivia.prototype.isNewLine = function () {
                return this.kind() === 5 /* NewLineTrivia */;
            };

            AbstractTrivia.prototype.isSkippedToken = function () {
                return this.kind() === 8 /* SkippedTokenTrivia */;
            };
            return AbstractTrivia;
        })();

        var SkippedTokenTrivia = (function (_super) {
            __extends(SkippedTokenTrivia, _super);
            function SkippedTokenTrivia(_skippedToken, _fullText) {
                _super.call(this, 8 /* SkippedTokenTrivia */);
                this._skippedToken = _skippedToken;
                this._fullText = _fullText;

                _skippedToken.parent = this;
            }
            SkippedTokenTrivia.prototype.clone = function () {
                return new SkippedTokenTrivia(this._skippedToken.clone(), this._fullText);
            };

            SkippedTokenTrivia.prototype.fullStart = function () {
                return this._skippedToken.fullStart();
            };

            SkippedTokenTrivia.prototype.fullWidth = function () {
                return this.fullText().length;
            };

            SkippedTokenTrivia.prototype.fullText = function () {
                return this._fullText;
            };

            SkippedTokenTrivia.prototype.skippedToken = function () {
                return this._skippedToken;
            };
            return SkippedTokenTrivia;
        })(AbstractTrivia);

        var DeferredTrivia = (function (_super) {
            __extends(DeferredTrivia, _super);
            function DeferredTrivia(kind, _text, _fullStart, _fullWidth) {
                _super.call(this, kind);
                this._text = _text;
                this._fullStart = _fullStart;
                this._fullWidth = _fullWidth;
            }
            DeferredTrivia.prototype.clone = function () {
                return new DeferredTrivia(this.kind(), this._text, this._fullStart, this._fullWidth);
            };

            DeferredTrivia.prototype.fullStart = function () {
                return this._fullStart;
            };

            DeferredTrivia.prototype.fullWidth = function () {
                return this._fullWidth;
            };

            DeferredTrivia.prototype.fullText = function () {
                return this._text.substr(this._fullStart, this._fullWidth);
            };

            DeferredTrivia.prototype.skippedToken = function () {
                throw TypeScript.Errors.invalidOperation();
            };
            return DeferredTrivia;
        })(AbstractTrivia);

        function deferredTrivia(kind, text, fullStart, fullWidth) {
            return new DeferredTrivia(kind, text, fullStart, fullWidth);
        }
        Syntax.deferredTrivia = deferredTrivia;

        function skippedTokenTrivia(token, text) {
            TypeScript.Debug.assert(!token.hasLeadingTrivia());
            TypeScript.Debug.assert(!token.hasTrailingTrivia());
            TypeScript.Debug.assert(token.fullWidth() > 0);
            return new SkippedTokenTrivia(token, token.fullText(text));
        }
        Syntax.skippedTokenTrivia = skippedTokenTrivia;

        // Breaks a multiline trivia up into individual line components.  If the trivia doesn't span
        // any lines, then the result will be a single string with the entire text of the trivia.
        // Otherwise, there will be one entry in the array for each line spanned by the trivia.  Each
        // entry will contain the line separator at the end of the string.
        function splitMultiLineCommentTriviaIntoMultipleLines(trivia) {
            // Debug.assert(trivia.kind === SyntaxKind.MultiLineCommentTrivia);
            var result = [];

            var triviaText = trivia.fullText();
            var currentIndex = 0;

            for (var i = 0; i < triviaText.length; i++) {
                var ch = triviaText.charCodeAt(i);

                // When we run into a newline for the first time, create the string builder and copy
                // all the values up to this newline into it.
                var isCarriageReturnLineFeed = false;
                switch (ch) {
                    case 13 /* carriageReturn */:
                        if (i < triviaText.length - 1 && triviaText.charCodeAt(i + 1) === 10 /* lineFeed */) {
                            // Consume the \r
                            i++;
                        }

                    case 10 /* lineFeed */:
                    case 8233 /* paragraphSeparator */:
                    case 8232 /* lineSeparator */:
                        // Eat from the last starting position through to the end of the newline.
                        result.push(triviaText.substring(currentIndex, i + 1));

                        // Set the current index to *after* the newline.
                        currentIndex = i + 1;
                        continue;
                }
            }

            result.push(triviaText.substring(currentIndex));
            return result;
        }
        Syntax.splitMultiLineCommentTriviaIntoMultipleLines = splitMultiLineCommentTriviaIntoMultipleLines;
    })(TypeScript.Syntax || (TypeScript.Syntax = {}));
    var Syntax = TypeScript.Syntax;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />

var TypeScript;
(function (TypeScript) {
    (function (Syntax) {
        var EmptyTriviaList = (function () {
            function EmptyTriviaList() {
            }
            EmptyTriviaList.prototype.kind = function () {
                return 3 /* TriviaList */;
            };

            EmptyTriviaList.prototype.isShared = function () {
                return true;
            };

            EmptyTriviaList.prototype.count = function () {
                return 0;
            };

            EmptyTriviaList.prototype.syntaxTriviaAt = function (index) {
                throw TypeScript.Errors.argumentOutOfRange("index");
            };

            EmptyTriviaList.prototype.last = function () {
                throw TypeScript.Errors.argumentOutOfRange("index");
            };

            EmptyTriviaList.prototype.fullWidth = function () {
                return 0;
            };

            EmptyTriviaList.prototype.fullText = function () {
                return "";
            };

            EmptyTriviaList.prototype.hasComment = function () {
                return false;
            };

            EmptyTriviaList.prototype.hasNewLine = function () {
                return false;
            };

            EmptyTriviaList.prototype.hasSkippedToken = function () {
                return false;
            };

            EmptyTriviaList.prototype.toArray = function () {
                return [];
            };

            EmptyTriviaList.prototype.clone = function () {
                return this;
            };
            return EmptyTriviaList;
        })();
        ;

        Syntax.emptyTriviaList = new EmptyTriviaList();

        function isComment(trivia) {
            return trivia.kind() === 6 /* MultiLineCommentTrivia */ || trivia.kind() === 7 /* SingleLineCommentTrivia */;
        }

        var SingletonSyntaxTriviaList = (function () {
            function SingletonSyntaxTriviaList(item) {
                this.item = item.clone();
                this.item.parent = this;
            }
            SingletonSyntaxTriviaList.prototype.kind = function () {
                return 3 /* TriviaList */;
            };

            SingletonSyntaxTriviaList.prototype.isShared = function () {
                return false;
            };

            SingletonSyntaxTriviaList.prototype.count = function () {
                return 1;
            };

            SingletonSyntaxTriviaList.prototype.syntaxTriviaAt = function (index) {
                if (index !== 0) {
                    throw TypeScript.Errors.argumentOutOfRange("index");
                }

                return this.item;
            };

            SingletonSyntaxTriviaList.prototype.last = function () {
                return this.item;
            };

            SingletonSyntaxTriviaList.prototype.fullWidth = function () {
                return this.item.fullWidth();
            };

            SingletonSyntaxTriviaList.prototype.fullText = function () {
                return this.item.fullText();
            };

            SingletonSyntaxTriviaList.prototype.hasComment = function () {
                return isComment(this.item);
            };

            SingletonSyntaxTriviaList.prototype.hasNewLine = function () {
                return this.item.kind() === 5 /* NewLineTrivia */;
            };

            SingletonSyntaxTriviaList.prototype.hasSkippedToken = function () {
                return this.item.kind() === 8 /* SkippedTokenTrivia */;
            };

            SingletonSyntaxTriviaList.prototype.toArray = function () {
                return [this.item];
            };

            SingletonSyntaxTriviaList.prototype.clone = function () {
                return new SingletonSyntaxTriviaList(this.item.clone());
            };
            return SingletonSyntaxTriviaList;
        })();

        var NormalSyntaxTriviaList = (function () {
            function NormalSyntaxTriviaList(trivia) {
                var _this = this;
                this.trivia = trivia.map(function (t) {
                    var cloned = t.clone();
                    cloned.parent = _this;
                    return cloned;
                });
            }
            NormalSyntaxTriviaList.prototype.kind = function () {
                return 3 /* TriviaList */;
            };

            NormalSyntaxTriviaList.prototype.isShared = function () {
                return false;
            };

            NormalSyntaxTriviaList.prototype.count = function () {
                return this.trivia.length;
            };

            NormalSyntaxTriviaList.prototype.syntaxTriviaAt = function (index) {
                if (index < 0 || index >= this.trivia.length) {
                    throw TypeScript.Errors.argumentOutOfRange("index");
                }

                return this.trivia[index];
            };

            NormalSyntaxTriviaList.prototype.last = function () {
                return this.trivia[this.trivia.length - 1];
            };

            NormalSyntaxTriviaList.prototype.fullWidth = function () {
                return TypeScript.ArrayUtilities.sum(this.trivia, function (t) {
                    return t.fullWidth();
                });
            };

            NormalSyntaxTriviaList.prototype.fullText = function () {
                var result = [];

                for (var i = 0, n = this.trivia.length; i < n; i++) {
                    result.push(this.trivia[i].fullText());
                }

                return result.join("");
            };

            NormalSyntaxTriviaList.prototype.hasComment = function () {
                for (var i = 0; i < this.trivia.length; i++) {
                    if (isComment(this.trivia[i])) {
                        return true;
                    }
                }

                return false;
            };

            NormalSyntaxTriviaList.prototype.hasNewLine = function () {
                for (var i = 0; i < this.trivia.length; i++) {
                    if (this.trivia[i].kind() === 5 /* NewLineTrivia */) {
                        return true;
                    }
                }

                return false;
            };

            NormalSyntaxTriviaList.prototype.hasSkippedToken = function () {
                for (var i = 0; i < this.trivia.length; i++) {
                    if (this.trivia[i].kind() === 8 /* SkippedTokenTrivia */) {
                        return true;
                    }
                }

                return false;
            };

            NormalSyntaxTriviaList.prototype.toArray = function () {
                return this.trivia.slice(0);
            };

            NormalSyntaxTriviaList.prototype.clone = function () {
                return new NormalSyntaxTriviaList(this.trivia.map(function (t) {
                    return t.clone();
                }));
            };
            return NormalSyntaxTriviaList;
        })();

        function triviaList(trivia) {
            if (trivia === undefined || trivia === null || trivia.length === 0) {
                return Syntax.emptyTriviaList;
            }

            if (trivia.length === 1) {
                return new SingletonSyntaxTriviaList(trivia[0]);
            }

            return new NormalSyntaxTriviaList(trivia);
        }
        Syntax.triviaList = triviaList;
    })(TypeScript.Syntax || (TypeScript.Syntax = {}));
    var Syntax = TypeScript.Syntax;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var SyntaxUtilities = (function () {
        function SyntaxUtilities() {
        }
        SyntaxUtilities.isAnyFunctionExpressionOrDeclaration = function (ast) {
            switch (ast.kind()) {
                case 219 /* SimpleArrowFunctionExpression */:
                case 218 /* ParenthesizedArrowFunctionExpression */:
                case 222 /* FunctionExpression */:
                case 129 /* FunctionDeclaration */:
                case 135 /* MemberFunctionDeclaration */:
                case 241 /* FunctionPropertyAssignment */:
                case 137 /* ConstructorDeclaration */:
                case 139 /* GetAccessor */:
                case 140 /* SetAccessor */:
                    return true;
            }

            return false;
        };

        SyntaxUtilities.isLastTokenOnLine = function (token, text) {
            var _nextToken = TypeScript.nextToken(token, text);
            if (_nextToken === null) {
                return true;
            }

            var lineMap = text.lineMap();
            var tokenLine = lineMap.getLineNumberFromPosition(TypeScript.end(token, text));
            var nextTokenLine = lineMap.getLineNumberFromPosition(TypeScript.start(_nextToken, text));

            return tokenLine !== nextTokenLine;
        };

        SyntaxUtilities.isLeftHandSizeExpression = function (element) {
            if (element) {
                switch (element.kind()) {
                    case 212 /* MemberAccessExpression */:
                    case 221 /* ElementAccessExpression */:
                    case 216 /* ObjectCreationExpression */:
                    case 213 /* InvocationExpression */:
                    case 214 /* ArrayLiteralExpression */:
                    case 217 /* ParenthesizedExpression */:
                    case 215 /* ObjectLiteralExpression */:
                    case 222 /* FunctionExpression */:
                    case 11 /* IdentifierName */:
                    case 12 /* RegularExpressionLiteral */:
                    case 13 /* NumericLiteral */:
                    case 14 /* StringLiteral */:
                    case 24 /* FalseKeyword */:
                    case 32 /* NullKeyword */:
                    case 35 /* ThisKeyword */:
                    case 37 /* TrueKeyword */:
                    case 50 /* SuperKeyword */:
                        return true;
                }
            }

            return false;
        };

        SyntaxUtilities.isExpression = function (element) {
            if (element) {
                switch (element.kind()) {
                    case 11 /* IdentifierName */:
                    case 12 /* RegularExpressionLiteral */:
                    case 13 /* NumericLiteral */:
                    case 14 /* StringLiteral */:
                    case 24 /* FalseKeyword */:
                    case 32 /* NullKeyword */:
                    case 35 /* ThisKeyword */:
                    case 37 /* TrueKeyword */:
                    case 50 /* SuperKeyword */:

                    case 164 /* PlusExpression */:
                    case 165 /* NegateExpression */:
                    case 166 /* BitwiseNotExpression */:
                    case 167 /* LogicalNotExpression */:
                    case 168 /* PreIncrementExpression */:
                    case 169 /* PreDecrementExpression */:
                    case 170 /* DeleteExpression */:
                    case 171 /* TypeOfExpression */:
                    case 172 /* VoidExpression */:
                    case 173 /* CommaExpression */:
                    case 174 /* AssignmentExpression */:
                    case 175 /* AddAssignmentExpression */:
                    case 176 /* SubtractAssignmentExpression */:
                    case 177 /* MultiplyAssignmentExpression */:
                    case 178 /* DivideAssignmentExpression */:
                    case 179 /* ModuloAssignmentExpression */:
                    case 180 /* AndAssignmentExpression */:
                    case 181 /* ExclusiveOrAssignmentExpression */:
                    case 182 /* OrAssignmentExpression */:
                    case 183 /* LeftShiftAssignmentExpression */:
                    case 184 /* SignedRightShiftAssignmentExpression */:
                    case 185 /* UnsignedRightShiftAssignmentExpression */:
                    case 186 /* ConditionalExpression */:
                    case 187 /* LogicalOrExpression */:
                    case 188 /* LogicalAndExpression */:
                    case 189 /* BitwiseOrExpression */:
                    case 190 /* BitwiseExclusiveOrExpression */:
                    case 191 /* BitwiseAndExpression */:
                    case 192 /* EqualsWithTypeConversionExpression */:
                    case 193 /* NotEqualsWithTypeConversionExpression */:
                    case 194 /* EqualsExpression */:
                    case 195 /* NotEqualsExpression */:
                    case 196 /* LessThanExpression */:
                    case 197 /* GreaterThanExpression */:
                    case 198 /* LessThanOrEqualExpression */:
                    case 199 /* GreaterThanOrEqualExpression */:
                    case 200 /* InstanceOfExpression */:
                    case 201 /* InExpression */:
                    case 202 /* LeftShiftExpression */:
                    case 203 /* SignedRightShiftExpression */:
                    case 204 /* UnsignedRightShiftExpression */:
                    case 205 /* MultiplyExpression */:
                    case 206 /* DivideExpression */:
                    case 207 /* ModuloExpression */:
                    case 208 /* AddExpression */:
                    case 209 /* SubtractExpression */:
                    case 210 /* PostIncrementExpression */:
                    case 211 /* PostDecrementExpression */:
                    case 212 /* MemberAccessExpression */:
                    case 213 /* InvocationExpression */:
                    case 214 /* ArrayLiteralExpression */:
                    case 215 /* ObjectLiteralExpression */:
                    case 216 /* ObjectCreationExpression */:
                    case 217 /* ParenthesizedExpression */:
                    case 218 /* ParenthesizedArrowFunctionExpression */:
                    case 219 /* SimpleArrowFunctionExpression */:
                    case 220 /* CastExpression */:
                    case 221 /* ElementAccessExpression */:
                    case 222 /* FunctionExpression */:
                    case 223 /* OmittedExpression */:
                        return true;
                }
            }

            return false;
        };

        SyntaxUtilities.isSwitchClause = function (element) {
            if (element) {
                switch (element.kind()) {
                    case 233 /* CaseSwitchClause */:
                    case 234 /* DefaultSwitchClause */:
                        return true;
                }
            }

            return false;
        };

        SyntaxUtilities.isTypeMember = function (element) {
            if (element) {
                switch (element.kind()) {
                    case 143 /* ConstructSignature */:
                    case 145 /* MethodSignature */:
                    case 144 /* IndexSignature */:
                    case 141 /* PropertySignature */:
                    case 142 /* CallSignature */:
                        return true;
                }
            }

            return false;
        };

        SyntaxUtilities.isClassElement = function (element) {
            if (element) {
                switch (element.kind()) {
                    case 137 /* ConstructorDeclaration */:
                    case 138 /* IndexMemberDeclaration */:
                    case 135 /* MemberFunctionDeclaration */:
                    case 139 /* GetAccessor */:
                    case 140 /* SetAccessor */:
                    case 135 /* MemberFunctionDeclaration */:
                    case 136 /* MemberVariableDeclaration */:
                        return true;
                }
            }

            return false;
        };

        SyntaxUtilities.isModuleElement = function (element) {
            if (element) {
                switch (element.kind()) {
                    case 133 /* ImportDeclaration */:
                    case 134 /* ExportAssignment */:
                    case 131 /* ClassDeclaration */:
                    case 128 /* InterfaceDeclaration */:
                    case 130 /* ModuleDeclaration */:
                    case 132 /* EnumDeclaration */:

                    case 129 /* FunctionDeclaration */:
                    case 148 /* VariableStatement */:
                    case 146 /* Block */:
                    case 147 /* IfStatement */:
                    case 149 /* ExpressionStatement */:
                    case 157 /* ThrowStatement */:
                    case 150 /* ReturnStatement */:
                    case 151 /* SwitchStatement */:
                    case 152 /* BreakStatement */:
                    case 153 /* ContinueStatement */:
                    case 155 /* ForInStatement */:
                    case 154 /* ForStatement */:
                    case 158 /* WhileStatement */:
                    case 163 /* WithStatement */:
                    case 156 /* EmptyStatement */:
                    case 159 /* TryStatement */:
                    case 160 /* LabeledStatement */:
                    case 161 /* DoStatement */:
                    case 162 /* DebuggerStatement */:
                        return true;
                }
            }

            return false;
        };

        SyntaxUtilities.isStatement = function (element) {
            if (element) {
                switch (element.kind()) {
                    case 129 /* FunctionDeclaration */:
                    case 148 /* VariableStatement */:
                    case 146 /* Block */:
                    case 147 /* IfStatement */:
                    case 149 /* ExpressionStatement */:
                    case 157 /* ThrowStatement */:
                    case 150 /* ReturnStatement */:
                    case 151 /* SwitchStatement */:
                    case 152 /* BreakStatement */:
                    case 153 /* ContinueStatement */:
                    case 155 /* ForInStatement */:
                    case 154 /* ForStatement */:
                    case 158 /* WhileStatement */:
                    case 163 /* WithStatement */:
                    case 156 /* EmptyStatement */:
                    case 159 /* TryStatement */:
                    case 160 /* LabeledStatement */:
                    case 161 /* DoStatement */:
                    case 162 /* DebuggerStatement */:
                        return true;
                }
            }

            return false;
        };

        SyntaxUtilities.isAngleBracket = function (positionedElement) {
            var element = positionedElement;
            var parent = positionedElement.parent;
            if (parent !== null && (element.kind() === 80 /* LessThanToken */ || element.kind() === 81 /* GreaterThanToken */)) {
                switch (parent.kind()) {
                    case 228 /* TypeArgumentList */:
                    case 229 /* TypeParameterList */:
                    case 220 /* CastExpression */:
                        return true;
                }
            }

            return false;
        };

        SyntaxUtilities.getToken = function (list, kind) {
            for (var i = 0, n = list.length; i < n; i++) {
                var token = list[i];
                if (token.kind() === kind) {
                    return token;
                }
            }

            return null;
        };

        SyntaxUtilities.containsToken = function (list, kind) {
            return SyntaxUtilities.getToken(list, kind) !== null;
        };

        SyntaxUtilities.hasExportKeyword = function (moduleElement) {
            return SyntaxUtilities.getExportKeyword(moduleElement) !== null;
        };

        SyntaxUtilities.getExportKeyword = function (moduleElement) {
            switch (moduleElement.kind()) {
                case 130 /* ModuleDeclaration */:
                case 131 /* ClassDeclaration */:
                case 129 /* FunctionDeclaration */:
                case 148 /* VariableStatement */:
                case 132 /* EnumDeclaration */:
                case 128 /* InterfaceDeclaration */:
                case 133 /* ImportDeclaration */:
                    return SyntaxUtilities.getToken(moduleElement.modifiers, 47 /* ExportKeyword */);
                default:
                    return null;
            }
        };

        SyntaxUtilities.isAmbientDeclarationSyntax = function (positionNode) {
            if (!positionNode) {
                return false;
            }

            var node = positionNode;
            switch (node.kind()) {
                case 130 /* ModuleDeclaration */:
                case 131 /* ClassDeclaration */:
                case 129 /* FunctionDeclaration */:
                case 148 /* VariableStatement */:
                case 132 /* EnumDeclaration */:
                    if (SyntaxUtilities.containsToken(node.modifiers, 63 /* DeclareKeyword */)) {
                        return true;
                    }

                case 133 /* ImportDeclaration */:
                case 137 /* ConstructorDeclaration */:
                case 135 /* MemberFunctionDeclaration */:
                case 139 /* GetAccessor */:
                case 140 /* SetAccessor */:
                case 136 /* MemberVariableDeclaration */:
                    if (SyntaxUtilities.isClassElement(node) || SyntaxUtilities.isModuleElement(node)) {
                        return SyntaxUtilities.isAmbientDeclarationSyntax(TypeScript.Syntax.containingNode(positionNode));
                    }

                case 243 /* EnumElement */:
                    return SyntaxUtilities.isAmbientDeclarationSyntax(TypeScript.Syntax.containingNode(TypeScript.Syntax.containingNode(positionNode)));

                default:
                    return SyntaxUtilities.isAmbientDeclarationSyntax(TypeScript.Syntax.containingNode(positionNode));
            }
        };
        return SyntaxUtilities;
    })();
    TypeScript.SyntaxUtilities = SyntaxUtilities;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    function visitNodeOrToken(visitor, element) {
        if (element === null) {
            return null;
        }
        if (TypeScript.isToken(element)) {
            return visitor.visitToken(element);
        }
        switch (element.kind()) {
            case 120 /* SourceUnit */: return visitor.visitSourceUnit(element);
            case 121 /* QualifiedName */: return visitor.visitQualifiedName(element);
            case 122 /* ObjectType */: return visitor.visitObjectType(element);
            case 123 /* FunctionType */: return visitor.visitFunctionType(element);
            case 124 /* ArrayType */: return visitor.visitArrayType(element);
            case 125 /* ConstructorType */: return visitor.visitConstructorType(element);
            case 126 /* GenericType */: return visitor.visitGenericType(element);
            case 127 /* TypeQuery */: return visitor.visitTypeQuery(element);
            case 128 /* InterfaceDeclaration */: return visitor.visitInterfaceDeclaration(element);
            case 129 /* FunctionDeclaration */: return visitor.visitFunctionDeclaration(element);
            case 130 /* ModuleDeclaration */: return visitor.visitModuleDeclaration(element);
            case 131 /* ClassDeclaration */: return visitor.visitClassDeclaration(element);
            case 132 /* EnumDeclaration */: return visitor.visitEnumDeclaration(element);
            case 133 /* ImportDeclaration */: return visitor.visitImportDeclaration(element);
            case 134 /* ExportAssignment */: return visitor.visitExportAssignment(element);
            case 135 /* MemberFunctionDeclaration */: return visitor.visitMemberFunctionDeclaration(element);
            case 136 /* MemberVariableDeclaration */: return visitor.visitMemberVariableDeclaration(element);
            case 137 /* ConstructorDeclaration */: return visitor.visitConstructorDeclaration(element);
            case 138 /* IndexMemberDeclaration */: return visitor.visitIndexMemberDeclaration(element);
            case 139 /* GetAccessor */: return visitor.visitGetAccessor(element);
            case 140 /* SetAccessor */: return visitor.visitSetAccessor(element);
            case 141 /* PropertySignature */: return visitor.visitPropertySignature(element);
            case 142 /* CallSignature */: return visitor.visitCallSignature(element);
            case 143 /* ConstructSignature */: return visitor.visitConstructSignature(element);
            case 144 /* IndexSignature */: return visitor.visitIndexSignature(element);
            case 145 /* MethodSignature */: return visitor.visitMethodSignature(element);
            case 146 /* Block */: return visitor.visitBlock(element);
            case 147 /* IfStatement */: return visitor.visitIfStatement(element);
            case 148 /* VariableStatement */: return visitor.visitVariableStatement(element);
            case 149 /* ExpressionStatement */: return visitor.visitExpressionStatement(element);
            case 150 /* ReturnStatement */: return visitor.visitReturnStatement(element);
            case 151 /* SwitchStatement */: return visitor.visitSwitchStatement(element);
            case 152 /* BreakStatement */: return visitor.visitBreakStatement(element);
            case 153 /* ContinueStatement */: return visitor.visitContinueStatement(element);
            case 154 /* ForStatement */: return visitor.visitForStatement(element);
            case 155 /* ForInStatement */: return visitor.visitForInStatement(element);
            case 156 /* EmptyStatement */: return visitor.visitEmptyStatement(element);
            case 157 /* ThrowStatement */: return visitor.visitThrowStatement(element);
            case 158 /* WhileStatement */: return visitor.visitWhileStatement(element);
            case 159 /* TryStatement */: return visitor.visitTryStatement(element);
            case 160 /* LabeledStatement */: return visitor.visitLabeledStatement(element);
            case 161 /* DoStatement */: return visitor.visitDoStatement(element);
            case 162 /* DebuggerStatement */: return visitor.visitDebuggerStatement(element);
            case 163 /* WithStatement */: return visitor.visitWithStatement(element);
            case 168 /* PreIncrementExpression */:
            case 169 /* PreDecrementExpression */:
            case 164 /* PlusExpression */:
            case 165 /* NegateExpression */:
            case 166 /* BitwiseNotExpression */:
            case 167 /* LogicalNotExpression */:
                return visitor.visitPrefixUnaryExpression(element);
            case 170 /* DeleteExpression */: return visitor.visitDeleteExpression(element);
            case 171 /* TypeOfExpression */: return visitor.visitTypeOfExpression(element);
            case 172 /* VoidExpression */: return visitor.visitVoidExpression(element);
            case 186 /* ConditionalExpression */: return visitor.visitConditionalExpression(element);
            case 205 /* MultiplyExpression */:
            case 206 /* DivideExpression */:
            case 207 /* ModuloExpression */:
            case 208 /* AddExpression */:
            case 209 /* SubtractExpression */:
            case 202 /* LeftShiftExpression */:
            case 203 /* SignedRightShiftExpression */:
            case 204 /* UnsignedRightShiftExpression */:
            case 196 /* LessThanExpression */:
            case 197 /* GreaterThanExpression */:
            case 198 /* LessThanOrEqualExpression */:
            case 199 /* GreaterThanOrEqualExpression */:
            case 200 /* InstanceOfExpression */:
            case 201 /* InExpression */:
            case 192 /* EqualsWithTypeConversionExpression */:
            case 193 /* NotEqualsWithTypeConversionExpression */:
            case 194 /* EqualsExpression */:
            case 195 /* NotEqualsExpression */:
            case 191 /* BitwiseAndExpression */:
            case 190 /* BitwiseExclusiveOrExpression */:
            case 189 /* BitwiseOrExpression */:
            case 188 /* LogicalAndExpression */:
            case 187 /* LogicalOrExpression */:
            case 182 /* OrAssignmentExpression */:
            case 180 /* AndAssignmentExpression */:
            case 181 /* ExclusiveOrAssignmentExpression */:
            case 183 /* LeftShiftAssignmentExpression */:
            case 184 /* SignedRightShiftAssignmentExpression */:
            case 185 /* UnsignedRightShiftAssignmentExpression */:
            case 175 /* AddAssignmentExpression */:
            case 176 /* SubtractAssignmentExpression */:
            case 177 /* MultiplyAssignmentExpression */:
            case 178 /* DivideAssignmentExpression */:
            case 179 /* ModuloAssignmentExpression */:
            case 174 /* AssignmentExpression */:
            case 173 /* CommaExpression */:
                return visitor.visitBinaryExpression(element);
            case 210 /* PostIncrementExpression */:
            case 211 /* PostDecrementExpression */:
                return visitor.visitPostfixUnaryExpression(element);
            case 212 /* MemberAccessExpression */: return visitor.visitMemberAccessExpression(element);
            case 213 /* InvocationExpression */: return visitor.visitInvocationExpression(element);
            case 214 /* ArrayLiteralExpression */: return visitor.visitArrayLiteralExpression(element);
            case 215 /* ObjectLiteralExpression */: return visitor.visitObjectLiteralExpression(element);
            case 216 /* ObjectCreationExpression */: return visitor.visitObjectCreationExpression(element);
            case 217 /* ParenthesizedExpression */: return visitor.visitParenthesizedExpression(element);
            case 218 /* ParenthesizedArrowFunctionExpression */: return visitor.visitParenthesizedArrowFunctionExpression(element);
            case 219 /* SimpleArrowFunctionExpression */: return visitor.visitSimpleArrowFunctionExpression(element);
            case 220 /* CastExpression */: return visitor.visitCastExpression(element);
            case 221 /* ElementAccessExpression */: return visitor.visitElementAccessExpression(element);
            case 222 /* FunctionExpression */: return visitor.visitFunctionExpression(element);
            case 223 /* OmittedExpression */: return visitor.visitOmittedExpression(element);
            case 224 /* VariableDeclaration */: return visitor.visitVariableDeclaration(element);
            case 225 /* VariableDeclarator */: return visitor.visitVariableDeclarator(element);
            case 226 /* ArgumentList */: return visitor.visitArgumentList(element);
            case 227 /* ParameterList */: return visitor.visitParameterList(element);
            case 228 /* TypeArgumentList */: return visitor.visitTypeArgumentList(element);
            case 229 /* TypeParameterList */: return visitor.visitTypeParameterList(element);
            case 230 /* ExtendsHeritageClause */:
            case 231 /* ImplementsHeritageClause */:
                return visitor.visitHeritageClause(element);
            case 232 /* EqualsValueClause */: return visitor.visitEqualsValueClause(element);
            case 233 /* CaseSwitchClause */: return visitor.visitCaseSwitchClause(element);
            case 234 /* DefaultSwitchClause */: return visitor.visitDefaultSwitchClause(element);
            case 235 /* ElseClause */: return visitor.visitElseClause(element);
            case 236 /* CatchClause */: return visitor.visitCatchClause(element);
            case 237 /* FinallyClause */: return visitor.visitFinallyClause(element);
            case 238 /* TypeParameter */: return visitor.visitTypeParameter(element);
            case 239 /* Constraint */: return visitor.visitConstraint(element);
            case 240 /* SimplePropertyAssignment */: return visitor.visitSimplePropertyAssignment(element);
            case 241 /* FunctionPropertyAssignment */: return visitor.visitFunctionPropertyAssignment(element);
            case 242 /* Parameter */: return visitor.visitParameter(element);
            case 243 /* EnumElement */: return visitor.visitEnumElement(element);
            case 244 /* TypeAnnotation */: return visitor.visitTypeAnnotation(element);
            case 245 /* ExternalModuleReference */: return visitor.visitExternalModuleReference(element);
            case 246 /* ModuleNameModuleReference */: return visitor.visitModuleNameModuleReference(element);
        }

        throw TypeScript.Errors.invalidOperation();
    }
    TypeScript.visitNodeOrToken = visitNodeOrToken;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var SyntaxWalker = (function () {
        function SyntaxWalker() {
        }
        SyntaxWalker.prototype.visitToken = function (token) {
        };

        SyntaxWalker.prototype.visitNode = function (node) {
            TypeScript.visitNodeOrToken(this, node);
        };

        SyntaxWalker.prototype.visitNodeOrToken = function (nodeOrToken) {
            if (TypeScript.isToken(nodeOrToken)) {
                this.visitToken(nodeOrToken);
            } else {
                this.visitNode(nodeOrToken);
            }
        };

        SyntaxWalker.prototype.visitOptionalToken = function (token) {
            if (token === null) {
                return;
            }

            this.visitToken(token);
        };

        SyntaxWalker.prototype.visitOptionalNode = function (node) {
            if (node === null) {
                return;
            }

            this.visitNode(node);
        };

        SyntaxWalker.prototype.visitOptionalNodeOrToken = function (nodeOrToken) {
            if (nodeOrToken === null) {
                return;
            }

            this.visitNodeOrToken(nodeOrToken);
        };

        SyntaxWalker.prototype.visitList = function (list) {
            for (var i = 0, n = list.length; i < n; i++) {
                this.visitNodeOrToken(list[i]);
            }
        };

        SyntaxWalker.prototype.visitSeparatedList = function (list) {
            for (var i = 0, n = TypeScript.childCount(list); i < n; i++) {
                var item = TypeScript.childAt(list, i);
                this.visitNodeOrToken(item);
            }
        };

        SyntaxWalker.prototype.visitSourceUnit = function (node) {
            this.visitList(node.moduleElements);
            this.visitToken(node.endOfFileToken);
        };

        SyntaxWalker.prototype.visitQualifiedName = function (node) {
            this.visitNodeOrToken(node.left);
            this.visitToken(node.dotToken);
            this.visitToken(node.right);
        };

        SyntaxWalker.prototype.visitObjectType = function (node) {
            this.visitToken(node.openBraceToken);
            this.visitSeparatedList(node.typeMembers);
            this.visitToken(node.closeBraceToken);
        };

        SyntaxWalker.prototype.visitFunctionType = function (node) {
            this.visitOptionalNode(node.typeParameterList);
            this.visitNode(node.parameterList);
            this.visitToken(node.equalsGreaterThanToken);
            this.visitNodeOrToken(node.type);
        };

        SyntaxWalker.prototype.visitArrayType = function (node) {
            this.visitNodeOrToken(node.type);
            this.visitToken(node.openBracketToken);
            this.visitToken(node.closeBracketToken);
        };

        SyntaxWalker.prototype.visitConstructorType = function (node) {
            this.visitToken(node.newKeyword);
            this.visitOptionalNode(node.typeParameterList);
            this.visitNode(node.parameterList);
            this.visitToken(node.equalsGreaterThanToken);
            this.visitNodeOrToken(node.type);
        };

        SyntaxWalker.prototype.visitGenericType = function (node) {
            this.visitNodeOrToken(node.name);
            this.visitNode(node.typeArgumentList);
        };

        SyntaxWalker.prototype.visitTypeQuery = function (node) {
            this.visitToken(node.typeOfKeyword);
            this.visitNodeOrToken(node.name);
        };

        SyntaxWalker.prototype.visitInterfaceDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.interfaceKeyword);
            this.visitToken(node.identifier);
            this.visitOptionalNode(node.typeParameterList);
            this.visitList(node.heritageClauses);
            this.visitNode(node.body);
        };

        SyntaxWalker.prototype.visitFunctionDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.functionKeyword);
            this.visitToken(node.identifier);
            this.visitNode(node.callSignature);
            this.visitOptionalNode(node.block);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitModuleDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.moduleKeyword);
            this.visitOptionalNodeOrToken(node.name);
            this.visitOptionalToken(node.stringLiteral);
            this.visitToken(node.openBraceToken);
            this.visitList(node.moduleElements);
            this.visitToken(node.closeBraceToken);
        };

        SyntaxWalker.prototype.visitClassDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.classKeyword);
            this.visitToken(node.identifier);
            this.visitOptionalNode(node.typeParameterList);
            this.visitList(node.heritageClauses);
            this.visitToken(node.openBraceToken);
            this.visitList(node.classElements);
            this.visitToken(node.closeBraceToken);
        };

        SyntaxWalker.prototype.visitEnumDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.enumKeyword);
            this.visitToken(node.identifier);
            this.visitToken(node.openBraceToken);
            this.visitSeparatedList(node.enumElements);
            this.visitToken(node.closeBraceToken);
        };

        SyntaxWalker.prototype.visitImportDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.importKeyword);
            this.visitToken(node.identifier);
            this.visitToken(node.equalsToken);
            this.visitNodeOrToken(node.moduleReference);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitExportAssignment = function (node) {
            this.visitToken(node.exportKeyword);
            this.visitToken(node.equalsToken);
            this.visitToken(node.identifier);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitMemberFunctionDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.propertyName);
            this.visitNode(node.callSignature);
            this.visitOptionalNode(node.block);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitMemberVariableDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitNode(node.variableDeclarator);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitConstructorDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.constructorKeyword);
            this.visitNode(node.callSignature);
            this.visitOptionalNode(node.block);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitIndexMemberDeclaration = function (node) {
            this.visitList(node.modifiers);
            this.visitNode(node.indexSignature);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitGetAccessor = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.getKeyword);
            this.visitToken(node.propertyName);
            this.visitNode(node.callSignature);
            this.visitNode(node.block);
        };

        SyntaxWalker.prototype.visitSetAccessor = function (node) {
            this.visitList(node.modifiers);
            this.visitToken(node.setKeyword);
            this.visitToken(node.propertyName);
            this.visitNode(node.callSignature);
            this.visitNode(node.block);
        };

        SyntaxWalker.prototype.visitPropertySignature = function (node) {
            this.visitToken(node.propertyName);
            this.visitOptionalToken(node.questionToken);
            this.visitOptionalNode(node.typeAnnotation);
        };

        SyntaxWalker.prototype.visitCallSignature = function (node) {
            this.visitOptionalNode(node.typeParameterList);
            this.visitNode(node.parameterList);
            this.visitOptionalNode(node.typeAnnotation);
        };

        SyntaxWalker.prototype.visitConstructSignature = function (node) {
            this.visitToken(node.newKeyword);
            this.visitNode(node.callSignature);
        };

        SyntaxWalker.prototype.visitIndexSignature = function (node) {
            this.visitToken(node.openBracketToken);
            this.visitSeparatedList(node.parameters);
            this.visitToken(node.closeBracketToken);
            this.visitOptionalNode(node.typeAnnotation);
        };

        SyntaxWalker.prototype.visitMethodSignature = function (node) {
            this.visitToken(node.propertyName);
            this.visitOptionalToken(node.questionToken);
            this.visitNode(node.callSignature);
        };

        SyntaxWalker.prototype.visitBlock = function (node) {
            this.visitToken(node.openBraceToken);
            this.visitList(node.statements);
            this.visitToken(node.closeBraceToken);
        };

        SyntaxWalker.prototype.visitIfStatement = function (node) {
            this.visitToken(node.ifKeyword);
            this.visitToken(node.openParenToken);
            this.visitNodeOrToken(node.condition);
            this.visitToken(node.closeParenToken);
            this.visitNodeOrToken(node.statement);
            this.visitOptionalNode(node.elseClause);
        };

        SyntaxWalker.prototype.visitVariableStatement = function (node) {
            this.visitList(node.modifiers);
            this.visitNode(node.variableDeclaration);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitExpressionStatement = function (node) {
            this.visitNodeOrToken(node.expression);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitReturnStatement = function (node) {
            this.visitToken(node.returnKeyword);
            this.visitOptionalNodeOrToken(node.expression);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitSwitchStatement = function (node) {
            this.visitToken(node.switchKeyword);
            this.visitToken(node.openParenToken);
            this.visitNodeOrToken(node.expression);
            this.visitToken(node.closeParenToken);
            this.visitToken(node.openBraceToken);
            this.visitList(node.switchClauses);
            this.visitToken(node.closeBraceToken);
        };

        SyntaxWalker.prototype.visitBreakStatement = function (node) {
            this.visitToken(node.breakKeyword);
            this.visitOptionalToken(node.identifier);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitContinueStatement = function (node) {
            this.visitToken(node.continueKeyword);
            this.visitOptionalToken(node.identifier);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitForStatement = function (node) {
            this.visitToken(node.forKeyword);
            this.visitToken(node.openParenToken);
            this.visitOptionalNode(node.variableDeclaration);
            this.visitOptionalNodeOrToken(node.initializer);
            this.visitToken(node.firstSemicolonToken);
            this.visitOptionalNodeOrToken(node.condition);
            this.visitToken(node.secondSemicolonToken);
            this.visitOptionalNodeOrToken(node.incrementor);
            this.visitToken(node.closeParenToken);
            this.visitNodeOrToken(node.statement);
        };

        SyntaxWalker.prototype.visitForInStatement = function (node) {
            this.visitToken(node.forKeyword);
            this.visitToken(node.openParenToken);
            this.visitOptionalNode(node.variableDeclaration);
            this.visitOptionalNodeOrToken(node.left);
            this.visitToken(node.inKeyword);
            this.visitNodeOrToken(node.expression);
            this.visitToken(node.closeParenToken);
            this.visitNodeOrToken(node.statement);
        };

        SyntaxWalker.prototype.visitEmptyStatement = function (node) {
            this.visitToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitThrowStatement = function (node) {
            this.visitToken(node.throwKeyword);
            this.visitNodeOrToken(node.expression);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitWhileStatement = function (node) {
            this.visitToken(node.whileKeyword);
            this.visitToken(node.openParenToken);
            this.visitNodeOrToken(node.condition);
            this.visitToken(node.closeParenToken);
            this.visitNodeOrToken(node.statement);
        };

        SyntaxWalker.prototype.visitTryStatement = function (node) {
            this.visitToken(node.tryKeyword);
            this.visitNode(node.block);
            this.visitOptionalNode(node.catchClause);
            this.visitOptionalNode(node.finallyClause);
        };

        SyntaxWalker.prototype.visitLabeledStatement = function (node) {
            this.visitToken(node.identifier);
            this.visitToken(node.colonToken);
            this.visitNodeOrToken(node.statement);
        };

        SyntaxWalker.prototype.visitDoStatement = function (node) {
            this.visitToken(node.doKeyword);
            this.visitNodeOrToken(node.statement);
            this.visitToken(node.whileKeyword);
            this.visitToken(node.openParenToken);
            this.visitNodeOrToken(node.condition);
            this.visitToken(node.closeParenToken);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitDebuggerStatement = function (node) {
            this.visitToken(node.debuggerKeyword);
            this.visitOptionalToken(node.semicolonToken);
        };

        SyntaxWalker.prototype.visitWithStatement = function (node) {
            this.visitToken(node.withKeyword);
            this.visitToken(node.openParenToken);
            this.visitNodeOrToken(node.condition);
            this.visitToken(node.closeParenToken);
            this.visitNodeOrToken(node.statement);
        };

        SyntaxWalker.prototype.visitPrefixUnaryExpression = function (node) {
            this.visitToken(node.operatorToken);
            this.visitNodeOrToken(node.operand);
        };

        SyntaxWalker.prototype.visitDeleteExpression = function (node) {
            this.visitToken(node.deleteKeyword);
            this.visitNodeOrToken(node.expression);
        };

        SyntaxWalker.prototype.visitTypeOfExpression = function (node) {
            this.visitToken(node.typeOfKeyword);
            this.visitNodeOrToken(node.expression);
        };

        SyntaxWalker.prototype.visitVoidExpression = function (node) {
            this.visitToken(node.voidKeyword);
            this.visitNodeOrToken(node.expression);
        };

        SyntaxWalker.prototype.visitConditionalExpression = function (node) {
            this.visitNodeOrToken(node.condition);
            this.visitToken(node.questionToken);
            this.visitNodeOrToken(node.whenTrue);
            this.visitToken(node.colonToken);
            this.visitNodeOrToken(node.whenFalse);
        };

        SyntaxWalker.prototype.visitBinaryExpression = function (node) {
            this.visitNodeOrToken(node.left);
            this.visitToken(node.operatorToken);
            this.visitNodeOrToken(node.right);
        };

        SyntaxWalker.prototype.visitPostfixUnaryExpression = function (node) {
            this.visitNodeOrToken(node.operand);
            this.visitToken(node.operatorToken);
        };

        SyntaxWalker.prototype.visitMemberAccessExpression = function (node) {
            this.visitNodeOrToken(node.expression);
            this.visitToken(node.dotToken);
            this.visitToken(node.name);
        };

        SyntaxWalker.prototype.visitInvocationExpression = function (node) {
            this.visitNodeOrToken(node.expression);
            this.visitNode(node.argumentList);
        };

        SyntaxWalker.prototype.visitArrayLiteralExpression = function (node) {
            this.visitToken(node.openBracketToken);
            this.visitSeparatedList(node.expressions);
            this.visitToken(node.closeBracketToken);
        };

        SyntaxWalker.prototype.visitObjectLiteralExpression = function (node) {
            this.visitToken(node.openBraceToken);
            this.visitSeparatedList(node.propertyAssignments);
            this.visitToken(node.closeBraceToken);
        };

        SyntaxWalker.prototype.visitObjectCreationExpression = function (node) {
            this.visitToken(node.newKeyword);
            this.visitNodeOrToken(node.expression);
            this.visitOptionalNode(node.argumentList);
        };

        SyntaxWalker.prototype.visitParenthesizedExpression = function (node) {
            this.visitToken(node.openParenToken);
            this.visitNodeOrToken(node.expression);
            this.visitToken(node.closeParenToken);
        };

        SyntaxWalker.prototype.visitParenthesizedArrowFunctionExpression = function (node) {
            this.visitNode(node.callSignature);
            this.visitToken(node.equalsGreaterThanToken);
            this.visitOptionalNode(node.block);
            this.visitOptionalNodeOrToken(node.expression);
        };

        SyntaxWalker.prototype.visitSimpleArrowFunctionExpression = function (node) {
            this.visitNode(node.parameter);
            this.visitToken(node.equalsGreaterThanToken);
            this.visitOptionalNode(node.block);
            this.visitOptionalNodeOrToken(node.expression);
        };

        SyntaxWalker.prototype.visitCastExpression = function (node) {
            this.visitToken(node.lessThanToken);
            this.visitNodeOrToken(node.type);
            this.visitToken(node.greaterThanToken);
            this.visitNodeOrToken(node.expression);
        };

        SyntaxWalker.prototype.visitElementAccessExpression = function (node) {
            this.visitNodeOrToken(node.expression);
            this.visitToken(node.openBracketToken);
            this.visitNodeOrToken(node.argumentExpression);
            this.visitToken(node.closeBracketToken);
        };

        SyntaxWalker.prototype.visitFunctionExpression = function (node) {
            this.visitToken(node.functionKeyword);
            this.visitOptionalToken(node.identifier);
            this.visitNode(node.callSignature);
            this.visitNode(node.block);
        };

        SyntaxWalker.prototype.visitOmittedExpression = function (node) {
        };

        SyntaxWalker.prototype.visitVariableDeclaration = function (node) {
            this.visitToken(node.varKeyword);
            this.visitSeparatedList(node.variableDeclarators);
        };

        SyntaxWalker.prototype.visitVariableDeclarator = function (node) {
            this.visitToken(node.propertyName);
            this.visitOptionalNode(node.typeAnnotation);
            this.visitOptionalNode(node.equalsValueClause);
        };

        SyntaxWalker.prototype.visitArgumentList = function (node) {
            this.visitOptionalNode(node.typeArgumentList);
            this.visitToken(node.openParenToken);
            this.visitSeparatedList(node.arguments);
            this.visitToken(node.closeParenToken);
        };

        SyntaxWalker.prototype.visitParameterList = function (node) {
            this.visitToken(node.openParenToken);
            this.visitSeparatedList(node.parameters);
            this.visitToken(node.closeParenToken);
        };

        SyntaxWalker.prototype.visitTypeArgumentList = function (node) {
            this.visitToken(node.lessThanToken);
            this.visitSeparatedList(node.typeArguments);
            this.visitToken(node.greaterThanToken);
        };

        SyntaxWalker.prototype.visitTypeParameterList = function (node) {
            this.visitToken(node.lessThanToken);
            this.visitSeparatedList(node.typeParameters);
            this.visitToken(node.greaterThanToken);
        };

        SyntaxWalker.prototype.visitHeritageClause = function (node) {
            this.visitToken(node.extendsOrImplementsKeyword);
            this.visitSeparatedList(node.typeNames);
        };

        SyntaxWalker.prototype.visitEqualsValueClause = function (node) {
            this.visitToken(node.equalsToken);
            this.visitNodeOrToken(node.value);
        };

        SyntaxWalker.prototype.visitCaseSwitchClause = function (node) {
            this.visitToken(node.caseKeyword);
            this.visitNodeOrToken(node.expression);
            this.visitToken(node.colonToken);
            this.visitList(node.statements);
        };

        SyntaxWalker.prototype.visitDefaultSwitchClause = function (node) {
            this.visitToken(node.defaultKeyword);
            this.visitToken(node.colonToken);
            this.visitList(node.statements);
        };

        SyntaxWalker.prototype.visitElseClause = function (node) {
            this.visitToken(node.elseKeyword);
            this.visitNodeOrToken(node.statement);
        };

        SyntaxWalker.prototype.visitCatchClause = function (node) {
            this.visitToken(node.catchKeyword);
            this.visitToken(node.openParenToken);
            this.visitToken(node.identifier);
            this.visitOptionalNode(node.typeAnnotation);
            this.visitToken(node.closeParenToken);
            this.visitNode(node.block);
        };

        SyntaxWalker.prototype.visitFinallyClause = function (node) {
            this.visitToken(node.finallyKeyword);
            this.visitNode(node.block);
        };

        SyntaxWalker.prototype.visitTypeParameter = function (node) {
            this.visitToken(node.identifier);
            this.visitOptionalNode(node.constraint);
        };

        SyntaxWalker.prototype.visitConstraint = function (node) {
            this.visitToken(node.extendsKeyword);
            this.visitNodeOrToken(node.type);
        };

        SyntaxWalker.prototype.visitSimplePropertyAssignment = function (node) {
            this.visitToken(node.propertyName);
            this.visitToken(node.colonToken);
            this.visitNodeOrToken(node.expression);
        };

        SyntaxWalker.prototype.visitFunctionPropertyAssignment = function (node) {
            this.visitToken(node.propertyName);
            this.visitNode(node.callSignature);
            this.visitNode(node.block);
        };

        SyntaxWalker.prototype.visitParameter = function (node) {
            this.visitOptionalToken(node.dotDotDotToken);
            this.visitList(node.modifiers);
            this.visitToken(node.identifier);
            this.visitOptionalToken(node.questionToken);
            this.visitOptionalNode(node.typeAnnotation);
            this.visitOptionalNode(node.equalsValueClause);
        };

        SyntaxWalker.prototype.visitEnumElement = function (node) {
            this.visitToken(node.propertyName);
            this.visitOptionalNode(node.equalsValueClause);
        };

        SyntaxWalker.prototype.visitTypeAnnotation = function (node) {
            this.visitToken(node.colonToken);
            this.visitNodeOrToken(node.type);
        };

        SyntaxWalker.prototype.visitExternalModuleReference = function (node) {
            this.visitToken(node.requireKeyword);
            this.visitToken(node.openParenToken);
            this.visitToken(node.stringLiteral);
            this.visitToken(node.closeParenToken);
        };

        SyntaxWalker.prototype.visitModuleNameModuleReference = function (node) {
            this.visitNodeOrToken(node.moduleName);
        };
        return SyntaxWalker;
    })();
    TypeScript.SyntaxWalker = SyntaxWalker;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var DepthLimitedWalker = (function (_super) {
        __extends(DepthLimitedWalker, _super);
        function DepthLimitedWalker(maximumDepth) {
            _super.call(this);
            this._depth = 0;
            this._maximumDepth = 0;
            this._maximumDepth = maximumDepth;
        }
        DepthLimitedWalker.prototype.visitNode = function (node) {
            if (this._depth < this._maximumDepth) {
                this._depth++;
                _super.prototype.visitNode.call(this, node);
                this._depth--;
            }
        };
        return DepthLimitedWalker;
    })(TypeScript.SyntaxWalker);
    TypeScript.DepthLimitedWalker = DepthLimitedWalker;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (Parser) {
        // The factory used to produce parse tree nodes.  Injected normally by the
        // TypeScript.Syntax.Abstract or TypeScript.Syntax.Conrete modules.
        Parser.syntaxFactory;

        

        

        var arrayPool = [];
        var arrayPoolCount = 0;

        function getArray() {
            if (arrayPoolCount === 0) {
                return [];
            }

            arrayPoolCount--;
            var result = arrayPool[arrayPoolCount];
            arrayPool[arrayPoolCount] = null;

            return result;
        }

        function returnZeroLengthArray(array) {
            if (array.length === 0) {
                returnArray(array);
            }
        }

        function returnArray(array) {
            array.length = 0;
            arrayPool[arrayPoolCount] = array;
            arrayPoolCount++;
        }

        // Contains the actual logic to parse typescript/javascript.  This is the code that generally
        // represents the logic necessary to handle all the language grammar constructs.  When the
        // language changes, this should generally only be the place necessary to fix up.
        function createParseSyntaxTree() {
            // Name of the file we're parsing.
            var fileName;

            // Underlying source where we pull nodes and tokens from.
            var source;

            var languageVersion;

            // TODO: do we need to store/restore this when speculative parsing?  I don't think so.  The
            // parsing logic already handles storing/restoring this and should work properly even if we're
            // speculative parsing.
            var listParsingState = 0;

            // Whether or not we are in strict parsing mode.  All that changes in strict parsing mode is
            // that some tokens that would be considered identifiers may be considered keywords.  When
            // rewinding, we need to store and restore this as the mode may have changed.
            //
            // TODO: do we need to store/restore this when speculative parsing?  I don't think so.  The
            // parsing logic already handles storing/restoring this and should work properly even if we're
            // speculative parsing.
            var isInStrictMode = false;

            // Current state of the parser.  If we need to rewind we will store and reset these values as
            // appropriate.
            // Diagnostics created when parsing invalid code.  Any diagnosics created when speculative
            // parsing need to removed when rewinding.  To do this we store the count of diagnostics when
            // we start speculative parsing.  And if we rewind, we restore this to the same count that we
            // started at.
            var diagnostics = [];

            var parseNodeData = 0;

            function parseSyntaxTree(_source, isDeclaration) {
                // First, set up our state.
                fileName = _source.fileName;
                source = _source;
                languageVersion = source.languageVersion;

                // Now actually parse the tree.
                var result = parseSyntaxTreeWorker(isDeclaration);

                // Now, clear out our state so that our singleton parser doesn't keep things alive.
                diagnostics = [];
                parseNodeData = 0 /* None */;
                fileName = null;
                source.release();
                source = null;
                _source = null;

                return result;
            }

            function parseSyntaxTreeWorker(isDeclaration) {
                var sourceUnit = parseSourceUnit();

                var allDiagnostics = source.tokenDiagnostics().concat(diagnostics);
                allDiagnostics.sort(function (a, b) {
                    return a.start() - b.start();
                });

                return new TypeScript.SyntaxTree(Parser.syntaxFactory.isConcrete, sourceUnit, isDeclaration, allDiagnostics, fileName, source.text, languageVersion);
            }

            function getRewindPoint() {
                var rewindPoint = source.getRewindPoint();

                rewindPoint.diagnosticsCount = diagnostics.length;

                // Values we keep around for debug asserting purposes.
                rewindPoint.isInStrictMode = isInStrictMode;
                rewindPoint.listParsingState = listParsingState;

                return rewindPoint;
            }

            function rewind(rewindPoint) {
                source.rewind(rewindPoint);

                diagnostics.length = rewindPoint.diagnosticsCount;
            }

            function releaseRewindPoint(rewindPoint) {
                // Debug.assert(listParsingState === rewindPoint.listParsingState);
                // Debug.assert(isInStrictMode === rewindPoint.isInStrictMode);
                source.releaseRewindPoint(rewindPoint);
            }

            function currentNode() {
                var node = source.currentNode();

                // We can only reuse a node if it was parsed under the same strict mode that we're
                // currently in.  i.e. if we originally parsed a node in non-strict mode, but then
                // the user added 'using strict' at the top of the file, then we can't use that node
                // again as the presense of strict mode may cause us to parse the tokens in the file
                // differetly.
                //
                // Note: we *can* reuse tokens when the strict mode changes.  That's because tokens
                // are unaffected by strict mode.  It's just the parser will decide what to do with it
                // differently depending on what mode it is in.
                if (node === null || TypeScript.parsedInStrictMode(node) !== isInStrictMode) {
                    return null;
                }

                return node;
            }

            function currentToken() {
                return source.currentToken();
            }

            function currentContextualToken() {
                // We're mutating the source here.  We are potentially overwriting the original token we
                // scanned with a regex token.  So we have to clear our state.
                return source.currentContextualToken();
            }

            function peekToken(n) {
                return source.peekToken(n);
            }

            function consumeToken(token) {
                source.consumeToken(token);
                return token;
            }

            function consumeNode(node) {
                source.consumeNode(node);
            }

            //this method is called very frequently
            //we should keep it simple so that it can be inlined.
            function eatToken(kind) {
                var token = currentToken();
                if (token.kind() === kind) {
                    return consumeToken(token);
                }

                //slow part of EatToken(SyntaxKind kind)
                return createMissingToken(kind, token);
            }

            // Eats the token if it is there.  Otherwise does nothing.  Will not report errors.
            function tryEatToken(kind) {
                var _currentToken = currentToken();
                if (_currentToken.kind() === kind) {
                    return consumeToken(_currentToken);
                }

                return null;
            }

            // An identifier is basically any word, unless it is a reserved keyword.  so 'foo' is an
            // identifier and 'return' is not.  Note: a word may or may not be an identifier depending
            // on the state of the parser.  For example, 'yield' is an identifier *unless* the parser
            // is in strict mode.
            function isIdentifier(token) {
                var tokenKind = token.kind();

                if (tokenKind === 11 /* IdentifierName */) {
                    return true;
                }

                // Keywords are only identifiers if they're FutureReservedStrictWords and we're in
                // strict mode.  *Or* if it's a typescript 'keyword'.
                if (tokenKind >= TypeScript.SyntaxKind.FirstFutureReservedStrictKeyword) {
                    if (tokenKind <= TypeScript.SyntaxKind.LastFutureReservedStrictKeyword) {
                        // Could be a keyword or identifier.  It's an identifier if we're not in strict
                        // mode.
                        return !isInStrictMode;
                    }

                    // If it's typescript keyword, then it's actually a javascript identifier.
                    return tokenKind <= TypeScript.SyntaxKind.LastTypeScriptKeyword;
                }

                // Anything else is not an identifier.
                return false;
            }

            // This method should be called when the grammar calls for an *IdentifierName* and not an
            // *Identifier*.
            function eatIdentifierNameToken() {
                var token = currentToken();

                // If we have an identifier name, then consume and return it.
                var tokenKind = token.kind();
                if (tokenKind === 11 /* IdentifierName */) {
                    return consumeToken(token);
                }

                // If we have a keyword, then it can be used as an identifier name.  However, we need
                // to convert it to an identifier so that no later parts of the systems see it as a
                // keyword.
                if (TypeScript.SyntaxFacts.isAnyKeyword(tokenKind)) {
                    return TypeScript.Syntax.convertKeywordToIdentifier(consumeToken(token));
                }

                return createMissingToken(11 /* IdentifierName */, token);
            }

            function eatOptionalIdentifierToken() {
                return isIdentifier(currentToken()) ? eatIdentifierToken() : null;
            }

            // This method should be called when the grammar calls for an *Identifier* and not an
            // *IdentifierName*.
            function eatIdentifierToken(diagnosticCode) {
                var token = currentToken();
                if (isIdentifier(token)) {
                    consumeToken(token);

                    if (token.kind() === 11 /* IdentifierName */) {
                        return token;
                    }

                    return TypeScript.Syntax.convertKeywordToIdentifier(token);
                }

                return createMissingToken(11 /* IdentifierName */, token, diagnosticCode);
            }

            function previousTokenHasTrailingNewLine(token) {
                var tokenFullStart = token.fullStart();
                if (tokenFullStart === 0) {
                    // First token in the document.  Thus it has no 'previous' token, and there is
                    // no preceding newline.
                    return false;
                }

                // If our previous token ended with a newline, then *by definition* we must have started
                // at the beginning of a line.
                var lineNumber = source.text.lineMap().getLineNumberFromPosition(tokenFullStart);
                var lineStart = source.text.lineMap().getLineStartPosition(lineNumber);

                return lineStart == tokenFullStart;
            }

            function canEatAutomaticSemicolon(allowWithoutNewLine) {
                var token = currentToken();

                // An automatic semicolon is always allowed if we're at the end of the file.
                var tokenKind = token.kind();
                if (tokenKind === 10 /* EndOfFileToken */) {
                    return true;
                }

                // Or if the next token is a close brace (regardless of which line it is on).
                if (tokenKind === 71 /* CloseBraceToken */) {
                    return true;
                }

                if (allowWithoutNewLine) {
                    return true;
                }

                // It is also allowed if there is a newline between the last token seen and the next one.
                if (previousTokenHasTrailingNewLine(token)) {
                    return true;
                }

                return false;
            }

            function canEatExplicitOrAutomaticSemicolon(allowWithoutNewline) {
                var token = currentToken();

                if (token.kind() === 78 /* SemicolonToken */) {
                    return true;
                }

                return canEatAutomaticSemicolon(allowWithoutNewline);
            }

            function eatExplicitOrAutomaticSemicolon(allowWithoutNewline) {
                var token = currentToken();

                // If we see a semicolon, then we can definitely eat it.
                if (token.kind() === 78 /* SemicolonToken */) {
                    return consumeToken(token);
                }

                // Check if an automatic semicolon could go here.  If so, then there's no problem and
                // we can proceed without error.  Return 'null' as there's no actual token for this
                // position.
                if (canEatAutomaticSemicolon(allowWithoutNewline)) {
                    return null;
                }

                // No semicolon could be consumed here at all.  Just call the standard eating function
                // so we get the token and the error for it.
                return eatToken(78 /* SemicolonToken */);
            }

            function createMissingToken(expectedKind, actual, diagnosticCode) {
                var diagnostic = getExpectedTokenDiagnostic(expectedKind, actual, diagnosticCode);
                addDiagnostic(diagnostic);

                // The missing token will be at the full start of the current token.  That way empty tokens
                // will always be between real tokens and not inside an actual token.
                return TypeScript.Syntax.emptyToken(expectedKind);
            }

            function getExpectedTokenDiagnostic(expectedKind, actual, diagnosticCode) {
                var token = currentToken();

                var args = null;

                // If a specialized diagnostic message was provided, just use that.
                if (!diagnosticCode) {
                    // They wanted something specific, just report that that token was missing.
                    if (TypeScript.SyntaxFacts.isAnyKeyword(expectedKind) || TypeScript.SyntaxFacts.isAnyPunctuation(expectedKind)) {
                        diagnosticCode = TypeScript.DiagnosticCode._0_expected;
                        args = [TypeScript.SyntaxFacts.getText(expectedKind)];
                    } else {
                        // They wanted an identifier.
                        // If the user supplied a keyword, give them a specialized message.
                        if (actual !== null && TypeScript.SyntaxFacts.isAnyKeyword(actual.kind())) {
                            diagnosticCode = TypeScript.DiagnosticCode.Identifier_expected_0_is_a_keyword;
                            args = [TypeScript.SyntaxFacts.getText(actual.kind())];
                        } else {
                            // Otherwise just report that an identifier was expected.
                            diagnosticCode = TypeScript.DiagnosticCode.Identifier_expected;
                        }
                    }
                }

                return new TypeScript.Diagnostic(fileName, source.text.lineMap(), TypeScript.start(token, source.text), TypeScript.width(token), diagnosticCode, args);
            }

            function getBinaryExpressionPrecedence(tokenKind) {
                switch (tokenKind) {
                    case 104 /* BarBarToken */: return 2 /* LogicalOrExpressionPrecedence */;
                    case 103 /* AmpersandAmpersandToken */: return 3 /* LogicalAndExpressionPrecedence */;
                    case 99 /* BarToken */: return 4 /* BitwiseOrExpressionPrecedence */;
                    case 100 /* CaretToken */: return 5 /* BitwiseExclusiveOrExpressionPrecedence */;
                    case 98 /* AmpersandToken */: return 6 /* BitwiseAndExpressionPrecedence */;
                    case 84 /* EqualsEqualsToken */:
                    case 86 /* ExclamationEqualsToken */:
                    case 87 /* EqualsEqualsEqualsToken */:
                    case 88 /* ExclamationEqualsEqualsToken */:
                        return 7 /* EqualityExpressionPrecedence */;
                    case 80 /* LessThanToken */:
                    case 81 /* GreaterThanToken */:
                    case 82 /* LessThanEqualsToken */:
                    case 83 /* GreaterThanEqualsToken */:
                    case 30 /* InstanceOfKeyword */:
                    case 29 /* InKeyword */:
                        return 8 /* RelationalExpressionPrecedence */;
                    case 95 /* LessThanLessThanToken */:
                    case 96 /* GreaterThanGreaterThanToken */:
                    case 97 /* GreaterThanGreaterThanGreaterThanToken */:
                        return 9 /* ShiftExpressionPrecdence */;
                    case 89 /* PlusToken */:
                    case 90 /* MinusToken */:
                        return 10 /* AdditiveExpressionPrecedence */;
                    case 91 /* AsteriskToken */:
                    case 118 /* SlashToken */:
                    case 92 /* PercentToken */:
                        return 11 /* MultiplicativeExpressionPrecedence */;
                }

                throw TypeScript.Errors.invalidOperation();
            }

            function addSkippedTokenAfterNodeOrToken(nodeOrToken, skippedToken) {
                if (TypeScript.isToken(nodeOrToken)) {
                    return addSkippedTokenAfterToken(nodeOrToken, skippedToken);
                } else if (TypeScript.isNode(nodeOrToken)) {
                    return addSkippedTokenAfterNode(nodeOrToken, skippedToken);
                } else {
                    throw TypeScript.Errors.invalidOperation();
                }
            }

            function replaceTokenInParent(oldToken, newToken) {
                // oldToken may be parented by a node or a list.
                replaceTokenInParentWorker(oldToken, newToken);

                var parent = oldToken.parent;
                newToken.parent = parent;

                // Parent must be a list or a node.  All of those have a 'data' element.
                TypeScript.Debug.assert(TypeScript.isNode(parent) || TypeScript.isList(parent) || TypeScript.isSeparatedList(parent));
                var dataElement = parent;
                if (dataElement.data) {
                    dataElement.data &= 4 /* NodeParsedInStrictModeMask */;
                }
            }

            function replaceTokenInParentWorker(oldToken, newToken) {
                var parent = oldToken.parent;

                if (TypeScript.isNode(parent)) {
                    var node = parent;
                    for (var key in node) {
                        if (node[key] === oldToken) {
                            node[key] = newToken;
                            return;
                        }
                    }
                } else if (TypeScript.isList(parent)) {
                    var list1 = parent;
                    for (var i = 0, n = list1.length; i < n; i++) {
                        if (list1[i] === oldToken) {
                            list1[i] = newToken;
                            return;
                        }
                    }
                } else if (TypeScript.isSeparatedList(parent)) {
                    var list2 = parent;
                    for (var i = 0, n = TypeScript.childCount(list2); i < n; i++) {
                        if (TypeScript.childAt(list2, i) === oldToken) {
                            if (i % 2 === 0) {
                                list2[i / 2] = newToken;
                            } else {
                                list2.separators[(i - 1) / 2] = newToken;
                            }
                            return;
                        }
                    }
                }

                throw TypeScript.Errors.invalidOperation();
            }

            function addSkippedTokenAfterNode(node, skippedToken) {
                var oldToken = TypeScript.lastToken(node);
                var newToken = addSkippedTokenAfterToken(oldToken, skippedToken);

                replaceTokenInParent(oldToken, newToken);
                return node;
            }

            function addSkippedTokensBeforeNode(node, skippedTokens) {
                if (skippedTokens.length > 0) {
                    var oldToken = TypeScript.firstToken(node);
                    var newToken = addSkippedTokensBeforeToken(oldToken, skippedTokens);

                    replaceTokenInParent(oldToken, newToken);
                }

                return node;
            }

            function addSkippedTokensBeforeToken(token, skippedTokens) {
                // Debug.assert(token.fullWidth() > 0 || token.kind() === SyntaxKind.EndOfFileToken);
                // Debug.assert(skippedTokens.length > 0);
                var leadingTrivia = [];
                for (var i = 0, n = skippedTokens.length; i < n; i++) {
                    var skippedToken = skippedTokens[i];
                    addSkippedTokenToTriviaArray(leadingTrivia, skippedToken);
                }

                addTriviaTo(token.leadingTrivia(source.text), leadingTrivia);

                var updatedToken = TypeScript.Syntax.withLeadingTrivia(token, TypeScript.Syntax.triviaList(leadingTrivia), source.text);

                // We've prepending this token with new leading trivia.  This means the full start of
                // the token is not where the scanner originally thought it was, but is instead at the
                // start of the first skipped token.
                updatedToken.setFullStart(skippedTokens[0].fullStart());

                // Don't need this array anymore.  Give it back so we can reuse it.
                returnArray(skippedTokens);

                return updatedToken;
            }

            function addSkippedTokensAfterToken(token, skippedTokens) {
                // Debug.assert(token.fullWidth() > 0);
                if (skippedTokens.length === 0) {
                    returnArray(skippedTokens);
                    return token;
                }

                var trailingTrivia = token.trailingTrivia(source.text).toArray();

                for (var i = 0, n = skippedTokens.length; i < n; i++) {
                    addSkippedTokenToTriviaArray(trailingTrivia, skippedTokens[i]);
                }

                // Don't need this array anymore.  Give it back so we can reuse it.
                returnArray(skippedTokens);
                return TypeScript.Syntax.withTrailingTrivia(token, TypeScript.Syntax.triviaList(trailingTrivia), source.text);
            }

            function addSkippedTokenAfterToken(token, skippedToken) {
                // Debug.assert(token.fullWidth() > 0);
                var trailingTrivia = token.trailingTrivia(source.text).toArray();
                addSkippedTokenToTriviaArray(trailingTrivia, skippedToken);

                return TypeScript.Syntax.withTrailingTrivia(token, TypeScript.Syntax.triviaList(trailingTrivia), source.text);
            }

            function addSkippedTokenToTriviaArray(array, skippedToken) {
                // Debug.assert(skippedToken.text().length > 0);
                // first, add the leading trivia of the skipped token to the array
                addTriviaTo(skippedToken.leadingTrivia(source.text), array);

                // now, add the text of the token as skipped text to the trivia array.
                var trimmedToken = TypeScript.Syntax.withTrailingTrivia(TypeScript.Syntax.withLeadingTrivia(skippedToken, TypeScript.Syntax.emptyTriviaList, source.text), TypeScript.Syntax.emptyTriviaList, source.text);

                // Because we removed the leading trivia from the skipped token, the full start of the
                // trimmed token is the start of the skipped token.
                trimmedToken.setFullStart(TypeScript.start(skippedToken, source.text));

                array.push(TypeScript.Syntax.skippedTokenTrivia(trimmedToken, source.text));

                // Finally, add the trailing trivia of the skipped token to the trivia array.
                addTriviaTo(skippedToken.trailingTrivia(source.text), array);
            }

            function addTriviaTo(list, array) {
                for (var i = 0, n = list.count(); i < n; i++) {
                    array.push(list.syntaxTriviaAt(i));
                }
            }

            function setStrictMode(_isInStrictMode) {
                isInStrictMode = _isInStrictMode;
                parseNodeData = _isInStrictMode ? 4 /* NodeParsedInStrictModeMask */ : 0;
            }

            function parseSourceUnit() {
                var savedIsInStrictMode = isInStrictMode;

                var skippedTokens = getArray();
                var moduleElements = parseSyntaxList(0 /* SourceUnit_ModuleElements */, skippedTokens, updateStrictModeState);

                setStrictMode(savedIsInStrictMode);

                var sourceUnit = new Parser.syntaxFactory.SourceUnitSyntax(parseNodeData, moduleElements, currentToken());

                sourceUnit = addSkippedTokensBeforeNode(sourceUnit, skippedTokens);

                if (TypeScript.Debug.shouldAssert(2 /* Aggressive */)) {
                    TypeScript.Debug.assert(TypeScript.fullWidth(sourceUnit) === source.text.length());

                    if (TypeScript.Debug.shouldAssert(3 /* VeryAggressive */)) {
                        TypeScript.Debug.assert(TypeScript.fullText(sourceUnit) === source.text.substr(0, source.text.length()));
                    }
                }

                return sourceUnit;
            }

            function updateStrictModeState(items) {
                if (!isInStrictMode) {
                    for (var i = 0; i < items.length; i++) {
                        var item = items[i];
                        if (!TypeScript.SyntaxFacts.isDirectivePrologueElement(item)) {
                            return;
                        }
                    }

                    setStrictMode(TypeScript.SyntaxFacts.isUseStrictDirective(items[items.length - 1]));
                }
            }

            function isModuleElement(inErrorRecovery) {
                if (TypeScript.SyntaxUtilities.isModuleElement(currentNode())) {
                    return true;
                }

                var _modifierCount = modifierCount();
                return isInterfaceEnumClassModuleImportOrExport(_modifierCount) || isStatement(_modifierCount, inErrorRecovery);
            }

            function tryParseModuleElement(inErrorRecovery) {
                var node = currentNode();
                if (TypeScript.SyntaxUtilities.isModuleElement(node)) {
                    consumeNode(node);
                    return node;
                }

                var _currentToken = currentToken();
                var _modifierCount = modifierCount();

                if (_modifierCount) {
                    switch (peekToken(_modifierCount).kind()) {
                        case 49 /* ImportKeyword */: return parseImportDeclaration();
                        case 65 /* ModuleKeyword */: return parseModuleDeclaration();
                        case 52 /* InterfaceKeyword */: return parseInterfaceDeclaration();
                        case 44 /* ClassKeyword */: return parseClassDeclaration();
                        case 46 /* EnumKeyword */: return parseEnumDeclaration();
                    }
                }

                // No modifiers.  If we see 'class, enum, import and export' we could technically
                // aggressively consume them as they can't start another construct.  However, it's
                // not uncommon in error recovery to run into a situation where we see those keywords,
                // but the code was using it as the name of an object property.  To avoid overzealously
                // consuming these, we only parse them out if we can see enough context to 'prove' that
                // they really do start the module element
                var nextToken = peekToken(1);
                var currentTokenKind = _currentToken.kind();
                switch (currentTokenKind) {
                    case 65 /* ModuleKeyword */:
                        if (isIdentifier(nextToken) || nextToken.kind() === 14 /* StringLiteral */) {
                            return parseModuleDeclaration();
                        }
                        break;

                    case 49 /* ImportKeyword */:
                        if (isIdentifier(nextToken)) {
                            return parseImportDeclaration();
                        }
                        break;

                    case 44 /* ClassKeyword */:
                        if (isIdentifier(nextToken)) {
                            return parseClassDeclaration();
                        }
                        break;

                    case 46 /* EnumKeyword */:
                        if (isIdentifier(nextToken)) {
                            return parseEnumDeclaration();
                        }
                        break;

                    case 52 /* InterfaceKeyword */:
                        if (isIdentifier(nextToken)) {
                            return parseInterfaceDeclaration();
                        }
                        break;

                    case 47 /* ExportKeyword */:
                        // 'export' could be a modifier on a statement (like export var ...).  So we
                        // only want to parse out an export assignment here if we actually see the equals.
                        if (nextToken.kind() === 107 /* EqualsToken */) {
                            return parseExportAssignment();
                        }
                        break;
                }

                return tryParseStatementWorker(_currentToken, currentTokenKind, _modifierCount, inErrorRecovery);
            }

            function parseImportDeclaration() {
                return new Parser.syntaxFactory.ImportDeclarationSyntax(parseNodeData, parseModifiers(), eatToken(49 /* ImportKeyword */), eatIdentifierToken(), eatToken(107 /* EqualsToken */), parseModuleReference(), eatExplicitOrAutomaticSemicolon(false));
            }

            function parseExportAssignment() {
                return new Parser.syntaxFactory.ExportAssignmentSyntax(parseNodeData, eatToken(47 /* ExportKeyword */), eatToken(107 /* EqualsToken */), eatIdentifierToken(), eatExplicitOrAutomaticSemicolon(false));
            }

            function parseModuleReference() {
                return isExternalModuleReference() ? parseExternalModuleReference() : parseModuleNameModuleReference();
            }

            function isExternalModuleReference() {
                return currentToken().kind() === 66 /* RequireKeyword */ && peekToken(1).kind() === 72 /* OpenParenToken */;
            }

            function parseExternalModuleReference() {
                return new Parser.syntaxFactory.ExternalModuleReferenceSyntax(parseNodeData, eatToken(66 /* RequireKeyword */), eatToken(72 /* OpenParenToken */), eatToken(14 /* StringLiteral */), eatToken(73 /* CloseParenToken */));
            }

            function parseModuleNameModuleReference() {
                return new Parser.syntaxFactory.ModuleNameModuleReferenceSyntax(parseNodeData, parseName(false));
            }

            function tryParseTypeArgumentList(inExpression) {
                var _currentToken = currentToken();
                if (_currentToken.kind() !== 80 /* LessThanToken */) {
                    return null;
                }

                if (!inExpression) {
                    // if we're not in an expression, this must be a type argument list.  Just parse
                    // it out as such.
                    var lessThanToken = consumeToken(_currentToken);

                    var skippedTokens = getArray();
                    var typeArguments = parseSeparatedSyntaxList(19 /* TypeArgumentList_Types */, skippedTokens);
                    lessThanToken = addSkippedTokensAfterToken(lessThanToken, skippedTokens);

                    return new Parser.syntaxFactory.TypeArgumentListSyntax(parseNodeData, lessThanToken, typeArguments, eatToken(81 /* GreaterThanToken */));
                }

                // If we're in an expression, then we only want to consume this as a type argument list
                // if we're sure that it's a type arg list and not an arithmetic expression.
                var rewindPoint = getRewindPoint();

                // We've seen a '<'.  Try to parse it out as a type argument list.
                var lessThanToken = consumeToken(_currentToken);

                var skippedTokens = getArray();
                var typeArguments = parseSeparatedSyntaxList(19 /* TypeArgumentList_Types */, skippedTokens);
                var lessThanToken = addSkippedTokensAfterToken(lessThanToken, skippedTokens);

                var greaterThanToken = eatToken(81 /* GreaterThanToken */);

                // We're in a context where '<' could be the start of a type argument list, or part
                // of an arithmetic expression.  We'll presume it's the latter unless we see the '>'
                // and a following token that guarantees that it's supposed to be a type argument list.
                if (greaterThanToken.fullWidth() === 0 || !canFollowTypeArgumentListInExpression(currentToken().kind())) {
                    rewind(rewindPoint);
                    releaseRewindPoint(rewindPoint);
                    return null;
                } else {
                    releaseRewindPoint(rewindPoint);
                    return new Parser.syntaxFactory.TypeArgumentListSyntax(parseNodeData, lessThanToken, typeArguments, greaterThanToken);
                }
            }

            function canFollowTypeArgumentListInExpression(kind) {
                switch (kind) {
                    case 72 /* OpenParenToken */:
                    case 76 /* DotToken */:

                    case 73 /* CloseParenToken */:
                    case 75 /* CloseBracketToken */:
                    case 106 /* ColonToken */:
                    case 78 /* SemicolonToken */:
                    case 79 /* CommaToken */:
                    case 105 /* QuestionToken */:
                    case 84 /* EqualsEqualsToken */:
                    case 87 /* EqualsEqualsEqualsToken */:
                    case 86 /* ExclamationEqualsToken */:
                    case 88 /* ExclamationEqualsEqualsToken */:
                    case 103 /* AmpersandAmpersandToken */:
                    case 104 /* BarBarToken */:
                    case 100 /* CaretToken */:
                    case 98 /* AmpersandToken */:
                    case 99 /* BarToken */:
                    case 71 /* CloseBraceToken */:
                    case 10 /* EndOfFileToken */:
                        // these cases can't legally follow a type arg list.  However, they're not legal
                        // expressions either.  The user is probably in the middle of a generic type. So
                        // treat it as such.
                        return true;

                    default:
                        // Anything else treat as an expression.
                        return false;
                }
            }

            function parseName(allowIdentifierName) {
                return tryParseName(allowIdentifierName) || eatIdentifierToken();
            }

            function eatRightSideOfName(allowIdentifierNames) {
                var _currentToken = currentToken();

                // Technically a keyword is valid here as all keywords are identifier names.
                // However, often we'll encounter this in error situations when the keyword
                // is actually starting another valid construct.
                // So, we check for the following specific case:
                //      name.
                //      keyword identifierNameOrKeyword
                // Note: the newlines are important here.  For example, if that above code
                // were rewritten into:
                //      name.keyword
                //      identifierNameOrKeyword
                // Then we would consider it valid.  That's because ASI would take effect and
                // the code would be implicitly: "name.keyword; identifierNameOrKeyword".
                // In the first case though, ASI will not take effect because there is not a
                // line terminator after the keyword.
                if (TypeScript.SyntaxFacts.isAnyKeyword(_currentToken.kind()) && previousTokenHasTrailingNewLine(_currentToken)) {
                    var token1 = peekToken(1);
                    if (!TypeScript.existsNewLineBetweenTokens(_currentToken, token1, source.text) && TypeScript.SyntaxFacts.isIdentifierNameOrAnyKeyword(token1)) {
                        return createMissingToken(11 /* IdentifierName */, _currentToken);
                    }
                }

                return allowIdentifierNames ? eatIdentifierNameToken() : eatIdentifierToken();
            }

            function tryParseName(allowIdentifierNames) {
                var token0 = currentToken();
                var shouldContinue = isIdentifier(token0);
                if (!shouldContinue) {
                    return null;
                }

                // Call eatIdentifierName to convert the token to an identifier if it is as keyword.
                var current = eatIdentifierToken();

                while (shouldContinue && currentToken().kind() === 76 /* DotToken */) {
                    var dotToken = consumeToken(currentToken());
                    var identifierName = eatRightSideOfName(allowIdentifierNames);

                    current = new Parser.syntaxFactory.QualifiedNameSyntax(parseNodeData, current, dotToken, identifierName);
                    shouldContinue = identifierName.fullWidth() > 0;
                }

                return current;
            }

            function parseEnumDeclaration() {
                var modifiers = parseModifiers();
                var enumKeyword = eatToken(46 /* EnumKeyword */);
                var identifier = eatIdentifierToken();

                var openBraceToken = eatToken(70 /* OpenBraceToken */);
                var enumElements = TypeScript.Syntax.emptySeparatedList();

                if (openBraceToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    enumElements = parseSeparatedSyntaxList(8 /* EnumDeclaration_EnumElements */, skippedTokens);
                    openBraceToken = addSkippedTokensAfterToken(openBraceToken, skippedTokens);
                }

                return new Parser.syntaxFactory.EnumDeclarationSyntax(parseNodeData, modifiers, enumKeyword, identifier, openBraceToken, enumElements, eatToken(71 /* CloseBraceToken */));
            }

            function isEnumElement(inErrorRecovery) {
                var node = currentNode();
                if (node !== null && node.kind() === 243 /* EnumElement */) {
                    return true;
                }

                return isPropertyName(currentToken(), inErrorRecovery);
            }

            function tryParseEnumElementEqualsValueClause() {
                return isEqualsValueClause(false) ? parseEqualsValueClause(true) : null;
            }

            function tryParseEnumElement(inErrorRecovery) {
                var node = currentNode();
                if (node !== null && node.kind() === 243 /* EnumElement */) {
                    consumeNode(node);
                    return node;
                }

                if (!isPropertyName(currentToken(), inErrorRecovery)) {
                    return null;
                }

                return new Parser.syntaxFactory.EnumElementSyntax(parseNodeData, eatPropertyName(), tryParseEnumElementEqualsValueClause());
            }

            function isModifier(token) {
                switch (token.kind()) {
                    case 57 /* PublicKeyword */:
                    case 55 /* PrivateKeyword */:
                    case 58 /* StaticKeyword */:
                    case 47 /* ExportKeyword */:
                    case 63 /* DeclareKeyword */:
                        return true;
                    default:
                        return false;
                }
            }

            function modifierCount() {
                var modifierCount = 0;
                while (isModifier(peekToken(modifierCount))) {
                    modifierCount++;
                }

                return modifierCount;
            }

            function parseModifiers() {
                var tokens = getArray();

                while (true) {
                    var token = currentToken();
                    if (isModifier(token)) {
                        tokens.push(consumeToken(token));
                        continue;
                    }

                    break;
                }

                var result = TypeScript.Syntax.list(tokens);

                // If the tokens array is greater than one, then we can't return it.  It will have been
                // copied directly into the syntax list.
                returnZeroLengthArray(tokens);

                return result;
            }

            function parseHeritageClauses() {
                var heritageClauses = TypeScript.Syntax.emptyList();

                if (isHeritageClause()) {
                    // NOTE: we can pass "null" for the skipped tokens here as we know we can't get
                    // any leading skipped tokens. We have an 'extends' or 'implements' keyword, so
                    // any skipped tokeds will get attached to that instead.
                    heritageClauses = parseSyntaxList(10 /* ClassOrInterfaceDeclaration_HeritageClauses */, null);
                }

                return heritageClauses;
            }

            function tryParseHeritageClauseTypeName() {
                return isHeritageClauseTypeName() ? tryParseNameOrGenericType() : null;
            }

            function parseClassDeclaration() {
                var modifiers = parseModifiers();

                var classKeyword = eatToken(44 /* ClassKeyword */);
                var identifier = eatIdentifierToken();
                var typeParameterList = tryParseTypeParameterList(false);
                var heritageClauses = parseHeritageClauses();
                var openBraceToken = eatToken(70 /* OpenBraceToken */);
                var classElements = TypeScript.Syntax.emptyList();

                if (openBraceToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    classElements = parseSyntaxList(1 /* ClassDeclaration_ClassElements */, skippedTokens);
                    openBraceToken = addSkippedTokensAfterToken(openBraceToken, skippedTokens);
                }
                ;

                return new Parser.syntaxFactory.ClassDeclarationSyntax(parseNodeData, modifiers, classKeyword, identifier, typeParameterList, heritageClauses, openBraceToken, classElements, eatToken(71 /* CloseBraceToken */));
            }

            function isAccessor(modifierCount, inErrorRecovery) {
                var tokenKind = peekToken(modifierCount).kind();
                if (tokenKind !== 64 /* GetKeyword */ && tokenKind !== 68 /* SetKeyword */) {
                    return false;
                }

                return isPropertyName(peekToken(modifierCount + 1), inErrorRecovery);
            }

            function parseAccessor(checkForStrictMode) {
                var modifiers = parseModifiers();
                var _currenToken = currentToken();
                var tokenKind = _currenToken.kind();

                if (tokenKind === 64 /* GetKeyword */) {
                    return parseGetMemberAccessorDeclaration(modifiers, _currenToken, checkForStrictMode);
                } else if (tokenKind === 68 /* SetKeyword */) {
                    return parseSetMemberAccessorDeclaration(modifiers, _currenToken, checkForStrictMode);
                } else {
                    throw TypeScript.Errors.invalidOperation();
                }
            }

            function parseGetMemberAccessorDeclaration(modifiers, getKeyword, checkForStrictMode) {
                return new Parser.syntaxFactory.GetAccessorSyntax(parseNodeData, modifiers, consumeToken(getKeyword), eatPropertyName(), parseCallSignature(false), parseBlock(false, checkForStrictMode));
            }

            function parseSetMemberAccessorDeclaration(modifiers, setKeyword, checkForStrictMode) {
                return new Parser.syntaxFactory.SetAccessorSyntax(parseNodeData, modifiers, consumeToken(setKeyword), eatPropertyName(), parseCallSignature(false), parseBlock(false, checkForStrictMode));
            }

            function isClassElement(inErrorRecovery) {
                if (TypeScript.SyntaxUtilities.isClassElement(currentNode())) {
                    return true;
                }

                // Note: the order of these calls is important.  Specifically, isMemberVariableDeclaration
                // checks for a subset of the conditions of the previous two calls.
                var _modifierCount = modifierCount();
                return isConstructorDeclaration(_modifierCount) || isMemberFunctionDeclaration(inErrorRecovery) || isAccessor(_modifierCount, inErrorRecovery) || isMemberVariableDeclaration(inErrorRecovery) || isIndexMemberDeclaration(_modifierCount);
            }

            function tryParseClassElement(inErrorRecovery) {
                var node = currentNode();
                if (TypeScript.SyntaxUtilities.isClassElement(node)) {
                    consumeNode(node);
                    return node;
                }

                var _modifierCount = modifierCount();
                if (isConstructorDeclaration(_modifierCount)) {
                    return parseConstructorDeclaration();
                } else if (isMemberFunctionDeclaration(inErrorRecovery)) {
                    return parseMemberFunctionDeclaration();
                } else if (isAccessor(_modifierCount, inErrorRecovery)) {
                    return parseAccessor(false);
                } else if (isMemberVariableDeclaration(inErrorRecovery)) {
                    return parseMemberVariableDeclaration();
                } else if (isIndexMemberDeclaration(_modifierCount)) {
                    return parseIndexMemberDeclaration();
                } else {
                    return null;
                }
            }

            function isConstructorDeclaration(modifierCount) {
                // Note: we deviate slightly from the spec here.  If we see 'constructor' then we
                // assume this is a constructor.  That means, if a user writes "public constructor;"
                // it won't be viewed as a member.  As a workaround, they can simply write:
                //      public 'constructor';
                return peekToken(modifierCount).kind() === 62 /* ConstructorKeyword */;
            }

            function parseConstructorDeclaration() {
                var modifiers = parseModifiers();
                var constructorKeyword = eatToken(62 /* ConstructorKeyword */);
                var callSignature = parseCallSignature(false);

                var semicolonToken = null;
                var block = null;

                if (isBlock()) {
                    block = parseBlock(false, true);
                } else {
                    semicolonToken = eatExplicitOrAutomaticSemicolon(false);
                }

                return new Parser.syntaxFactory.ConstructorDeclarationSyntax(parseNodeData, modifiers, constructorKeyword, callSignature, block, semicolonToken);
            }

            function isMemberFunctionDeclaration(inErrorRecovery) {
                var index = 0;

                while (true) {
                    var token = peekToken(index);
                    if (isPropertyName(token, inErrorRecovery) && isCallSignature(index + 1)) {
                        return true;
                    }

                    // We weren't at the name of the function.  If we have a modifier token, then
                    // consume it and try again.
                    if (isModifier(token)) {
                        index++;
                        continue;
                    }

                    // Wasn't a member function.
                    return false;
                }
            }

            function parseMemberFunctionDeclaration() {
                var modifierArray = getArray();

                while (true) {
                    var _currentToken = currentToken();
                    if (isPropertyName(_currentToken, false) && isCallSignature(1)) {
                        break;
                    }

                    modifierArray.push(consumeToken(_currentToken));
                }

                var modifiers = TypeScript.Syntax.list(modifierArray);
                returnZeroLengthArray(modifierArray);

                var propertyName = eatPropertyName();
                var callSignature = parseCallSignature(false);

                // If we got an errant => then we want to parse what's coming up without requiring an
                // open brace.
                var parseBlockEvenWithNoOpenBrace = tryAddUnexpectedEqualsGreaterThanToken(callSignature);

                var block = null;
                var semicolon = null;

                if (parseBlockEvenWithNoOpenBrace || isBlock()) {
                    block = parseBlock(parseBlockEvenWithNoOpenBrace, true);
                } else {
                    semicolon = eatExplicitOrAutomaticSemicolon(false);
                }

                return new Parser.syntaxFactory.MemberFunctionDeclarationSyntax(parseNodeData, modifiers, propertyName, callSignature, block, semicolon);
            }

            function isDefinitelyMemberVariablePropertyName(index) {
                // keywords are also property names.  Only accept a keyword as a property
                // name if is of the form:
                //      public;
                //      public=
                //      public:
                //      public }
                //      public <eof>
                if (TypeScript.SyntaxFacts.isAnyKeyword(peekToken(index).kind())) {
                    switch (peekToken(index + 1).kind()) {
                        case 78 /* SemicolonToken */:
                        case 107 /* EqualsToken */:
                        case 106 /* ColonToken */:
                        case 71 /* CloseBraceToken */:
                        case 10 /* EndOfFileToken */:
                            return true;
                        default:
                            return false;
                    }
                } else {
                    // If was a property name and not a keyword, then we're good to go.
                    return true;
                }
            }

            function isMemberVariableDeclaration(inErrorRecovery) {
                var index = 0;

                while (true) {
                    var token = peekToken(index);
                    if (isPropertyName(token, inErrorRecovery) && isDefinitelyMemberVariablePropertyName(index)) {
                        return true;
                    }

                    // We weren't at the name of the variable.  If we have a modifier token, then
                    // consume it and try again.
                    if (isModifier(peekToken(index))) {
                        index++;
                        continue;
                    }

                    // Wasn't a member variable.
                    return false;
                }
            }

            function parseMemberVariableDeclaration() {
                var modifierArray = getArray();

                while (true) {
                    var _currentToken = currentToken();
                    if (isPropertyName(_currentToken, false) && isDefinitelyMemberVariablePropertyName(0)) {
                        break;
                    }

                    modifierArray.push(consumeToken(_currentToken));
                }

                var modifiers = TypeScript.Syntax.list(modifierArray);
                returnZeroLengthArray(modifierArray);

                return new Parser.syntaxFactory.MemberVariableDeclarationSyntax(parseNodeData, modifiers, tryParseVariableDeclarator(true, true), eatExplicitOrAutomaticSemicolon(false));
            }

            function isIndexMemberDeclaration(modifierCount) {
                return isIndexSignature(modifierCount);
            }

            function parseIndexMemberDeclaration() {
                return new Parser.syntaxFactory.IndexMemberDeclarationSyntax(parseNodeData, parseModifiers(), parseIndexSignature(), eatExplicitOrAutomaticSemicolon(false));
            }

            function tryAddUnexpectedEqualsGreaterThanToken(callSignature) {
                var token0 = currentToken();

                var hasEqualsGreaterThanToken = token0.kind() === 85 /* EqualsGreaterThanToken */;
                if (hasEqualsGreaterThanToken) {
                    // We can only do this if the call signature actually contains a final token that we
                    // could add the => to.
                    var _lastToken = TypeScript.lastToken(callSignature);
                    if (_lastToken && _lastToken.fullWidth() > 0) {
                        // Previously the language allowed "function f() => expr;" as a shorthand for
                        // "function f() { return expr; }.
                        //
                        // Detect if the user is typing this and attempt recovery.
                        var diagnostic = new TypeScript.Diagnostic(fileName, source.text.lineMap(), TypeScript.start(token0, source.text), TypeScript.width(token0), TypeScript.DiagnosticCode.Unexpected_token_0_expected, [TypeScript.SyntaxFacts.getText(70 /* OpenBraceToken */)]);
                        addDiagnostic(diagnostic);

                        consumeToken(token0);

                        // Note: we only do this if we're creating a concrete syntax tree (which contains
                        // everything, including skipped tokens, in it).
                        if (Parser.syntaxFactory.isConcrete) {
                            addSkippedTokenAfterNode(callSignature, token0);
                        }
                        return true;
                    }
                }

                return false;
            }

            function isFunctionDeclaration(modifierCount) {
                return peekToken(modifierCount).kind() === 27 /* FunctionKeyword */;
            }

            function parseFunctionDeclaration() {
                var modifiers = parseModifiers();
                var functionKeyword = eatToken(27 /* FunctionKeyword */);
                var identifier = eatIdentifierToken();
                var callSignature = parseCallSignature(false);

                // If we got an errant => then we want to parse what's coming up without requiring an
                // open brace.
                var parseBlockEvenWithNoOpenBrace = tryAddUnexpectedEqualsGreaterThanToken(callSignature);

                var semicolonToken = null;
                var block = null;

                // Parse a block if we're on a bock, or if we saw a '=>'
                if (parseBlockEvenWithNoOpenBrace || isBlock()) {
                    block = parseBlock(parseBlockEvenWithNoOpenBrace, true);
                } else {
                    semicolonToken = eatExplicitOrAutomaticSemicolon(false);
                }

                return new Parser.syntaxFactory.FunctionDeclarationSyntax(parseNodeData, modifiers, functionKeyword, identifier, callSignature, block, semicolonToken);
            }

            function parseModuleDeclaration() {
                var modifiers = parseModifiers();
                var moduleKeyword = eatToken(65 /* ModuleKeyword */);

                var moduleName = null;
                var stringLiteral = null;

                if (currentToken().kind() === 14 /* StringLiteral */) {
                    stringLiteral = eatToken(14 /* StringLiteral */);
                } else {
                    moduleName = parseName(false);
                }

                var openBraceToken = eatToken(70 /* OpenBraceToken */);

                var moduleElements = TypeScript.Syntax.emptyList();
                if (openBraceToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    moduleElements = parseSyntaxList(2 /* ModuleDeclaration_ModuleElements */, skippedTokens);
                    openBraceToken = addSkippedTokensAfterToken(openBraceToken, skippedTokens);
                }

                return new Parser.syntaxFactory.ModuleDeclarationSyntax(parseNodeData, modifiers, moduleKeyword, moduleName, stringLiteral, openBraceToken, moduleElements, eatToken(71 /* CloseBraceToken */));
            }

            function parseInterfaceDeclaration() {
                return new Parser.syntaxFactory.InterfaceDeclarationSyntax(parseNodeData, parseModifiers(), eatToken(52 /* InterfaceKeyword */), eatIdentifierToken(), tryParseTypeParameterList(false), parseHeritageClauses(), parseObjectType());
            }

            function parseObjectType() {
                var openBraceToken = eatToken(70 /* OpenBraceToken */);

                var typeMembers = TypeScript.Syntax.emptySeparatedList();
                if (openBraceToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    typeMembers = parseSeparatedSyntaxList(9 /* ObjectType_TypeMembers */, skippedTokens);
                    openBraceToken = addSkippedTokensAfterToken(openBraceToken, skippedTokens);
                }

                return new Parser.syntaxFactory.ObjectTypeSyntax(parseNodeData, openBraceToken, typeMembers, eatToken(71 /* CloseBraceToken */));
            }

            function isTypeMember(inErrorRecovery) {
                if (TypeScript.SyntaxUtilities.isTypeMember(currentNode())) {
                    return true;
                }

                return isCallSignature(0) || isConstructSignature() || isIndexSignature(0) || isMethodSignature(inErrorRecovery) || isPropertySignature(inErrorRecovery);
            }

            function tryParseTypeMember(inErrorRecovery) {
                var node = currentNode();
                if (TypeScript.SyntaxUtilities.isTypeMember(node)) {
                    consumeNode(node);
                    return node;
                }

                if (isCallSignature(0)) {
                    return parseCallSignature(false);
                } else if (isConstructSignature()) {
                    return parseConstructSignature();
                } else if (isIndexSignature(0)) {
                    return parseIndexSignature();
                } else if (isMethodSignature(inErrorRecovery)) {
                    // Note: it is important that isFunctionSignature is called before isPropertySignature.
                    // isPropertySignature checks for a subset of isFunctionSignature.
                    return parseMethodSignature();
                } else if (isPropertySignature(inErrorRecovery)) {
                    return parsePropertySignature();
                } else {
                    return null;
                }
            }

            function parseConstructSignature() {
                return new Parser.syntaxFactory.ConstructSignatureSyntax(parseNodeData, eatToken(31 /* NewKeyword */), parseCallSignature(false));
            }

            function parseIndexSignature() {
                var openBracketToken = eatToken(74 /* OpenBracketToken */);

                var skippedTokens = getArray();
                var parameters = parseSeparatedSyntaxList(18 /* IndexSignature_Parameters */, skippedTokens);
                openBracketToken = addSkippedTokensAfterToken(openBracketToken, skippedTokens);

                return new Parser.syntaxFactory.IndexSignatureSyntax(parseNodeData, openBracketToken, parameters, eatToken(75 /* CloseBracketToken */), parseOptionalTypeAnnotation(false));
            }

            function parseMethodSignature() {
                return new Parser.syntaxFactory.MethodSignatureSyntax(parseNodeData, eatPropertyName(), tryEatToken(105 /* QuestionToken */), parseCallSignature(false));
            }

            function parsePropertySignature() {
                return new Parser.syntaxFactory.PropertySignatureSyntax(parseNodeData, eatPropertyName(), tryEatToken(105 /* QuestionToken */), parseOptionalTypeAnnotation(false));
            }

            function isCallSignature(peekIndex) {
                var tokenKind = peekToken(peekIndex).kind();
                return tokenKind === 72 /* OpenParenToken */ || tokenKind === 80 /* LessThanToken */;
            }

            function isConstructSignature() {
                if (currentToken().kind() !== 31 /* NewKeyword */) {
                    return false;
                }

                return isCallSignature(1);
            }

            function isIndexSignature(peekIndex) {
                return peekToken(peekIndex).kind() === 74 /* OpenBracketToken */;
            }

            function isMethodSignature(inErrorRecovery) {
                if (isPropertyName(currentToken(), inErrorRecovery)) {
                    // id(
                    if (isCallSignature(1)) {
                        return true;
                    }

                    // id?(
                    if (peekToken(1).kind() === 105 /* QuestionToken */ && isCallSignature(2)) {
                        return true;
                    }
                }

                return false;
            }

            function isPropertySignature(inErrorRecovery) {
                var _currentToken = currentToken();

                // Keywords can start properties.  However, they're often intended to start something
                // else.  If we see a modifier before something that can be a property, then don't
                // try parse it out as a property.  For example, if we have:
                //
                //      public foo
                //
                // Then don't parse 'public' as a property name.  Note: if you have:
                //
                //      public
                //      foo
                //
                // Then we *should* parse it as a property name, as ASI takes effect here.
                if (isModifier(_currentToken)) {
                    if (!TypeScript.existsNewLineBetweenTokens(_currentToken, peekToken(1), source.text) && isPropertyName(peekToken(1), inErrorRecovery)) {
                        return false;
                    }
                }

                // Note: property names also start function signatures.  So it's important that we call this
                // after we calll isFunctionSignature.
                return isPropertyName(_currentToken, inErrorRecovery);
            }

            function isHeritageClause() {
                var tokenKind = currentToken().kind();
                return tokenKind === 48 /* ExtendsKeyword */ || tokenKind === 51 /* ImplementsKeyword */;
            }

            function isNotHeritageClauseTypeName() {
                var tokenKind = currentToken().kind();
                if (tokenKind === 51 /* ImplementsKeyword */ || tokenKind === 48 /* ExtendsKeyword */) {
                    return isIdentifier(peekToken(1));
                }

                return false;
            }

            function isHeritageClauseTypeName() {
                if (isIdentifier(currentToken())) {
                    // We want to make sure that the "extends" in "extends foo" or the "implements" in
                    // "implements foo" is not considered a type name.
                    return !isNotHeritageClauseTypeName();
                }

                return false;
            }

            function tryParseHeritageClause() {
                var extendsOrImplementsKeyword = currentToken();
                var tokenKind = extendsOrImplementsKeyword.kind();
                if (tokenKind !== 48 /* ExtendsKeyword */ && tokenKind !== 51 /* ImplementsKeyword */) {
                    return null;
                }

                consumeToken(extendsOrImplementsKeyword);

                var skippedTokens = getArray();
                var typeNames = parseSeparatedSyntaxList(11 /* HeritageClause_TypeNameList */, skippedTokens);
                extendsOrImplementsKeyword = addSkippedTokensAfterToken(extendsOrImplementsKeyword, skippedTokens);

                return new Parser.syntaxFactory.HeritageClauseSyntax(parseNodeData, extendsOrImplementsKeyword, typeNames);
            }

            function isInterfaceEnumClassModuleImportOrExport(modifierCount) {
                var _currentToken = currentToken();

                if (modifierCount) {
                    switch (peekToken(modifierCount).kind()) {
                        case 49 /* ImportKeyword */:
                        case 65 /* ModuleKeyword */:
                        case 52 /* InterfaceKeyword */:
                        case 44 /* ClassKeyword */:
                        case 46 /* EnumKeyword */:
                            return true;
                    }
                }

                // no modifiers.  While certain of these keywords are javascript keywords as well, it
                // is possible to run into them in some circumstances in error recovery where we don't
                // want to consider them the start of the module element construct.  For example, they
                // might be hte name in an object literal.  Because of that, we check the next token to
                // make sure it really is the start of a module element.
                var nextToken = peekToken(1);

                switch (_currentToken.kind()) {
                    case 65 /* ModuleKeyword */:
                        if (isIdentifier(nextToken) || nextToken.kind() === 14 /* StringLiteral */) {
                            return true;
                        }
                        break;

                    case 49 /* ImportKeyword */:
                    case 44 /* ClassKeyword */:
                    case 46 /* EnumKeyword */:
                    case 52 /* InterfaceKeyword */:
                        if (isIdentifier(nextToken)) {
                            return true;
                        }
                        break;

                    case 47 /* ExportKeyword */:
                        if (nextToken.kind() === 107 /* EqualsToken */) {
                            return true;
                        }
                        break;
                }

                return false;
            }

            function isStatement(modifierCount, inErrorRecovery) {
                if (TypeScript.SyntaxUtilities.isStatement(currentNode())) {
                    return true;
                }

                var _currentToken = currentToken();
                var currentTokenKind = _currentToken.kind();
                switch (currentTokenKind) {
                    case 57 /* PublicKeyword */:
                    case 55 /* PrivateKeyword */:
                    case 58 /* StaticKeyword */:
                        // None of the above are actually keywords.  And they might show up in a real
                        // statement (i.e. "public();").  However, if we see 'public <identifier>' then
                        // that can't possibly be a statement (and instead will be a class element),
                        // and we should not parse it out here.
                        var token1 = peekToken(1);
                        if (TypeScript.SyntaxFacts.isIdentifierNameOrAnyKeyword(token1)) {
                            // Definitely not a statement.
                            return false;
                        }

                        break;

                    case 28 /* IfKeyword */:
                    case 70 /* OpenBraceToken */:
                    case 33 /* ReturnKeyword */:
                    case 34 /* SwitchKeyword */:
                    case 36 /* ThrowKeyword */:
                    case 15 /* BreakKeyword */:
                    case 18 /* ContinueKeyword */:
                    case 26 /* ForKeyword */:
                    case 42 /* WhileKeyword */:
                    case 43 /* WithKeyword */:
                    case 22 /* DoKeyword */:
                    case 38 /* TryKeyword */:
                    case 19 /* DebuggerKeyword */:
                        return true;
                }

                // Check for common things that might appear where we expect a statement, but which we
                // do not want to consume.  This can happen when the user does not terminate their
                // existing block properly.  We don't want to accidently consume these as expression
                // below.
                if (isInterfaceEnumClassModuleImportOrExport(modifierCount)) {
                    return false;
                }

                // More complicated cases.
                return isLabeledStatement(_currentToken) || isVariableStatement(modifierCount) || isFunctionDeclaration(modifierCount) || isEmptyStatement(_currentToken, inErrorRecovery) || isExpressionStatement(_currentToken);
            }

            function parseStatement(inErrorRecovery) {
                return tryParseStatement(inErrorRecovery) || parseExpressionStatement();
            }

            function tryParseStatement(inErrorRecovery) {
                var node = currentNode();
                if (TypeScript.SyntaxUtilities.isStatement(node)) {
                    consumeNode(node);
                    return node;
                }

                var _currentToken = currentToken();
                var currentTokenKind = _currentToken.kind();
                return tryParseStatementWorker(_currentToken, currentTokenKind, modifierCount(), inErrorRecovery);
            }

            function tryParseStatementWorker(_currentToken, currentTokenKind, modifierCount, inErrorRecovery) {
                switch (currentTokenKind) {
                    case 57 /* PublicKeyword */:
                    case 55 /* PrivateKeyword */:
                    case 58 /* StaticKeyword */:
                        // None of the above are actually keywords.  And they might show up in a real
                        // statement (i.e. "public();").  However, if we see 'public <identifier>' then
                        // that can't possibly be a statement (and instead will be a class element),
                        // and we should not parse it out here.
                        if (TypeScript.SyntaxFacts.isIdentifierNameOrAnyKeyword(peekToken(1))) {
                            // Definitely not a statement.
                            return null;
                        } else {
                            break;
                        }

                    case 28 /* IfKeyword */: return parseIfStatement(_currentToken);
                    case 70 /* OpenBraceToken */: return parseBlock(false, false);
                    case 33 /* ReturnKeyword */: return parseReturnStatement(_currentToken);
                    case 34 /* SwitchKeyword */: return parseSwitchStatement(_currentToken);
                    case 36 /* ThrowKeyword */: return parseThrowStatement(_currentToken);
                    case 15 /* BreakKeyword */: return parseBreakStatement(_currentToken);
                    case 18 /* ContinueKeyword */: return parseContinueStatement(_currentToken);
                    case 26 /* ForKeyword */: return parseForOrForInStatement(_currentToken);
                    case 42 /* WhileKeyword */: return parseWhileStatement(_currentToken);
                    case 43 /* WithKeyword */: return parseWithStatement(_currentToken);
                    case 22 /* DoKeyword */: return parseDoStatement(_currentToken);
                    case 38 /* TryKeyword */: return parseTryStatement(_currentToken);
                    case 19 /* DebuggerKeyword */: return parseDebuggerStatement(_currentToken);
                }

                // Check for common things that might appear where we expect a statement, but which we
                // do not want to consume.  This can happen when the user does not terminate their
                // existing block properly.  We don't want to accidently consume these as expression
                // below.
                if (isInterfaceEnumClassModuleImportOrExport(modifierCount)) {
                    return null;
                } else if (isVariableStatement(modifierCount)) {
                    return parseVariableStatement();
                } else if (isLabeledStatement(_currentToken)) {
                    return parseLabeledStatement(_currentToken);
                } else if (isFunctionDeclaration(modifierCount)) {
                    return parseFunctionDeclaration();
                } else if (isEmptyStatement(_currentToken, inErrorRecovery)) {
                    return parseEmptyStatement(_currentToken);
                } else if (isExpressionStatement(_currentToken)) {
                    return parseExpressionStatement();
                } else {
                    return null;
                }
            }

            function parseDebuggerStatement(debuggerKeyword) {
                return new Parser.syntaxFactory.DebuggerStatementSyntax(parseNodeData, consumeToken(debuggerKeyword), eatExplicitOrAutomaticSemicolon(false));
            }

            function parseDoStatement(doKeyword) {
                // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html
                // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in
                // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby
                //  do;while(0)x will have a semicolon inserted before x.
                return new Parser.syntaxFactory.DoStatementSyntax(parseNodeData, consumeToken(doKeyword), parseStatement(false), eatToken(42 /* WhileKeyword */), eatToken(72 /* OpenParenToken */), parseExpression(true), eatToken(73 /* CloseParenToken */), eatExplicitOrAutomaticSemicolon(true));
            }

            function isLabeledStatement(currentToken) {
                return isIdentifier(currentToken) && peekToken(1).kind() === 106 /* ColonToken */;
            }

            function parseLabeledStatement(identifierToken) {
                return new Parser.syntaxFactory.LabeledStatementSyntax(parseNodeData, consumeToken(identifierToken), eatToken(106 /* ColonToken */), parseStatement(false));
            }

            function parseTryStatement(tryKeyword) {
                var tryKeyword = consumeToken(tryKeyword);

                var savedListParsingState = listParsingState;
                listParsingState |= (1 << 6 /* TryBlock_Statements */);
                var block = parseBlock(false, false);
                listParsingState = savedListParsingState;

                var catchClause = null;
                if (currentToken().kind() === 17 /* CatchKeyword */) {
                    catchClause = parseCatchClause();
                }

                // If we don't have a catch clause, then we must have a finally clause.  Try to parse
                // one out no matter what.
                var finallyClause = null;
                if (catchClause === null || currentToken().kind() === 25 /* FinallyKeyword */) {
                    finallyClause = parseFinallyClause();
                }

                return new Parser.syntaxFactory.TryStatementSyntax(parseNodeData, tryKeyword, block, catchClause, finallyClause);
            }

            function parseCatchClauseBlock() {
                var savedListParsingState = listParsingState;
                listParsingState |= (1 << 7 /* CatchBlock_Statements */);
                var block = parseBlock(false, false);
                listParsingState = savedListParsingState;

                return block;
            }

            function parseCatchClause() {
                return new Parser.syntaxFactory.CatchClauseSyntax(parseNodeData, eatToken(17 /* CatchKeyword */), eatToken(72 /* OpenParenToken */), eatIdentifierToken(), parseOptionalTypeAnnotation(false), eatToken(73 /* CloseParenToken */), parseCatchClauseBlock());
            }

            function parseFinallyClause() {
                return new Parser.syntaxFactory.FinallyClauseSyntax(parseNodeData, eatToken(25 /* FinallyKeyword */), parseBlock(false, false));
            }

            function parseWithStatement(withKeyword) {
                return new Parser.syntaxFactory.WithStatementSyntax(parseNodeData, consumeToken(withKeyword), eatToken(72 /* OpenParenToken */), parseExpression(true), eatToken(73 /* CloseParenToken */), parseStatement(false));
            }

            function parseWhileStatement(whileKeyword) {
                return new Parser.syntaxFactory.WhileStatementSyntax(parseNodeData, consumeToken(whileKeyword), eatToken(72 /* OpenParenToken */), parseExpression(true), eatToken(73 /* CloseParenToken */), parseStatement(false));
            }

            function isEmptyStatement(currentToken, inErrorRecovery) {
                // If we're in error recovery, then we don't want to treat ';' as an empty statement.
                // The problem is that ';' can show up in far too many contexts, and if we see one
                // and assume it's a statement, then we may bail out innapropriately from whatever
                // we're parsing.  For example, if we have a semicolon in the middle of a class, then
                // we really don't want to assume the class is over and we're on a statement in the
                // outer module.  We just want to consume and move on.
                if (inErrorRecovery) {
                    return false;
                }

                return currentToken.kind() === 78 /* SemicolonToken */;
            }

            function parseEmptyStatement(semicolonToken) {
                return new Parser.syntaxFactory.EmptyStatementSyntax(parseNodeData, consumeToken(semicolonToken));
            }

            function parseForOrForInStatement(forKeyword) {
                // Debug.assert(isForOrForInStatement());
                consumeToken(forKeyword);
                var openParenToken = eatToken(72 /* OpenParenToken */);

                var _currentToken = currentToken();
                var tokenKind = _currentToken.kind();
                if (tokenKind === 40 /* VarKeyword */) {
                    // for ( var VariableDeclarationListNoIn; Expressionopt ; Expressionopt ) Statement
                    // for ( var VariableDeclarationNoIn in Expression ) Statement
                    return parseForOrForInStatementWithVariableDeclaration(forKeyword, openParenToken);
                } else if (tokenKind === 78 /* SemicolonToken */) {
                    // for ( ; Expressionopt ; Expressionopt ) Statement
                    return parseForStatementWithNoVariableDeclarationOrInitializer(forKeyword, openParenToken);
                } else {
                    // for ( ExpressionNoInopt; Expressionopt ; Expressionopt ) Statement
                    // for ( LeftHandSideExpression in Expression ) Statement
                    return parseForOrForInStatementWithInitializer(forKeyword, openParenToken);
                }
            }

            function parseForOrForInStatementWithVariableDeclaration(forKeyword, openParenToken) {
                // Debug.assert(forKeyword.kind === SyntaxKind.ForKeyword && openParenToken.kind() === SyntaxKind.OpenParenToken);
                // Debug.assert(currentToken().kind() === SyntaxKind.VarKeyword);
                // for ( var VariableDeclarationListNoIn; Expressionopt ; Expressionopt ) Statement
                // for ( var VariableDeclarationNoIn in Expression ) Statement
                var variableDeclaration = parseVariableDeclaration(false);
                return currentToken().kind() === 29 /* InKeyword */ ? parseForInStatementWithVariableDeclarationOrInitializer(forKeyword, openParenToken, variableDeclaration, null) : parseForStatementWithVariableDeclarationOrInitializer(forKeyword, openParenToken, variableDeclaration, null);
            }

            function parseForInStatementWithVariableDeclarationOrInitializer(forKeyword, openParenToken, variableDeclaration, initializer) {
                // for ( var VariableDeclarationNoIn in Expression ) Statement
                return new Parser.syntaxFactory.ForInStatementSyntax(parseNodeData, forKeyword, openParenToken, variableDeclaration, initializer, eatToken(29 /* InKeyword */), parseExpression(true), eatToken(73 /* CloseParenToken */), parseStatement(false));
            }

            function parseForOrForInStatementWithInitializer(forKeyword, openParenToken) {
                // Debug.assert(forKeyword.kind() === SyntaxKind.ForKeyword && openParenToken.kind() === SyntaxKind.OpenParenToken);
                // for ( ExpressionNoInopt; Expressionopt ; Expressionopt ) Statement
                // for ( LeftHandSideExpression in Expression ) Statement
                var initializer = parseExpression(false);
                return currentToken().kind() === 29 /* InKeyword */ ? parseForInStatementWithVariableDeclarationOrInitializer(forKeyword, openParenToken, null, initializer) : parseForStatementWithVariableDeclarationOrInitializer(forKeyword, openParenToken, null, initializer);
            }

            function parseForStatementWithNoVariableDeclarationOrInitializer(forKeyword, openParenToken) {
                // Debug.assert(forKeyword.kind() === SyntaxKind.ForKeyword && openParenToken.kind() === SyntaxKind.OpenParenToken);
                // Debug.assert(currentToken().kind() === SyntaxKind.SemicolonToken);
                // for ( ; Expressionopt ; Expressionopt ) Statement
                return parseForStatementWithVariableDeclarationOrInitializer(forKeyword, openParenToken, null, null);
            }

            function tryParseForStatementCondition() {
                var tokenKind = currentToken().kind();
                if (tokenKind !== 78 /* SemicolonToken */ && tokenKind !== 73 /* CloseParenToken */ && tokenKind !== 10 /* EndOfFileToken */) {
                    return parseExpression(true);
                }

                return null;
            }

            function tryParseForStatementIncrementor() {
                var tokenKind = currentToken().kind();
                if (tokenKind !== 73 /* CloseParenToken */ && tokenKind !== 10 /* EndOfFileToken */) {
                    return parseExpression(true);
                }

                return null;
            }

            function parseForStatementWithVariableDeclarationOrInitializer(forKeyword, openParenToken, variableDeclaration, initializer) {
                // NOTE: From the es5 section on Automatic Semicolon Insertion.
                // a semicolon is never inserted automatically if the semicolon would then ... become
                // one of the two semicolons in the header of a for statement
                return new Parser.syntaxFactory.ForStatementSyntax(parseNodeData, forKeyword, openParenToken, variableDeclaration, initializer, eatToken(78 /* SemicolonToken */), tryParseForStatementCondition(), eatToken(78 /* SemicolonToken */), tryParseForStatementIncrementor(), eatToken(73 /* CloseParenToken */), parseStatement(false));
            }

            function tryEatBreakOrContinueLabel() {
                // If there is no newline after the break keyword, then we can consume an optional
                // identifier.
                var identifier = null;
                if (!canEatExplicitOrAutomaticSemicolon(false)) {
                    if (isIdentifier(currentToken())) {
                        return eatIdentifierToken();
                    }
                }

                return null;
            }

            function parseBreakStatement(breakKeyword) {
                return new Parser.syntaxFactory.BreakStatementSyntax(parseNodeData, consumeToken(breakKeyword), tryEatBreakOrContinueLabel(), eatExplicitOrAutomaticSemicolon(false));
            }

            function parseContinueStatement(continueKeyword) {
                return new Parser.syntaxFactory.ContinueStatementSyntax(parseNodeData, consumeToken(continueKeyword), tryEatBreakOrContinueLabel(), eatExplicitOrAutomaticSemicolon(false));
            }

            function parseSwitchStatement(switchKeyword) {
                // Debug.assert(isSwitchStatement());
                consumeToken(switchKeyword);
                var openParenToken = eatToken(72 /* OpenParenToken */);
                var expression = parseExpression(true);
                var closeParenToken = eatToken(73 /* CloseParenToken */);
                var openBraceToken = eatToken(70 /* OpenBraceToken */);

                var switchClauses = TypeScript.Syntax.emptyList();
                if (openBraceToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    switchClauses = parseSyntaxList(3 /* SwitchStatement_SwitchClauses */, skippedTokens);
                    openBraceToken = addSkippedTokensAfterToken(openBraceToken, skippedTokens);
                }

                return new Parser.syntaxFactory.SwitchStatementSyntax(parseNodeData, switchKeyword, openParenToken, expression, closeParenToken, openBraceToken, switchClauses, eatToken(71 /* CloseBraceToken */));
            }

            function isSwitchClause() {
                if (TypeScript.SyntaxUtilities.isSwitchClause(currentNode())) {
                    return true;
                }

                var currentTokenKind = currentToken().kind();
                return currentTokenKind === 16 /* CaseKeyword */ || currentTokenKind === 20 /* DefaultKeyword */;
            }

            function tryParseSwitchClause() {
                // Debug.assert(isSwitchClause());
                var node = currentNode();
                if (TypeScript.SyntaxUtilities.isSwitchClause(node)) {
                    consumeNode(node);
                    return node;
                }

                var _currentToken = currentToken();
                var kind = _currentToken.kind();
                if (kind === 16 /* CaseKeyword */) {
                    return parseCaseSwitchClause(_currentToken);
                } else if (kind === 20 /* DefaultKeyword */) {
                    return parseDefaultSwitchClause(_currentToken);
                } else {
                    return null;
                }
            }

            function parseCaseSwitchClause(caseKeyword) {
                // Debug.assert(isCaseSwitchClause());
                consumeToken(caseKeyword);
                var expression = parseExpression(true);
                var colonToken = eatToken(106 /* ColonToken */);
                var statements = TypeScript.Syntax.emptyList();

                // TODO: allow parsing of the list evne if there's no colon.  However, we have to make
                // sure we add any skipped tokens to the right previous node or token.
                if (colonToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    statements = parseSyntaxList(4 /* SwitchClause_Statements */, skippedTokens);
                    colonToken = addSkippedTokensAfterToken(colonToken, skippedTokens);
                }

                return new Parser.syntaxFactory.CaseSwitchClauseSyntax(parseNodeData, caseKeyword, expression, colonToken, statements);
            }

            function parseDefaultSwitchClause(defaultKeyword) {
                // Debug.assert(isDefaultSwitchClause());
                consumeToken(defaultKeyword);
                var colonToken = eatToken(106 /* ColonToken */);
                var statements = TypeScript.Syntax.emptyList();

                // TODO: Allow parsing without a colon here.  However, ensure that we attach any skipped
                // tokens to the defaultKeyword.
                if (colonToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    statements = parseSyntaxList(4 /* SwitchClause_Statements */, skippedTokens);
                    colonToken = addSkippedTokensAfterToken(colonToken, skippedTokens);
                }

                return new Parser.syntaxFactory.DefaultSwitchClauseSyntax(parseNodeData, defaultKeyword, colonToken, statements);
            }

            function parseThrowStatementExpression() {
                // Because of automatic semicolon insertion, we need to report error if this
                // throw could be terminated with a semicolon.  Note: we can't call 'parseExpression'
                // directly as that might consume an expression on the following line.
                return canEatExplicitOrAutomaticSemicolon(false) ? createMissingToken(11 /* IdentifierName */, null) : parseExpression(true);
            }

            function parseThrowStatement(throwKeyword) {
                return new Parser.syntaxFactory.ThrowStatementSyntax(parseNodeData, consumeToken(throwKeyword), parseThrowStatementExpression(), eatExplicitOrAutomaticSemicolon(false));
            }

            function tryParseReturnStatementExpression() {
                return !canEatExplicitOrAutomaticSemicolon(false) ? parseExpression(true) : null;
            }

            function parseReturnStatement(returnKeyword) {
                return new Parser.syntaxFactory.ReturnStatementSyntax(parseNodeData, consumeToken(returnKeyword), tryParseReturnStatementExpression(), eatExplicitOrAutomaticSemicolon(false));
            }

            function isExpressionStatement(currentToken) {
                // As per the gramar, neither { nor 'function' can start an expression statement.
                var tokenKind = currentToken.kind();
                return tokenKind !== 70 /* OpenBraceToken */ && tokenKind !== 27 /* FunctionKeyword */ && isExpression(currentToken);
            }

            function isAssignmentOrOmittedExpression() {
                var _currentToken = currentToken();
                return _currentToken.kind() === 79 /* CommaToken */ || isExpression(_currentToken);
            }

            function tryParseAssignmentOrOmittedExpression() {
                // Debug.assert(isAssignmentOrOmittedExpression());
                if (currentToken().kind() === 79 /* CommaToken */) {
                    return new Parser.syntaxFactory.OmittedExpressionSyntax(parseNodeData);
                }

                return tryParseAssignmentExpressionOrHigher(false, true);
            }

            function isExpression(currentToken) {
                switch (currentToken.kind()) {
                    case 13 /* NumericLiteral */:
                    case 14 /* StringLiteral */:
                    case 12 /* RegularExpressionLiteral */:

                    case 74 /* OpenBracketToken */:

                    case 72 /* OpenParenToken */:

                    case 80 /* LessThanToken */:

                    case 93 /* PlusPlusToken */:
                    case 94 /* MinusMinusToken */:
                    case 89 /* PlusToken */:
                    case 90 /* MinusToken */:
                    case 102 /* TildeToken */:
                    case 101 /* ExclamationToken */:

                    case 70 /* OpenBraceToken */:

                    case 85 /* EqualsGreaterThanToken */:

                    case 118 /* SlashToken */:
                    case 119 /* SlashEqualsToken */:

                    case 50 /* SuperKeyword */:
                    case 35 /* ThisKeyword */:
                    case 37 /* TrueKeyword */:
                    case 24 /* FalseKeyword */:
                    case 32 /* NullKeyword */:

                    case 31 /* NewKeyword */:

                    case 21 /* DeleteKeyword */:
                    case 41 /* VoidKeyword */:
                    case 39 /* TypeOfKeyword */:

                    case 27 /* FunctionKeyword */:
                        return true;
                }

                return isIdentifier(currentToken);
            }

            function parseExpressionStatement() {
                return new Parser.syntaxFactory.ExpressionStatementSyntax(parseNodeData, parseExpression(true), eatExplicitOrAutomaticSemicolon(false));
            }

            function parseIfStatement(ifKeyword) {
                return new Parser.syntaxFactory.IfStatementSyntax(parseNodeData, consumeToken(ifKeyword), eatToken(72 /* OpenParenToken */), parseExpression(true), eatToken(73 /* CloseParenToken */), parseStatement(false), parseOptionalElseClause());
            }

            function parseOptionalElseClause() {
                return currentToken().kind() === 23 /* ElseKeyword */ ? parseElseClause() : null;
            }

            function parseElseClause() {
                return new Parser.syntaxFactory.ElseClauseSyntax(parseNodeData, eatToken(23 /* ElseKeyword */), parseStatement(false));
            }

            function isVariableStatement(modifierCount) {
                return peekToken(modifierCount).kind() === 40 /* VarKeyword */;
            }

            function parseVariableStatement() {
                return new Parser.syntaxFactory.VariableStatementSyntax(parseNodeData, parseModifiers(), parseVariableDeclaration(true), eatExplicitOrAutomaticSemicolon(false));
            }

            function parseVariableDeclaration(allowIn) {
                // Debug.assert(currentToken().kind() === SyntaxKind.VarKeyword);
                var varKeyword = eatToken(40 /* VarKeyword */);

                // Debug.assert(varKeyword.fullWidth() > 0);
                var listParsingState = allowIn ? 12 /* VariableDeclaration_VariableDeclarators_AllowIn */ : 13 /* VariableDeclaration_VariableDeclarators_DisallowIn */;

                var skippedTokens = getArray();
                var variableDeclarators = parseSeparatedSyntaxList(listParsingState, skippedTokens);
                varKeyword = addSkippedTokensAfterToken(varKeyword, skippedTokens);

                return new Parser.syntaxFactory.VariableDeclarationSyntax(parseNodeData, varKeyword, variableDeclarators);
            }

            function isVariableDeclarator() {
                var node = currentNode();
                if (node !== null && node.kind() === 225 /* VariableDeclarator */) {
                    return true;
                }

                return isIdentifier(currentToken());
            }

            function canReuseVariableDeclaratorNode(node) {
                if (node === null || node.kind() !== 225 /* VariableDeclarator */) {
                    return false;
                }

                // Very subtle incremental parsing bug.  Consider the following code:
                //
                //      var v = new List < A, B
                //
                // This is actually legal code.  It's a list of variable declarators "v = new List<A"
                // on one side and "B" on the other. If you then change that to:
                //
                //      var v = new List < A, B >()
                //
                // then we have a problem.  "v = new List<A" doesn't intersect the change range, so we
                // start reparsing at "B" and we completely fail to handle this properly.
                //
                // In order to prevent this, we do not allow a variable declarator to be reused if it
                // has an initializer.
                var variableDeclarator = node;
                return variableDeclarator.equalsValueClause === null;
            }

            function tryParseVariableDeclarator(allowIn, allowPropertyName) {
                // TODO(cyrusn): What if the 'allowIn' context has changed between when we last parsed
                // and now?  We could end up with an incorrect tree.  For example, say we had in the old
                // tree "var i = a in b".  Then, in the new tree the declarator portion moved into:
                // "for (var i = a in b".  We would not want to reuse the declarator as the "in b" portion
                // would need to be consumed by the for declaration instead.  Need to see if it is possible
                // to hit this case.
                var node = currentNode();
                if (canReuseVariableDeclaratorNode(node)) {
                    consumeNode(node);
                    return node;
                }

                if (allowPropertyName) {
                    // Debug.assert(isPropertyName(currentToken(), /*inErrorRecovery:*/ false));
                }

                if (!allowPropertyName && !isIdentifier(currentToken())) {
                    return null;
                }

                var propertyName = allowPropertyName ? eatPropertyName() : eatIdentifierToken();
                var equalsValueClause = null;
                var typeAnnotation = null;

                if (propertyName.fullWidth() > 0) {
                    typeAnnotation = parseOptionalTypeAnnotation(false);

                    if (isEqualsValueClause(false)) {
                        equalsValueClause = parseEqualsValueClause(allowIn);
                    }
                }

                return new Parser.syntaxFactory.VariableDeclaratorSyntax(parseNodeData, propertyName, typeAnnotation, equalsValueClause);
            }

            function isEqualsValueClause(inParameter) {
                var token0 = currentToken();
                if (token0.kind() === 107 /* EqualsToken */) {
                    return true;
                }

                // It's not uncommon during typing for the user to miss writing the '=' token.  Check if
                // there is no newline after the last token and if we're on an expression.  If so, parse
                // this as an equals-value clause with a missing equals.
                if (!previousTokenHasTrailingNewLine(token0)) {
                    var tokenKind = token0.kind();

                    // The 'isExpression' call below returns true for "=>".  That's because it smartly
                    // assumes that there is just a missing identifier and the user wanted a lambda.
                    // While this is sensible, we don't want to allow that here as that would mean we're
                    // glossing over multiple erorrs and we're probably making things worse.  So don't
                    // treat this as an equals value clause and let higher up code handle things.
                    if (tokenKind === 85 /* EqualsGreaterThanToken */) {
                        return false;
                    }

                    // There are two places where we allow equals-value clauses.  The first is in a
                    // variable declarator.  The second is with a parameter.  For variable declarators
                    // it's more likely that a { would be a allowed (as an object literal).  While this
                    // is also allowed for parameters, the risk is that we consume the { as an object
                    // literal when it really will be for the block following the parameter.
                    if (tokenKind === 70 /* OpenBraceToken */ && inParameter) {
                        return false;
                    }

                    return isExpression(token0);
                }

                return false;
            }

            function parseEqualsValueClause(allowIn) {
                return new Parser.syntaxFactory.EqualsValueClauseSyntax(parseNodeData, eatToken(107 /* EqualsToken */), tryParseAssignmentExpressionOrHigher(true, allowIn));
            }

            function parseExpression(allowIn) {
                // Expression[in]:
                //      AssignmentExpression[in]
                //      Expression[in] , AssignmentExpression[in]
                var leftOperand = tryParseAssignmentExpressionOrHigher(true, allowIn);
                while (true) {
                    var _currentToken = currentToken();
                    if (_currentToken.kind() !== 79 /* CommaToken */) {
                        break;
                    }

                    leftOperand = new Parser.syntaxFactory.BinaryExpressionSyntax(parseNodeData, leftOperand, consumeToken(_currentToken), tryParseAssignmentExpressionOrHigher(true, allowIn));
                }

                return leftOperand;
            }

            // Called when you need to parse an expression, but you do not want to allow 'CommaExpressions'.
            // i.e. if you have "var a = 1, b = 2" then when we parse '1' we want to parse with higher
            // precedence than 'comma'.  Otherwise we'll get: "var a = (1, (b = 2))", instead of
            // "var a = (1), b = (2)");
            function tryParseAssignmentExpressionOrHigher(force, allowIn) {
                // Augmented by TypeScript:
                //
                //  AssignmentExpression[in]:
                //      1) ConditionalExpression[in]
                //      2) LeftHandSideExpression = AssignmentExpression[in]
                //      3) LeftHandSideExpression AssignmentOperator AssignmentExpression[in]
                //      4) ArrowFunctionExpression <-- added by TypeScript
                //
                // Open spec question.  Right now, there is no 'ArrowFunctionExpression[in]' variant.
                // Thus, if the user has:
                //
                //      for (var a = () => b in c) {}
                //
                // Then we will fail to parse (because the 'in' will be consumed as part of the body of
                // the lambda, and not as part of the 'for' statement).  This is likely not an issue
                // whatsoever as there seems to be no good reason why anyone would ever write code like
                // the above.
                //
                // Note: for ease of implementation we treat productions '2' and '3' as the same thing.
                // (i.e. they're both BinaryExpressions with an assignment operator in it).
                // First, check if we have production '4' (an arrow function).  Note that if we do, we
                // must *not* recurse for productsion 1, 2 or 3. An ArrowFunction is not a
                // LeftHandSideExpression, nor does it start a ConditionalExpression.  So we are done
                // with AssignmentExpression if we see one.
                var _currentToken = currentToken();
                var arrowFunction = tryParseAnyArrowFunctionExpression(_currentToken);
                if (arrowFunction !== null) {
                    return arrowFunction;
                }

                // Now try to see if we're in production '1', '2' or '3'.  A conditional expression can
                // start with a LogicalOrExpression, while the assignment productions can only start with
                // LeftHandSideExpressions.
                //
                // So, first, we try to just parse out a BinaryExpression.  If we get something that is a
                // LeftHandSide or higher, then we can try to parse out the assignment expression part.
                // Otherwise, we try to parse out the conditional expression bit.  We want to allow any
                // binary expression here, so we pass in the 'lowest' precedence here so that it matches
                // and consumes anything.
                var leftOperand = tryParseBinaryExpressionOrHigher(_currentToken, force, 1 /* Lowest */, allowIn);
                if (leftOperand === null) {
                    return null;
                }

                if (TypeScript.SyntaxUtilities.isLeftHandSizeExpression(leftOperand)) {
                    // Note: we call currentOperatorToken so that we get an appropriately merged token
                    // for cases like > > =  becoming >>=
                    var operatorToken = currentOperatorToken();

                    // Check for recursive assignment expressions.
                    if (TypeScript.SyntaxFacts.isAssignmentOperatorToken(operatorToken.kind())) {
                        return new Parser.syntaxFactory.BinaryExpressionSyntax(parseNodeData, leftOperand, consumeToken(operatorToken), tryParseAssignmentExpressionOrHigher(true, allowIn));
                    }
                }

                // It wasn't an assignment or a lambda.  This is a conditional expression:
                return parseConditionalExpressionRest(allowIn, leftOperand);
            }

            function tryParseAnyArrowFunctionExpression(_currentToken) {
                return isSimpleArrowFunctionExpression(_currentToken) ? parseSimpleArrowFunctionExpression() : tryParseParenthesizedArrowFunctionExpression();
            }

            function tryParseUnaryExpressionOrHigher(_currentToken, force) {
                var currentTokenKind = _currentToken.kind();

                switch (currentTokenKind) {
                    case 89 /* PlusToken */:
                    case 90 /* MinusToken */:
                    case 102 /* TildeToken */:
                    case 101 /* ExclamationToken */:
                    case 93 /* PlusPlusToken */:
                    case 94 /* MinusMinusToken */:
                        return new Parser.syntaxFactory.PrefixUnaryExpressionSyntax(parseNodeData, consumeToken(_currentToken), tryParseUnaryExpressionOrHigher(currentToken(), true));
                    case 39 /* TypeOfKeyword */: return parseTypeOfExpression(_currentToken);
                    case 41 /* VoidKeyword */: return parseVoidExpression(_currentToken);
                    case 21 /* DeleteKeyword */: return parseDeleteExpression(_currentToken);
                    case 80 /* LessThanToken */: return parseCastExpression(_currentToken);
                    default:
                        return tryParsePostfixExpressionOrHigher(_currentToken, force);
                }
            }

            function tryParseBinaryExpressionOrHigher(_currentToken, force, precedence, allowIn) {
                // The binary expressions are incredibly left recursive in their definitions. We
                // clearly can't implement that through recursion.  So, instead, we first bottom out
                // of all the recursion by jumping to this production and consuming a UnaryExpression
                // first.
                //
                // MultiplicativeExpression: See 11.5
                //      UnaryExpression
                var leftOperand = tryParseUnaryExpressionOrHigher(_currentToken, force);
                if (leftOperand === null) {
                    return null;
                }

                // We then pop up the stack consuming the other side of the binary exprssion if it exists.
                return parseBinaryExpressionRest(precedence, allowIn, leftOperand);
            }

            function parseConditionalExpressionRest(allowIn, leftOperand) {
                // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher.
                var _currentToken = currentToken();

                // Now check for conditional expression.
                if (_currentToken.kind() !== 105 /* QuestionToken */) {
                    return leftOperand;
                }

                // Note: we explicitly do *not* pass 'allowIn' to the whenTrue part.  An 'in' expression is always
                // allowed in the 'true' part of a conditional expression.
                return new Parser.syntaxFactory.ConditionalExpressionSyntax(parseNodeData, leftOperand, consumeToken(_currentToken), tryParseAssignmentExpressionOrHigher(true, true), eatToken(106 /* ColonToken */), tryParseAssignmentExpressionOrHigher(true, allowIn));
            }

            function parseBinaryExpressionRest(precedence, allowIn, leftOperand) {
                while (true) {
                    // We either have a binary operator here, or we're finished.  We call
                    // currentOperatorToken versus currentToken here so that we merge token sequences
                    // like > and = into >=
                    var operatorToken = currentOperatorToken();
                    var tokenKind = operatorToken.kind();

                    // Only proceed if we see binary expression token.  However we don't parse
                    // assignment expressions or comma expressions here.  Those are taken care of
                    // respectively in parseAssignmentExpression and parseExpression.
                    if (!TypeScript.SyntaxFacts.isBinaryExpressionOperatorToken(tokenKind) || tokenKind === 79 /* CommaToken */ || TypeScript.SyntaxFacts.isAssignmentOperatorToken(tokenKind)) {
                        break;
                    }

                    // also, if it's the 'in' operator, only allow if our caller allows it.
                    if (tokenKind === 29 /* InKeyword */ && !allowIn) {
                        break;
                    }

                    var newPrecedence = getBinaryExpressionPrecedence(tokenKind);

                    // All binary operators must have precedence > 0
                    // Debug.assert(newPrecedence > 0);
                    // Check the precedence to see if we should "take" this operator
                    if (newPrecedence <= precedence) {
                        break;
                    }

                    // Precedence is okay, so we'll "take" this operator.
                    // Now skip the operator token we're on.
                    leftOperand = new Parser.syntaxFactory.BinaryExpressionSyntax(parseNodeData, leftOperand, consumeToken(operatorToken), tryParseBinaryExpressionOrHigher(currentToken(), true, newPrecedence, allowIn));
                }

                return leftOperand;
            }

            function currentOperatorToken() {
                var token0 = currentToken();

                // If we see a > we need to see if we can actually merge this contextually into a
                // >>  >>>  >=  >>=  >>>=  token.
                if (token0.kind() === 81 /* GreaterThanToken */) {
                    return currentContextualToken();
                    // var kind = token0.kind;
                    //Debug.assert(kind() === SyntaxKind.GreaterThanToken || kind() === SyntaxKind.GreaterThanGreaterThanToken ||
                    //             kind() === SyntaxKind.GreaterThanGreaterThanGreaterThanToken || kind() === SyntaxKind.GreaterThanEqualsToken ||
                    //             kind() === SyntaxKind.GreaterThanGreaterThanEqualsToken || kind() === SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken);
                }

                return token0;
            }

            function tryParseMemberExpressionOrHigher(_currentToken, force, inObjectCreation) {
                // Note: to make our lives simpler, we decompose the the NewExpression productions and
                // place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
                // like so:
                //
                //   PrimaryExpression : See 11.1
                //      this
                //      Identifier
                //      Literal
                //      ArrayLiteral
                //      ObjectLiteral
                //      (Expression)
                //      FunctionExpression
                //      new MemberExpression Arguments?
                //
                //   MemberExpression : See 11.2
                //      PrimaryExpression
                //      MemberExpression[Expression]
                //      MemberExpression.IdentifierName
                //
                //   CallExpression : See 11.2
                //      MemberExpression
                //      CallExpression Arguments
                //      CallExpression[Expression]
                //      CallExpression.IdentifierName
                //
                // Technically this is ambiguous.  i.e. CallExpression defines:
                //
                //   CallExpression:
                //      CallExpression Arguments
                //
                // If you see: "new Foo()"
                //
                // Then that could be treated as a single ObjectCreationExpression, or it could be
                // treated as the invocation of "new Foo".  We disambiguate that in code (to match
                // the original grammar) by making sure that if we see an ObjectCreationExpression
                // we always consume arguments if they are there. So we treat "new Foo()" as an
                // object creation only, and not at all as an invocation)  Another way to think
                // about this is that for every "new" that we see, we will consume an argument list if
                // it is there as part of the *associated* object creation node.  Any additional
                // argument lists we see, will become invocation expressions.
                //
                // Because there are no other places in the grammar now that refer to FunctionExpression
                // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression
                // production.
                //
                // Because CallExpression and MemberExpression are left recursive, we need to bottom out
                // of the recursion immediately.  So we parse out a primary expression to start with.
                var expression = tryParsePrimaryExpression(_currentToken, force);
                if (expression === null) {
                    return null;
                }

                return parseMemberExpressionRest(expression, inObjectCreation);
            }

            function parseCallExpressionRest(expression) {
                while (true) {
                    var _currentToken = currentToken();
                    var currentTokenKind = _currentToken.kind();

                    switch (currentTokenKind) {
                        case 72 /* OpenParenToken */:
                            expression = new Parser.syntaxFactory.InvocationExpressionSyntax(parseNodeData, expression, parseArgumentList(null));
                            continue;

                        case 80 /* LessThanToken */:
                            // See if this is the start of a generic invocation.  If so, consume it and
                            // keep checking for postfix expressions.  Otherwise, it's just a '<' that's
                            // part of an arithmetic expression.  Break out so we consume it higher in the
                            // stack.
                            var argumentList = tryParseArgumentList();
                            if (argumentList === null) {
                                break;
                            }

                            expression = new Parser.syntaxFactory.InvocationExpressionSyntax(parseNodeData, expression, argumentList);
                            continue;

                        case 74 /* OpenBracketToken */:
                            expression = parseElementAccessExpression(expression, _currentToken, false);
                            continue;

                        case 76 /* DotToken */:
                            expression = new Parser.syntaxFactory.MemberAccessExpressionSyntax(parseNodeData, expression, consumeToken(_currentToken), eatIdentifierNameToken());
                            continue;
                    }

                    return expression;
                }
            }

            function parseMemberExpressionRest(expression, inObjectCreation) {
                while (true) {
                    var _currentToken = currentToken();
                    var currentTokenKind = _currentToken.kind();

                    switch (currentTokenKind) {
                        case 74 /* OpenBracketToken */:
                            expression = parseElementAccessExpression(expression, _currentToken, inObjectCreation);
                            continue;

                        case 76 /* DotToken */:
                            expression = new Parser.syntaxFactory.MemberAccessExpressionSyntax(parseNodeData, expression, consumeToken(_currentToken), eatIdentifierNameToken());
                            continue;
                    }

                    return expression;
                }
            }

            function tryParseLeftHandSideExpressionOrHigher(_currentToken, force) {
                // Original Ecma:
                // LeftHandSideExpression: See 11.2
                //      NewExpression
                //      CallExpression
                //
                // Our simplification:
                //
                // LeftHandSideExpression: See 11.2
                //      MemberExpression
                //      CallExpression
                //
                // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with
                // MemberExpression to make our lives easier.
                //
                // to best understand the below code, it's important to see how CallExpression expands
                // out into its own productions:
                //
                // CallExpression:
                //      MemberExpression Arguments
                //      CallExpression Arguments
                //      CallExpression[Expression]
                //      CallExpression.IdentifierName
                //      super   (   ArgumentListopt   )
                //      super.IdentifierName
                //
                // Because of the recursion in these calls, we need to bottom out first.  There are two
                // bottom out states we can run into.  Either we see 'super' which must start either of
                // the last two CallExpression productions.  Or we have a MemberExpression which either
                // completes the LeftHandSideExpression, or starts the beginning of the first four
                // CallExpression productions.
                var expression = null;
                if (_currentToken.kind() === 50 /* SuperKeyword */) {
                    expression = parseSuperExpression(_currentToken);
                } else {
                    expression = tryParseMemberExpressionOrHigher(_currentToken, force, false);
                    if (expression === null) {
                        return null;
                    }
                }

                // Now, we *may* be complete.  However, we might have consumed the start of a
                // CallExpression.  As such, we need to consume the rest of it here to be complete.
                return parseCallExpressionRest(expression);
            }

            function parseSuperExpression(superToken) {
                var expression = consumeToken(superToken);

                // If we have seen "super" it must be followed by '(' or '.'.
                // If it wasn't then just try to parse out a '.' and report an error.
                var currentTokenKind = currentToken().kind();
                return currentTokenKind === 72 /* OpenParenToken */ || currentTokenKind === 76 /* DotToken */ ? expression : new Parser.syntaxFactory.MemberAccessExpressionSyntax(parseNodeData, expression, eatToken(76 /* DotToken */), eatIdentifierNameToken());
            }

            function tryParsePostfixExpressionOrHigher(_currentToken, force) {
                var expression = tryParseLeftHandSideExpressionOrHigher(_currentToken, force);
                if (expression === null) {
                    return null;
                }

                var _currentToken = currentToken();
                var currentTokenKind = _currentToken.kind();

                switch (currentTokenKind) {
                    case 93 /* PlusPlusToken */:
                    case 94 /* MinusMinusToken */:
                        // Because of automatic semicolon insertion, we should only consume the ++ or --
                        // if it is on the same line as the previous token.
                        if (previousTokenHasTrailingNewLine(_currentToken)) {
                            break;
                        }

                        return new Parser.syntaxFactory.PostfixUnaryExpressionSyntax(parseNodeData, expression, consumeToken(_currentToken));
                }

                return expression;
            }

            function tryParseGenericArgumentList() {
                // Debug.assert(currentToken().kind() === SyntaxKind.LessThanToken);
                // If we have a '<', then only parse this as a arugment list if the type arguments
                // are complete and we have an open paren.  if we don't, rewind and return nothing.
                var rewindPoint = getRewindPoint();

                var typeArgumentList = tryParseTypeArgumentList(true);
                var token0 = currentToken();
                var tokenKind = token0.kind();

                var isOpenParen = tokenKind === 72 /* OpenParenToken */;
                var isDot = tokenKind === 76 /* DotToken */;
                var isOpenParenOrDot = isOpenParen || isDot;

                var argumentList = null;
                if (typeArgumentList === null || !isOpenParenOrDot) {
                    // Wasn't generic.  Rewind to where we started so this can be parsed as an
                    // arithmetic expression.
                    rewind(rewindPoint);
                    releaseRewindPoint(rewindPoint);
                    return null;
                } else {
                    releaseRewindPoint(rewindPoint);

                    // It's not uncommon for a user to type: "Foo<T>."
                    //
                    // This is not legal in typescript (as an parameter list must follow the type
                    // arguments).  We want to give a good error message for this as otherwise
                    // we'll bail out here and give a poor error message when we try to parse this
                    // as an arithmetic expression.
                    if (isDot) {
                        // A parameter list must follow a generic type argument list.
                        var diagnostic = new TypeScript.Diagnostic(fileName, source.text.lineMap(), TypeScript.start(token0, source.text), TypeScript.width(token0), TypeScript.DiagnosticCode.A_parameter_list_must_follow_a_generic_type_argument_list_expected, null);
                        addDiagnostic(diagnostic);

                        return new Parser.syntaxFactory.ArgumentListSyntax(parseNodeData, typeArgumentList, TypeScript.Syntax.emptyToken(72 /* OpenParenToken */), TypeScript.Syntax.emptySeparatedList(), TypeScript.Syntax.emptyToken(73 /* CloseParenToken */));
                    } else {
                        return parseArgumentList(typeArgumentList);
                    }
                }
            }

            function tryParseArgumentList() {
                var tokenKind = currentToken().kind();
                if (tokenKind === 80 /* LessThanToken */) {
                    return tryParseGenericArgumentList();
                }

                if (tokenKind === 72 /* OpenParenToken */) {
                    return parseArgumentList(null);
                }

                return null;
            }

            function parseArgumentList(typeArgumentList) {
                var openParenToken = eatToken(72 /* OpenParenToken */);

                // Don't use the name 'arguments' it prevents V8 from optimizing this method.
                var _arguments = TypeScript.Syntax.emptySeparatedList();

                if (openParenToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    _arguments = parseSeparatedSyntaxList(14 /* ArgumentList_AssignmentExpressions */, skippedTokens);
                    openParenToken = addSkippedTokensAfterToken(openParenToken, skippedTokens);
                }

                return new Parser.syntaxFactory.ArgumentListSyntax(parseNodeData, typeArgumentList, openParenToken, _arguments, eatToken(73 /* CloseParenToken */));
            }

            function tryParseArgumentListExpression() {
                // Generally while parsing lists, we don't want to 'force' the parser to parse
                // the item.  That way, if the expected item isn't htere, we can bail out and
                // move to a higher stage of list parsing.  However, it's extremely common to
                // see something like "Foo(, a".  in this case, even though there isn't an expression
                // after the open paren, we still want to force parsing an expression (which will
                // cause a missing identiifer to be created), so that we will then consume the
                // comma and the following list items).
                var force = currentToken().kind() === 79 /* CommaToken */;
                return tryParseAssignmentExpressionOrHigher(force, true);
            }

            function parseElementAccessArgumentExpression(openBracketToken, inObjectCreation) {
                // It's not uncommon for a user to write: "new Type[]".  Check for that common pattern
                // and report a better error message.
                if (inObjectCreation && currentToken().kind() === 75 /* CloseBracketToken */) {
                    var errorStart = TypeScript.start(openBracketToken, source.text);
                    var errorEnd = TypeScript.end(currentToken(), source.text);
                    var diagnostic = new TypeScript.Diagnostic(fileName, source.text.lineMap(), errorStart, errorEnd - errorStart, TypeScript.DiagnosticCode.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead, null);
                    addDiagnostic(diagnostic);

                    return TypeScript.Syntax.emptyToken(11 /* IdentifierName */);
                } else {
                    return parseExpression(true);
                }
            }

            function parseElementAccessExpression(expression, openBracketToken, inObjectCreation) {
                // Debug.assert(currentToken().kind() === SyntaxKind.OpenBracketToken);
                return new Parser.syntaxFactory.ElementAccessExpressionSyntax(parseNodeData, expression, consumeToken(openBracketToken), parseElementAccessArgumentExpression(openBracketToken, inObjectCreation), eatToken(75 /* CloseBracketToken */));
            }

            function tryParsePrimaryExpression(_currentToken, force) {
                if (isIdentifier(_currentToken)) {
                    return eatIdentifierToken();
                }

                var currentTokenKind = _currentToken.kind();
                switch (currentTokenKind) {
                    case 35 /* ThisKeyword */:
                    case 37 /* TrueKeyword */:
                    case 24 /* FalseKeyword */:
                    case 32 /* NullKeyword */:
                    case 13 /* NumericLiteral */:
                    case 12 /* RegularExpressionLiteral */:
                    case 14 /* StringLiteral */:
                        return consumeToken(_currentToken);

                    case 27 /* FunctionKeyword */: return parseFunctionExpression(_currentToken);
                    case 74 /* OpenBracketToken */: return parseArrayLiteralExpression(_currentToken);
                    case 70 /* OpenBraceToken */: return parseObjectLiteralExpression(_currentToken);
                    case 72 /* OpenParenToken */: return parseParenthesizedExpression(_currentToken);
                    case 31 /* NewKeyword */: return parseObjectCreationExpression(_currentToken);

                    case 118 /* SlashToken */:
                    case 119 /* SlashEqualsToken */:
                        // If we see a standalone / or /= and we're expecting a term, then try to reparse
                        // it as a regular expression.
                        var result = tryReparseDivideAsRegularExpression();

                        // If we get a result, then use it. Otherwise, create a missing identifier so
                        // that parsing can continue.  Note: we do this even if 'force' is false.  That's
                        // because we *do* want to consider a standalone / as an expression that should be
                        // returned from tryParseExpression even when 'force' is set to false.
                        return result || eatIdentifierToken(TypeScript.DiagnosticCode.Expression_expected);
                }

                if (!force) {
                    return null;
                }

                // Nothing else worked, report an error and produce a missing token.
                return eatIdentifierToken(TypeScript.DiagnosticCode.Expression_expected);
            }

            function tryReparseDivideAsRegularExpression() {
                // If we see a / or /= token, then that may actually be the start of a regex in certain
                // contexts.
                // var currentToken = this.currentToken();
                // Debug.assert(SyntaxFacts.isAnyDivideToken(currentToken.kind()));
                // Ok, from our quick lexical check, this could be a place where a regular expression could
                // go.  Now we have to do a bunch of work.  Ask the source to retrive the token at the
                // current position again.  But this time allow it to retrieve it as a regular expression.
                var currentToken = currentContextualToken();

                // Note: we *must* have gotten a /, /= or regular expression.  Or else something went *very*
                // wrong with our logic above.
                // Debug.assert(SyntaxFacts.isAnyDivideOrRegularExpressionToken(currentToken.kind()));
                var tokenKind = currentToken.kind();
                if (tokenKind === 118 /* SlashToken */ || tokenKind === 119 /* SlashEqualsToken */) {
                    // Still came back as a / or /=.   This is not a regular expression literal.
                    return null;
                } else if (tokenKind === 12 /* RegularExpressionLiteral */) {
                    return consumeToken(currentToken);
                } else {
                    throw TypeScript.Errors.invalidOperation();
                }
            }

            function parseTypeOfExpression(typeOfKeyword) {
                return new Parser.syntaxFactory.TypeOfExpressionSyntax(parseNodeData, consumeToken(typeOfKeyword), tryParseUnaryExpressionOrHigher(currentToken(), true));
            }

            function parseDeleteExpression(deleteKeyword) {
                return new Parser.syntaxFactory.DeleteExpressionSyntax(parseNodeData, consumeToken(deleteKeyword), tryParseUnaryExpressionOrHigher(currentToken(), true));
            }

            function parseVoidExpression(voidKeyword) {
                return new Parser.syntaxFactory.VoidExpressionSyntax(parseNodeData, consumeToken(voidKeyword), tryParseUnaryExpressionOrHigher(currentToken(), true));
            }

            function parseFunctionExpression(functionKeyword) {
                return new Parser.syntaxFactory.FunctionExpressionSyntax(parseNodeData, consumeToken(functionKeyword), eatOptionalIdentifierToken(), parseCallSignature(false), parseBlock(false, true));
            }

            function parseObjectCreationExpression(newKeyword) {
                // ObjectCreationExpression
                //      new MemberExpression Arguments?
                //
                // Note: if we see arguments we absolutely take them and attach them tightly to this
                // object creation expression.
                //
                // See comment in tryParseMemberExpressionOrHigher for a more complete explanation of
                // this decision.
                return new Parser.syntaxFactory.ObjectCreationExpressionSyntax(parseNodeData, consumeToken(newKeyword), tryParseMemberExpressionOrHigher(currentToken(), true, true), tryParseArgumentList());
            }

            function parseCastExpression(lessThanToken) {
                return new Parser.syntaxFactory.CastExpressionSyntax(parseNodeData, consumeToken(lessThanToken), parseType(), eatToken(81 /* GreaterThanToken */), tryParseUnaryExpressionOrHigher(currentToken(), true));
            }

            function parseParenthesizedExpression(openParenToken) {
                return new Parser.syntaxFactory.ParenthesizedExpressionSyntax(parseNodeData, consumeToken(openParenToken), parseExpression(true), eatToken(73 /* CloseParenToken */));
            }

            function tryParseParenthesizedArrowFunctionExpression() {
                var tokenKind = currentToken().kind();
                if (tokenKind !== 72 /* OpenParenToken */ && tokenKind !== 80 /* LessThanToken */) {
                    return null;
                }

                // Because arrow functions and parenthesized expressions look similar, we have to check far
                // enough ahead to be sure we've actually got an arrow function. For example, both nodes can
                // start with:
                //    (a = b, c = d, ..., e = f).
                //So we effectively need infinite lookahead to decide which node we're in.
                //
                // First, check for things that definitely have enough information to let us know it's an
                // arrow function.
                if (isDefinitelyArrowFunctionExpression()) {
                    // We have something like "() =>" or "(a) =>".  Definitely a lambda, so parse it
                    // unilaterally as such.
                    return tryParseParenthesizedArrowFunctionExpressionWorker(false);
                }

                // Now, look for cases where we're sure it's not an arrow function.  This will help save us
                // a costly parse.
                if (!isPossiblyArrowFunctionExpression()) {
                    return null;
                }

                // Then, try to actually parse it as a arrow function, and only return if we see an =>
                var rewindPoint = getRewindPoint();

                var arrowFunction = tryParseParenthesizedArrowFunctionExpressionWorker(true);
                if (arrowFunction === null) {
                    rewind(rewindPoint);
                }

                releaseRewindPoint(rewindPoint);
                return arrowFunction;
            }

            function tryParseParenthesizedArrowFunctionExpressionWorker(requireArrow) {
                var _currentToken = currentToken();

                // Debug.assert(currentToken.kind() === SyntaxKind.OpenParenToken || currentToken.kind() === SyntaxKind.LessThanToken);
                var callSignature = parseCallSignature(true);

                if (requireArrow && currentToken().kind() !== 85 /* EqualsGreaterThanToken */) {
                    return null;
                }

                var equalsGreaterThanToken = eatToken(85 /* EqualsGreaterThanToken */);

                var block = tryParseArrowFunctionBlock();
                var expression = null;
                if (block === null) {
                    expression = tryParseAssignmentExpressionOrHigher(true, true);
                }

                return new Parser.syntaxFactory.ParenthesizedArrowFunctionExpressionSyntax(parseNodeData, callSignature, equalsGreaterThanToken, block, expression);
            }

            function tryParseArrowFunctionBlock() {
                if (isBlock()) {
                    return parseBlock(false, false);
                } else {
                    // We didn't have a block.  However, we may be in an error situation.  For example,
                    // if the user wrote:
                    //
                    //  a =>
                    //      var v = 0;
                    //  }
                    //
                    // (i.e. they're missing the open brace).  See if that's the case so we can try to
                    // recover better.  If we don't do this, then the next close curly we see may end
                    // up preemptively closing the containing construct.
                    var _modifierCount = modifierCount();
                    if (isStatement(_modifierCount, false) && !isExpressionStatement(currentToken()) && !isFunctionDeclaration(_modifierCount)) {
                        // We've seen a statement (and it isn't an expressionStatement like 'foo()'),
                        // so treat this like a block with a missing open brace.
                        return parseBlock(true, false);
                    } else {
                        return null;
                    }
                }
            }

            function isSimpleArrowFunctionExpression(_currentToken) {
                // ERROR RECOVERY TWEAK:
                // If we see a standalone => try to parse it as an arrow function as that's likely what
                // the user intended to write.
                if (_currentToken.kind() === 85 /* EqualsGreaterThanToken */) {
                    return true;
                }

                return isIdentifier(_currentToken) && peekToken(1).kind() === 85 /* EqualsGreaterThanToken */;
            }

            function parseSimpleArrowFunctionExpression() {
                // Debug.assert(isSimpleArrowFunctionExpression());
                var parameter = eatSimpleParameter();
                var equalsGreaterThanToken = eatToken(85 /* EqualsGreaterThanToken */);

                var block = tryParseArrowFunctionBlock();
                var expression = null;
                if (block === null) {
                    expression = tryParseAssignmentExpressionOrHigher(true, true);
                }

                return new Parser.syntaxFactory.SimpleArrowFunctionExpressionSyntax(parseNodeData, parameter, equalsGreaterThanToken, block, expression);
            }

            function isBlock() {
                return currentToken().kind() === 70 /* OpenBraceToken */;
            }

            function isDefinitelyArrowFunctionExpression() {
                var token0 = currentToken();
                if (token0.kind() !== 72 /* OpenParenToken */) {
                    // If it didn't start with an (, then it could be generic.  That's too complicated
                    // and we can't say it's 'definitely' an arrow function.
                    return false;
                }

                var token1 = peekToken(1);
                var token1Kind = token1.kind();

                var token2;

                if (token1Kind === 73 /* CloseParenToken */) {
                    // ()
                    // Definitely an arrow function.  Could never be a parenthesized expression.
                    // *However*, because of error situations, we could end up with things like "().foo".
                    // In this case, we don't want to think of this as the start of an arrow function.
                    // To prevent this, we are a little stricter, and we require that we at least see:
                    //      "():"  or  "() =>"  or "() {}".  Note: the last one is illegal.  However it
                    // most likely is a missing => and not a parenthesized expression.
                    token2 = peekToken(2);
                    var token2Kind = token2.kind();
                    return token2Kind === 106 /* ColonToken */ || token2Kind === 85 /* EqualsGreaterThanToken */ || token2Kind === 70 /* OpenBraceToken */;
                }

                if (token1Kind === 77 /* DotDotDotToken */) {
                    // (...
                    // Definitely an arrow function.  Could never be a parenthesized expression.
                    return true;
                }

                token2 = peekToken(2);
                token2Kind = token2.kind();

                if (token1Kind === 57 /* PublicKeyword */ || token1Kind === 55 /* PrivateKeyword */) {
                    if (isIdentifier(token2)) {
                        // "(public id" or "(function id".  Definitely an arrow function.  Could never
                        // be a parenthesized expression.  Note: this will be an *illegal* arrow
                        // function (as accessibility modifiers are not allowed in it).  However, that
                        // will be reported by the grammar checker walker.
                        return true;
                    }
                }

                if (!isIdentifier(token1)) {
                    // All other arrow functions must start with (id
                    // so this is definitely not an arrow function.
                    return false;
                }

                // (id
                //
                // Lots of options here.  Check for things that make us certain it's an
                // arrow function.
                if (token2Kind === 106 /* ColonToken */) {
                    // (id:
                    // Definitely an arrow function.  Could never be a parenthesized expression.
                    return true;
                }

                var token3 = peekToken(3);
                var token3Kind = token3.kind();
                if (token2Kind === 105 /* QuestionToken */) {
                    // (id?
                    // Could be an arrow function, or a parenthesized conditional expression.
                    // Check for the things that could only be arrow functions.
                    if (token3Kind === 106 /* ColonToken */ || token3Kind === 73 /* CloseParenToken */ || token3Kind === 79 /* CommaToken */) {
                        // (id?:
                        // (id?)
                        // (id?,
                        // These are the only cases where this could be an arrow function.
                        // And none of them can be parenthesized expression.
                        return true;
                    }
                }

                if (token2Kind === 73 /* CloseParenToken */) {
                    // (id)
                    // Could be an arrow function, or a parenthesized conditional expression.
                    if (token3Kind === 85 /* EqualsGreaterThanToken */) {
                        // (id) =>
                        // Definitely an arrow function.  Could not be a parenthesized expression.
                        return true;
                    }
                    // Note: "(id):" *looks* like it could be an arrow function.  However, it could
                    // show up in:  "foo ? (id):
                    // So we can't return true here for that case.
                }

                // TODO: Add more cases if you're sure that there is enough information to know to
                // parse this as an arrow function.  Note: be very careful here.
                // Anything else wasn't clear enough.  Try to parse the expression as an arrow function and bail out
                // if we fail.
                return false;
            }

            function isPossiblyArrowFunctionExpression() {
                var token0 = currentToken();
                if (token0.kind() !== 72 /* OpenParenToken */) {
                    // If it didn't start with an (, then it could be generic.  That's too complicated
                    // and we have to say it's possibly an arrow function.
                    return true;
                }

                var token1 = peekToken(1);

                if (!isIdentifier(token1)) {
                    // All other arrow functions must start with (id
                    // so this is definitely not an arrow function.
                    return false;
                }

                var token2 = peekToken(2);
                var token2Kind = token2.kind();
                if (token2Kind === 107 /* EqualsToken */) {
                    // (id =
                    //
                    // This *could* be an arrow function.  i.e. (id = 0) => { }
                    // Or it could be a parenthesized expression.  So we'll have to actually
                    // try to parse it.
                    return true;
                }

                if (token2Kind === 79 /* CommaToken */) {
                    // (id,
                    // This *could* be an arrow function.  i.e. (id, id2) => { }
                    // Or it could be a parenthesized expression (as javascript supports
                    // the comma operator).  So we'll have to actually try to parse it.
                    return true;
                }

                if (token2Kind === 73 /* CloseParenToken */) {
                    // (id)
                    var token3 = peekToken(3);
                    if (token3.kind() === 106 /* ColonToken */) {
                        // (id):
                        //
                        // This could be an arrow function. i.e. (id): number => { }
                        // Or it could be parenthesized exprssion: foo ? (id) :
                        // So we'll have to actually try to parse it.
                        return true;
                    }
                }

                // Nothing else could be an arrow function.
                return false;
            }

            function parseObjectLiteralExpression(openBraceToken) {
                // Debug.assert(currentToken().kind() === SyntaxKind.OpenBraceToken);
                consumeToken(openBraceToken);

                // Debug.assert(openBraceToken.fullWidth() > 0);
                var skippedTokens = getArray();
                var propertyAssignments = parseSeparatedSyntaxList(15 /* ObjectLiteralExpression_PropertyAssignments */, skippedTokens);
                openBraceToken = addSkippedTokensAfterToken(openBraceToken, skippedTokens);

                return new Parser.syntaxFactory.ObjectLiteralExpressionSyntax(parseNodeData, openBraceToken, propertyAssignments, eatToken(71 /* CloseBraceToken */));
            }

            function tryParsePropertyAssignment(inErrorRecovery) {
                // Debug.assert(isPropertyAssignment(/*inErrorRecovery:*/ false));
                if (isAccessor(modifierCount(), inErrorRecovery)) {
                    return parseAccessor(true);
                } else if (isFunctionPropertyAssignment(inErrorRecovery)) {
                    return parseFunctionPropertyAssignment();
                } else if (isSimplePropertyAssignment(inErrorRecovery)) {
                    return parseSimplePropertyAssignment();
                } else {
                    return null;
                }
            }

            function isPropertyAssignment(inErrorRecovery) {
                return isAccessor(modifierCount(), inErrorRecovery) || isFunctionPropertyAssignment(inErrorRecovery) || isSimplePropertyAssignment(inErrorRecovery);
            }

            function eatPropertyName() {
                var _currentToken = currentToken();
                return TypeScript.SyntaxFacts.isIdentifierNameOrAnyKeyword(_currentToken) ? eatIdentifierNameToken() : consumeToken(_currentToken);
            }

            function isFunctionPropertyAssignment(inErrorRecovery) {
                return isPropertyName(currentToken(), inErrorRecovery) && isCallSignature(1);
            }

            function parseFunctionPropertyAssignment() {
                return new Parser.syntaxFactory.FunctionPropertyAssignmentSyntax(parseNodeData, eatPropertyName(), parseCallSignature(false), parseBlock(false, true));
            }

            function isSimplePropertyAssignment(inErrorRecovery) {
                return isPropertyName(currentToken(), inErrorRecovery);
            }

            function parseSimplePropertyAssignment() {
                return new Parser.syntaxFactory.SimplePropertyAssignmentSyntax(parseNodeData, eatPropertyName(), eatToken(106 /* ColonToken */), tryParseAssignmentExpressionOrHigher(true, true));
            }

            function isPropertyName(token, inErrorRecovery) {
                // NOTE: we do *not* want to check "isIdentifier" here.  Any IdentifierName is
                // allowed here, even reserved words like keywords.
                if (TypeScript.SyntaxFacts.isIdentifierNameOrAnyKeyword(token)) {
                    // Except: if we're in error recovery, then we don't want to consider keywords.
                    // After all, if we have:
                    //
                    //      { a: 1
                    //      return
                    //
                    // we don't want consider 'return' to be the next property in the object literal.
                    if (inErrorRecovery) {
                        return isIdentifier(token);
                    } else {
                        return true;
                    }
                }

                var kind = token.kind();
                return kind === 14 /* StringLiteral */ || kind === 13 /* NumericLiteral */;
            }

            function parseArrayLiteralExpression(openBracketToken) {
                // Debug.assert(currentToken().kind() === SyntaxKind.OpenBracketToken);
                consumeToken(openBracketToken);

                // Debug.assert(openBracketToken.fullWidth() > 0);
                var skippedTokens = getArray();
                var expressions = parseSeparatedSyntaxList(16 /* ArrayLiteralExpression_AssignmentExpressions */, skippedTokens);
                openBracketToken = addSkippedTokensAfterToken(openBracketToken, skippedTokens);

                return new Parser.syntaxFactory.ArrayLiteralExpressionSyntax(parseNodeData, openBracketToken, expressions, eatToken(75 /* CloseBracketToken */));
            }

            function parseBlock(parseBlockEvenWithNoOpenBrace, checkForStrictMode) {
                var openBraceToken = eatToken(70 /* OpenBraceToken */);
                var statements = TypeScript.Syntax.emptyList();

                if (parseBlockEvenWithNoOpenBrace || openBraceToken.fullWidth() > 0) {
                    var savedIsInStrictMode = isInStrictMode;

                    var processItems = checkForStrictMode ? updateStrictModeState : null;
                    var skippedTokens = getArray();
                    var statements = parseSyntaxList(5 /* Block_Statements */, skippedTokens, processItems);
                    openBraceToken = addSkippedTokensAfterToken(openBraceToken, skippedTokens);

                    setStrictMode(savedIsInStrictMode);
                }

                return new Parser.syntaxFactory.BlockSyntax(parseNodeData, openBraceToken, statements, eatToken(71 /* CloseBraceToken */));
            }

            function parseCallSignature(requireCompleteTypeParameterList) {
                return new Parser.syntaxFactory.CallSignatureSyntax(parseNodeData, tryParseTypeParameterList(requireCompleteTypeParameterList), parseParameterList(), parseOptionalTypeAnnotation(false));
            }

            function tryParseTypeParameterList(requireCompleteTypeParameterList) {
                var _currentToken = currentToken();
                if (_currentToken.kind() !== 80 /* LessThanToken */) {
                    return null;
                }

                var rewindPoint = getRewindPoint();

                var lessThanToken = consumeToken(_currentToken);

                var skippedTokens = getArray();
                var typeParameters = parseSeparatedSyntaxList(20 /* TypeParameterList_TypeParameters */, skippedTokens);
                lessThanToken = addSkippedTokensAfterToken(lessThanToken, skippedTokens);

                var greaterThanToken = eatToken(81 /* GreaterThanToken */);

                // return null if we were required to have a '>' token and we did not  have one.
                if (requireCompleteTypeParameterList && greaterThanToken.fullWidth() === 0) {
                    rewind(rewindPoint);
                    releaseRewindPoint(rewindPoint);
                    return null;
                } else {
                    releaseRewindPoint(rewindPoint);
                    return new Parser.syntaxFactory.TypeParameterListSyntax(parseNodeData, lessThanToken, typeParameters, greaterThanToken);
                }
            }

            function isTypeParameter() {
                return isIdentifier(currentToken());
            }

            function tryParseTypeParameter() {
                // Debug.assert(isTypeParameter());
                if (!isIdentifier(currentToken())) {
                    return null;
                }

                return new Parser.syntaxFactory.TypeParameterSyntax(parseNodeData, eatIdentifierToken(), tryParseConstraint());
            }

            function tryParseConstraint() {
                if (currentToken().kind() !== 48 /* ExtendsKeyword */) {
                    return null;
                }

                return new Parser.syntaxFactory.ConstraintSyntax(parseNodeData, eatToken(48 /* ExtendsKeyword */), parseType());
            }

            function parseParameterList() {
                var openParenToken = eatToken(72 /* OpenParenToken */);
                var parameters = TypeScript.Syntax.emptySeparatedList();

                if (openParenToken.fullWidth() > 0) {
                    var skippedTokens = getArray();
                    parameters = parseSeparatedSyntaxList(17 /* ParameterList_Parameters */, skippedTokens);
                    openParenToken = addSkippedTokensAfterToken(openParenToken, skippedTokens);
                }

                return new Parser.syntaxFactory.ParameterListSyntax(parseNodeData, openParenToken, parameters, eatToken(73 /* CloseParenToken */));
            }

            function parseOptionalTypeAnnotation(allowStringLiteral) {
                return currentToken().kind() === 106 /* ColonToken */ ? parseTypeAnnotation(allowStringLiteral) : null;
            }

            function parseTypeAnnotationType(allowStringLiteral) {
                if (allowStringLiteral) {
                    var _currentToken = currentToken();
                    if (_currentToken.kind() === 14 /* StringLiteral */) {
                        return consumeToken(_currentToken);
                    }
                }

                return parseType();
            }

            function parseTypeAnnotation(allowStringLiteral) {
                return new Parser.syntaxFactory.TypeAnnotationSyntax(parseNodeData, consumeToken(currentToken()), parseTypeAnnotationType(allowStringLiteral));
            }

            function isType() {
                var _currentToken = currentToken();

                switch (_currentToken.kind()) {
                    case 39 /* TypeOfKeyword */:
                    case 60 /* AnyKeyword */:
                    case 67 /* NumberKeyword */:
                    case 61 /* BooleanKeyword */:
                    case 69 /* StringKeyword */:
                    case 41 /* VoidKeyword */:
                    case 70 /* OpenBraceToken */:
                    case 72 /* OpenParenToken */:
                    case 80 /* LessThanToken */:
                    case 31 /* NewKeyword */:
                        return true;
                    default:
                        return isIdentifier(_currentToken);
                }
            }

            function parseType() {
                return tryParseType() || eatIdentifierToken(TypeScript.DiagnosticCode.Type_expected);
            }

            function tryParseType() {
                // First consume any underlying element type.
                var type = tryParseNonArrayType();

                while (type) {
                    var _currentToken = currentToken();

                    if (previousTokenHasTrailingNewLine(_currentToken) || _currentToken.kind() !== 74 /* OpenBracketToken */) {
                        break;
                    }

                    type = new Parser.syntaxFactory.ArrayTypeSyntax(parseNodeData, type, consumeToken(_currentToken), eatToken(75 /* CloseBracketToken */));
                }

                return type;
            }

            function parseTypeQuery(typeOfKeyword) {
                return new Parser.syntaxFactory.TypeQuerySyntax(parseNodeData, consumeToken(typeOfKeyword), parseName(true));
            }

            function tryParseNonArrayType() {
                var _currentToken = currentToken();
                switch (_currentToken.kind()) {
                    case 60 /* AnyKeyword */:
                    case 67 /* NumberKeyword */:
                    case 61 /* BooleanKeyword */:
                    case 69 /* StringKeyword */:
                        // if any of these are followed by '.', then this is actually a module name,
                        // and these keywords will be reinterpreted as an identifier.
                        if (peekToken(1).kind() === 76 /* DotToken */) {
                            break;
                        }

                        return consumeToken(_currentToken);
                    case 72 /* OpenParenToken */:
                    case 80 /* LessThanToken */: return parseFunctionType();
                    case 41 /* VoidKeyword */: return consumeToken(_currentToken);
                    case 70 /* OpenBraceToken */: return parseObjectType();
                    case 31 /* NewKeyword */: return parseConstructorType();
                    case 39 /* TypeOfKeyword */: return parseTypeQuery(_currentToken);
                }

                return tryParseNameOrGenericType();
            }

            function tryParseNameOrGenericType() {
                var name = tryParseName(false);
                if (name === null) {
                    return null;
                }

                // TypeReference:
                //      TypeName   [no LineTerminator here]   TypeArgumentsopt
                //
                // Only consume type arguments if they appear on the same line.
                if (previousTokenHasTrailingNewLine(currentToken())) {
                    return name;
                }

                var typeArgumentList = tryParseTypeArgumentList(false);
                return typeArgumentList === null ? name : new Parser.syntaxFactory.GenericTypeSyntax(parseNodeData, name, typeArgumentList);
            }

            function parseFunctionType() {
                return new Parser.syntaxFactory.FunctionTypeSyntax(parseNodeData, tryParseTypeParameterList(false), parseParameterList(), eatToken(85 /* EqualsGreaterThanToken */), parseType());
            }

            function parseConstructorType() {
                return new Parser.syntaxFactory.ConstructorTypeSyntax(parseNodeData, eatToken(31 /* NewKeyword */), tryParseTypeParameterList(false), parseParameterList(), eatToken(85 /* EqualsGreaterThanToken */), parseType());
            }

            function isParameter() {
                if (currentNode() !== null && currentNode().kind() === 242 /* Parameter */) {
                    return true;
                }

                var token = currentToken();
                var tokenKind = token.kind();
                if (tokenKind === 77 /* DotDotDotToken */) {
                    return true;
                }

                if (isModifier(token) && !isModifierUsedAsParameterIdentifier(token)) {
                    return true;
                }

                return isIdentifier(token);
            }

            // Modifiers are perfectly legal names for parameters.  i.e.  you can have: foo(public: number) { }
            // Most of the time we want to treat the modifier as a modifier.  However, if we're certain
            // it's a parameter identifier, then don't consider it as a modifier.
            function isModifierUsedAsParameterIdentifier(token) {
                if (isIdentifier(token)) {
                    // Check for:
                    // foo(public)
                    // foo(public: ...
                    // foo(public= ...
                    // foo(public, ...
                    // foo(public? ...
                    //
                    // In all these cases, it's not actually a modifier, but is instead the identifier.
                    // In any other case treat it as the modifier.
                    var nextTokenKind = peekToken(1).kind();
                    switch (nextTokenKind) {
                        case 73 /* CloseParenToken */:
                        case 106 /* ColonToken */:
                        case 107 /* EqualsToken */:
                        case 79 /* CommaToken */:
                        case 105 /* QuestionToken */:
                            return true;
                    }
                }

                return false;
            }

            function eatSimpleParameter() {
                return new Parser.syntaxFactory.ParameterSyntax(parseNodeData, null, TypeScript.Syntax.emptyList(), eatIdentifierToken(), null, null, null);
            }

            function tryParseParameter() {
                var node = currentNode();
                if (node !== null && node.kind() === 242 /* Parameter */) {
                    consumeNode(node);
                    return node;
                }

                var dotDotDotToken = tryEatToken(77 /* DotDotDotToken */);

                var modifierArray = getArray();

                while (true) {
                    var _currentToken = currentToken();
                    if (isModifier(_currentToken) && !isModifierUsedAsParameterIdentifier(_currentToken)) {
                        modifierArray.push(consumeToken(_currentToken));
                        continue;
                    }

                    break;
                }

                var modifiers = TypeScript.Syntax.list(modifierArray);
                returnZeroLengthArray(modifierArray);

                // If we're not forcing, and we don't see anything to indicate this is a parameter, then
                // bail out.
                if (!isIdentifier(currentToken()) && dotDotDotToken === null && modifiers.length === 0) {
                    return null;
                }

                var identifier = eatIdentifierToken();
                var questionToken = tryEatToken(105 /* QuestionToken */);
                var typeAnnotation = parseOptionalTypeAnnotation(true);

                var equalsValueClause = null;
                if (isEqualsValueClause(true)) {
                    equalsValueClause = parseEqualsValueClause(true);
                }

                return new Parser.syntaxFactory.ParameterSyntax(parseNodeData, dotDotDotToken, modifiers, identifier, questionToken, typeAnnotation, equalsValueClause);
            }

            function parseSyntaxList(currentListType, skippedTokens, processItems) {
                if (typeof processItems === "undefined") { processItems = null; }
                var savedListParsingState = listParsingState;
                listParsingState |= (1 << currentListType);

                var result = parseSyntaxListWorker(currentListType, skippedTokens, processItems);

                listParsingState = savedListParsingState;

                return result;
            }

            function parseSeparatedSyntaxList(currentListType, skippedTokens) {
                var savedListParsingState = listParsingState;
                listParsingState |= (1 << currentListType);

                var result = parseSeparatedSyntaxListWorker(currentListType, skippedTokens);

                listParsingState = savedListParsingState;

                return result;
            }

            // Returns true if we should abort parsing.
            function abortParsingListOrMoveToNextToken(currentListType, nodes, separators, skippedTokens) {
                // Ok.  We're at a token that is not a terminator for the list and wasn't the start of
                // an item in the list. Definitely report an error for this token.
                reportUnexpectedTokenDiagnostic(currentListType);

                for (var state = ListParsingState.LastListParsingState; state >= ListParsingState.FirstListParsingState; state--) {
                    if ((listParsingState & (1 << state)) !== 0) {
                        if (isExpectedListTerminator(state) || isExpectedListItem(state, true)) {
                            // Abort parsing this list.
                            return true;
                        }
                    }
                }

                // Otherwise, if none of the lists we're in can capture this token, then we need to
                // unilaterally skip it.  Note: we've already reported an error above.
                addSkippedTokenToList(nodes, separators, skippedTokens, consumeToken(currentToken()));

                // Continue parsing this list.  Attach this token to whatever we've seen already.
                return false;
            }

            function addSkippedTokenToList(nodes, separators, skippedTokens, skippedToken) {
                // Now, add this skipped token to the last item we successfully parsed in the list.  Or
                // add it to the list of skipped tokens if we haven't parsed anything.  Our caller will
                // have to deal with them.
                //
                // Note: we only bother doing this if we're creating a concrete syntax tree.
                if (Parser.syntaxFactory.isConcrete) {
                    var length = nodes.length + (separators ? separators.length : 0);

                    for (var i = length - 1; i >= 0; i--) {
                        var array = separators && (i % 2 === 1) ? separators : nodes;
                        var arrayIndex = separators ? TypeScript.IntegerUtilities.integerDivide(i, 2) : i;

                        var item = array[arrayIndex];
                        var _lastToken = TypeScript.lastToken(item);
                        if (_lastToken && _lastToken.fullWidth() > 0) {
                            array[arrayIndex] = addSkippedTokenAfterNodeOrToken(item, skippedToken);
                            return;
                        }
                    }

                    // Didn't have anything in the list we could add to.  Add to the skipped items array
                    // for our caller to handle.
                    skippedTokens.push(skippedToken);
                }
            }

            function tryParseExpectedListItem(currentListType, inErrorRecovery, items, processItems) {
                var item = tryParseExpectedListItemWorker(currentListType, inErrorRecovery);

                if (item === null) {
                    return false;
                }

                // Debug.assert(item !== null);
                items.push(item);

                if (processItems !== null) {
                    processItems(items);
                }

                return true;
            }

            function listIsTerminated(currentListType) {
                return isExpectedListTerminator(currentListType) || currentToken().kind() === 10 /* EndOfFileToken */;
            }

            function parseSyntaxListWorker(currentListType, skippedTokens, processItems) {
                var items = getArray();

                while (true) {
                    // Try to parse an item of the list.  If we fail then decide if we need to abort or
                    // continue parsing.
                    var succeeded = tryParseExpectedListItem(currentListType, false, items, processItems);

                    if (!succeeded) {
                        // We weren't able to parse out a list element.
                        // That may have been because the list is complete.  In that case, break out
                        // and return the items we were able parse.
                        if (listIsTerminated(currentListType)) {
                            break;
                        }

                        // List wasn't complete and we didn't get an item.  Figure out if we should bail out
                        // or skip a token and continue.
                        var abort = abortParsingListOrMoveToNextToken(currentListType, items, null, skippedTokens);
                        if (abort) {
                            break;
                        }
                    }
                    // We either parsed an element.  Or we failed to, but weren't at the end of the list
                    // and didn't want to abort. Continue parsing elements.
                }

                var result = TypeScript.Syntax.list(items);

                // Can't return if it has more then 1 element.  In that case, the list will have been
                // copied into the SyntaxList.
                returnZeroLengthArray(items);

                return result;
            }

            function parseSeparatedSyntaxListWorker(currentListType, skippedTokens) {
                var nodes = getArray();
                var separators = getArray();

                // Debug.assert(nodes.length === 0);
                // Debug.assert(separators.length === 0);
                // Debug.assert(skippedTokens.length === 0);
                // Debug.assert(<any>skippedTokens !== nodes);
                // Debug.assert(skippedTokens !== separators);
                // Debug.assert(<any>nodes !== separators);
                var _separatorKind = currentListType === 9 /* ObjectType_TypeMembers */ ? 78 /* SemicolonToken */ : 79 /* CommaToken */;
                var allowAutomaticSemicolonInsertion = _separatorKind === 78 /* SemicolonToken */;

                var inErrorRecovery = false;
                while (true) {
                    // Try to parse an item of the list.  If we fail then decide if we need to abort or
                    // continue parsing.
                    // Debug.assert(oldItemsCount % 2 === 0);
                    var succeeded = tryParseExpectedListItem(currentListType, inErrorRecovery, nodes, null);

                    if (!succeeded) {
                        // We weren't able to parse out a list element.
                        // Debug.assert(items === null || items.length % 2 === 0);
                        // That may have been because the list is complete.  In that case, break out
                        // and return the items we were able parse.
                        if (listIsTerminated(currentListType)) {
                            break;
                        }

                        // List wasn't complete and we didn't get an item.  Figure out if we should bail out
                        // or skip a token and continue.
                        var abort = abortParsingListOrMoveToNextToken(currentListType, nodes, separators, skippedTokens);
                        if (abort) {
                            break;
                        } else {
                            // We just skipped a token.  We're now in error recovery mode.
                            inErrorRecovery = true;
                            continue;
                        }
                    }

                    // Debug.assert(newItemsCount % 2 === 1);
                    // We were able to successfully parse out a list item.  So we're no longer in error
                    // recovery.
                    inErrorRecovery = false;

                    // Now, we have to see if we have a separator or not.  If we do have a separator
                    // we've got to consume it and continue trying to parse list items.  Note: we always
                    // allow 'comma' as a separator (for error tolerance).  We will later do a post pass
                    // to report when a comma was used improperly in a list that needed semicolons.
                    var _currentToken = currentToken();
                    var tokenKind = _currentToken.kind();
                    if (tokenKind === _separatorKind || tokenKind === 79 /* CommaToken */) {
                        // Consume the last separator and continue parsing list elements.
                        separators.push(consumeToken(_currentToken));
                        continue;
                    }

                    // We didn't see the expected separator.  There are two reasons this might happen.
                    // First, we may actually be at the end of the list.  If we are, then we're done
                    // parsing list elements.
                    if (listIsTerminated(currentListType)) {
                        break;
                    }

                    // Otherwise, it might be a case where we can parse out an implicit semicolon.
                    // Note: it's important that we check this *after* the check above for
                    // 'listIsTerminated'.  Consider the following case:
                    //
                    //      {
                    //          a       // <-- just finished parsing 'a'
                    //      }
                    //
                    // Automatic semicolon insertion rules state: "When, as the program is parsed from
                    // left to right, a token (called the offending token) is encountered that is not
                    // allowed by any production of the grammar".  So we should only ever insert a
                    // semicolon if we couldn't consume something normally.  in the above case, we can
                    // consume the '}' just fine.  So ASI doesn't apply.
                    if (allowAutomaticSemicolonInsertion && canEatAutomaticSemicolon(false)) {
                        var semicolonToken = eatExplicitOrAutomaticSemicolon(false) || TypeScript.Syntax.emptyToken(78 /* SemicolonToken */);
                        separators.push(semicolonToken);

                        continue;
                    }

                    // We weren't at the end of the list.  And thre was no separator we could parse out.
                    // Try parse the separator we expected, and continue parsing more list elements.
                    // This time mark that we're in error recovery mode though.
                    //
                    // Note: trying to eat this token will emit the appropriate diagnostic.
                    separators.push(eatToken(_separatorKind));

                    // Now that we're in 'error recovery' mode we cantweak some parsing rules as
                    // appropriate.  For example, if we have:
                    //
                    //      var v = { a
                    //      return
                    //
                    // Then we'll be missing the comma.  As such, we want to parse 'return' in a less
                    // tolerant manner.  Normally 'return' could be a property in an object literal.
                    // However, in error recovery mode, we do *not* want it to be.
                    //
                    // Continue trying to parse out list elements.
                    inErrorRecovery = true;
                }

                var result = TypeScript.Syntax.separatedList(nodes, separators);

                // Can't return if it has more then 0 elements.  In that case, the list will have been
                // copied into the SyntaxList.
                returnZeroLengthArray(nodes);
                returnZeroLengthArray(separators);

                return result;
            }

            function reportUnexpectedTokenDiagnostic(listType) {
                var token = currentToken();

                var diagnostic = new TypeScript.Diagnostic(fileName, source.text.lineMap(), TypeScript.start(token, source.text), TypeScript.width(token), TypeScript.DiagnosticCode.Unexpected_token_0_expected, [getExpectedListElementType(listType)]);
                addDiagnostic(diagnostic);
            }

            function addDiagnostic(diagnostic) {
                // Except: if we already have a diagnostic for this position, don't report another one.
                if (diagnostics.length > 0 && diagnostics[diagnostics.length - 1].start() === diagnostic.start()) {
                    return;
                }

                diagnostics.push(diagnostic);
            }

            function isExpectedListTerminator(currentListType) {
                switch (currentListType) {
                    case 0 /* SourceUnit_ModuleElements */: return isExpectedSourceUnit_ModuleElementsTerminator();
                    case 1 /* ClassDeclaration_ClassElements */: return isExpectedClassDeclaration_ClassElementsTerminator();
                    case 2 /* ModuleDeclaration_ModuleElements */: return isExpectedModuleDeclaration_ModuleElementsTerminator();
                    case 3 /* SwitchStatement_SwitchClauses */: return isExpectedSwitchStatement_SwitchClausesTerminator();
                    case 4 /* SwitchClause_Statements */: return isExpectedSwitchClause_StatementsTerminator();
                    case 5 /* Block_Statements */: return isExpectedBlock_StatementsTerminator();
                    case 6 /* TryBlock_Statements */: return isExpectedTryBlock_StatementsTerminator();
                    case 7 /* CatchBlock_Statements */: return isExpectedCatchBlock_StatementsTerminator();
                    case 8 /* EnumDeclaration_EnumElements */: return isExpectedEnumDeclaration_EnumElementsTerminator();
                    case 9 /* ObjectType_TypeMembers */: return isExpectedObjectType_TypeMembersTerminator();
                    case 10 /* ClassOrInterfaceDeclaration_HeritageClauses */: return isExpectedClassOrInterfaceDeclaration_HeritageClausesTerminator();
                    case 11 /* HeritageClause_TypeNameList */: return isExpectedHeritageClause_TypeNameListTerminator();
                    case 12 /* VariableDeclaration_VariableDeclarators_AllowIn */: return isExpectedVariableDeclaration_VariableDeclarators_AllowInTerminator();
                    case 13 /* VariableDeclaration_VariableDeclarators_DisallowIn */: return isExpectedVariableDeclaration_VariableDeclarators_DisallowInTerminator();
                    case 14 /* ArgumentList_AssignmentExpressions */: return isExpectedArgumentList_AssignmentExpressionsTerminator();
                    case 15 /* ObjectLiteralExpression_PropertyAssignments */: return isExpectedObjectLiteralExpression_PropertyAssignmentsTerminator();
                    case 16 /* ArrayLiteralExpression_AssignmentExpressions */: return isExpectedLiteralExpression_AssignmentExpressionsTerminator();
                    case 17 /* ParameterList_Parameters */: return isExpectedParameterList_ParametersTerminator();
                    case 18 /* IndexSignature_Parameters */: return isExpectedIndexSignature_ParametersTerminator();
                    case 19 /* TypeArgumentList_Types */: return isExpectedTypeArgumentList_TypesTerminator();
                    case 20 /* TypeParameterList_TypeParameters */: return isExpectedTypeParameterList_TypeParametersTerminator();
                    default:
                        throw TypeScript.Errors.invalidOperation();
                }
            }

            function isExpectedSourceUnit_ModuleElementsTerminator() {
                return currentToken().kind() === 10 /* EndOfFileToken */;
            }

            function isExpectedEnumDeclaration_EnumElementsTerminator() {
                return currentToken().kind() === 71 /* CloseBraceToken */;
            }

            function isExpectedModuleDeclaration_ModuleElementsTerminator() {
                return currentToken().kind() === 71 /* CloseBraceToken */;
            }

            function isExpectedObjectType_TypeMembersTerminator() {
                return currentToken().kind() === 71 /* CloseBraceToken */;
            }

            function isExpectedObjectLiteralExpression_PropertyAssignmentsTerminator() {
                return currentToken().kind() === 71 /* CloseBraceToken */;
            }

            function isExpectedLiteralExpression_AssignmentExpressionsTerminator() {
                return currentToken().kind() === 75 /* CloseBracketToken */;
            }

            function isExpectedTypeArgumentList_TypesTerminator() {
                var token = currentToken();
                var tokenKind = token.kind();
                if (tokenKind === 81 /* GreaterThanToken */) {
                    return true;
                }

                // If we're at a token that can follow the type argument list, then we'll also consider
                // the list terminated.
                if (canFollowTypeArgumentListInExpression(tokenKind)) {
                    return true;
                }

                // TODO: add more cases as necessary for error tolerance.
                return false;
            }

            function isExpectedTypeParameterList_TypeParametersTerminator() {
                var tokenKind = currentToken().kind();
                if (tokenKind === 81 /* GreaterThanToken */) {
                    return true;
                }

                // These commonly follow type parameter lists.
                if (tokenKind === 72 /* OpenParenToken */ || tokenKind === 70 /* OpenBraceToken */ || tokenKind === 48 /* ExtendsKeyword */ || tokenKind === 51 /* ImplementsKeyword */) {
                    return true;
                }

                // TODO: add more cases as necessary for error tolerance.
                return false;
            }

            function isExpectedParameterList_ParametersTerminator() {
                var tokenKind = currentToken().kind();
                if (tokenKind === 73 /* CloseParenToken */) {
                    return true;
                }

                // We may also see a { in an error case.  i.e.:
                // function (a, b, c  {
                if (tokenKind === 70 /* OpenBraceToken */) {
                    return true;
                }

                // We may also see a => in an error case.  i.e.:
                // (f: number => { ... }
                if (tokenKind === 85 /* EqualsGreaterThanToken */) {
                    return true;
                }

                return false;
            }

            function isExpectedIndexSignature_ParametersTerminator() {
                var tokenKind = currentToken().kind();
                if (tokenKind === 75 /* CloseBracketToken */) {
                    return true;
                }

                // We may also see a { in an error case.  i.e.:
                // function (a, b, c  {
                if (tokenKind === 70 /* OpenBraceToken */) {
                    return true;
                }

                return false;
            }

            function isExpectedVariableDeclaration_VariableDeclarators_DisallowInTerminator() {
                // This is the case when we're parsing variable declarations in a for/for-in statement.
                var tokenKind = currentToken().kind();

                if (tokenKind === 78 /* SemicolonToken */ || tokenKind === 73 /* CloseParenToken */) {
                    return true;
                }

                if (tokenKind === 29 /* InKeyword */) {
                    return true;
                }

                return false;
            }

            function isExpectedVariableDeclaration_VariableDeclarators_AllowInTerminator() {
                //// This is the case when we're parsing variable declarations in a variable statement.
                // ERROR RECOVERY TWEAK:
                // For better error recovery, if we see a => then we just stop immediately.  We've got an
                // arrow function here and it's going to be very unlikely that we'll resynchronize and get
                // another variable declaration.
                if (currentToken().kind() === 85 /* EqualsGreaterThanToken */) {
                    return true;
                }

                // We're done when we can eat a semicolon.
                return canEatExplicitOrAutomaticSemicolon(false);
            }

            function isExpectedClassOrInterfaceDeclaration_HeritageClausesTerminator() {
                var tokenKind = currentToken().kind();
                if (tokenKind === 70 /* OpenBraceToken */ || tokenKind === 71 /* CloseBraceToken */) {
                    return true;
                }

                return false;
            }

            function isExpectedHeritageClause_TypeNameListTerminator() {
                var tokenKind = currentToken().kind();
                if (tokenKind === 48 /* ExtendsKeyword */ || tokenKind === 51 /* ImplementsKeyword */) {
                    return true;
                }

                if (isExpectedClassOrInterfaceDeclaration_HeritageClausesTerminator()) {
                    return true;
                }

                return false;
            }

            function isExpectedArgumentList_AssignmentExpressionsTerminator() {
                var token0 = currentToken();
                var tokenKind = token0.kind();
                return tokenKind === 73 /* CloseParenToken */ || tokenKind === 78 /* SemicolonToken */;
            }

            function isExpectedClassDeclaration_ClassElementsTerminator() {
                return currentToken().kind() === 71 /* CloseBraceToken */;
            }

            function isExpectedSwitchStatement_SwitchClausesTerminator() {
                return currentToken().kind() === 71 /* CloseBraceToken */;
            }

            function isExpectedSwitchClause_StatementsTerminator() {
                return currentToken().kind() === 71 /* CloseBraceToken */ || isSwitchClause();
            }

            function isExpectedBlock_StatementsTerminator() {
                return currentToken().kind() === 71 /* CloseBraceToken */;
            }

            function isExpectedTryBlock_StatementsTerminator() {
                var tokenKind = currentToken().kind();
                return tokenKind === 17 /* CatchKeyword */ || tokenKind === 25 /* FinallyKeyword */;
            }

            function isExpectedCatchBlock_StatementsTerminator() {
                return currentToken().kind() === 25 /* FinallyKeyword */;
            }

            function isExpectedListItem(currentListType, inErrorRecovery) {
                switch (currentListType) {
                    case 0 /* SourceUnit_ModuleElements */: return isModuleElement(inErrorRecovery);
                    case 1 /* ClassDeclaration_ClassElements */: return isClassElement(inErrorRecovery);
                    case 2 /* ModuleDeclaration_ModuleElements */: return isModuleElement(inErrorRecovery);
                    case 3 /* SwitchStatement_SwitchClauses */: return isSwitchClause();
                    case 4 /* SwitchClause_Statements */: return isStatement(modifierCount(), inErrorRecovery);
                    case 5 /* Block_Statements */: return isStatement(modifierCount(), inErrorRecovery);

                    case 6 /* TryBlock_Statements */: return false;
                    case 7 /* CatchBlock_Statements */: return false;
                    case 8 /* EnumDeclaration_EnumElements */: return isEnumElement(inErrorRecovery);
                    case 9 /* ObjectType_TypeMembers */: return isTypeMember(inErrorRecovery);
                    case 10 /* ClassOrInterfaceDeclaration_HeritageClauses */: return isHeritageClause();
                    case 11 /* HeritageClause_TypeNameList */: return isHeritageClauseTypeName();
                    case 12 /* VariableDeclaration_VariableDeclarators_AllowIn */: return isVariableDeclarator();
                    case 13 /* VariableDeclaration_VariableDeclarators_DisallowIn */: return isVariableDeclarator();
                    case 14 /* ArgumentList_AssignmentExpressions */: return isExpectedArgumentList_AssignmentExpression();
                    case 15 /* ObjectLiteralExpression_PropertyAssignments */: return isPropertyAssignment(inErrorRecovery);
                    case 16 /* ArrayLiteralExpression_AssignmentExpressions */: return isAssignmentOrOmittedExpression();
                    case 17 /* ParameterList_Parameters */: return isParameter();
                    case 18 /* IndexSignature_Parameters */: return isParameter();
                    case 19 /* TypeArgumentList_Types */: return isType();
                    case 20 /* TypeParameterList_TypeParameters */: return isTypeParameter();
                    default: throw TypeScript.Errors.invalidOperation();
                }
            }

            function isExpectedArgumentList_AssignmentExpression() {
                var _currentToken = currentToken();
                if (isExpression(_currentToken)) {
                    return true;
                }

                // If we're on a comma then the user has written something like "Foo(a,," or "Foo(,".
                // Instead of skipping the comma, create an empty expression to go before the comma
                // so that the tree is more well formed and doesn't have skipped tokens.
                if (_currentToken.kind() === 79 /* CommaToken */) {
                    return true;
                }

                return false;
            }

            function tryParseExpectedListItemWorker(currentListType, inErrorRecovery) {
                switch (currentListType) {
                    case 0 /* SourceUnit_ModuleElements */: return tryParseModuleElement(inErrorRecovery);
                    case 1 /* ClassDeclaration_ClassElements */: return tryParseClassElement(inErrorRecovery);
                    case 2 /* ModuleDeclaration_ModuleElements */: return tryParseModuleElement(inErrorRecovery);
                    case 3 /* SwitchStatement_SwitchClauses */: return tryParseSwitchClause();
                    case 4 /* SwitchClause_Statements */: return tryParseStatement(inErrorRecovery);
                    case 5 /* Block_Statements */: return tryParseStatement(inErrorRecovery);
                    case 6 /* TryBlock_Statements */: return tryParseStatement(inErrorRecovery);
                    case 7 /* CatchBlock_Statements */: return tryParseStatement(inErrorRecovery);
                    case 8 /* EnumDeclaration_EnumElements */: return tryParseEnumElement(inErrorRecovery);
                    case 9 /* ObjectType_TypeMembers */: return tryParseTypeMember(inErrorRecovery);
                    case 10 /* ClassOrInterfaceDeclaration_HeritageClauses */: return tryParseHeritageClause();
                    case 11 /* HeritageClause_TypeNameList */: return tryParseHeritageClauseTypeName();
                    case 12 /* VariableDeclaration_VariableDeclarators_AllowIn */: return tryParseVariableDeclarator(true, false);
                    case 13 /* VariableDeclaration_VariableDeclarators_DisallowIn */: return tryParseVariableDeclarator(false, false);
                    case 14 /* ArgumentList_AssignmentExpressions */: return tryParseArgumentListExpression();
                    case 15 /* ObjectLiteralExpression_PropertyAssignments */: return tryParsePropertyAssignment(inErrorRecovery);
                    case 16 /* ArrayLiteralExpression_AssignmentExpressions */: return tryParseAssignmentOrOmittedExpression();
                    case 17 /* ParameterList_Parameters */: return tryParseParameter();
                    case 18 /* IndexSignature_Parameters */: return tryParseParameter();
                    case 19 /* TypeArgumentList_Types */: return tryParseType();
                    case 20 /* TypeParameterList_TypeParameters */: return tryParseTypeParameter();
                    default: throw TypeScript.Errors.invalidOperation();
                }
            }

            function getExpectedListElementType(currentListType) {
                switch (currentListType) {
                    case 0 /* SourceUnit_ModuleElements */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.module_class_interface_enum_import_or_statement, null);
                    case 10 /* ClassOrInterfaceDeclaration_HeritageClauses */: return '{';
                    case 1 /* ClassDeclaration_ClassElements */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.constructor_function_accessor_or_variable, null);
                    case 2 /* ModuleDeclaration_ModuleElements */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.module_class_interface_enum_import_or_statement, null);
                    case 3 /* SwitchStatement_SwitchClauses */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.case_or_default_clause, null);
                    case 4 /* SwitchClause_Statements */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.statement, null);
                    case 5 /* Block_Statements */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.statement, null);
                    case 12 /* VariableDeclaration_VariableDeclarators_AllowIn */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.identifier, null);
                    case 13 /* VariableDeclaration_VariableDeclarators_DisallowIn */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.identifier, null);
                    case 8 /* EnumDeclaration_EnumElements */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.identifier, null);
                    case 9 /* ObjectType_TypeMembers */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.call_construct_index_property_or_function_signature, null);
                    case 14 /* ArgumentList_AssignmentExpressions */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.expression, null);
                    case 11 /* HeritageClause_TypeNameList */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.type_name, null);
                    case 15 /* ObjectLiteralExpression_PropertyAssignments */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.property_or_accessor, null);
                    case 17 /* ParameterList_Parameters */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.parameter, null);
                    case 18 /* IndexSignature_Parameters */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.parameter, null);
                    case 19 /* TypeArgumentList_Types */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.type, null);
                    case 20 /* TypeParameterList_TypeParameters */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.type_parameter, null);
                    case 16 /* ArrayLiteralExpression_AssignmentExpressions */: return TypeScript.getLocalizedText(TypeScript.DiagnosticCode.expression, null);
                    default: throw TypeScript.Errors.invalidOperation();
                }
            }

            return parseSyntaxTree;
        }

        // The precedence of expressions in typescript.  While we're parsing an expression, we will
        // continue to consume and form new trees if the precedence is *strictly* greater than our current
        // precedence.  For example, if we have: a + b * c, we will first parse 'a' with precedence 1 (Lowest).
        // We will then see the + with precedence 10.  10 is greater than 1 so we will decide to create
        // a binary expression with the result of parsing the sub expression "b * c".  We'll then parse
        // the term 'b' (passing in precedence 10).  We will then see the * with precedence 11.  11 is
        // greater than 10, so we will create a binary expression from "b" and "c", return that, and
        // join it with "a" producing:
        //
        //      +
        //     / \
        //    a   *
        //       / \
        //      b   c
        //
        // If we instead had: "a * b + c", we would first parser 'a' with precedence 1 (lowest).  We would then see
        // the * with precedence 11.  11 is greater than 1 so we will decide to create a binary expression
        // with the result of parsing the sub expression "b + c".  We'll then parse the term 'b' (passing in
        // precedence 11).  We will then see the + with precedence 10.  10 is less than 11, so we won't
        // continue parsing subexpressions and will just return the expression 'b'.  The caller will join
        // that into "a * b" (and will be back at precedence 1). It will then see the + with precedence 10.
        // 10 is greater than 1 so it will parse the sub expression and make a binary expression out of it
        // producing:
        //
        //        +
        //       / \
        //      *   c
        //     / \
        //    a   b
        //
        // Note: because all these binary expressions have left-to-right precedence, if we see a * b * c
        // then we parse it as:
        //
        //        *
        //       / \
        //      *   c
        //     / \
        //    a   b
        //
        // The code to do this uses the above logic.  It will see an operator with the same precedence,
        // and so it won't consume it.
        var BinaryExpressionPrecedence;
        (function (BinaryExpressionPrecedence) {
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["Lowest"] = 1] = "Lowest";

            // Intuitively, logical || have the lowest precedence.  "a || b && c" is "a || (b && c)", not
            // "(a || b) && c"
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["LogicalOrExpressionPrecedence"] = 2] = "LogicalOrExpressionPrecedence";
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["LogicalAndExpressionPrecedence"] = 3] = "LogicalAndExpressionPrecedence";
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["BitwiseOrExpressionPrecedence"] = 4] = "BitwiseOrExpressionPrecedence";
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["BitwiseExclusiveOrExpressionPrecedence"] = 5] = "BitwiseExclusiveOrExpressionPrecedence";
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["BitwiseAndExpressionPrecedence"] = 6] = "BitwiseAndExpressionPrecedence";
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["EqualityExpressionPrecedence"] = 7] = "EqualityExpressionPrecedence";
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["RelationalExpressionPrecedence"] = 8] = "RelationalExpressionPrecedence";
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["ShiftExpressionPrecdence"] = 9] = "ShiftExpressionPrecdence";
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["AdditiveExpressionPrecedence"] = 10] = "AdditiveExpressionPrecedence";

            // Intuitively, multiplicative expressions have the highest precedence.  After all, if you have:
            //   a + b * c
            //
            // Then you have "a + (b * c)" not "(a + b) * c"
            BinaryExpressionPrecedence[BinaryExpressionPrecedence["MultiplicativeExpressionPrecedence"] = 11] = "MultiplicativeExpressionPrecedence";
        })(BinaryExpressionPrecedence || (BinaryExpressionPrecedence = {}));

        // The current state of the parser wrt to list parsing.  The way to read these is as:
        // CurrentProduction_SubList.  i.e. "Block_Statements" means "we're parsing a Block, and we're
        // currently parsing list of statements within it".  This is used by the list parsing mechanism
        // to parse the elements of the lists, and recover from errors we encounter when we run into
        // unexpected code.
        //
        // For example, when we are in ArgumentList_Arguments, we will continue trying to consume code
        // as long as "isArgument" is true.  If we run into a token for which "isArgument" is not true
        // we will do the following:
        //
        // If the token is a StopToken for ArgumentList_Arguments (like ")" ) then we will stop parsing
        // the list of arguments with no error.
        //
        // Otherwise, we *do* report an error for this unexpected token, and then enter error recovery
        // mode to decide how to try to recover from this unexpected token.
        //
        // Error recovery will walk up the list of states we're in seeing if the token is a stop token
        // for that construct *or* could start another element within what construct.  For example, if
        // the unexpected token was '}' then that would be a stop token for Block_Statements.
        // Alternatively, if the unexpected token was 'return', then that would be a start token for
        // the next statment in Block_Statements.
        //
        // If either of those cases are true, We will then return *without* consuming  that token.
        // (Remember, we've already reported an error).  Now we're just letting the higher up parse
        // constructs eventually try to consume that token.
        //
        // If none of the higher up states consider this a stop or start token, then we will simply
        // consume the token and add it to our list of 'skipped tokens'.  We will then repeat the
        // above algorithm until we resynchronize at some point.
        var ListParsingState;
        (function (ListParsingState) {
            ListParsingState[ListParsingState["SourceUnit_ModuleElements"] = 0] = "SourceUnit_ModuleElements";
            ListParsingState[ListParsingState["ClassDeclaration_ClassElements"] = 1] = "ClassDeclaration_ClassElements";
            ListParsingState[ListParsingState["ModuleDeclaration_ModuleElements"] = 2] = "ModuleDeclaration_ModuleElements";
            ListParsingState[ListParsingState["SwitchStatement_SwitchClauses"] = 3] = "SwitchStatement_SwitchClauses";
            ListParsingState[ListParsingState["SwitchClause_Statements"] = 4] = "SwitchClause_Statements";
            ListParsingState[ListParsingState["Block_Statements"] = 5] = "Block_Statements";
            ListParsingState[ListParsingState["TryBlock_Statements"] = 6] = "TryBlock_Statements";
            ListParsingState[ListParsingState["CatchBlock_Statements"] = 7] = "CatchBlock_Statements";
            ListParsingState[ListParsingState["EnumDeclaration_EnumElements"] = 8] = "EnumDeclaration_EnumElements";
            ListParsingState[ListParsingState["ObjectType_TypeMembers"] = 9] = "ObjectType_TypeMembers";
            ListParsingState[ListParsingState["ClassOrInterfaceDeclaration_HeritageClauses"] = 10] = "ClassOrInterfaceDeclaration_HeritageClauses";
            ListParsingState[ListParsingState["HeritageClause_TypeNameList"] = 11] = "HeritageClause_TypeNameList";
            ListParsingState[ListParsingState["VariableDeclaration_VariableDeclarators_AllowIn"] = 12] = "VariableDeclaration_VariableDeclarators_AllowIn";
            ListParsingState[ListParsingState["VariableDeclaration_VariableDeclarators_DisallowIn"] = 13] = "VariableDeclaration_VariableDeclarators_DisallowIn";
            ListParsingState[ListParsingState["ArgumentList_AssignmentExpressions"] = 14] = "ArgumentList_AssignmentExpressions";
            ListParsingState[ListParsingState["ObjectLiteralExpression_PropertyAssignments"] = 15] = "ObjectLiteralExpression_PropertyAssignments";
            ListParsingState[ListParsingState["ArrayLiteralExpression_AssignmentExpressions"] = 16] = "ArrayLiteralExpression_AssignmentExpressions";
            ListParsingState[ListParsingState["ParameterList_Parameters"] = 17] = "ParameterList_Parameters";
            ListParsingState[ListParsingState["IndexSignature_Parameters"] = 18] = "IndexSignature_Parameters";
            ListParsingState[ListParsingState["TypeArgumentList_Types"] = 19] = "TypeArgumentList_Types";
            ListParsingState[ListParsingState["TypeParameterList_TypeParameters"] = 20] = "TypeParameterList_TypeParameters";

            ListParsingState[ListParsingState["FirstListParsingState"] = ListParsingState.SourceUnit_ModuleElements] = "FirstListParsingState";
            ListParsingState[ListParsingState["LastListParsingState"] = ListParsingState.TypeParameterList_TypeParameters] = "LastListParsingState";
        })(ListParsingState || (ListParsingState = {}));

        // We keep the parser around as a singleton.  This is because calling createParser is actually
        // expensive in V8 currently.  We then clear it after a parse so that it doesn't  keep state
        // alive unintentionally.
        var parseSyntaxTree = createParseSyntaxTree();

        function parse(fileName, text, languageVersion, isDeclaration) {
            return parseSource(TypeScript.Scanner.createParserSource(fileName, text, languageVersion), isDeclaration);
        }
        Parser.parse = parse;

        function parseSource(source, isDeclaration) {
            return parseSyntaxTree(source, isDeclaration);
        }
        Parser.parseSource = parseSource;
    })(TypeScript.Parser || (TypeScript.Parser = {}));
    var Parser = TypeScript.Parser;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (Syntax) {
        (function (Concrete) {
            // Inject this module as the factory for producing syntax nodes in the parser.
            TypeScript.Parser.syntaxFactory = Concrete;
            Concrete.isConcrete = true;

            var SourceUnitSyntax = (function (_super) {
                __extends(SourceUnitSyntax, _super);
                function SourceUnitSyntax(data, moduleElements, endOfFileToken) {
                    _super.call(this, data);
                    this.syntaxTree = null;
                    this.parent = null, this.moduleElements = moduleElements, this.endOfFileToken = endOfFileToken, !TypeScript.isShared(moduleElements) && (moduleElements.parent = this), endOfFileToken.parent = this;
                }
                return SourceUnitSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.SourceUnitSyntax = SourceUnitSyntax;
            var QualifiedNameSyntax = (function (_super) {
                __extends(QualifiedNameSyntax, _super);
                function QualifiedNameSyntax(data, left, dotToken, right) {
                    _super.call(this, data);
                    this.left = left, this.dotToken = dotToken, this.right = right, left.parent = this, dotToken.parent = this, right.parent = this;
                }
                return QualifiedNameSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.QualifiedNameSyntax = QualifiedNameSyntax;
            var ObjectTypeSyntax = (function (_super) {
                __extends(ObjectTypeSyntax, _super);
                function ObjectTypeSyntax(data, openBraceToken, typeMembers, closeBraceToken) {
                    _super.call(this, data);
                    this.openBraceToken = openBraceToken, this.typeMembers = typeMembers, this.closeBraceToken = closeBraceToken, openBraceToken.parent = this, !TypeScript.isShared(typeMembers) && (typeMembers.parent = this), closeBraceToken.parent = this;
                }
                return ObjectTypeSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ObjectTypeSyntax = ObjectTypeSyntax;
            var FunctionTypeSyntax = (function (_super) {
                __extends(FunctionTypeSyntax, _super);
                function FunctionTypeSyntax(data, typeParameterList, parameterList, equalsGreaterThanToken, type) {
                    _super.call(this, data);
                    this.typeParameterList = typeParameterList, this.parameterList = parameterList, this.equalsGreaterThanToken = equalsGreaterThanToken, this.type = type, typeParameterList && (typeParameterList.parent = this), parameterList.parent = this, equalsGreaterThanToken.parent = this, type.parent = this;
                }
                return FunctionTypeSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.FunctionTypeSyntax = FunctionTypeSyntax;
            var ArrayTypeSyntax = (function (_super) {
                __extends(ArrayTypeSyntax, _super);
                function ArrayTypeSyntax(data, type, openBracketToken, closeBracketToken) {
                    _super.call(this, data);
                    this.type = type, this.openBracketToken = openBracketToken, this.closeBracketToken = closeBracketToken, type.parent = this, openBracketToken.parent = this, closeBracketToken.parent = this;
                }
                return ArrayTypeSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ArrayTypeSyntax = ArrayTypeSyntax;
            var ConstructorTypeSyntax = (function (_super) {
                __extends(ConstructorTypeSyntax, _super);
                function ConstructorTypeSyntax(data, newKeyword, typeParameterList, parameterList, equalsGreaterThanToken, type) {
                    _super.call(this, data);
                    this.newKeyword = newKeyword, this.typeParameterList = typeParameterList, this.parameterList = parameterList, this.equalsGreaterThanToken = equalsGreaterThanToken, this.type = type, newKeyword.parent = this, typeParameterList && (typeParameterList.parent = this), parameterList.parent = this, equalsGreaterThanToken.parent = this, type.parent = this;
                }
                return ConstructorTypeSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ConstructorTypeSyntax = ConstructorTypeSyntax;
            var GenericTypeSyntax = (function (_super) {
                __extends(GenericTypeSyntax, _super);
                function GenericTypeSyntax(data, name, typeArgumentList) {
                    _super.call(this, data);
                    this.name = name, this.typeArgumentList = typeArgumentList, name.parent = this, typeArgumentList.parent = this;
                }
                return GenericTypeSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.GenericTypeSyntax = GenericTypeSyntax;
            var TypeQuerySyntax = (function (_super) {
                __extends(TypeQuerySyntax, _super);
                function TypeQuerySyntax(data, typeOfKeyword, name) {
                    _super.call(this, data);
                    this.typeOfKeyword = typeOfKeyword, this.name = name, typeOfKeyword.parent = this, name.parent = this;
                }
                return TypeQuerySyntax;
            })(TypeScript.SyntaxNode);
            Concrete.TypeQuerySyntax = TypeQuerySyntax;
            var InterfaceDeclarationSyntax = (function (_super) {
                __extends(InterfaceDeclarationSyntax, _super);
                function InterfaceDeclarationSyntax(data, modifiers, interfaceKeyword, identifier, typeParameterList, heritageClauses, body) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.interfaceKeyword = interfaceKeyword, this.identifier = identifier, this.typeParameterList = typeParameterList, this.heritageClauses = heritageClauses, this.body = body, !TypeScript.isShared(modifiers) && (modifiers.parent = this), interfaceKeyword.parent = this, identifier.parent = this, typeParameterList && (typeParameterList.parent = this), !TypeScript.isShared(heritageClauses) && (heritageClauses.parent = this), body.parent = this;
                }
                return InterfaceDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.InterfaceDeclarationSyntax = InterfaceDeclarationSyntax;
            var FunctionDeclarationSyntax = (function (_super) {
                __extends(FunctionDeclarationSyntax, _super);
                function FunctionDeclarationSyntax(data, modifiers, functionKeyword, identifier, callSignature, block, semicolonToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.functionKeyword = functionKeyword, this.identifier = identifier, this.callSignature = callSignature, this.block = block, this.semicolonToken = semicolonToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), functionKeyword.parent = this, identifier.parent = this, callSignature.parent = this, block && (block.parent = this), semicolonToken && (semicolonToken.parent = this);
                }
                return FunctionDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.FunctionDeclarationSyntax = FunctionDeclarationSyntax;
            var ModuleDeclarationSyntax = (function (_super) {
                __extends(ModuleDeclarationSyntax, _super);
                function ModuleDeclarationSyntax(data, modifiers, moduleKeyword, name, stringLiteral, openBraceToken, moduleElements, closeBraceToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.moduleKeyword = moduleKeyword, this.name = name, this.stringLiteral = stringLiteral, this.openBraceToken = openBraceToken, this.moduleElements = moduleElements, this.closeBraceToken = closeBraceToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), moduleKeyword.parent = this, name && (name.parent = this), stringLiteral && (stringLiteral.parent = this), openBraceToken.parent = this, !TypeScript.isShared(moduleElements) && (moduleElements.parent = this), closeBraceToken.parent = this;
                }
                return ModuleDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ModuleDeclarationSyntax = ModuleDeclarationSyntax;
            var ClassDeclarationSyntax = (function (_super) {
                __extends(ClassDeclarationSyntax, _super);
                function ClassDeclarationSyntax(data, modifiers, classKeyword, identifier, typeParameterList, heritageClauses, openBraceToken, classElements, closeBraceToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.classKeyword = classKeyword, this.identifier = identifier, this.typeParameterList = typeParameterList, this.heritageClauses = heritageClauses, this.openBraceToken = openBraceToken, this.classElements = classElements, this.closeBraceToken = closeBraceToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), classKeyword.parent = this, identifier.parent = this, typeParameterList && (typeParameterList.parent = this), !TypeScript.isShared(heritageClauses) && (heritageClauses.parent = this), openBraceToken.parent = this, !TypeScript.isShared(classElements) && (classElements.parent = this), closeBraceToken.parent = this;
                }
                return ClassDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ClassDeclarationSyntax = ClassDeclarationSyntax;
            var EnumDeclarationSyntax = (function (_super) {
                __extends(EnumDeclarationSyntax, _super);
                function EnumDeclarationSyntax(data, modifiers, enumKeyword, identifier, openBraceToken, enumElements, closeBraceToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.enumKeyword = enumKeyword, this.identifier = identifier, this.openBraceToken = openBraceToken, this.enumElements = enumElements, this.closeBraceToken = closeBraceToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), enumKeyword.parent = this, identifier.parent = this, openBraceToken.parent = this, !TypeScript.isShared(enumElements) && (enumElements.parent = this), closeBraceToken.parent = this;
                }
                return EnumDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.EnumDeclarationSyntax = EnumDeclarationSyntax;
            var ImportDeclarationSyntax = (function (_super) {
                __extends(ImportDeclarationSyntax, _super);
                function ImportDeclarationSyntax(data, modifiers, importKeyword, identifier, equalsToken, moduleReference, semicolonToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.importKeyword = importKeyword, this.identifier = identifier, this.equalsToken = equalsToken, this.moduleReference = moduleReference, this.semicolonToken = semicolonToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), importKeyword.parent = this, identifier.parent = this, equalsToken.parent = this, moduleReference.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return ImportDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ImportDeclarationSyntax = ImportDeclarationSyntax;
            var ExportAssignmentSyntax = (function (_super) {
                __extends(ExportAssignmentSyntax, _super);
                function ExportAssignmentSyntax(data, exportKeyword, equalsToken, identifier, semicolonToken) {
                    _super.call(this, data);
                    this.exportKeyword = exportKeyword, this.equalsToken = equalsToken, this.identifier = identifier, this.semicolonToken = semicolonToken, exportKeyword.parent = this, equalsToken.parent = this, identifier.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return ExportAssignmentSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ExportAssignmentSyntax = ExportAssignmentSyntax;
            var MemberFunctionDeclarationSyntax = (function (_super) {
                __extends(MemberFunctionDeclarationSyntax, _super);
                function MemberFunctionDeclarationSyntax(data, modifiers, propertyName, callSignature, block, semicolonToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.propertyName = propertyName, this.callSignature = callSignature, this.block = block, this.semicolonToken = semicolonToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), propertyName.parent = this, callSignature.parent = this, block && (block.parent = this), semicolonToken && (semicolonToken.parent = this);
                }
                return MemberFunctionDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.MemberFunctionDeclarationSyntax = MemberFunctionDeclarationSyntax;
            var MemberVariableDeclarationSyntax = (function (_super) {
                __extends(MemberVariableDeclarationSyntax, _super);
                function MemberVariableDeclarationSyntax(data, modifiers, variableDeclarator, semicolonToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.variableDeclarator = variableDeclarator, this.semicolonToken = semicolonToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), variableDeclarator.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return MemberVariableDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.MemberVariableDeclarationSyntax = MemberVariableDeclarationSyntax;
            var ConstructorDeclarationSyntax = (function (_super) {
                __extends(ConstructorDeclarationSyntax, _super);
                function ConstructorDeclarationSyntax(data, modifiers, constructorKeyword, callSignature, block, semicolonToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.constructorKeyword = constructorKeyword, this.callSignature = callSignature, this.block = block, this.semicolonToken = semicolonToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), constructorKeyword.parent = this, callSignature.parent = this, block && (block.parent = this), semicolonToken && (semicolonToken.parent = this);
                }
                return ConstructorDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ConstructorDeclarationSyntax = ConstructorDeclarationSyntax;
            var IndexMemberDeclarationSyntax = (function (_super) {
                __extends(IndexMemberDeclarationSyntax, _super);
                function IndexMemberDeclarationSyntax(data, modifiers, indexSignature, semicolonToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.indexSignature = indexSignature, this.semicolonToken = semicolonToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), indexSignature.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return IndexMemberDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.IndexMemberDeclarationSyntax = IndexMemberDeclarationSyntax;
            var GetAccessorSyntax = (function (_super) {
                __extends(GetAccessorSyntax, _super);
                function GetAccessorSyntax(data, modifiers, getKeyword, propertyName, callSignature, block) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.getKeyword = getKeyword, this.propertyName = propertyName, this.callSignature = callSignature, this.block = block, !TypeScript.isShared(modifiers) && (modifiers.parent = this), getKeyword.parent = this, propertyName.parent = this, callSignature.parent = this, block.parent = this;
                }
                return GetAccessorSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.GetAccessorSyntax = GetAccessorSyntax;
            var SetAccessorSyntax = (function (_super) {
                __extends(SetAccessorSyntax, _super);
                function SetAccessorSyntax(data, modifiers, setKeyword, propertyName, callSignature, block) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.setKeyword = setKeyword, this.propertyName = propertyName, this.callSignature = callSignature, this.block = block, !TypeScript.isShared(modifiers) && (modifiers.parent = this), setKeyword.parent = this, propertyName.parent = this, callSignature.parent = this, block.parent = this;
                }
                return SetAccessorSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.SetAccessorSyntax = SetAccessorSyntax;
            var PropertySignatureSyntax = (function (_super) {
                __extends(PropertySignatureSyntax, _super);
                function PropertySignatureSyntax(data, propertyName, questionToken, typeAnnotation) {
                    _super.call(this, data);
                    this.propertyName = propertyName, this.questionToken = questionToken, this.typeAnnotation = typeAnnotation, propertyName.parent = this, questionToken && (questionToken.parent = this), typeAnnotation && (typeAnnotation.parent = this);
                }
                return PropertySignatureSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.PropertySignatureSyntax = PropertySignatureSyntax;
            var CallSignatureSyntax = (function (_super) {
                __extends(CallSignatureSyntax, _super);
                function CallSignatureSyntax(data, typeParameterList, parameterList, typeAnnotation) {
                    _super.call(this, data);
                    this.typeParameterList = typeParameterList, this.parameterList = parameterList, this.typeAnnotation = typeAnnotation, typeParameterList && (typeParameterList.parent = this), parameterList.parent = this, typeAnnotation && (typeAnnotation.parent = this);
                }
                return CallSignatureSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.CallSignatureSyntax = CallSignatureSyntax;
            var ConstructSignatureSyntax = (function (_super) {
                __extends(ConstructSignatureSyntax, _super);
                function ConstructSignatureSyntax(data, newKeyword, callSignature) {
                    _super.call(this, data);
                    this.newKeyword = newKeyword, this.callSignature = callSignature, newKeyword.parent = this, callSignature.parent = this;
                }
                return ConstructSignatureSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ConstructSignatureSyntax = ConstructSignatureSyntax;
            var IndexSignatureSyntax = (function (_super) {
                __extends(IndexSignatureSyntax, _super);
                function IndexSignatureSyntax(data, openBracketToken, parameters, closeBracketToken, typeAnnotation) {
                    _super.call(this, data);
                    this.openBracketToken = openBracketToken, this.parameters = parameters, this.closeBracketToken = closeBracketToken, this.typeAnnotation = typeAnnotation, openBracketToken.parent = this, !TypeScript.isShared(parameters) && (parameters.parent = this), closeBracketToken.parent = this, typeAnnotation && (typeAnnotation.parent = this);
                }
                return IndexSignatureSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.IndexSignatureSyntax = IndexSignatureSyntax;
            var MethodSignatureSyntax = (function (_super) {
                __extends(MethodSignatureSyntax, _super);
                function MethodSignatureSyntax(data, propertyName, questionToken, callSignature) {
                    _super.call(this, data);
                    this.propertyName = propertyName, this.questionToken = questionToken, this.callSignature = callSignature, propertyName.parent = this, questionToken && (questionToken.parent = this), callSignature.parent = this;
                }
                return MethodSignatureSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.MethodSignatureSyntax = MethodSignatureSyntax;
            var BlockSyntax = (function (_super) {
                __extends(BlockSyntax, _super);
                function BlockSyntax(data, openBraceToken, statements, closeBraceToken) {
                    _super.call(this, data);
                    this.openBraceToken = openBraceToken, this.statements = statements, this.closeBraceToken = closeBraceToken, openBraceToken.parent = this, !TypeScript.isShared(statements) && (statements.parent = this), closeBraceToken.parent = this;
                }
                return BlockSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.BlockSyntax = BlockSyntax;
            var IfStatementSyntax = (function (_super) {
                __extends(IfStatementSyntax, _super);
                function IfStatementSyntax(data, ifKeyword, openParenToken, condition, closeParenToken, statement, elseClause) {
                    _super.call(this, data);
                    this.ifKeyword = ifKeyword, this.openParenToken = openParenToken, this.condition = condition, this.closeParenToken = closeParenToken, this.statement = statement, this.elseClause = elseClause, ifKeyword.parent = this, openParenToken.parent = this, condition.parent = this, closeParenToken.parent = this, statement.parent = this, elseClause && (elseClause.parent = this);
                }
                return IfStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.IfStatementSyntax = IfStatementSyntax;
            var VariableStatementSyntax = (function (_super) {
                __extends(VariableStatementSyntax, _super);
                function VariableStatementSyntax(data, modifiers, variableDeclaration, semicolonToken) {
                    _super.call(this, data);
                    this.modifiers = modifiers, this.variableDeclaration = variableDeclaration, this.semicolonToken = semicolonToken, !TypeScript.isShared(modifiers) && (modifiers.parent = this), variableDeclaration.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return VariableStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.VariableStatementSyntax = VariableStatementSyntax;
            var ExpressionStatementSyntax = (function (_super) {
                __extends(ExpressionStatementSyntax, _super);
                function ExpressionStatementSyntax(data, expression, semicolonToken) {
                    _super.call(this, data);
                    this.expression = expression, this.semicolonToken = semicolonToken, expression.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return ExpressionStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ExpressionStatementSyntax = ExpressionStatementSyntax;
            var ReturnStatementSyntax = (function (_super) {
                __extends(ReturnStatementSyntax, _super);
                function ReturnStatementSyntax(data, returnKeyword, expression, semicolonToken) {
                    _super.call(this, data);
                    this.returnKeyword = returnKeyword, this.expression = expression, this.semicolonToken = semicolonToken, returnKeyword.parent = this, expression && (expression.parent = this), semicolonToken && (semicolonToken.parent = this);
                }
                return ReturnStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ReturnStatementSyntax = ReturnStatementSyntax;
            var SwitchStatementSyntax = (function (_super) {
                __extends(SwitchStatementSyntax, _super);
                function SwitchStatementSyntax(data, switchKeyword, openParenToken, expression, closeParenToken, openBraceToken, switchClauses, closeBraceToken) {
                    _super.call(this, data);
                    this.switchKeyword = switchKeyword, this.openParenToken = openParenToken, this.expression = expression, this.closeParenToken = closeParenToken, this.openBraceToken = openBraceToken, this.switchClauses = switchClauses, this.closeBraceToken = closeBraceToken, switchKeyword.parent = this, openParenToken.parent = this, expression.parent = this, closeParenToken.parent = this, openBraceToken.parent = this, !TypeScript.isShared(switchClauses) && (switchClauses.parent = this), closeBraceToken.parent = this;
                }
                return SwitchStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.SwitchStatementSyntax = SwitchStatementSyntax;
            var BreakStatementSyntax = (function (_super) {
                __extends(BreakStatementSyntax, _super);
                function BreakStatementSyntax(data, breakKeyword, identifier, semicolonToken) {
                    _super.call(this, data);
                    this.breakKeyword = breakKeyword, this.identifier = identifier, this.semicolonToken = semicolonToken, breakKeyword.parent = this, identifier && (identifier.parent = this), semicolonToken && (semicolonToken.parent = this);
                }
                return BreakStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.BreakStatementSyntax = BreakStatementSyntax;
            var ContinueStatementSyntax = (function (_super) {
                __extends(ContinueStatementSyntax, _super);
                function ContinueStatementSyntax(data, continueKeyword, identifier, semicolonToken) {
                    _super.call(this, data);
                    this.continueKeyword = continueKeyword, this.identifier = identifier, this.semicolonToken = semicolonToken, continueKeyword.parent = this, identifier && (identifier.parent = this), semicolonToken && (semicolonToken.parent = this);
                }
                return ContinueStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ContinueStatementSyntax = ContinueStatementSyntax;
            var ForStatementSyntax = (function (_super) {
                __extends(ForStatementSyntax, _super);
                function ForStatementSyntax(data, forKeyword, openParenToken, variableDeclaration, initializer, firstSemicolonToken, condition, secondSemicolonToken, incrementor, closeParenToken, statement) {
                    _super.call(this, data);
                    this.forKeyword = forKeyword, this.openParenToken = openParenToken, this.variableDeclaration = variableDeclaration, this.initializer = initializer, this.firstSemicolonToken = firstSemicolonToken, this.condition = condition, this.secondSemicolonToken = secondSemicolonToken, this.incrementor = incrementor, this.closeParenToken = closeParenToken, this.statement = statement, forKeyword.parent = this, openParenToken.parent = this, variableDeclaration && (variableDeclaration.parent = this), initializer && (initializer.parent = this), firstSemicolonToken.parent = this, condition && (condition.parent = this), secondSemicolonToken.parent = this, incrementor && (incrementor.parent = this), closeParenToken.parent = this, statement.parent = this;
                }
                return ForStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ForStatementSyntax = ForStatementSyntax;
            var ForInStatementSyntax = (function (_super) {
                __extends(ForInStatementSyntax, _super);
                function ForInStatementSyntax(data, forKeyword, openParenToken, variableDeclaration, left, inKeyword, expression, closeParenToken, statement) {
                    _super.call(this, data);
                    this.forKeyword = forKeyword, this.openParenToken = openParenToken, this.variableDeclaration = variableDeclaration, this.left = left, this.inKeyword = inKeyword, this.expression = expression, this.closeParenToken = closeParenToken, this.statement = statement, forKeyword.parent = this, openParenToken.parent = this, variableDeclaration && (variableDeclaration.parent = this), left && (left.parent = this), inKeyword.parent = this, expression.parent = this, closeParenToken.parent = this, statement.parent = this;
                }
                return ForInStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ForInStatementSyntax = ForInStatementSyntax;
            var EmptyStatementSyntax = (function (_super) {
                __extends(EmptyStatementSyntax, _super);
                function EmptyStatementSyntax(data, semicolonToken) {
                    _super.call(this, data);
                    this.semicolonToken = semicolonToken, semicolonToken.parent = this;
                }
                return EmptyStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.EmptyStatementSyntax = EmptyStatementSyntax;
            var ThrowStatementSyntax = (function (_super) {
                __extends(ThrowStatementSyntax, _super);
                function ThrowStatementSyntax(data, throwKeyword, expression, semicolonToken) {
                    _super.call(this, data);
                    this.throwKeyword = throwKeyword, this.expression = expression, this.semicolonToken = semicolonToken, throwKeyword.parent = this, expression.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return ThrowStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ThrowStatementSyntax = ThrowStatementSyntax;
            var WhileStatementSyntax = (function (_super) {
                __extends(WhileStatementSyntax, _super);
                function WhileStatementSyntax(data, whileKeyword, openParenToken, condition, closeParenToken, statement) {
                    _super.call(this, data);
                    this.whileKeyword = whileKeyword, this.openParenToken = openParenToken, this.condition = condition, this.closeParenToken = closeParenToken, this.statement = statement, whileKeyword.parent = this, openParenToken.parent = this, condition.parent = this, closeParenToken.parent = this, statement.parent = this;
                }
                return WhileStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.WhileStatementSyntax = WhileStatementSyntax;
            var TryStatementSyntax = (function (_super) {
                __extends(TryStatementSyntax, _super);
                function TryStatementSyntax(data, tryKeyword, block, catchClause, finallyClause) {
                    _super.call(this, data);
                    this.tryKeyword = tryKeyword, this.block = block, this.catchClause = catchClause, this.finallyClause = finallyClause, tryKeyword.parent = this, block.parent = this, catchClause && (catchClause.parent = this), finallyClause && (finallyClause.parent = this);
                }
                return TryStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.TryStatementSyntax = TryStatementSyntax;
            var LabeledStatementSyntax = (function (_super) {
                __extends(LabeledStatementSyntax, _super);
                function LabeledStatementSyntax(data, identifier, colonToken, statement) {
                    _super.call(this, data);
                    this.identifier = identifier, this.colonToken = colonToken, this.statement = statement, identifier.parent = this, colonToken.parent = this, statement.parent = this;
                }
                return LabeledStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.LabeledStatementSyntax = LabeledStatementSyntax;
            var DoStatementSyntax = (function (_super) {
                __extends(DoStatementSyntax, _super);
                function DoStatementSyntax(data, doKeyword, statement, whileKeyword, openParenToken, condition, closeParenToken, semicolonToken) {
                    _super.call(this, data);
                    this.doKeyword = doKeyword, this.statement = statement, this.whileKeyword = whileKeyword, this.openParenToken = openParenToken, this.condition = condition, this.closeParenToken = closeParenToken, this.semicolonToken = semicolonToken, doKeyword.parent = this, statement.parent = this, whileKeyword.parent = this, openParenToken.parent = this, condition.parent = this, closeParenToken.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return DoStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.DoStatementSyntax = DoStatementSyntax;
            var DebuggerStatementSyntax = (function (_super) {
                __extends(DebuggerStatementSyntax, _super);
                function DebuggerStatementSyntax(data, debuggerKeyword, semicolonToken) {
                    _super.call(this, data);
                    this.debuggerKeyword = debuggerKeyword, this.semicolonToken = semicolonToken, debuggerKeyword.parent = this, semicolonToken && (semicolonToken.parent = this);
                }
                return DebuggerStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.DebuggerStatementSyntax = DebuggerStatementSyntax;
            var WithStatementSyntax = (function (_super) {
                __extends(WithStatementSyntax, _super);
                function WithStatementSyntax(data, withKeyword, openParenToken, condition, closeParenToken, statement) {
                    _super.call(this, data);
                    this.withKeyword = withKeyword, this.openParenToken = openParenToken, this.condition = condition, this.closeParenToken = closeParenToken, this.statement = statement, withKeyword.parent = this, openParenToken.parent = this, condition.parent = this, closeParenToken.parent = this, statement.parent = this;
                }
                return WithStatementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.WithStatementSyntax = WithStatementSyntax;
            var PrefixUnaryExpressionSyntax = (function (_super) {
                __extends(PrefixUnaryExpressionSyntax, _super);
                function PrefixUnaryExpressionSyntax(data, operatorToken, operand) {
                    _super.call(this, data);
                    this.operatorToken = operatorToken, this.operand = operand, operatorToken.parent = this, operand.parent = this;
                }
                PrefixUnaryExpressionSyntax.prototype.kind = function () {
                    return TypeScript.SyntaxFacts.getPrefixUnaryExpressionFromOperatorToken(this.operatorToken.kind());
                };
                return PrefixUnaryExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.PrefixUnaryExpressionSyntax = PrefixUnaryExpressionSyntax;
            var DeleteExpressionSyntax = (function (_super) {
                __extends(DeleteExpressionSyntax, _super);
                function DeleteExpressionSyntax(data, deleteKeyword, expression) {
                    _super.call(this, data);
                    this.deleteKeyword = deleteKeyword, this.expression = expression, deleteKeyword.parent = this, expression.parent = this;
                }
                return DeleteExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.DeleteExpressionSyntax = DeleteExpressionSyntax;
            var TypeOfExpressionSyntax = (function (_super) {
                __extends(TypeOfExpressionSyntax, _super);
                function TypeOfExpressionSyntax(data, typeOfKeyword, expression) {
                    _super.call(this, data);
                    this.typeOfKeyword = typeOfKeyword, this.expression = expression, typeOfKeyword.parent = this, expression.parent = this;
                }
                return TypeOfExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.TypeOfExpressionSyntax = TypeOfExpressionSyntax;
            var VoidExpressionSyntax = (function (_super) {
                __extends(VoidExpressionSyntax, _super);
                function VoidExpressionSyntax(data, voidKeyword, expression) {
                    _super.call(this, data);
                    this.voidKeyword = voidKeyword, this.expression = expression, voidKeyword.parent = this, expression.parent = this;
                }
                return VoidExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.VoidExpressionSyntax = VoidExpressionSyntax;
            var ConditionalExpressionSyntax = (function (_super) {
                __extends(ConditionalExpressionSyntax, _super);
                function ConditionalExpressionSyntax(data, condition, questionToken, whenTrue, colonToken, whenFalse) {
                    _super.call(this, data);
                    this.condition = condition, this.questionToken = questionToken, this.whenTrue = whenTrue, this.colonToken = colonToken, this.whenFalse = whenFalse, condition.parent = this, questionToken.parent = this, whenTrue.parent = this, colonToken.parent = this, whenFalse.parent = this;
                }
                return ConditionalExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ConditionalExpressionSyntax = ConditionalExpressionSyntax;
            var BinaryExpressionSyntax = (function (_super) {
                __extends(BinaryExpressionSyntax, _super);
                function BinaryExpressionSyntax(data, left, operatorToken, right) {
                    _super.call(this, data);
                    this.left = left, this.operatorToken = operatorToken, this.right = right, left.parent = this, operatorToken.parent = this, right.parent = this;
                }
                BinaryExpressionSyntax.prototype.kind = function () {
                    return TypeScript.SyntaxFacts.getBinaryExpressionFromOperatorToken(this.operatorToken.kind());
                };
                return BinaryExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.BinaryExpressionSyntax = BinaryExpressionSyntax;
            var PostfixUnaryExpressionSyntax = (function (_super) {
                __extends(PostfixUnaryExpressionSyntax, _super);
                function PostfixUnaryExpressionSyntax(data, operand, operatorToken) {
                    _super.call(this, data);
                    this.operand = operand, this.operatorToken = operatorToken, operand.parent = this, operatorToken.parent = this;
                }
                PostfixUnaryExpressionSyntax.prototype.kind = function () {
                    return TypeScript.SyntaxFacts.getPostfixUnaryExpressionFromOperatorToken(this.operatorToken.kind());
                };
                return PostfixUnaryExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.PostfixUnaryExpressionSyntax = PostfixUnaryExpressionSyntax;
            var MemberAccessExpressionSyntax = (function (_super) {
                __extends(MemberAccessExpressionSyntax, _super);
                function MemberAccessExpressionSyntax(data, expression, dotToken, name) {
                    _super.call(this, data);
                    this.expression = expression, this.dotToken = dotToken, this.name = name, expression.parent = this, dotToken.parent = this, name.parent = this;
                }
                return MemberAccessExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.MemberAccessExpressionSyntax = MemberAccessExpressionSyntax;
            var InvocationExpressionSyntax = (function (_super) {
                __extends(InvocationExpressionSyntax, _super);
                function InvocationExpressionSyntax(data, expression, argumentList) {
                    _super.call(this, data);
                    this.expression = expression, this.argumentList = argumentList, expression.parent = this, argumentList.parent = this;
                }
                return InvocationExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.InvocationExpressionSyntax = InvocationExpressionSyntax;
            var ArrayLiteralExpressionSyntax = (function (_super) {
                __extends(ArrayLiteralExpressionSyntax, _super);
                function ArrayLiteralExpressionSyntax(data, openBracketToken, expressions, closeBracketToken) {
                    _super.call(this, data);
                    this.openBracketToken = openBracketToken, this.expressions = expressions, this.closeBracketToken = closeBracketToken, openBracketToken.parent = this, !TypeScript.isShared(expressions) && (expressions.parent = this), closeBracketToken.parent = this;
                }
                return ArrayLiteralExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ArrayLiteralExpressionSyntax = ArrayLiteralExpressionSyntax;
            var ObjectLiteralExpressionSyntax = (function (_super) {
                __extends(ObjectLiteralExpressionSyntax, _super);
                function ObjectLiteralExpressionSyntax(data, openBraceToken, propertyAssignments, closeBraceToken) {
                    _super.call(this, data);
                    this.openBraceToken = openBraceToken, this.propertyAssignments = propertyAssignments, this.closeBraceToken = closeBraceToken, openBraceToken.parent = this, !TypeScript.isShared(propertyAssignments) && (propertyAssignments.parent = this), closeBraceToken.parent = this;
                }
                return ObjectLiteralExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ObjectLiteralExpressionSyntax = ObjectLiteralExpressionSyntax;
            var ObjectCreationExpressionSyntax = (function (_super) {
                __extends(ObjectCreationExpressionSyntax, _super);
                function ObjectCreationExpressionSyntax(data, newKeyword, expression, argumentList) {
                    _super.call(this, data);
                    this.newKeyword = newKeyword, this.expression = expression, this.argumentList = argumentList, newKeyword.parent = this, expression.parent = this, argumentList && (argumentList.parent = this);
                }
                return ObjectCreationExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ObjectCreationExpressionSyntax = ObjectCreationExpressionSyntax;
            var ParenthesizedExpressionSyntax = (function (_super) {
                __extends(ParenthesizedExpressionSyntax, _super);
                function ParenthesizedExpressionSyntax(data, openParenToken, expression, closeParenToken) {
                    _super.call(this, data);
                    this.openParenToken = openParenToken, this.expression = expression, this.closeParenToken = closeParenToken, openParenToken.parent = this, expression.parent = this, closeParenToken.parent = this;
                }
                return ParenthesizedExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ParenthesizedExpressionSyntax = ParenthesizedExpressionSyntax;
            var ParenthesizedArrowFunctionExpressionSyntax = (function (_super) {
                __extends(ParenthesizedArrowFunctionExpressionSyntax, _super);
                function ParenthesizedArrowFunctionExpressionSyntax(data, callSignature, equalsGreaterThanToken, block, expression) {
                    _super.call(this, data);
                    this.callSignature = callSignature, this.equalsGreaterThanToken = equalsGreaterThanToken, this.block = block, this.expression = expression, callSignature.parent = this, equalsGreaterThanToken.parent = this, block && (block.parent = this), expression && (expression.parent = this);
                }
                return ParenthesizedArrowFunctionExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ParenthesizedArrowFunctionExpressionSyntax = ParenthesizedArrowFunctionExpressionSyntax;
            var SimpleArrowFunctionExpressionSyntax = (function (_super) {
                __extends(SimpleArrowFunctionExpressionSyntax, _super);
                function SimpleArrowFunctionExpressionSyntax(data, parameter, equalsGreaterThanToken, block, expression) {
                    _super.call(this, data);
                    this.parameter = parameter, this.equalsGreaterThanToken = equalsGreaterThanToken, this.block = block, this.expression = expression, parameter.parent = this, equalsGreaterThanToken.parent = this, block && (block.parent = this), expression && (expression.parent = this);
                }
                return SimpleArrowFunctionExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.SimpleArrowFunctionExpressionSyntax = SimpleArrowFunctionExpressionSyntax;
            var CastExpressionSyntax = (function (_super) {
                __extends(CastExpressionSyntax, _super);
                function CastExpressionSyntax(data, lessThanToken, type, greaterThanToken, expression) {
                    _super.call(this, data);
                    this.lessThanToken = lessThanToken, this.type = type, this.greaterThanToken = greaterThanToken, this.expression = expression, lessThanToken.parent = this, type.parent = this, greaterThanToken.parent = this, expression.parent = this;
                }
                return CastExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.CastExpressionSyntax = CastExpressionSyntax;
            var ElementAccessExpressionSyntax = (function (_super) {
                __extends(ElementAccessExpressionSyntax, _super);
                function ElementAccessExpressionSyntax(data, expression, openBracketToken, argumentExpression, closeBracketToken) {
                    _super.call(this, data);
                    this.expression = expression, this.openBracketToken = openBracketToken, this.argumentExpression = argumentExpression, this.closeBracketToken = closeBracketToken, expression.parent = this, openBracketToken.parent = this, argumentExpression.parent = this, closeBracketToken.parent = this;
                }
                return ElementAccessExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ElementAccessExpressionSyntax = ElementAccessExpressionSyntax;
            var FunctionExpressionSyntax = (function (_super) {
                __extends(FunctionExpressionSyntax, _super);
                function FunctionExpressionSyntax(data, functionKeyword, identifier, callSignature, block) {
                    _super.call(this, data);
                    this.functionKeyword = functionKeyword, this.identifier = identifier, this.callSignature = callSignature, this.block = block, functionKeyword.parent = this, identifier && (identifier.parent = this), callSignature.parent = this, block.parent = this;
                }
                return FunctionExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.FunctionExpressionSyntax = FunctionExpressionSyntax;
            var OmittedExpressionSyntax = (function (_super) {
                __extends(OmittedExpressionSyntax, _super);
                function OmittedExpressionSyntax(data) {
                    _super.call(this, data);
                }
                return OmittedExpressionSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.OmittedExpressionSyntax = OmittedExpressionSyntax;
            var VariableDeclarationSyntax = (function (_super) {
                __extends(VariableDeclarationSyntax, _super);
                function VariableDeclarationSyntax(data, varKeyword, variableDeclarators) {
                    _super.call(this, data);
                    this.varKeyword = varKeyword, this.variableDeclarators = variableDeclarators, varKeyword.parent = this, !TypeScript.isShared(variableDeclarators) && (variableDeclarators.parent = this);
                }
                return VariableDeclarationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.VariableDeclarationSyntax = VariableDeclarationSyntax;
            var VariableDeclaratorSyntax = (function (_super) {
                __extends(VariableDeclaratorSyntax, _super);
                function VariableDeclaratorSyntax(data, propertyName, typeAnnotation, equalsValueClause) {
                    _super.call(this, data);
                    this.propertyName = propertyName, this.typeAnnotation = typeAnnotation, this.equalsValueClause = equalsValueClause, propertyName.parent = this, typeAnnotation && (typeAnnotation.parent = this), equalsValueClause && (equalsValueClause.parent = this);
                }
                return VariableDeclaratorSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.VariableDeclaratorSyntax = VariableDeclaratorSyntax;
            var ArgumentListSyntax = (function (_super) {
                __extends(ArgumentListSyntax, _super);
                function ArgumentListSyntax(data, typeArgumentList, openParenToken, _arguments, closeParenToken) {
                    _super.call(this, data);
                    this.typeArgumentList = typeArgumentList, this.openParenToken = openParenToken, this.arguments = _arguments, this.closeParenToken = closeParenToken, typeArgumentList && (typeArgumentList.parent = this), openParenToken.parent = this, !TypeScript.isShared(_arguments) && (_arguments.parent = this), closeParenToken.parent = this;
                }
                return ArgumentListSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ArgumentListSyntax = ArgumentListSyntax;
            var ParameterListSyntax = (function (_super) {
                __extends(ParameterListSyntax, _super);
                function ParameterListSyntax(data, openParenToken, parameters, closeParenToken) {
                    _super.call(this, data);
                    this.openParenToken = openParenToken, this.parameters = parameters, this.closeParenToken = closeParenToken, openParenToken.parent = this, !TypeScript.isShared(parameters) && (parameters.parent = this), closeParenToken.parent = this;
                }
                return ParameterListSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ParameterListSyntax = ParameterListSyntax;
            var TypeArgumentListSyntax = (function (_super) {
                __extends(TypeArgumentListSyntax, _super);
                function TypeArgumentListSyntax(data, lessThanToken, typeArguments, greaterThanToken) {
                    _super.call(this, data);
                    this.lessThanToken = lessThanToken, this.typeArguments = typeArguments, this.greaterThanToken = greaterThanToken, lessThanToken.parent = this, !TypeScript.isShared(typeArguments) && (typeArguments.parent = this), greaterThanToken.parent = this;
                }
                return TypeArgumentListSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.TypeArgumentListSyntax = TypeArgumentListSyntax;
            var TypeParameterListSyntax = (function (_super) {
                __extends(TypeParameterListSyntax, _super);
                function TypeParameterListSyntax(data, lessThanToken, typeParameters, greaterThanToken) {
                    _super.call(this, data);
                    this.lessThanToken = lessThanToken, this.typeParameters = typeParameters, this.greaterThanToken = greaterThanToken, lessThanToken.parent = this, !TypeScript.isShared(typeParameters) && (typeParameters.parent = this), greaterThanToken.parent = this;
                }
                return TypeParameterListSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.TypeParameterListSyntax = TypeParameterListSyntax;
            var HeritageClauseSyntax = (function (_super) {
                __extends(HeritageClauseSyntax, _super);
                function HeritageClauseSyntax(data, extendsOrImplementsKeyword, typeNames) {
                    _super.call(this, data);
                    this.extendsOrImplementsKeyword = extendsOrImplementsKeyword, this.typeNames = typeNames, extendsOrImplementsKeyword.parent = this, !TypeScript.isShared(typeNames) && (typeNames.parent = this);
                }
                HeritageClauseSyntax.prototype.kind = function () {
                    return this.extendsOrImplementsKeyword.kind() === 48 /* ExtendsKeyword */ ? 230 /* ExtendsHeritageClause */ : 231 /* ImplementsHeritageClause */;
                };
                return HeritageClauseSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.HeritageClauseSyntax = HeritageClauseSyntax;
            var EqualsValueClauseSyntax = (function (_super) {
                __extends(EqualsValueClauseSyntax, _super);
                function EqualsValueClauseSyntax(data, equalsToken, value) {
                    _super.call(this, data);
                    this.equalsToken = equalsToken, this.value = value, equalsToken.parent = this, value.parent = this;
                }
                return EqualsValueClauseSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.EqualsValueClauseSyntax = EqualsValueClauseSyntax;
            var CaseSwitchClauseSyntax = (function (_super) {
                __extends(CaseSwitchClauseSyntax, _super);
                function CaseSwitchClauseSyntax(data, caseKeyword, expression, colonToken, statements) {
                    _super.call(this, data);
                    this.caseKeyword = caseKeyword, this.expression = expression, this.colonToken = colonToken, this.statements = statements, caseKeyword.parent = this, expression.parent = this, colonToken.parent = this, !TypeScript.isShared(statements) && (statements.parent = this);
                }
                return CaseSwitchClauseSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.CaseSwitchClauseSyntax = CaseSwitchClauseSyntax;
            var DefaultSwitchClauseSyntax = (function (_super) {
                __extends(DefaultSwitchClauseSyntax, _super);
                function DefaultSwitchClauseSyntax(data, defaultKeyword, colonToken, statements) {
                    _super.call(this, data);
                    this.defaultKeyword = defaultKeyword, this.colonToken = colonToken, this.statements = statements, defaultKeyword.parent = this, colonToken.parent = this, !TypeScript.isShared(statements) && (statements.parent = this);
                }
                return DefaultSwitchClauseSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.DefaultSwitchClauseSyntax = DefaultSwitchClauseSyntax;
            var ElseClauseSyntax = (function (_super) {
                __extends(ElseClauseSyntax, _super);
                function ElseClauseSyntax(data, elseKeyword, statement) {
                    _super.call(this, data);
                    this.elseKeyword = elseKeyword, this.statement = statement, elseKeyword.parent = this, statement.parent = this;
                }
                return ElseClauseSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ElseClauseSyntax = ElseClauseSyntax;
            var CatchClauseSyntax = (function (_super) {
                __extends(CatchClauseSyntax, _super);
                function CatchClauseSyntax(data, catchKeyword, openParenToken, identifier, typeAnnotation, closeParenToken, block) {
                    _super.call(this, data);
                    this.catchKeyword = catchKeyword, this.openParenToken = openParenToken, this.identifier = identifier, this.typeAnnotation = typeAnnotation, this.closeParenToken = closeParenToken, this.block = block, catchKeyword.parent = this, openParenToken.parent = this, identifier.parent = this, typeAnnotation && (typeAnnotation.parent = this), closeParenToken.parent = this, block.parent = this;
                }
                return CatchClauseSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.CatchClauseSyntax = CatchClauseSyntax;
            var FinallyClauseSyntax = (function (_super) {
                __extends(FinallyClauseSyntax, _super);
                function FinallyClauseSyntax(data, finallyKeyword, block) {
                    _super.call(this, data);
                    this.finallyKeyword = finallyKeyword, this.block = block, finallyKeyword.parent = this, block.parent = this;
                }
                return FinallyClauseSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.FinallyClauseSyntax = FinallyClauseSyntax;
            var TypeParameterSyntax = (function (_super) {
                __extends(TypeParameterSyntax, _super);
                function TypeParameterSyntax(data, identifier, constraint) {
                    _super.call(this, data);
                    this.identifier = identifier, this.constraint = constraint, identifier.parent = this, constraint && (constraint.parent = this);
                }
                return TypeParameterSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.TypeParameterSyntax = TypeParameterSyntax;
            var ConstraintSyntax = (function (_super) {
                __extends(ConstraintSyntax, _super);
                function ConstraintSyntax(data, extendsKeyword, type) {
                    _super.call(this, data);
                    this.extendsKeyword = extendsKeyword, this.type = type, extendsKeyword.parent = this, type.parent = this;
                }
                return ConstraintSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ConstraintSyntax = ConstraintSyntax;
            var SimplePropertyAssignmentSyntax = (function (_super) {
                __extends(SimplePropertyAssignmentSyntax, _super);
                function SimplePropertyAssignmentSyntax(data, propertyName, colonToken, expression) {
                    _super.call(this, data);
                    this.propertyName = propertyName, this.colonToken = colonToken, this.expression = expression, propertyName.parent = this, colonToken.parent = this, expression.parent = this;
                }
                return SimplePropertyAssignmentSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.SimplePropertyAssignmentSyntax = SimplePropertyAssignmentSyntax;
            var FunctionPropertyAssignmentSyntax = (function (_super) {
                __extends(FunctionPropertyAssignmentSyntax, _super);
                function FunctionPropertyAssignmentSyntax(data, propertyName, callSignature, block) {
                    _super.call(this, data);
                    this.propertyName = propertyName, this.callSignature = callSignature, this.block = block, propertyName.parent = this, callSignature.parent = this, block.parent = this;
                }
                return FunctionPropertyAssignmentSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.FunctionPropertyAssignmentSyntax = FunctionPropertyAssignmentSyntax;
            var ParameterSyntax = (function (_super) {
                __extends(ParameterSyntax, _super);
                function ParameterSyntax(data, dotDotDotToken, modifiers, identifier, questionToken, typeAnnotation, equalsValueClause) {
                    _super.call(this, data);
                    this.dotDotDotToken = dotDotDotToken, this.modifiers = modifiers, this.identifier = identifier, this.questionToken = questionToken, this.typeAnnotation = typeAnnotation, this.equalsValueClause = equalsValueClause, dotDotDotToken && (dotDotDotToken.parent = this), !TypeScript.isShared(modifiers) && (modifiers.parent = this), identifier.parent = this, questionToken && (questionToken.parent = this), typeAnnotation && (typeAnnotation.parent = this), equalsValueClause && (equalsValueClause.parent = this);
                }
                return ParameterSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ParameterSyntax = ParameterSyntax;
            var EnumElementSyntax = (function (_super) {
                __extends(EnumElementSyntax, _super);
                function EnumElementSyntax(data, propertyName, equalsValueClause) {
                    _super.call(this, data);
                    this.propertyName = propertyName, this.equalsValueClause = equalsValueClause, propertyName.parent = this, equalsValueClause && (equalsValueClause.parent = this);
                }
                return EnumElementSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.EnumElementSyntax = EnumElementSyntax;
            var TypeAnnotationSyntax = (function (_super) {
                __extends(TypeAnnotationSyntax, _super);
                function TypeAnnotationSyntax(data, colonToken, type) {
                    _super.call(this, data);
                    this.colonToken = colonToken, this.type = type, colonToken.parent = this, type.parent = this;
                }
                return TypeAnnotationSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.TypeAnnotationSyntax = TypeAnnotationSyntax;
            var ExternalModuleReferenceSyntax = (function (_super) {
                __extends(ExternalModuleReferenceSyntax, _super);
                function ExternalModuleReferenceSyntax(data, requireKeyword, openParenToken, stringLiteral, closeParenToken) {
                    _super.call(this, data);
                    this.requireKeyword = requireKeyword, this.openParenToken = openParenToken, this.stringLiteral = stringLiteral, this.closeParenToken = closeParenToken, requireKeyword.parent = this, openParenToken.parent = this, stringLiteral.parent = this, closeParenToken.parent = this;
                }
                return ExternalModuleReferenceSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ExternalModuleReferenceSyntax = ExternalModuleReferenceSyntax;
            var ModuleNameModuleReferenceSyntax = (function (_super) {
                __extends(ModuleNameModuleReferenceSyntax, _super);
                function ModuleNameModuleReferenceSyntax(data, moduleName) {
                    _super.call(this, data);
                    this.moduleName = moduleName, moduleName.parent = this;
                }
                return ModuleNameModuleReferenceSyntax;
            })(TypeScript.SyntaxNode);
            Concrete.ModuleNameModuleReferenceSyntax = ModuleNameModuleReferenceSyntax;

            SourceUnitSyntax.prototype.__kind = 120 /* SourceUnit */, QualifiedNameSyntax.prototype.__kind = 121 /* QualifiedName */, ObjectTypeSyntax.prototype.__kind = 122 /* ObjectType */, FunctionTypeSyntax.prototype.__kind = 123 /* FunctionType */, ArrayTypeSyntax.prototype.__kind = 124 /* ArrayType */, ConstructorTypeSyntax.prototype.__kind = 125 /* ConstructorType */, GenericTypeSyntax.prototype.__kind = 126 /* GenericType */, TypeQuerySyntax.prototype.__kind = 127 /* TypeQuery */, InterfaceDeclarationSyntax.prototype.__kind = 128 /* InterfaceDeclaration */, FunctionDeclarationSyntax.prototype.__kind = 129 /* FunctionDeclaration */, ModuleDeclarationSyntax.prototype.__kind = 130 /* ModuleDeclaration */, ClassDeclarationSyntax.prototype.__kind = 131 /* ClassDeclaration */, EnumDeclarationSyntax.prototype.__kind = 132 /* EnumDeclaration */, ImportDeclarationSyntax.prototype.__kind = 133 /* ImportDeclaration */, ExportAssignmentSyntax.prototype.__kind = 134 /* ExportAssignment */, MemberFunctionDeclarationSyntax.prototype.__kind = 135 /* MemberFunctionDeclaration */, MemberVariableDeclarationSyntax.prototype.__kind = 136 /* MemberVariableDeclaration */, ConstructorDeclarationSyntax.prototype.__kind = 137 /* ConstructorDeclaration */, IndexMemberDeclarationSyntax.prototype.__kind = 138 /* IndexMemberDeclaration */, GetAccessorSyntax.prototype.__kind = 139 /* GetAccessor */, SetAccessorSyntax.prototype.__kind = 140 /* SetAccessor */, PropertySignatureSyntax.prototype.__kind = 141 /* PropertySignature */, CallSignatureSyntax.prototype.__kind = 142 /* CallSignature */, ConstructSignatureSyntax.prototype.__kind = 143 /* ConstructSignature */, IndexSignatureSyntax.prototype.__kind = 144 /* IndexSignature */, MethodSignatureSyntax.prototype.__kind = 145 /* MethodSignature */, BlockSyntax.prototype.__kind = 146 /* Block */, IfStatementSyntax.prototype.__kind = 147 /* IfStatement */, VariableStatementSyntax.prototype.__kind = 148 /* VariableStatement */, ExpressionStatementSyntax.prototype.__kind = 149 /* ExpressionStatement */, ReturnStatementSyntax.prototype.__kind = 150 /* ReturnStatement */, SwitchStatementSyntax.prototype.__kind = 151 /* SwitchStatement */, BreakStatementSyntax.prototype.__kind = 152 /* BreakStatement */, ContinueStatementSyntax.prototype.__kind = 153 /* ContinueStatement */, ForStatementSyntax.prototype.__kind = 154 /* ForStatement */, ForInStatementSyntax.prototype.__kind = 155 /* ForInStatement */, EmptyStatementSyntax.prototype.__kind = 156 /* EmptyStatement */, ThrowStatementSyntax.prototype.__kind = 157 /* ThrowStatement */, WhileStatementSyntax.prototype.__kind = 158 /* WhileStatement */, TryStatementSyntax.prototype.__kind = 159 /* TryStatement */, LabeledStatementSyntax.prototype.__kind = 160 /* LabeledStatement */, DoStatementSyntax.prototype.__kind = 161 /* DoStatement */, DebuggerStatementSyntax.prototype.__kind = 162 /* DebuggerStatement */, WithStatementSyntax.prototype.__kind = 163 /* WithStatement */, DeleteExpressionSyntax.prototype.__kind = 170 /* DeleteExpression */, TypeOfExpressionSyntax.prototype.__kind = 171 /* TypeOfExpression */, VoidExpressionSyntax.prototype.__kind = 172 /* VoidExpression */, ConditionalExpressionSyntax.prototype.__kind = 186 /* ConditionalExpression */, MemberAccessExpressionSyntax.prototype.__kind = 212 /* MemberAccessExpression */, InvocationExpressionSyntax.prototype.__kind = 213 /* InvocationExpression */, ArrayLiteralExpressionSyntax.prototype.__kind = 214 /* ArrayLiteralExpression */, ObjectLiteralExpressionSyntax.prototype.__kind = 215 /* ObjectLiteralExpression */, ObjectCreationExpressionSyntax.prototype.__kind = 216 /* ObjectCreationExpression */, ParenthesizedExpressionSyntax.prototype.__kind = 217 /* ParenthesizedExpression */, ParenthesizedArrowFunctionExpressionSyntax.prototype.__kind = 218 /* ParenthesizedArrowFunctionExpression */, SimpleArrowFunctionExpressionSyntax.prototype.__kind = 219 /* SimpleArrowFunctionExpression */, CastExpressionSyntax.prototype.__kind = 220 /* CastExpression */, ElementAccessExpressionSyntax.prototype.__kind = 221 /* ElementAccessExpression */, FunctionExpressionSyntax.prototype.__kind = 222 /* FunctionExpression */, OmittedExpressionSyntax.prototype.__kind = 223 /* OmittedExpression */, VariableDeclarationSyntax.prototype.__kind = 224 /* VariableDeclaration */, VariableDeclaratorSyntax.prototype.__kind = 225 /* VariableDeclarator */, ArgumentListSyntax.prototype.__kind = 226 /* ArgumentList */, ParameterListSyntax.prototype.__kind = 227 /* ParameterList */, TypeArgumentListSyntax.prototype.__kind = 228 /* TypeArgumentList */, TypeParameterListSyntax.prototype.__kind = 229 /* TypeParameterList */, EqualsValueClauseSyntax.prototype.__kind = 232 /* EqualsValueClause */, CaseSwitchClauseSyntax.prototype.__kind = 233 /* CaseSwitchClause */, DefaultSwitchClauseSyntax.prototype.__kind = 234 /* DefaultSwitchClause */, ElseClauseSyntax.prototype.__kind = 235 /* ElseClause */, CatchClauseSyntax.prototype.__kind = 236 /* CatchClause */, FinallyClauseSyntax.prototype.__kind = 237 /* FinallyClause */, TypeParameterSyntax.prototype.__kind = 238 /* TypeParameter */, ConstraintSyntax.prototype.__kind = 239 /* Constraint */, SimplePropertyAssignmentSyntax.prototype.__kind = 240 /* SimplePropertyAssignment */, FunctionPropertyAssignmentSyntax.prototype.__kind = 241 /* FunctionPropertyAssignment */, ParameterSyntax.prototype.__kind = 242 /* Parameter */, EnumElementSyntax.prototype.__kind = 243 /* EnumElement */, TypeAnnotationSyntax.prototype.__kind = 244 /* TypeAnnotation */, ExternalModuleReferenceSyntax.prototype.__kind = 245 /* ExternalModuleReference */, ModuleNameModuleReferenceSyntax.prototype.__kind = 246 /* ModuleNameModuleReference */;
        })(Syntax.Concrete || (Syntax.Concrete = {}));
        var Concrete = Syntax.Concrete;
    })(TypeScript.Syntax || (TypeScript.Syntax = {}));
    var Syntax = TypeScript.Syntax;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    TypeScript.syntaxDiagnosticsTime = 0;

    var SyntaxTree = (function () {
        function SyntaxTree(isConcrete, sourceUnit, isDeclaration, diagnostics, fileName, text, languageVersion) {
            this.text = text;
            this._allDiagnostics = null;
            this._isConcrete = isConcrete;
            this._sourceUnit = sourceUnit;
            this._isDeclaration = isDeclaration;
            this._parserDiagnostics = diagnostics;
            this._fileName = fileName;
            this._lineMap = text.lineMap();
            this._languageVersion = languageVersion;

            sourceUnit.syntaxTree = this;
        }
        SyntaxTree.prototype.isConcrete = function () {
            return this._isConcrete;
        };

        SyntaxTree.prototype.sourceUnit = function () {
            return this._sourceUnit;
        };

        SyntaxTree.prototype.isDeclaration = function () {
            return this._isDeclaration;
        };

        SyntaxTree.prototype.computeDiagnostics = function () {
            if (this._parserDiagnostics.length > 0) {
                return this._parserDiagnostics;
            }

            // No parser reported diagnostics.  Check for any additional grammar diagnostics.
            var diagnostics = [];
            TypeScript.visitNodeOrToken(new GrammarCheckerWalker(this, diagnostics), this.sourceUnit());

            return diagnostics;
        };

        SyntaxTree.prototype.diagnostics = function () {
            if (this._allDiagnostics === null) {
                var start = new Date().getTime();
                this._allDiagnostics = this.computeDiagnostics();
                TypeScript.syntaxDiagnosticsTime += new Date().getTime() - start;
            }

            return this._allDiagnostics;
        };

        SyntaxTree.prototype.fileName = function () {
            return this._fileName;
        };

        SyntaxTree.prototype.lineMap = function () {
            return this._lineMap;
        };

        SyntaxTree.prototype.languageVersion = function () {
            return this._languageVersion;
        };

        SyntaxTree.prototype.cacheSyntaxTreeInfo = function () {
            // If we're not keeping around the syntax tree, store the diagnostics and line
            // map so they don't have to be recomputed.
            var sourceUnit = this.sourceUnit();
            var firstToken = firstSyntaxTreeToken(this);
            var leadingTrivia = firstToken.leadingTrivia(this.text);

            this._isExternalModule = externalModuleIndicatorSpanWorker(this, firstToken) !== null;

            var amdDependencies = [];
            for (var i = 0, n = leadingTrivia.count(); i < n; i++) {
                var trivia = leadingTrivia.syntaxTriviaAt(i);
                if (trivia.isComment()) {
                    var amdDependency = this.getAmdDependency(trivia.fullText());
                    if (amdDependency) {
                        amdDependencies.push(amdDependency);
                    }
                }
            }

            this._amdDependencies = amdDependencies;
        };

        SyntaxTree.prototype.getAmdDependency = function (comment) {
            var amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s+path=('|")(.+?)\1/gim;
            var match = amdDependencyRegEx.exec(comment);
            return match ? match[2] : null;
        };

        SyntaxTree.prototype.isExternalModule = function () {
            // October 11, 2013
            // External modules are written as separate source files that contain at least one
            // external import declaration, export assignment, or top-level exported declaration.
            if (this._isExternalModule === undefined) {
                // force the info about isExternalModule to get created.
                this.cacheSyntaxTreeInfo();
                TypeScript.Debug.assert(this._isExternalModule !== undefined);
            }

            return this._isExternalModule;
        };

        SyntaxTree.prototype.amdDependencies = function () {
            if (this._amdDependencies === undefined) {
                this.cacheSyntaxTreeInfo();
                TypeScript.Debug.assert(this._amdDependencies !== undefined);
            }

            return this._amdDependencies;
        };
        return SyntaxTree;
    })();
    TypeScript.SyntaxTree = SyntaxTree;

    var GrammarCheckerWalker = (function (_super) {
        __extends(GrammarCheckerWalker, _super);
        function GrammarCheckerWalker(syntaxTree, diagnostics) {
            _super.call(this);
            this.syntaxTree = syntaxTree;
            this.diagnostics = diagnostics;
            this.inAmbientDeclaration = false;
            this.inBlock = false;
            this.inObjectLiteralExpression = false;
            this.text = syntaxTree.text;
        }
        GrammarCheckerWalker.prototype.pushDiagnostic = function (element, diagnosticKey, args) {
            if (typeof args === "undefined") { args = null; }
            this.diagnostics.push(new TypeScript.Diagnostic(this.syntaxTree.fileName(), this.syntaxTree.lineMap(), TypeScript.start(element, this.text), TypeScript.width(element), diagnosticKey, args));
        };

        GrammarCheckerWalker.prototype.visitCatchClause = function (node) {
            if (this.checkForCatchClauseTypeAnnotation(node) || this.checkForDisallowedEvalOrArguments(node, node.identifier)) {
                return;
            }

            _super.prototype.visitCatchClause.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkForCatchClauseTypeAnnotation = function (node) {
            if (node.typeAnnotation) {
                this.pushDiagnostic(node.typeAnnotation.colonToken, TypeScript.DiagnosticCode.Catch_clause_parameter_cannot_have_a_type_annotation);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkParameterListOrder = function (node) {
            var seenOptionalParameter = false;
            var parameterCount = node.parameters.length;

            for (var i = 0; i < parameterCount; i++) {
                var parameter = node.parameters[i];

                if (parameter.dotDotDotToken) {
                    if (i !== (parameterCount - 1)) {
                        this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.A_rest_parameter_must_be_last_in_a_parameter_list);
                        return true;
                    }

                    if (parameter.questionToken) {
                        this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.A_rest_parameter_cannot_be_optional);
                        return true;
                    }

                    if (parameter.equalsValueClause) {
                        this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.A_rest_parameter_cannot_have_an_initializer);
                        return true;
                    }
                } else if (parameter.questionToken || parameter.equalsValueClause) {
                    seenOptionalParameter = true;

                    if (parameter.questionToken && parameter.equalsValueClause) {
                        this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.Parameter_cannot_have_question_mark_and_initializer);
                        return true;
                    }
                } else {
                    if (seenOptionalParameter) {
                        this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.A_required_parameter_cannot_follow_an_optional_parameter);
                        return true;
                    }
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkParameterListAcessibilityModifiers = function (node) {
            for (var i = 0, n = node.parameters.length; i < n; i++) {
                var parameter = node.parameters[i];

                if (this.checkParameterAccessibilityModifiers(node, parameter)) {
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkParameterAccessibilityModifiers = function (parameterList, parameter) {
            if (parameter.modifiers.length > 0) {
                var modifiers = parameter.modifiers;

                for (var i = 0, n = modifiers.length; i < n; i++) {
                    var modifier = modifiers[i];

                    if (this.checkParameterAccessibilityModifier(parameterList, modifier, i)) {
                        return true;
                    }
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkParameterAccessibilityModifier = function (parameterList, modifier, modifierIndex) {
            if (modifier.kind() !== 57 /* PublicKeyword */ && modifier.kind() !== 55 /* PrivateKeyword */) {
                this.pushDiagnostic(modifier, TypeScript.DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, [modifier.text()]);
                return true;
            } else {
                if (modifierIndex > 0) {
                    this.pushDiagnostic(modifier, TypeScript.DiagnosticCode.Accessibility_modifier_already_seen);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForTrailingSeparator = function (list) {
            // If we have at least one child, and we have an even number of children, then that
            // means we have an illegal trailing separator.
            if (TypeScript.childCount(list) === 0 || TypeScript.childCount(list) % 2 === 1) {
                return false;
            }

            var child = TypeScript.childAt(list, TypeScript.childCount(list) - 1);
            this.pushDiagnostic(child, TypeScript.DiagnosticCode.Trailing_separator_not_allowed);

            return true;
        };

        GrammarCheckerWalker.prototype.checkForAtLeastOneElement = function (parent, list, reportToken, listKind) {
            if (TypeScript.childCount(list) > 0) {
                return false;
            }

            this.pushDiagnostic(reportToken, TypeScript.DiagnosticCode._0_list_cannot_be_empty, [listKind]);
            return true;
        };

        GrammarCheckerWalker.prototype.visitParameterList = function (node) {
            if (this.checkParameterListAcessibilityModifiers(node) || this.checkParameterListOrder(node) || this.checkForTrailingSeparator(node.parameters)) {
                return;
            }

            _super.prototype.visitParameterList.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitHeritageClause = function (node) {
            if (this.checkForTrailingSeparator(node.typeNames) || this.checkForAtLeastOneElement(node, node.typeNames, node.extendsOrImplementsKeyword, TypeScript.SyntaxFacts.getText(node.extendsOrImplementsKeyword.kind()))) {
                return;
            }

            _super.prototype.visitHeritageClause.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitArgumentList = function (node) {
            if (this.checkForTrailingSeparator(node.arguments)) {
                return;
            }

            _super.prototype.visitArgumentList.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitVariableDeclaration = function (node) {
            if (this.checkForAtLeastOneElement(node, node.variableDeclarators, node.varKeyword, TypeScript.getLocalizedText(TypeScript.DiagnosticCode.variable_declaration, null)) || this.checkForTrailingSeparator(node.variableDeclarators)) {
                return;
            }

            _super.prototype.visitVariableDeclaration.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitTypeArgumentList = function (node) {
            if (this.checkForTrailingSeparator(node.typeArguments) || this.checkForAtLeastOneElement(node, node.typeArguments, node.lessThanToken, TypeScript.getLocalizedText(TypeScript.DiagnosticCode.type_argument, null))) {
                return;
            }

            _super.prototype.visitTypeArgumentList.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitTypeParameterList = function (node) {
            if (this.checkForTrailingSeparator(node.typeParameters) || this.checkForAtLeastOneElement(node, node.typeParameters, node.lessThanToken, TypeScript.getLocalizedText(TypeScript.DiagnosticCode.type_parameter, null))) {
                return;
            }

            _super.prototype.visitTypeParameterList.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkIndexSignatureParameter = function (node) {
            if (node.parameters.length !== 1) {
                this.pushDiagnostic(node.openBracketToken, TypeScript.DiagnosticCode.Index_signature_must_have_exactly_one_parameter);
                return true;
            }

            var parameter = node.parameters[0];

            if (parameter.dotDotDotToken) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.Index_signatures_cannot_have_rest_parameters);
                return true;
            } else if (parameter.modifiers.length > 0) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.Index_signature_parameter_cannot_have_accessibility_modifiers);
                return true;
            } else if (parameter.questionToken) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.Index_signature_parameter_cannot_have_a_question_mark);
                return true;
            } else if (parameter.equalsValueClause) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.Index_signature_parameter_cannot_have_an_initializer);
                return true;
            } else if (!parameter.typeAnnotation) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.Index_signature_parameter_must_have_a_type_annotation);
                return true;
            } else if (parameter.typeAnnotation.type.kind() !== 69 /* StringKeyword */ && parameter.typeAnnotation.type.kind() !== 67 /* NumberKeyword */) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.Index_signature_parameter_type_must_be_string_or_number);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitIndexSignature = function (node) {
            if (this.checkIndexSignatureParameter(node)) {
                return;
            }

            if (!node.typeAnnotation) {
                this.pushDiagnostic(node, TypeScript.DiagnosticCode.Index_signature_must_have_a_type_annotation);
                return;
            }

            _super.prototype.visitIndexSignature.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkClassDeclarationHeritageClauses = function (node) {
            var seenExtendsClause = false;
            var seenImplementsClause = false;

            for (var i = 0, n = node.heritageClauses.length; i < n; i++) {
                TypeScript.Debug.assert(i <= 2);
                var heritageClause = node.heritageClauses[i];

                if (heritageClause.extendsOrImplementsKeyword.kind() === 48 /* ExtendsKeyword */) {
                    if (seenExtendsClause) {
                        this.pushDiagnostic(heritageClause, TypeScript.DiagnosticCode.extends_clause_already_seen);
                        return true;
                    }

                    if (seenImplementsClause) {
                        this.pushDiagnostic(heritageClause, TypeScript.DiagnosticCode.extends_clause_must_precede_implements_clause);
                        return true;
                    }

                    if (heritageClause.typeNames.length > 1) {
                        this.pushDiagnostic(heritageClause, TypeScript.DiagnosticCode.Classes_can_only_extend_a_single_class);
                        return true;
                    }

                    seenExtendsClause = true;
                } else {
                    TypeScript.Debug.assert(heritageClause.extendsOrImplementsKeyword.kind() === 51 /* ImplementsKeyword */);
                    if (seenImplementsClause) {
                        this.pushDiagnostic(heritageClause, TypeScript.DiagnosticCode.implements_clause_already_seen);
                        return true;
                    }

                    seenImplementsClause = true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForDisallowedDeclareModifier = function (modifiers) {
            if (this.inAmbientDeclaration) {
                // If we're already in an ambient declaration, then 'declare' is not allowed.
                var declareToken = TypeScript.SyntaxUtilities.getToken(modifiers, 63 /* DeclareKeyword */);

                if (declareToken) {
                    this.pushDiagnostic(declareToken, TypeScript.DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForRequiredDeclareModifier = function (moduleElement, reportToken, modifiers) {
            if (!this.inAmbientDeclaration && this.syntaxTree.isDeclaration()) {
                // We're at the top level in a declaration file, a 'declare' modifiers is required
                // on most module elements.
                if (!TypeScript.SyntaxUtilities.containsToken(modifiers, 63 /* DeclareKeyword */)) {
                    this.pushDiagnostic(reportToken, TypeScript.DiagnosticCode.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file);
                    return true;
                }
            }
        };

        GrammarCheckerWalker.prototype.visitClassDeclaration = function (node) {
            if (this.checkForDisallowedDeclareModifier(node.modifiers) || this.checkForRequiredDeclareModifier(node, node.identifier, node.modifiers) || this.checkModuleElementModifiers(node.modifiers) || this.checkClassDeclarationHeritageClauses(node)) {
                return;
            }

            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = this.inAmbientDeclaration || this.syntaxTree.isDeclaration() || TypeScript.SyntaxUtilities.containsToken(node.modifiers, 63 /* DeclareKeyword */);
            _super.prototype.visitClassDeclaration.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.checkInterfaceDeclarationHeritageClauses = function (node) {
            var seenExtendsClause = false;

            for (var i = 0, n = node.heritageClauses.length; i < n; i++) {
                TypeScript.Debug.assert(i <= 1);
                var heritageClause = node.heritageClauses[i];

                if (heritageClause.extendsOrImplementsKeyword.kind() === 48 /* ExtendsKeyword */) {
                    if (seenExtendsClause) {
                        this.pushDiagnostic(heritageClause, TypeScript.DiagnosticCode.extends_clause_already_seen);
                        return true;
                    }

                    seenExtendsClause = true;
                } else {
                    TypeScript.Debug.assert(heritageClause.extendsOrImplementsKeyword.kind() === 51 /* ImplementsKeyword */);
                    this.pushDiagnostic(heritageClause, TypeScript.DiagnosticCode.Interface_declaration_cannot_have_implements_clause);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkInterfaceModifiers = function (modifiers) {
            for (var i = 0, n = modifiers.length; i < n; i++) {
                var modifier = modifiers[i];
                if (modifier.kind() === 63 /* DeclareKeyword */) {
                    this.pushDiagnostic(modifier, TypeScript.DiagnosticCode.A_declare_modifier_cannot_be_used_with_an_interface_declaration);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitInterfaceDeclaration = function (node) {
            if (this.checkInterfaceModifiers(node.modifiers) || this.checkModuleElementModifiers(node.modifiers) || this.checkInterfaceDeclarationHeritageClauses(node)) {
                return;
            }

            _super.prototype.visitInterfaceDeclaration.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkClassElementModifiers = function (list) {
            var seenAccessibilityModifier = false;
            var seenStaticModifier = false;

            for (var i = 0, n = list.length; i < n; i++) {
                var modifier = list[i];
                if (modifier.kind() === 57 /* PublicKeyword */ || modifier.kind() === 55 /* PrivateKeyword */) {
                    if (seenAccessibilityModifier) {
                        this.pushDiagnostic(modifier, TypeScript.DiagnosticCode.Accessibility_modifier_already_seen);
                        return true;
                    }

                    if (seenStaticModifier) {
                        var previousToken = list[i - 1];
                        this.pushDiagnostic(modifier, TypeScript.DiagnosticCode._0_modifier_must_precede_1_modifier, [modifier.text(), previousToken.text()]);
                        return true;
                    }

                    seenAccessibilityModifier = true;
                } else if (modifier.kind() === 58 /* StaticKeyword */) {
                    if (seenStaticModifier) {
                        this.pushDiagnostic(modifier, TypeScript.DiagnosticCode._0_modifier_already_seen, [modifier.text()]);
                        return true;
                    }

                    seenStaticModifier = true;
                } else {
                    this.pushDiagnostic(modifier, TypeScript.DiagnosticCode._0_modifier_cannot_appear_on_a_class_element, [modifier.text()]);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitMemberVariableDeclaration = function (node) {
            if (this.checkClassElementModifiers(node.modifiers)) {
                return;
            }

            _super.prototype.visitMemberVariableDeclaration.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitMemberFunctionDeclaration = function (node) {
            if (this.checkClassElementModifiers(node.modifiers)) {
                return;
            }

            _super.prototype.visitMemberFunctionDeclaration.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkGetAccessorParameter = function (node) {
            if (node.callSignature.parameterList.parameters.length !== 0) {
                this.pushDiagnostic(node.propertyName, TypeScript.DiagnosticCode.get_accessor_cannot_have_parameters);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitIndexMemberDeclaration = function (node) {
            if (this.checkIndexMemberModifiers(node)) {
                return;
            }

            _super.prototype.visitIndexMemberDeclaration.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkIndexMemberModifiers = function (node) {
            if (node.modifiers.length > 0) {
                this.pushDiagnostic(TypeScript.childAt(node.modifiers, 0), TypeScript.DiagnosticCode.Modifiers_cannot_appear_here);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkEcmaScriptVersionIsAtLeast = function (parent, reportToken, languageVersion, diagnosticKey) {
            if (this.syntaxTree.languageVersion() < languageVersion) {
                this.pushDiagnostic(reportToken, diagnosticKey);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitObjectLiteralExpression = function (node) {
            var savedInObjectLiteralExpression = this.inObjectLiteralExpression;
            this.inObjectLiteralExpression = true;
            _super.prototype.visitObjectLiteralExpression.call(this, node);
            this.inObjectLiteralExpression = savedInObjectLiteralExpression;
        };

        GrammarCheckerWalker.prototype.visitGetAccessor = function (node) {
            if (this.checkForAccessorDeclarationInAmbientContext(node) || this.checkEcmaScriptVersionIsAtLeast(node, node.propertyName, 1 /* EcmaScript5 */, TypeScript.DiagnosticCode.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher) || this.checkForDisallowedModifiers(node, node.modifiers) || this.checkClassElementModifiers(node.modifiers) || this.checkForDisallowedAccessorTypeParameters(node.callSignature) || this.checkGetAccessorParameter(node)) {
                return;
            }

            _super.prototype.visitGetAccessor.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkForDisallowedSetAccessorTypeAnnotation = function (accessor) {
            if (accessor.callSignature.typeAnnotation) {
                this.pushDiagnostic(accessor.callSignature.typeAnnotation, TypeScript.DiagnosticCode.Type_annotation_cannot_appear_on_a_set_accessor);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForDisallowedAccessorTypeParameters = function (callSignature) {
            if (callSignature.typeParameterList !== null) {
                this.pushDiagnostic(callSignature.typeParameterList, TypeScript.DiagnosticCode.Type_parameters_cannot_appear_on_an_accessor);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForAccessorDeclarationInAmbientContext = function (accessor) {
            if (this.inAmbientDeclaration) {
                this.pushDiagnostic(accessor, TypeScript.DiagnosticCode.Accessors_are_not_allowed_in_ambient_contexts);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkSetAccessorParameter = function (node) {
            var parameters = node.callSignature.parameterList.parameters;
            if (TypeScript.childCount(parameters) !== 1) {
                this.pushDiagnostic(node.propertyName, TypeScript.DiagnosticCode.set_accessor_must_have_exactly_one_parameter);
                return true;
            }

            var parameter = parameters[0];

            if (parameter.questionToken) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.set_accessor_parameter_cannot_be_optional);
                return true;
            }

            if (parameter.equalsValueClause) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.set_accessor_parameter_cannot_have_an_initializer);
                return true;
            }

            if (parameter.dotDotDotToken) {
                this.pushDiagnostic(parameter, TypeScript.DiagnosticCode.set_accessor_cannot_have_rest_parameter);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitSetAccessor = function (node) {
            if (this.checkForAccessorDeclarationInAmbientContext(node) || this.checkEcmaScriptVersionIsAtLeast(node, node.propertyName, 1 /* EcmaScript5 */, TypeScript.DiagnosticCode.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher) || this.checkForDisallowedModifiers(node, node.modifiers) || this.checkClassElementModifiers(node.modifiers) || this.checkForDisallowedAccessorTypeParameters(node.callSignature) || this.checkForDisallowedSetAccessorTypeAnnotation(node) || this.checkSetAccessorParameter(node)) {
                return;
            }

            _super.prototype.visitSetAccessor.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitEnumDeclaration = function (node) {
            if (this.checkForDisallowedDeclareModifier(node.modifiers) || this.checkForRequiredDeclareModifier(node, node.identifier, node.modifiers) || this.checkModuleElementModifiers(node.modifiers), this.checkEnumElements(node)) {
                return;
            }

            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = this.inAmbientDeclaration || this.syntaxTree.isDeclaration() || TypeScript.SyntaxUtilities.containsToken(node.modifiers, 63 /* DeclareKeyword */);
            _super.prototype.visitEnumDeclaration.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.checkEnumElements = function (node) {
            var previousValueWasComputed = false;
            for (var i = 0, n = TypeScript.childCount(node.enumElements); i < n; i++) {
                var child = TypeScript.childAt(node.enumElements, i);

                if (i % 2 === 0) {
                    var enumElement = child;

                    if (!enumElement.equalsValueClause && previousValueWasComputed) {
                        this.pushDiagnostic(enumElement, TypeScript.DiagnosticCode.Enum_member_must_have_initializer);
                        return true;
                    }

                    if (enumElement.equalsValueClause) {
                        var value = enumElement.equalsValueClause.value;
                        previousValueWasComputed = !TypeScript.Syntax.isIntegerLiteral(value);
                    }
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitEnumElement = function (node) {
            if (this.inAmbientDeclaration && node.equalsValueClause) {
                var expression = node.equalsValueClause.value;
                if (!TypeScript.Syntax.isIntegerLiteral(expression)) {
                    this.pushDiagnostic(node.equalsValueClause.value, TypeScript.DiagnosticCode.Ambient_enum_elements_can_only_have_integer_literal_initializers);
                    return;
                }
            }

            _super.prototype.visitEnumElement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitInvocationExpression = function (node) {
            if (node.expression.kind() === 50 /* SuperKeyword */ && node.argumentList.typeArgumentList !== null) {
                this.pushDiagnostic(node, TypeScript.DiagnosticCode.super_invocation_cannot_have_type_arguments);
            }

            _super.prototype.visitInvocationExpression.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkModuleElementModifiers = function (modifiers) {
            var seenExportModifier = false;
            var seenDeclareModifier = false;

            for (var i = 0, n = modifiers.length; i < n; i++) {
                var modifier = modifiers[i];
                if (modifier.kind() === 57 /* PublicKeyword */ || modifier.kind() === 55 /* PrivateKeyword */ || modifier.kind() === 58 /* StaticKeyword */) {
                    this.pushDiagnostic(modifier, TypeScript.DiagnosticCode._0_modifier_cannot_appear_on_a_module_element, [modifier.text()]);
                    return true;
                }

                if (modifier.kind() === 63 /* DeclareKeyword */) {
                    if (seenDeclareModifier) {
                        this.pushDiagnostic(modifier, TypeScript.DiagnosticCode.Accessibility_modifier_already_seen);
                        return;
                    }

                    seenDeclareModifier = true;
                } else if (modifier.kind() === 47 /* ExportKeyword */) {
                    if (seenExportModifier) {
                        this.pushDiagnostic(modifier, TypeScript.DiagnosticCode._0_modifier_already_seen, [modifier.text()]);
                        return;
                    }

                    if (seenDeclareModifier) {
                        this.pushDiagnostic(modifier, TypeScript.DiagnosticCode._0_modifier_must_precede_1_modifier, [TypeScript.SyntaxFacts.getText(47 /* ExportKeyword */), TypeScript.SyntaxFacts.getText(63 /* DeclareKeyword */)]);
                        return;
                    }

                    seenExportModifier = true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForDisallowedImportDeclaration = function (node) {
            if (!node.stringLiteral) {
                for (var i = 0, n = node.moduleElements.length; i < n; i++) {
                    var child = node.moduleElements[i];
                    if (child.kind() === 133 /* ImportDeclaration */) {
                        var importDeclaration = child;
                        if (importDeclaration.moduleReference.kind() === 245 /* ExternalModuleReference */) {
                            this.pushDiagnostic(importDeclaration, TypeScript.DiagnosticCode.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
                        }
                    }
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForDisallowedDeclareModifierOnImportDeclaration = function (modifiers) {
            var declareToken = TypeScript.SyntaxUtilities.getToken(modifiers, 63 /* DeclareKeyword */);

            if (declareToken) {
                this.pushDiagnostic(declareToken, TypeScript.DiagnosticCode.A_declare_modifier_cannot_be_used_with_an_import_declaration);
                return true;
            }
        };

        GrammarCheckerWalker.prototype.visitImportDeclaration = function (node) {
            if (this.checkForDisallowedDeclareModifierOnImportDeclaration(node.modifiers) || this.checkModuleElementModifiers(node.modifiers)) {
                return;
            }

            _super.prototype.visitImportDeclaration.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitModuleDeclaration = function (node) {
            if (this.checkForDisallowedDeclareModifier(node.modifiers) || this.checkForRequiredDeclareModifier(node, node.stringLiteral ? node.stringLiteral : TypeScript.firstToken(node.name), node.modifiers) || this.checkModuleElementModifiers(node.modifiers) || this.checkForDisallowedImportDeclaration(node)) {
                return;
            }

            if (node.stringLiteral) {
                if (!this.inAmbientDeclaration && !TypeScript.SyntaxUtilities.containsToken(node.modifiers, 63 /* DeclareKeyword */)) {
                    this.pushDiagnostic(node.stringLiteral, TypeScript.DiagnosticCode.Only_ambient_modules_can_use_quoted_names);
                    return;
                }
            }

            if (!node.stringLiteral && this.checkForDisallowedExportAssignment(node)) {
                return;
            }

            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = this.inAmbientDeclaration || this.syntaxTree.isDeclaration() || TypeScript.SyntaxUtilities.containsToken(node.modifiers, 63 /* DeclareKeyword */);
            _super.prototype.visitModuleDeclaration.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.checkForDisallowedExportAssignment = function (node) {
            for (var i = 0, n = node.moduleElements.length; i < n; i++) {
                var child = node.moduleElements[i];

                if (child.kind() === 134 /* ExportAssignment */) {
                    this.pushDiagnostic(child, TypeScript.DiagnosticCode.Export_assignment_cannot_be_used_in_internal_modules);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitBlock = function (node) {
            if (this.checkForBlockInAmbientContext(node)) {
                return;
            }

            var savedInBlock = this.inBlock;
            this.inBlock = true;
            _super.prototype.visitBlock.call(this, node);
            this.inBlock = savedInBlock;
        };

        GrammarCheckerWalker.prototype.checkForBlockInAmbientContext = function (node) {
            if (this.inAmbientDeclaration || this.syntaxTree.isDeclaration()) {
                // Provide a specialized message for a block as a statement versus the block as a
                // function body.
                if (node.parent.kind() === 1 /* List */) {
                    this.pushDiagnostic(TypeScript.firstToken(node), TypeScript.DiagnosticCode.Statements_are_not_allowed_in_ambient_contexts);
                } else {
                    this.pushDiagnostic(TypeScript.firstToken(node), TypeScript.DiagnosticCode.A_function_implementation_cannot_be_declared_in_an_ambient_context);
                }

                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForStatementInAmbientContxt = function (node) {
            if (this.inAmbientDeclaration || this.syntaxTree.isDeclaration()) {
                this.pushDiagnostic(TypeScript.firstToken(node), TypeScript.DiagnosticCode.Statements_are_not_allowed_in_ambient_contexts);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitBreakStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node) || this.checkBreakStatementTarget(node)) {
                return;
            }

            _super.prototype.visitBreakStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitContinueStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node) || this.checkContinueStatementTarget(node)) {
                return;
            }

            _super.prototype.visitContinueStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkBreakStatementTarget = function (node) {
            // Invalid break statements are considered syntax errors in ES5.
            // Note: the order here is important.  If the 'break' has a target, then it can jump to
            // any enclosing laballed statment.  If it has no target, it must be in an iteration or
            // swtich statement.
            if (node.identifier) {
                var breakableLabels = this.getEnclosingLabels(node, true, false);

                if (!TypeScript.ArrayUtilities.any(breakableLabels, function (s) {
                    return TypeScript.tokenValueText(s.identifier) === TypeScript.tokenValueText(node.identifier);
                })) {
                    // The target of the continue statement wasn't to a reachable label.
                    //
                    // Let hte user know, with a specialized message if the target was to an
                    // unreachable label (as opposed to a non-existed label)
                    var breakableLabels = this.getEnclosingLabels(node, true, true);
                    if (TypeScript.ArrayUtilities.any(breakableLabels, function (s) {
                        return TypeScript.tokenValueText(s.identifier) === TypeScript.tokenValueText(node.identifier);
                    })) {
                        this.pushDiagnostic(node, TypeScript.DiagnosticCode.Jump_target_cannot_cross_function_boundary);
                    } else {
                        this.pushDiagnostic(node, TypeScript.DiagnosticCode.Jump_target_not_found);
                    }

                    return true;
                }
            } else if (!this.inIterationStatement(node, false) && !this.inSwitchStatement(node)) {
                if (this.inIterationStatement(node, true)) {
                    this.pushDiagnostic(node, TypeScript.DiagnosticCode.Jump_target_cannot_cross_function_boundary);
                } else {
                    this.pushDiagnostic(node, TypeScript.DiagnosticCode.break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement);
                }

                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.inSwitchStatement = function (ast) {
            while (ast) {
                if (ast.kind() === 151 /* SwitchStatement */) {
                    return true;
                }

                if (TypeScript.SyntaxUtilities.isAnyFunctionExpressionOrDeclaration(ast)) {
                    return false;
                }

                ast = ast.parent;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.isIterationStatement = function (ast) {
            switch (ast.kind()) {
                case 154 /* ForStatement */:
                case 155 /* ForInStatement */:
                case 158 /* WhileStatement */:
                case 161 /* DoStatement */:
                    return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.inIterationStatement = function (element, crossFunctions) {
            while (element) {
                if (this.isIterationStatement(element)) {
                    return true;
                }

                if (!crossFunctions && TypeScript.SyntaxUtilities.isAnyFunctionExpressionOrDeclaration(element)) {
                    return false;
                }

                element = element.parent;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.getEnclosingLabels = function (element, breakable, crossFunctions) {
            var result = [];

            element = element.parent;
            while (element) {
                if (element.kind() === 160 /* LabeledStatement */) {
                    var labeledStatement = element;
                    if (breakable) {
                        // Breakable labels can be placed on any construct
                        result.push(labeledStatement);
                    } else {
                        // They're asking for continuable labels.  Continuable labels must be on
                        // a loop construct.
                        if (this.labelIsOnContinuableConstruct(labeledStatement.statement)) {
                            result.push(labeledStatement);
                        }
                    }
                }

                if (!crossFunctions && TypeScript.SyntaxUtilities.isAnyFunctionExpressionOrDeclaration(element)) {
                    break;
                }

                element = element.parent;
            }

            return result;
        };

        GrammarCheckerWalker.prototype.labelIsOnContinuableConstruct = function (statement) {
            switch (statement.kind()) {
                case 160 /* LabeledStatement */:
                    // Labels work transitively.  i.e. if you have:
                    //      foo:
                    //      bar:
                    //      while(...)
                    //
                    // Then both 'foo' and 'bar' are in the label set for 'while' and are thus
                    // continuable.
                    return this.labelIsOnContinuableConstruct(statement.statement);

                case 158 /* WhileStatement */:
                case 154 /* ForStatement */:
                case 155 /* ForInStatement */:
                case 161 /* DoStatement */:
                    return true;

                default:
                    return false;
            }
        };

        GrammarCheckerWalker.prototype.checkContinueStatementTarget = function (node) {
            // Invalid continue statements are considered syntax errors in ES5.
            if (!this.inIterationStatement(node, false)) {
                if (this.inIterationStatement(node, true)) {
                    this.pushDiagnostic(node, TypeScript.DiagnosticCode.Jump_target_cannot_cross_function_boundary);
                } else {
                    this.pushDiagnostic(node, TypeScript.DiagnosticCode.continue_statement_can_only_be_used_within_an_enclosing_iteration_statement);
                }

                return true;
            } else if (node.identifier) {
                var continuableLabels = this.getEnclosingLabels(node, false, false);

                if (!TypeScript.ArrayUtilities.any(continuableLabels, function (s) {
                    return TypeScript.tokenValueText(s.identifier) === TypeScript.tokenValueText(node.identifier);
                })) {
                    // The target of the continue statement wasn't to a reachable label.
                    //
                    // Let hte user know, with a specialized message if the target was to an
                    // unreachable label (as opposed to a non-existed label)
                    var continuableLabels = this.getEnclosingLabels(node, false, true);

                    if (TypeScript.ArrayUtilities.any(continuableLabels, function (s) {
                        return TypeScript.tokenValueText(s.identifier) === TypeScript.tokenValueText(node.identifier);
                    })) {
                        this.pushDiagnostic(node, TypeScript.DiagnosticCode.Jump_target_cannot_cross_function_boundary);
                    } else {
                        this.pushDiagnostic(node, TypeScript.DiagnosticCode.Jump_target_not_found);
                    }

                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitDebuggerStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitDebuggerStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitDoStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitDoStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitEmptyStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitEmptyStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitExpressionStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitExpressionStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitForInStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node) || this.checkForInStatementVariableDeclaration(node) || this.checkForInLeftHandSideExpression(node)) {
                return;
            }

            _super.prototype.visitForInStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkForInLeftHandSideExpression = function (node) {
            if (node.left && !TypeScript.SyntaxUtilities.isLeftHandSizeExpression(node.left)) {
                this.pushDiagnostic(node.left, TypeScript.DiagnosticCode.Invalid_left_hand_side_in_for_in_statement);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForInStatementVariableDeclaration = function (node) {
            // The parser accepts a Variable Declaration in a ForInStatement, but the grammar only
            // allows a very restricted form.  Specifically, there must be only a single Variable
            // Declarator in the Declaration.
            if (node.variableDeclaration && node.variableDeclaration.variableDeclarators.length > 1) {
                this.pushDiagnostic(node.variableDeclaration, TypeScript.DiagnosticCode.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitForStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitForStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitIfStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitIfStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitLabeledStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node) || this.checkForInvalidLabelIdentifier(node)) {
                return;
            }

            _super.prototype.visitLabeledStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkForInvalidLabelIdentifier = function (node) {
            // Invalid break statements are considered syntax errors in ES5.
            // Note that break/continue are treated differently.  ES5 says this about a break statement:
            // A program is considered syntactically incorrect if ...:
            //
            // The program contains a break statement with the optional Identifier, where Identifier
            // does not appear in the label set of an enclosing (but not crossing function boundaries)
            // **Statement.**
            //
            // However, it says this about continue statements:
            //
            // The program contains a continue statement with the optional Identifier, where Identifier
            // does not appear in the label set of an enclosing (but not crossing function boundaries)
            // **IterationStatement.**
            // In other words, you can 'break' to any enclosing statement.  But you can only 'continue'
            // to an enclosing *iteration* statement.
            var labelIdentifier = TypeScript.tokenValueText(node.identifier);

            var breakableLabels = this.getEnclosingLabels(node, true, false);

            // It is invalid to have a label enclosed in a label of the same name.
            var matchingLabel = TypeScript.ArrayUtilities.firstOrDefault(breakableLabels, function (s) {
                return TypeScript.tokenValueText(s.identifier) === labelIdentifier;
            });
            if (matchingLabel) {
                this.pushDiagnostic(node.identifier, TypeScript.DiagnosticCode.Duplicate_identifier_0, [labelIdentifier]);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitReturnStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node) || this.checkForReturnStatementNotInFunctionBody(node)) {
                return;
            }

            _super.prototype.visitReturnStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkForReturnStatementNotInFunctionBody = function (node) {
            for (var element = node; element; element = element.parent) {
                if (TypeScript.SyntaxUtilities.isAnyFunctionExpressionOrDeclaration(element)) {
                    return false;
                }
            }

            this.pushDiagnostic(TypeScript.firstToken(node), TypeScript.DiagnosticCode.return_statement_must_be_contained_within_a_function_body);
            return true;
        };

        GrammarCheckerWalker.prototype.visitSwitchStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitSwitchStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitThrowStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitThrowStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitTryStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitTryStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitWhileStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node)) {
                return;
            }

            _super.prototype.visitWhileStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitWithStatement = function (node) {
            if (this.checkForStatementInAmbientContxt(node) || this.checkForWithInStrictMode(node)) {
                return;
            }

            _super.prototype.visitWithStatement.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkForWithInStrictMode = function (node) {
            if (TypeScript.parsedInStrictMode(node)) {
                this.pushDiagnostic(TypeScript.firstToken(node), TypeScript.DiagnosticCode.with_statements_are_not_allowed_in_strict_mode);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkForDisallowedModifiers = function (parent, modifiers) {
            if (this.inBlock || this.inObjectLiteralExpression) {
                if (modifiers.length > 0) {
                    this.pushDiagnostic(TypeScript.childAt(modifiers, 0), TypeScript.DiagnosticCode.Modifiers_cannot_appear_here);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitFunctionDeclaration = function (node) {
            if (this.checkForDisallowedDeclareModifier(node.modifiers) || this.checkForDisallowedModifiers(node, node.modifiers) || this.checkForRequiredDeclareModifier(node, node.identifier, node.modifiers) || this.checkModuleElementModifiers(node.modifiers) || this.checkForDisallowedEvalOrArguments(node, node.identifier)) {
                return;
            }

            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = this.inAmbientDeclaration || this.syntaxTree.isDeclaration() || TypeScript.SyntaxUtilities.containsToken(node.modifiers, 63 /* DeclareKeyword */);
            _super.prototype.visitFunctionDeclaration.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.visitFunctionExpression = function (node) {
            if (this.checkForDisallowedEvalOrArguments(node, node.identifier)) {
                return;
            }

            _super.prototype.visitFunctionExpression.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitVariableStatement = function (node) {
            if (this.checkForDisallowedDeclareModifier(node.modifiers) || this.checkForDisallowedModifiers(node, node.modifiers) || this.checkForRequiredDeclareModifier(node, node.variableDeclaration.varKeyword, node.modifiers) || this.checkModuleElementModifiers(node.modifiers)) {
                return;
            }

            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = this.inAmbientDeclaration || this.syntaxTree.isDeclaration() || TypeScript.SyntaxUtilities.containsToken(node.modifiers, 63 /* DeclareKeyword */);
            _super.prototype.visitVariableStatement.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.checkListSeparators = function (parent, list, kind) {
            for (var i = 0, n = TypeScript.childCount(list); i < n; i++) {
                var child = TypeScript.childAt(list, i);
                if (i % 2 === 1 && child.kind() !== kind) {
                    this.pushDiagnostic(child, TypeScript.DiagnosticCode._0_expected, [TypeScript.SyntaxFacts.getText(kind)]);
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitObjectType = function (node) {
            if (this.checkListSeparators(node, node.typeMembers, 78 /* SemicolonToken */)) {
                return;
            }

            // All code in an object type is implicitly ambient. (i.e. parameters can't have initializer, etc.)
            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = true;
            _super.prototype.visitObjectType.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.visitArrayType = function (node) {
            // All code in an object type is implicitly ambient. (i.e. parameters can't have initializer, etc.)
            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = true;
            _super.prototype.visitArrayType.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.visitFunctionType = function (node) {
            // All code in an object type is implicitly ambient. (i.e. parameters can't have initializer, etc.)
            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = true;
            _super.prototype.visitFunctionType.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.visitConstructorType = function (node) {
            // All code in an object type is implicitly ambient. (i.e. parameters can't have initializer, etc.)
            var savedInAmbientDeclaration = this.inAmbientDeclaration;
            this.inAmbientDeclaration = true;
            _super.prototype.visitConstructorType.call(this, node);
            this.inAmbientDeclaration = savedInAmbientDeclaration;
        };

        GrammarCheckerWalker.prototype.visitVariableDeclarator = function (node) {
            if (this.checkVariableDeclaratorInitializer(node) || this.checkVariableDeclaratorIdentifier(node)) {
                return;
            }

            _super.prototype.visitVariableDeclarator.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkVariableDeclaratorIdentifier = function (node) {
            if (node.parent.kind() !== 136 /* MemberVariableDeclaration */) {
                if (this.checkForDisallowedEvalOrArguments(node, node.propertyName)) {
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkVariableDeclaratorInitializer = function (node) {
            if (this.inAmbientDeclaration && node.equalsValueClause) {
                this.pushDiagnostic(TypeScript.firstToken(node.equalsValueClause.value), TypeScript.DiagnosticCode.Initializers_are_not_allowed_in_ambient_contexts);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitConstructorDeclaration = function (node) {
            if (this.checkClassElementModifiers(node.modifiers) || this.checkConstructorModifiers(node.modifiers) || this.checkConstructorTypeParameterList(node) || this.checkConstructorTypeAnnotation(node)) {
                return;
            }

            _super.prototype.visitConstructorDeclaration.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkConstructorModifiers = function (modifiers) {
            for (var i = 0, n = modifiers.length; i < n; i++) {
                var child = modifiers[i];
                if (child.kind() !== 57 /* PublicKeyword */) {
                    this.pushDiagnostic(child, TypeScript.DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, [TypeScript.SyntaxFacts.getText(child.kind())]);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkConstructorTypeParameterList = function (node) {
            if (node.callSignature.typeParameterList) {
                this.pushDiagnostic(node.callSignature.typeParameterList, TypeScript.DiagnosticCode.Type_parameters_cannot_appear_on_a_constructor_declaration);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.checkConstructorTypeAnnotation = function (node) {
            if (node.callSignature.typeAnnotation) {
                this.pushDiagnostic(node.callSignature.typeAnnotation, TypeScript.DiagnosticCode.Type_annotation_cannot_appear_on_a_constructor_declaration);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitBinaryExpression = function (node) {
            if (this.isIllegalAssignment(node)) {
                return;
            }

            _super.prototype.visitBinaryExpression.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitPrefixUnaryExpression = function (node) {
            if (TypeScript.parsedInStrictMode(node) && this.isPreIncrementOrDecrementExpression(node) && this.isEvalOrArguments(node.operand)) {
                this.pushDiagnostic(node.operatorToken, TypeScript.DiagnosticCode.Invalid_use_of_0_in_strict_mode, [this.getEvalOrArguments(node.operand)]);
            }

            _super.prototype.visitPrefixUnaryExpression.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitPostfixUnaryExpression = function (node) {
            if (TypeScript.parsedInStrictMode(node) && this.isEvalOrArguments(node.operand)) {
                this.pushDiagnostic(node.operatorToken, TypeScript.DiagnosticCode.Invalid_use_of_0_in_strict_mode, [this.getEvalOrArguments(node.operand)]);
            }

            _super.prototype.visitPostfixUnaryExpression.call(this, node);
        };

        GrammarCheckerWalker.prototype.visitParameter = function (node) {
            if (this.checkForDisallowedEvalOrArguments(node, node.identifier)) {
                return;
            }

            _super.prototype.visitParameter.call(this, node);
        };

        GrammarCheckerWalker.prototype.checkForDisallowedEvalOrArguments = function (node, token) {
            if (token) {
                if (TypeScript.parsedInStrictMode(node) && this.isEvalOrArguments(token)) {
                    this.pushDiagnostic(token, TypeScript.DiagnosticCode.Invalid_use_of_0_in_strict_mode, [this.getEvalOrArguments(token)]);
                    return true;
                }
            }

            return false;
        };

        GrammarCheckerWalker.prototype.isPreIncrementOrDecrementExpression = function (node) {
            switch (node.kind()) {
                case 169 /* PreDecrementExpression */:
                case 168 /* PreIncrementExpression */:
                    return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.visitDeleteExpression = function (node) {
            if (TypeScript.parsedInStrictMode(node) && node.expression.kind() === 11 /* IdentifierName */) {
                this.pushDiagnostic(TypeScript.firstToken(node), TypeScript.DiagnosticCode.delete_cannot_be_called_on_an_identifier_in_strict_mode);
                return;
            }

            _super.prototype.visitDeleteExpression.call(this, node);
        };

        GrammarCheckerWalker.prototype.isIllegalAssignment = function (node) {
            if (TypeScript.parsedInStrictMode(node) && TypeScript.SyntaxFacts.isAssignmentOperatorToken(node.operatorToken.kind()) && this.isEvalOrArguments(node.left)) {
                this.pushDiagnostic(node.operatorToken, TypeScript.DiagnosticCode.Invalid_use_of_0_in_strict_mode, [this.getEvalOrArguments(node.left)]);
                return true;
            }

            return false;
        };

        GrammarCheckerWalker.prototype.getEvalOrArguments = function (expr) {
            if (expr.kind() === 11 /* IdentifierName */) {
                var text = TypeScript.tokenValueText(expr);
                if (text === "eval" || text === "arguments") {
                    return text;
                }
            }

            return null;
        };

        GrammarCheckerWalker.prototype.isEvalOrArguments = function (expr) {
            return this.getEvalOrArguments(expr) !== null;
        };
        return GrammarCheckerWalker;
    })(TypeScript.SyntaxWalker);

    function firstSyntaxTreeToken(syntaxTree) {
        // We don't just access the firstToken of the tree here as the tree may be abstract and may
        // not have a firstToken in it.
        var scanner = TypeScript.Scanner.createScanner(syntaxTree.languageVersion(), syntaxTree.text, function () {
        });
        return scanner.scan(false);
    }

    function externalModuleIndicatorSpan(syntaxTree) {
        var firstToken = firstSyntaxTreeToken(syntaxTree);
        return externalModuleIndicatorSpanWorker(syntaxTree, firstToken);
    }
    TypeScript.externalModuleIndicatorSpan = externalModuleIndicatorSpan;

    function externalModuleIndicatorSpanWorker(syntaxTree, firstToken) {
        var leadingTrivia = firstToken.leadingTrivia(syntaxTree.text);
        return implicitImportSpan(leadingTrivia) || topLevelImportOrExportSpan(syntaxTree.sourceUnit());
    }
    TypeScript.externalModuleIndicatorSpanWorker = externalModuleIndicatorSpanWorker;

    function implicitImportSpan(sourceUnitLeadingTrivia) {
        for (var i = 0, n = sourceUnitLeadingTrivia.count(); i < n; i++) {
            var trivia = sourceUnitLeadingTrivia.syntaxTriviaAt(i);

            if (trivia.isComment()) {
                var span = implicitImportSpanWorker(trivia);
                if (span) {
                    return span;
                }
            }
        }

        return null;
    }

    function implicitImportSpanWorker(trivia) {
        var implicitImportRegEx = /^(\/\/\/\s*<implicit-import\s*)*\/>/gim;
        var match = implicitImportRegEx.exec(trivia.fullText());

        if (match) {
            return new TypeScript.TextSpan(trivia.fullStart(), trivia.fullWidth());
        }

        return null;
    }

    function topLevelImportOrExportSpan(node) {
        for (var i = 0, n = node.moduleElements.length; i < n; i++) {
            var moduleElement = node.moduleElements[i];

            var _firstToken = TypeScript.firstToken(moduleElement);
            if (_firstToken !== null && _firstToken.kind() === 47 /* ExportKeyword */) {
                return new TypeScript.TextSpan(TypeScript.start(_firstToken), TypeScript.width(_firstToken));
            }

            if (moduleElement.kind() === 133 /* ImportDeclaration */) {
                var importDecl = moduleElement;
                if (importDecl.moduleReference.kind() === 245 /* ExternalModuleReference */) {
                    var literal = importDecl.moduleReference.stringLiteral;
                    return new TypeScript.TextSpan(TypeScript.start(literal), TypeScript.width(literal));
                }
            }
        }

        return null;
    }
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var Unicode = (function () {
        function Unicode() {
        }
        Unicode.lookupInUnicodeMap = function (code, map) {
            // Bail out quickly if it couldn't possibly be in the map.
            if (code < map[0]) {
                return false;
            }

            // Perform binary search in one of the unicode range maps
            var lo = 0;
            var hi = map.length;
            var mid;

            while (lo + 1 < hi) {
                mid = lo + (hi - lo) / 2;

                // mid has to be even to catch a range's beginning
                mid -= mid % 2;
                if (map[mid] <= code && code <= map[mid + 1]) {
                    return true;
                }

                if (code < map[mid]) {
                    hi = mid;
                } else {
                    lo = mid + 2;
                }
            }

            return false;
        };

        Unicode.isIdentifierStart = function (code, languageVersion) {
            if (languageVersion === 0 /* EcmaScript3 */) {
                return Unicode.lookupInUnicodeMap(code, Unicode.unicodeES3IdentifierStart);
            } else if (languageVersion === 1 /* EcmaScript5 */) {
                return Unicode.lookupInUnicodeMap(code, Unicode.unicodeES5IdentifierStart);
            } else {
                throw TypeScript.Errors.argumentOutOfRange("languageVersion");
            }
        };

        Unicode.isIdentifierPart = function (code, languageVersion) {
            if (languageVersion === 0 /* EcmaScript3 */) {
                return Unicode.lookupInUnicodeMap(code, Unicode.unicodeES3IdentifierPart);
            } else if (languageVersion === 1 /* EcmaScript5 */) {
                return Unicode.lookupInUnicodeMap(code, Unicode.unicodeES5IdentifierPart);
            } else {
                throw TypeScript.Errors.argumentOutOfRange("languageVersion");
            }
        };
        /*
        As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers
        IdentifierStart ::
        Can contain Unicode 3.0.0  categories:
        “Uppercase letter (Lu)”,
        “Lowercase letter (Ll)”,
        “Titlecase letter (Lt)”,
        “Modifier letter (Lm)”,
        “Other letter (Lo)”, or
        “Letter number (Nl)”.
        IdentifierPart :: =
        Can contain IdentifierStart + Unicode 3.0.0  categories:
        “Non-spacing mark (Mn)”,
        “Combining spacing mark (Mc)”,
        “Decimal number (Nd)”, or
        “Connector punctuation (Pc)”.
        
        Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at:
        http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt
        */
        Unicode.unicodeES3IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500];
        Unicode.unicodeES3IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500];

        /*
        As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers
        IdentifierStart ::
        Can contain Unicode 6.2  categories:
        “Uppercase letter (Lu)”,
        “Lowercase letter (Ll)”,
        “Titlecase letter (Lt)”,
        “Modifier letter (Lm)”,
        “Other letter (Lo)”, or
        “Letter number (Nl)”.
        IdentifierPart ::
        Can contain IdentifierStart + Unicode 6.2  categories:
        “Non-spacing mark (Mn)”,
        “Combining spacing mark (Mc)”,
        “Decimal number (Nd)”,
        “Connector punctuation (Pc)”,
        <ZWNJ>, or
        <ZWJ>.
        
        Codepoint ranges for ES5 Identifiers are extracted from the Unicode 6.2 specification at:
        http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt
        */
        Unicode.unicodeES5IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500];
        Unicode.unicodeES5IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500];
        return Unicode;
    })();
    TypeScript.Unicode = Unicode;
})(TypeScript || (TypeScript = {}));
///<reference path='..\text\references.ts' />
///<reference path='characterInfo.ts' />
///<reference path='constants.ts' />
///<reference path='formattingOptions.ts' />
// ///<reference path='indentation.ts' />
///<reference path='languageVersion.ts' />
// Scanner depends on SyntaxKind and SyntaxFacts
///<reference path='syntaxKind.ts' />
///<reference path='syntaxFacts.ts' />
///<reference path='scanner.ts' />
///<reference path='scannerUtilities.generated.ts' />
///<reference path='slidingWindow.ts' />
///<reference path='syntax.ts' />
///<reference path='syntaxElement.ts' />
///<reference path='syntaxFacts2.ts' />
///<reference path='syntaxList.ts' />
///<reference path='syntaxNode.ts' />
///<reference path='syntaxNodeOrToken.ts' />
///<reference path='syntaxNodes.interfaces.generated.ts' />
// SyntaxDedenter depends on SyntaxRewriter
// ///<reference path='syntaxDedenter.ts' />
// SyntaxIndenter depends on SyntaxRewriter
// ///<reference path='syntaxIndenter.ts' />
///<reference path='syntaxToken.ts' />
///<reference path='syntaxTrivia.ts' />
///<reference path='syntaxTriviaList.ts' />
///<reference path='syntaxUtilities.ts' />
///<reference path='syntaxVisitor.generated.ts' />
///<reference path='syntaxWalker.generated.ts' />
// SyntaxInformationMap depends on SyntaxWalker
// ///<reference path='syntaxNodeInvariantsChecker.ts' />
// DepthLimitedWalker depends on PositionTrackingWalker
///<reference path='depthLimitedWalker.ts' />
///<reference path='parser.ts' />
// Concrete nodes depend on the parser.
///<reference path='syntaxNodes.concrete.generated.ts' />
// SyntaxTree depends on PositionTrackingWalker
///<reference path='syntaxTree.ts' />
///<reference path='unicode.ts' />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var NullLogger = (function () {
        function NullLogger() {
        }
        NullLogger.prototype.information = function () {
            return false;
        };
        NullLogger.prototype.debug = function () {
            return false;
        };
        NullLogger.prototype.warning = function () {
            return false;
        };
        NullLogger.prototype.error = function () {
            return false;
        };
        NullLogger.prototype.fatal = function () {
            return false;
        };
        NullLogger.prototype.log = function (s) {
        };
        return NullLogger;
    })();
    TypeScript.NullLogger = NullLogger;

    function timeFunction(logger, funcDescription, func) {
        var start = (new Date()).getTime();
        var result = func();
        var end = (new Date()).getTime();
        if (logger.information()) {
            logger.log(funcDescription + " completed in " + (end - start) + " msec");
        }
        return result;
    }
    TypeScript.timeFunction = timeFunction;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var Document = (function () {
        function Document(compilationSettings, fileName, referencedFiles, _scriptSnapshot, byteOrderMark, version, isOpen, _syntaxTree, _topLevelDecl) {
            this.compilationSettings = compilationSettings;
            this.fileName = fileName;
            this.referencedFiles = referencedFiles;
            this._scriptSnapshot = _scriptSnapshot;
            this.byteOrderMark = byteOrderMark;
            this.version = version;
            this.isOpen = isOpen;
            this._syntaxTree = _syntaxTree;
            this._topLevelDecl = _topLevelDecl;
            this._bloomFilter = null;
            this._declASTMap = [];
            this._astDeclMap = [];
        }
        Document.prototype.isDeclareFile = function () {
            return TypeScript.isDTSFile(this.fileName);
        };

        Document.prototype.sourceUnit = function () {
            // If we don't have a script, create one from our parse tree.
            return this.syntaxTree().sourceUnit();
        };

        Document.prototype.diagnostics = function () {
            return this.syntaxTree().diagnostics();
        };

        Document.prototype.lineMap = function () {
            return this.syntaxTree().lineMap();
        };

        Document.prototype.syntaxTree = function () {
            if (!this._syntaxTree) {
                var start = new Date().getTime();

                this._syntaxTree = TypeScript.Parser.parse(this.fileName, TypeScript.SimpleText.fromScriptSnapshot(this._scriptSnapshot), this.compilationSettings.codeGenTarget(), this.isDeclareFile());

                var time = new Date().getTime() - start;

                TypeScript.syntaxTreeParseTime += time;
            }

            return this._syntaxTree;
        };

        Document.prototype.bloomFilter = function () {
            if (!this._bloomFilter) {
                var identifiers = TypeScript.createIntrinsicsObject();
                var pre = function (cur) {
                    if (TypeScript.ASTHelpers.isValidAstNode(cur)) {
                        if (cur.kind() === 11 /* IdentifierName */) {
                            var nodeText = TypeScript.tokenValueText(cur);

                            identifiers[nodeText] = true;
                        }
                    }
                };

                TypeScript.getAstWalkerFactory().simpleWalk(this.sourceUnit(), pre, null, identifiers);

                var identifierCount = 0;
                for (var name in identifiers) {
                    if (identifiers[name]) {
                        identifierCount++;
                    }
                }

                this._bloomFilter = new TypeScript.BloomFilter(identifierCount);
                this._bloomFilter.addKeys(identifiers);
            }
            return this._bloomFilter;
        };

        // Returns true if this file should get emitted into its own unique output file.
        // Otherwise, it should be written into a single output file along with the rest of hte
        // documents in the compilation.
        Document.prototype.emitToOwnOutputFile = function () {
            // If we haven't specified an output file in our settings, then we're definitely
            // emitting to our own file.  Also, if we're an external module, then we're
            // definitely emitting to our own file.
            return !this.compilationSettings.outFileOption() || this.syntaxTree().isExternalModule();
        };

        Document.prototype.update = function (scriptSnapshot, version, isOpen, textChangeRange) {
            // See if we are currently holding onto a syntax tree.  We may not be because we're
            // either a closed file, or we've just been lazy and haven't had to create the syntax
            // tree yet.  Access the field instead of the method so we don't accidently realize
            // the old syntax tree.
            var oldSyntaxTree = this._syntaxTree;

            if (textChangeRange !== null && TypeScript.Debug.shouldAssert(1 /* Normal */)) {
                var oldText = this._scriptSnapshot;
                var newText = scriptSnapshot;

                TypeScript.Debug.assert((oldText.getLength() - textChangeRange.span().length() + textChangeRange.newLength()) === newText.getLength());

                if (TypeScript.Debug.shouldAssert(3 /* VeryAggressive */)) {
                    var oldTextPrefix = oldText.getText(0, textChangeRange.span().start());
                    var newTextPrefix = newText.getText(0, textChangeRange.span().start());
                    TypeScript.Debug.assert(oldTextPrefix === newTextPrefix);

                    var oldTextSuffix = oldText.getText(textChangeRange.span().end(), oldText.getLength());
                    var newTextSuffix = newText.getText(textChangeRange.newSpan().end(), newText.getLength());
                    TypeScript.Debug.assert(oldTextSuffix === newTextSuffix);
                }
            }

            var text = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot);

            // If we don't have a text change, or we don't have an old syntax tree, then do a full
            // parse.  Otherwise, do an incremental parse.
            var newSyntaxTree = textChangeRange === null || oldSyntaxTree === null || Document.incrementalParse === null ? TypeScript.Parser.parse(this.fileName, text, this.compilationSettings.codeGenTarget(), TypeScript.isDTSFile(this.fileName)) : Document.incrementalParse(oldSyntaxTree, textChangeRange, text);

            return new Document(this.compilationSettings, this.fileName, this.referencedFiles, scriptSnapshot, this.byteOrderMark, version, isOpen, newSyntaxTree, null);
        };

        Document.create = function (compilationSettings, fileName, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles) {
            return new Document(compilationSettings, fileName, referencedFiles, scriptSnapshot, byteOrderMark, version, isOpen, null, null);
        };

        Document.prototype.topLevelDecl = function () {
            if (this._topLevelDecl === null) {
                this._topLevelDecl = TypeScript.DeclarationCreator.create(this, this.compilationSettings);
            }

            return this._topLevelDecl;
        };

        Document.prototype._getDeclForAST = function (ast) {
            // Ensure we actually have created all our decls before we try to find a mathcing decl
            // for this ast.
            this.topLevelDecl();
            return this._astDeclMap[TypeScript.syntaxID(ast)];
        };

        Document.prototype.getEnclosingDecl = function (ast) {
            if (ast.kind() === 120 /* SourceUnit */) {
                return this._getDeclForAST(ast);
            }

            // First, walk up the ISyntaxElement, looking for a decl corresponding to that ISyntaxElement node.
            ast = ast.parent;
            var decl = null;
            while (ast) {
                //if (ast.kind === SyntaxKind.ModuleDeclaration) {
                //    var moduleDecl = <ModuleDeclarationSyntax>ast;
                //    decl = this._getDeclForAST(<ISyntaxElement>moduleDecl.stringLiteral || ArrayUtilities.last(getModuleNames(moduleDecl.name)));
                //}
                //else {
                decl = this._getDeclForAST(ast);

                //}
                if (decl) {
                    break;
                }

                ast = ast.parent;
            }

            // Now, skip over certain decls.  The resolver never considers these the 'enclosing'
            // decl for an ISyntaxElement node.
            return decl._getEnclosingDeclFromParentDecl();
        };

        Document.prototype._setDeclForAST = function (ast, decl) {
            TypeScript.Debug.assert(decl.fileName() === this.fileName);
            this._astDeclMap[TypeScript.syntaxID(ast)] = decl;
        };

        Document.prototype._getASTForDecl = function (decl) {
            return this._declASTMap[decl.declID];
        };

        Document.prototype._setASTForDecl = function (decl, ast) {
            TypeScript.Debug.assert(decl.fileName() === this.fileName);
            this._declASTMap[decl.declID] = ast;
        };
        // By default, our Document class doesn't support incremental update of its contents.
        // However, we enable other layers (like teh services layer) to inject the capability
        // into us by setting this function.
        Document.incrementalParse = null;
        return Document;
    })();
    TypeScript.Document = Document;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    function hasFlag(val, flag) {
        return (val & flag) !== 0;
    }
    TypeScript.hasFlag = hasFlag;

    (function (ModuleGenTarget) {
        ModuleGenTarget[ModuleGenTarget["Unspecified"] = 0] = "Unspecified";
        ModuleGenTarget[ModuleGenTarget["Synchronous"] = 1] = "Synchronous";
        ModuleGenTarget[ModuleGenTarget["Asynchronous"] = 2] = "Asynchronous";
    })(TypeScript.ModuleGenTarget || (TypeScript.ModuleGenTarget = {}));
    var ModuleGenTarget = TypeScript.ModuleGenTarget;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var proto = "__proto__";

    var BlockIntrinsics = (function () {
        function BlockIntrinsics() {
            this.prototype = undefined;
            this.toString = undefined;
            this.toLocaleString = undefined;
            this.valueOf = undefined;
            this.hasOwnProperty = undefined;
            this.propertyIsEnumerable = undefined;
            this.isPrototypeOf = undefined;
            // initialize the 'constructor' field
            this["constructor"] = undefined;

            // First we set it to null, because that's the only way to erase the value in node. Then we set it to undefined in case we are not in node, since
            // in StringHashTable below, we check for undefined explicitly.
            this[proto] = null;
            this[proto] = undefined;
        }
        return BlockIntrinsics;
    })();

    function createIntrinsicsObject() {
        return new BlockIntrinsics();
    }
    TypeScript.createIntrinsicsObject = createIntrinsicsObject;

    var StringHashTable = (function () {
        function StringHashTable() {
            this.itemCount = 0;
            this.table = createIntrinsicsObject();
        }
        StringHashTable.prototype.getAllKeys = function () {
            var result = [];

            for (var k in this.table) {
                if (this.table[k] !== undefined) {
                    result.push(k);
                }
            }

            return result;
        };

        StringHashTable.prototype.add = function (key, data) {
            if (this.table[key] !== undefined) {
                return false;
            }

            this.table[key] = data;
            this.itemCount++;
            return true;
        };

        StringHashTable.prototype.addOrUpdate = function (key, data) {
            if (this.table[key] !== undefined) {
                this.table[key] = data;
                return false;
            }

            this.table[key] = data;
            this.itemCount++;
            return true;
        };

        StringHashTable.prototype.map = function (fn, context) {
            for (var k in this.table) {
                var data = this.table[k];

                if (data !== undefined) {
                    fn(k, this.table[k], context);
                }
            }
        };

        StringHashTable.prototype.every = function (fn, context) {
            for (var k in this.table) {
                var data = this.table[k];

                if (data !== undefined) {
                    if (!fn(k, this.table[k], context)) {
                        return false;
                    }
                }
            }

            return true;
        };

        StringHashTable.prototype.some = function (fn, context) {
            for (var k in this.table) {
                var data = this.table[k];

                if (data !== undefined) {
                    if (fn(k, this.table[k], context)) {
                        return true;
                    }
                }
            }

            return false;
        };

        StringHashTable.prototype.count = function () {
            return this.itemCount;
        };

        StringHashTable.prototype.lookup = function (key) {
            var data = this.table[key];
            return data === undefined ? null : data;
        };

        StringHashTable.prototype.remove = function (key) {
            if (this.table[key] !== undefined) {
                this.table[key] = undefined;
                this.itemCount--;
            }
        };
        return StringHashTable;
    })();
    TypeScript.StringHashTable = StringHashTable;

    var IdentiferNameHashTable = (function (_super) {
        __extends(IdentiferNameHashTable, _super);
        function IdentiferNameHashTable() {
            _super.apply(this, arguments);
        }
        IdentiferNameHashTable.prototype.getAllKeys = function () {
            var result = [];

            _super.prototype.map.call(this, function (k, v, c) {
                if (v !== undefined) {
                    result.push(k.substring(1));
                }
            }, null);

            return result;
        };

        IdentiferNameHashTable.prototype.add = function (key, data) {
            return _super.prototype.add.call(this, "#" + key, data);
        };

        IdentiferNameHashTable.prototype.addOrUpdate = function (key, data) {
            return _super.prototype.addOrUpdate.call(this, "#" + key, data);
        };

        IdentiferNameHashTable.prototype.map = function (fn, context) {
            return _super.prototype.map.call(this, function (k, v, c) {
                return fn(k.substring(1), v, c);
            }, context);
        };

        IdentiferNameHashTable.prototype.every = function (fn, context) {
            return _super.prototype.every.call(this, function (k, v, c) {
                return fn(k.substring(1), v, c);
            }, context);
        };

        IdentiferNameHashTable.prototype.some = function (fn, context) {
            return _super.prototype.some.call(this, function (k, v, c) {
                return fn(k.substring(1), v, c);
            }, context);
        };

        IdentiferNameHashTable.prototype.lookup = function (key) {
            return _super.prototype.lookup.call(this, "#" + key);
        };
        return IdentiferNameHashTable;
    })(StringHashTable);
    TypeScript.IdentiferNameHashTable = IdentiferNameHashTable;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var Comment = (function () {
        function Comment(_trivia, endsLine, _start, _end) {
            this._trivia = _trivia;
            this.endsLine = endsLine;
            this._start = _start;
            this._end = _end;
        }
        Comment.prototype.start = function () {
            return this._start;
        };

        Comment.prototype.end = function () {
            return this._end;
        };

        Comment.prototype.fullText = function () {
            return this._trivia.fullText();
        };

        Comment.prototype.kind = function () {
            return this._trivia.kind();
        };

        Comment.prototype.structuralEquals = function (ast, includingPosition) {
            if (includingPosition) {
                if (this.start() !== ast.start() || this.end() !== ast.end()) {
                    return false;
                }
            }

            return this._trivia.fullText() === ast._trivia.fullText() && this.endsLine === ast.endsLine;
        };
        return Comment;
    })();
    TypeScript.Comment = Comment;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (ASTHelpers) {
        function scriptIsElided(sourceUnit) {
            return TypeScript.isDTSFile(sourceUnit.syntaxTree.fileName()) || moduleMembersAreElided(sourceUnit.moduleElements);
        }
        ASTHelpers.scriptIsElided = scriptIsElided;

        function moduleIsElided(declaration) {
            return TypeScript.hasModifier(declaration.modifiers, TypeScript.PullElementFlags.Ambient) || moduleMembersAreElided(declaration.moduleElements);
        }
        ASTHelpers.moduleIsElided = moduleIsElided;

        function moduleMembersAreElided(members) {
            for (var i = 0, n = members.length; i < n; i++) {
                var member = members[i];

                // We should emit *this* module if it contains any non-interface types.
                // Caveat: if we have contain a module, then we should be emitted *if we want to
                // emit that inner module as well.
                if (member.kind() === 130 /* ModuleDeclaration */) {
                    if (!moduleIsElided(member)) {
                        return false;
                    }
                } else if (member.kind() !== 128 /* InterfaceDeclaration */) {
                    return false;
                }
            }

            return true;
        }

        function enumIsElided(declaration) {
            if (TypeScript.hasModifier(declaration.modifiers, TypeScript.PullElementFlags.Ambient)) {
                return true;
            }

            return false;
        }
        ASTHelpers.enumIsElided = enumIsElided;

        function isValidAstNode(ast) {
            return ast && !TypeScript.isShared(ast) && TypeScript.start(ast) !== -1 && TypeScript.end(ast) !== -1;
        }
        ASTHelpers.isValidAstNode = isValidAstNode;

        function isValidSpan(ast) {
            if (!ast)
                return false;

            if (ast.start() === -1 || ast.end() === -1)
                return false;

            return true;
        }
        ASTHelpers.isValidSpan = isValidSpan;

        ///
        /// Return the ISyntaxElement containing "position"
        ///
        function getAstAtPosition(script, pos, useTrailingTriviaAsLimChar, forceInclusive) {
            if (typeof useTrailingTriviaAsLimChar === "undefined") { useTrailingTriviaAsLimChar = true; }
            if (typeof forceInclusive === "undefined") { forceInclusive = false; }
            var top = null;

            var pre = function (cur, walker) {
                if (!TypeScript.isShared(cur) && isValidAstNode(cur)) {
                    var isInvalid1 = cur.kind() === 149 /* ExpressionStatement */ && TypeScript.width(cur) === 0;

                    if (isInvalid1) {
                        walker.options.goChildren = false;
                    } else {
                        // Add "cur" to the stack if it contains our position
                        // For "identifier" nodes, we need a special case: A position equal to "limChar" is
                        // valid, since the position corresponds to a caret position (in between characters)
                        // For example:
                        //  bar
                        //  0123
                        // If "position === 3", the caret is at the "right" of the "r" character, which should be considered valid
                        var inclusive = forceInclusive || cur.kind() === 11 /* IdentifierName */ || cur.kind() === 212 /* MemberAccessExpression */ || cur.kind() === 121 /* QualifiedName */ || cur.kind() === 224 /* VariableDeclaration */ || cur.kind() === 225 /* VariableDeclarator */ || cur.kind() === 213 /* InvocationExpression */ || pos === TypeScript.end(script) + TypeScript.lastToken(script).trailingTriviaWidth();

                        var minChar = TypeScript.start(cur);
                        var limChar = TypeScript.end(cur) + (useTrailingTriviaAsLimChar ? TypeScript.trailingTriviaWidth(cur) : 0) + (inclusive ? 1 : 0);
                        if (pos >= minChar && pos < limChar) {
                            // Ignore empty lists
                            if ((cur.kind() !== 1 /* List */ && cur.kind() !== 2 /* SeparatedList */) || TypeScript.end(cur) > TypeScript.start(cur)) {
                                // TODO: Since ISyntaxElement is sometimes not correct wrt to position, only add "cur" if it's better
                                //       than top of the stack.
                                if (top === null) {
                                    top = cur;
                                } else if (TypeScript.start(cur) >= TypeScript.start(top) && (TypeScript.end(cur) + (useTrailingTriviaAsLimChar ? TypeScript.trailingTriviaWidth(cur) : 0)) <= (TypeScript.end(top) + (useTrailingTriviaAsLimChar ? TypeScript.trailingTriviaWidth(top) : 0))) {
                                    // this new node appears to be better than the one we're
                                    // storing.  Make this the new node.
                                    // However, If the current top is a missing identifier, we
                                    // don't want to replace it with another missing identifier.
                                    // We want to return the first missing identifier found in a
                                    // depth first walk of  the tree.
                                    if (TypeScript.width(top) !== 0 || TypeScript.width(cur) !== 0) {
                                        top = cur;
                                    }
                                }
                            }
                        }

                        // Don't go further down the tree if pos is outside of [minChar, limChar]
                        walker.options.goChildren = (minChar <= pos && pos <= limChar);
                    }
                }
            };

            TypeScript.getAstWalkerFactory().walk(script, pre);
            return top;
        }
        ASTHelpers.getAstAtPosition = getAstAtPosition;

        function getExtendsHeritageClause(clauses) {
            return getHeritageClause(clauses, 230 /* ExtendsHeritageClause */);
        }
        ASTHelpers.getExtendsHeritageClause = getExtendsHeritageClause;

        function getImplementsHeritageClause(clauses) {
            return getHeritageClause(clauses, 231 /* ImplementsHeritageClause */);
        }
        ASTHelpers.getImplementsHeritageClause = getImplementsHeritageClause;

        function getHeritageClause(clauses, kind) {
            if (clauses) {
                for (var i = 0, n = clauses.length; i < n; i++) {
                    var child = clauses[i];

                    if (child.typeNames.length > 0 && child.kind() === kind) {
                        return child;
                    }
                }
            }

            return null;
        }

        function isCallExpression(ast) {
            return (ast && ast.kind() === 213 /* InvocationExpression */) || (ast && ast.kind() === 216 /* ObjectCreationExpression */);
        }
        ASTHelpers.isCallExpression = isCallExpression;

        function isCallExpressionTarget(ast) {
            return !!getCallExpressionTarget(ast);
        }
        ASTHelpers.isCallExpressionTarget = isCallExpressionTarget;

        function getCallExpressionTarget(ast) {
            if (!ast) {
                return null;
            }

            var current = ast;

            while (current && current.parent) {
                if (current.parent.kind() === 212 /* MemberAccessExpression */ && current.parent.name === current) {
                    current = current.parent;
                    continue;
                }

                break;
            }

            if (current && current.parent) {
                if (current.parent.kind() === 213 /* InvocationExpression */ || current.parent.kind() === 216 /* ObjectCreationExpression */) {
                    return current === current.parent.expression ? current : null;
                }
            }
            return null;
        }
        ASTHelpers.getCallExpressionTarget = getCallExpressionTarget;

        function isNameOfSomeDeclaration(ast) {
            if (ast === null || ast.parent === null) {
                return false;
            }
            if (ast.kind() !== 11 /* IdentifierName */) {
                return false;
            }

            switch (ast.parent.kind()) {
                case 131 /* ClassDeclaration */:
                    return ast.parent.identifier === ast;
                case 128 /* InterfaceDeclaration */:
                    return ast.parent.identifier === ast;
                case 132 /* EnumDeclaration */:
                    return ast.parent.identifier === ast;
                case 130 /* ModuleDeclaration */:
                    return ast.parent.name === ast || ast.parent.stringLiteral === ast;
                case 225 /* VariableDeclarator */:
                    return ast.parent.propertyName === ast;
                case 129 /* FunctionDeclaration */:
                    return ast.parent.identifier === ast;
                case 135 /* MemberFunctionDeclaration */:
                    return ast.parent.propertyName === ast;
                case 242 /* Parameter */:
                    return ast.parent.identifier === ast;
                case 238 /* TypeParameter */:
                    return ast.parent.identifier === ast;
                case 240 /* SimplePropertyAssignment */:
                    return ast.parent.propertyName === ast;
                case 241 /* FunctionPropertyAssignment */:
                    return ast.parent.propertyName === ast;
                case 243 /* EnumElement */:
                    return ast.parent.propertyName === ast;
                case 133 /* ImportDeclaration */:
                    return ast.parent.identifier === ast;
                case 145 /* MethodSignature */:
                    return ast.parent.propertyName === ast;
                case 141 /* PropertySignature */:
                    return ast.parent.propertyName === ast;
            }

            return false;
        }

        function isDeclarationASTOrDeclarationNameAST(ast) {
            return isNameOfSomeDeclaration(ast) || ASTHelpers.isDeclarationAST(ast);
        }
        ASTHelpers.isDeclarationASTOrDeclarationNameAST = isDeclarationASTOrDeclarationNameAST;

        function getEnclosingParameterForInitializer(ast) {
            var current = ast;
            while (current) {
                switch (current.kind()) {
                    case 232 /* EqualsValueClause */:
                        if (current.parent && current.parent.kind() === 242 /* Parameter */) {
                            return current.parent;
                        }
                        break;
                    case 131 /* ClassDeclaration */:
                    case 128 /* InterfaceDeclaration */:
                    case 130 /* ModuleDeclaration */:
                        // exit early
                        return null;
                }

                current = current.parent;
            }
            return null;
        }
        ASTHelpers.getEnclosingParameterForInitializer = getEnclosingParameterForInitializer;

        function getEnclosingMemberDeclaration(ast) {
            var current = ast;

            while (current) {
                switch (current.kind()) {
                    case 136 /* MemberVariableDeclaration */:
                    case 145 /* MethodSignature */:
                    case 135 /* MemberFunctionDeclaration */:
                    case 139 /* GetAccessor */:
                    case 140 /* SetAccessor */:
                        return current;
                    case 131 /* ClassDeclaration */:
                    case 128 /* InterfaceDeclaration */:
                    case 130 /* ModuleDeclaration */:
                        // exit early
                        return null;
                }
                current = current.parent;
            }

            return null;
        }
        ASTHelpers.getEnclosingMemberDeclaration = getEnclosingMemberDeclaration;

        function isNameOfFunction(ast) {
            return ast && ast.parent && ast.kind() === 11 /* IdentifierName */ && ast.parent.kind() === 129 /* FunctionDeclaration */ && ast.parent.identifier === ast;
        }
        ASTHelpers.isNameOfFunction = isNameOfFunction;

        function isNameOfMemberFunction(ast) {
            return ast && ast.parent && ast.kind() === 11 /* IdentifierName */ && ast.parent.kind() === 135 /* MemberFunctionDeclaration */ && ast.parent.propertyName === ast;
        }
        ASTHelpers.isNameOfMemberFunction = isNameOfMemberFunction;

        function isNameOfMemberAccessExpression(ast) {
            if (ast && ast.parent && ast.parent.kind() === 212 /* MemberAccessExpression */ && ast.parent.name === ast) {
                return true;
            }

            return false;
        }
        ASTHelpers.isNameOfMemberAccessExpression = isNameOfMemberAccessExpression;

        function isRightSideOfQualifiedName(ast) {
            if (ast && ast.parent && ast.parent.kind() === 121 /* QualifiedName */ && ast.parent.right === ast) {
                return true;
            }

            return false;
        }
        ASTHelpers.isRightSideOfQualifiedName = isRightSideOfQualifiedName;

        function parentIsModuleDeclaration(ast) {
            return ast.parent && ast.parent.kind() === 130 /* ModuleDeclaration */;
        }
        ASTHelpers.parentIsModuleDeclaration = parentIsModuleDeclaration;

        function isDeclarationAST(ast) {
            switch (ast.kind()) {
                case 225 /* VariableDeclarator */:
                    return getVariableStatement(ast) !== null;

                case 133 /* ImportDeclaration */:
                case 131 /* ClassDeclaration */:
                case 128 /* InterfaceDeclaration */:
                case 242 /* Parameter */:
                case 219 /* SimpleArrowFunctionExpression */:
                case 218 /* ParenthesizedArrowFunctionExpression */:
                case 144 /* IndexSignature */:
                case 129 /* FunctionDeclaration */:
                case 130 /* ModuleDeclaration */:
                case 124 /* ArrayType */:
                case 122 /* ObjectType */:
                case 238 /* TypeParameter */:
                case 137 /* ConstructorDeclaration */:
                case 135 /* MemberFunctionDeclaration */:
                case 139 /* GetAccessor */:
                case 140 /* SetAccessor */:
                case 136 /* MemberVariableDeclaration */:
                case 138 /* IndexMemberDeclaration */:
                case 132 /* EnumDeclaration */:
                case 243 /* EnumElement */:
                case 240 /* SimplePropertyAssignment */:
                case 241 /* FunctionPropertyAssignment */:
                case 222 /* FunctionExpression */:
                case 142 /* CallSignature */:
                case 143 /* ConstructSignature */:
                case 145 /* MethodSignature */:
                case 141 /* PropertySignature */:
                    return true;
                default:
                    return false;
            }
        }
        ASTHelpers.isDeclarationAST = isDeclarationAST;

        function preComments(element, text) {
            if (element) {
                switch (element.kind()) {
                    case 148 /* VariableStatement */:
                    case 149 /* ExpressionStatement */:
                    case 131 /* ClassDeclaration */:
                    case 133 /* ImportDeclaration */:
                    case 129 /* FunctionDeclaration */:
                    case 130 /* ModuleDeclaration */:
                    case 132 /* EnumDeclaration */:
                    case 147 /* IfStatement */:
                    case 240 /* SimplePropertyAssignment */:
                    case 135 /* MemberFunctionDeclaration */:
                    case 128 /* InterfaceDeclaration */:
                    case 139 /* GetAccessor */:
                    case 140 /* SetAccessor */:
                    case 150 /* ReturnStatement */:
                    case 137 /* ConstructorDeclaration */:
                    case 136 /* MemberVariableDeclaration */:
                    case 243 /* EnumElement */:
                    case 142 /* CallSignature */:
                    case 143 /* ConstructSignature */:
                    case 144 /* IndexSignature */:
                    case 141 /* PropertySignature */:
                    case 145 /* MethodSignature */:
                    case 241 /* FunctionPropertyAssignment */:
                    case 242 /* Parameter */:
                        return convertNodeLeadingComments(element, text);
                }
            }

            return null;
        }
        ASTHelpers.preComments = preComments;

        function postComments(element, text) {
            if (element) {
                switch (element.kind()) {
                    case 149 /* ExpressionStatement */:
                        return convertNodeTrailingComments(element, text, true);
                    case 148 /* VariableStatement */:
                    case 131 /* ClassDeclaration */:
                    case 133 /* ImportDeclaration */:
                    case 129 /* FunctionDeclaration */:
                    case 130 /* ModuleDeclaration */:
                    case 132 /* EnumDeclaration */:
                    case 147 /* IfStatement */:
                    case 240 /* SimplePropertyAssignment */:
                    case 135 /* MemberFunctionDeclaration */:
                    case 128 /* InterfaceDeclaration */:
                    case 139 /* GetAccessor */:
                    case 140 /* SetAccessor */:
                    case 150 /* ReturnStatement */:
                    case 137 /* ConstructorDeclaration */:
                    case 136 /* MemberVariableDeclaration */:
                    case 243 /* EnumElement */:
                    case 142 /* CallSignature */:
                    case 143 /* ConstructSignature */:
                    case 144 /* IndexSignature */:
                    case 141 /* PropertySignature */:
                    case 145 /* MethodSignature */:
                    case 241 /* FunctionPropertyAssignment */:
                    case 242 /* Parameter */:
                        return convertNodeTrailingComments(element, text);
                }
            }

            return null;
        }
        ASTHelpers.postComments = postComments;

        function convertNodeTrailingComments(node, text, allowWithNewLine) {
            if (typeof allowWithNewLine === "undefined") { allowWithNewLine = false; }
            // Bail out quickly before doing any expensive math computation.
            var _lastToken = TypeScript.lastToken(node);
            if (_lastToken === null || !_lastToken.hasTrailingTrivia()) {
                return null;
            }

            if (!allowWithNewLine && TypeScript.SyntaxUtilities.isLastTokenOnLine(_lastToken, text)) {
                return null;
            }

            return convertComments(_lastToken.trailingTrivia(text), TypeScript.fullStart(node) + TypeScript.fullWidth(node) - _lastToken.trailingTriviaWidth(text));
        }

        function convertNodeLeadingComments(element, text) {
            if (element) {
                return convertTokenLeadingComments(TypeScript.firstToken(element), text);
            }

            return null;
        }

        function convertTokenLeadingComments(token, text) {
            if (token === null) {
                return null;
            }

            return token.hasLeadingTrivia() ? convertComments(token.leadingTrivia(text), token.fullStart()) : null;
        }
        ASTHelpers.convertTokenLeadingComments = convertTokenLeadingComments;

        function convertTokenTrailingComments(token, text) {
            if (token === null) {
                return null;
            }

            return token.hasTrailingTrivia() ? convertComments(token.trailingTrivia(text), TypeScript.fullEnd(token) - token.trailingTriviaWidth(text)) : null;
        }
        ASTHelpers.convertTokenTrailingComments = convertTokenTrailingComments;

        function convertComments(triviaList, commentStartPosition) {
            var result = null;

            for (var i = 0, n = triviaList.count(); i < n; i++) {
                var trivia = triviaList.syntaxTriviaAt(i);

                if (trivia.isComment()) {
                    var hasTrailingNewLine = ((i + 1) < n) && triviaList.syntaxTriviaAt(i + 1).isNewLine();
                    result = result || [];
                    result.push(convertComment(trivia, commentStartPosition, hasTrailingNewLine));
                }

                commentStartPosition += trivia.fullWidth();
            }

            return result;
        }

        function convertComment(trivia, commentStartPosition, hasTrailingNewLine) {
            var comment = new TypeScript.Comment(trivia, hasTrailingNewLine, commentStartPosition, commentStartPosition + trivia.fullWidth());

            return comment;
        }

        function docComments(ast, text) {
            if (isDeclarationAST(ast)) {
                var comments = null;

                if (ast.kind() === 225 /* VariableDeclarator */) {
                    // Get the doc comments for a variable off of the variable statement.  That's what
                    // they'll be attached to in the tree.
                    comments = TypeScript.ASTHelpers.preComments(getVariableStatement(ast), text);
                } else if (ast.kind() === 242 /* Parameter */) {
                    // First check if the parameter was written like so:
                    //      (
                    //          /** blah */ a,
                    //          /** blah */ b);
                    comments = TypeScript.ASTHelpers.preComments(ast, text);
                    if (!comments) {
                        // Now check if it was written like so:
                        //      (/** blah */ a, /** blah */ b);
                        // In this case, the comment will belong to the preceding token.
                        var previousToken = TypeScript.findToken(TypeScript.syntaxTree(ast).sourceUnit(), TypeScript.firstToken(ast).fullStart() - 1);
                        if (previousToken && (previousToken.kind() === 72 /* OpenParenToken */ || previousToken.kind() === 79 /* CommaToken */)) {
                            comments = convertTokenTrailingComments(previousToken, text);
                        }
                    }
                } else {
                    comments = TypeScript.ASTHelpers.preComments(ast, text);
                }

                if (comments && comments.length > 0) {
                    return comments.filter(function (c) {
                        return isDocComment(c);
                    });
                }
            }

            return TypeScript.sentinelEmptyArray;
        }
        ASTHelpers.docComments = docComments;

        function isDocComment(comment) {
            if (comment.kind() === 6 /* MultiLineCommentTrivia */) {
                var fullText = comment.fullText();
                return fullText.charAt(2) === "*" && fullText.charAt(3) !== "/";
            }

            return false;
        }
        ASTHelpers.isDocComment = isDocComment;

        function getParameterList(ast) {
            if (ast) {
                switch (ast.kind()) {
                    case 137 /* ConstructorDeclaration */:
                        return getParameterList(ast.callSignature);
                    case 129 /* FunctionDeclaration */:
                        return getParameterList(ast.callSignature);
                    case 218 /* ParenthesizedArrowFunctionExpression */:
                        return getParameterList(ast.callSignature);
                    case 143 /* ConstructSignature */:
                        return getParameterList(ast.callSignature);
                    case 135 /* MemberFunctionDeclaration */:
                        return getParameterList(ast.callSignature);
                    case 241 /* FunctionPropertyAssignment */:
                        return getParameterList(ast.callSignature);
                    case 222 /* FunctionExpression */:
                        return getParameterList(ast.callSignature);
                    case 145 /* MethodSignature */:
                        return getParameterList(ast.callSignature);
                    case 125 /* ConstructorType */:
                        return ast.parameterList;
                    case 123 /* FunctionType */:
                        return ast.parameterList;
                    case 142 /* CallSignature */:
                        return ast.parameterList;
                    case 139 /* GetAccessor */:
                        return getParameterList(ast.callSignature);
                    case 140 /* SetAccessor */:
                        return getParameterList(ast.callSignature);
                }
            }

            return null;
        }
        ASTHelpers.getParameterList = getParameterList;

        function getType(ast) {
            if (ast) {
                switch (ast.kind()) {
                    case 129 /* FunctionDeclaration */:
                        return getType(ast.callSignature);
                    case 218 /* ParenthesizedArrowFunctionExpression */:
                        return getType(ast.callSignature);
                    case 143 /* ConstructSignature */:
                        return getType(ast.callSignature);
                    case 135 /* MemberFunctionDeclaration */:
                        return getType(ast.callSignature);
                    case 241 /* FunctionPropertyAssignment */:
                        return getType(ast.callSignature);
                    case 222 /* FunctionExpression */:
                        return getType(ast.callSignature);
                    case 145 /* MethodSignature */:
                        return getType(ast.callSignature);
                    case 142 /* CallSignature */:
                        return getType(ast.typeAnnotation);
                    case 144 /* IndexSignature */:
                        return getType(ast.typeAnnotation);
                    case 141 /* PropertySignature */:
                        return getType(ast.typeAnnotation);
                    case 139 /* GetAccessor */:
                        return getType(ast.callSignature);
                    case 242 /* Parameter */:
                        return getType(ast.typeAnnotation);
                    case 136 /* MemberVariableDeclaration */:
                        return getType(ast.variableDeclarator);
                    case 225 /* VariableDeclarator */:
                        return getType(ast.typeAnnotation);
                    case 236 /* CatchClause */:
                        return getType(ast.typeAnnotation);
                    case 125 /* ConstructorType */:
                        return ast.type;
                    case 123 /* FunctionType */:
                        return ast.type;
                    case 244 /* TypeAnnotation */:
                        return ast.type;
                }
            }

            return null;
        }
        ASTHelpers.getType = getType;

        function getVariableStatement(variableDeclarator) {
            if (variableDeclarator && variableDeclarator.parent && variableDeclarator.parent.parent && variableDeclarator.parent.parent.parent && variableDeclarator.parent.kind() === 2 /* SeparatedList */ && variableDeclarator.parent.parent.kind() === 224 /* VariableDeclaration */ && variableDeclarator.parent.parent.parent.kind() === 148 /* VariableStatement */) {
                return variableDeclarator.parent.parent.parent;
            }

            return null;
        }

        function getVariableDeclaratorModifiers(variableDeclarator) {
            var variableStatement = getVariableStatement(variableDeclarator);
            return variableStatement ? variableStatement.modifiers : TypeScript.Syntax.emptyList();
        }
        ASTHelpers.getVariableDeclaratorModifiers = getVariableDeclaratorModifiers;

        function isIntegerLiteralAST(expression) {
            if (expression) {
                switch (expression.kind()) {
                    case 164 /* PlusExpression */:
                    case 165 /* NegateExpression */:
                        // Note: if there is a + or - sign, we can only allow a normal integer following
                        // (and not a hex integer).  i.e. -0xA is a legal expression, but it is not a
                        // *literal*.
                        expression = expression.operand;
                        return expression.kind() === 13 /* NumericLiteral */ && TypeScript.IntegerUtilities.isInteger(expression.text());

                    case 13 /* NumericLiteral */:
                        // If it doesn't have a + or -, then either an integer literal or a hex literal
                        // is acceptable.
                        var text = expression.text();
                        return TypeScript.IntegerUtilities.isInteger(text) || TypeScript.IntegerUtilities.isHexInteger(text);
                }
            }

            return false;
        }
        ASTHelpers.isIntegerLiteralAST = isIntegerLiteralAST;

        function getEnclosingModuleDeclaration(ast) {
            while (ast) {
                if (ast.kind() === 130 /* ModuleDeclaration */) {
                    return ast;
                }

                ast = ast.parent;
            }

            return null;
        }
        ASTHelpers.getEnclosingModuleDeclaration = getEnclosingModuleDeclaration;

        function isEntireNameOfModuleDeclaration(nameAST) {
            return parentIsModuleDeclaration(nameAST) && nameAST.parent.name === nameAST;
        }

        function getModuleDeclarationFromNameAST(ast) {
            if (ast) {
                switch (ast.kind()) {
                    case 14 /* StringLiteral */:
                        if (parentIsModuleDeclaration(ast) && ast.parent.stringLiteral === ast) {
                            return ast.parent;
                        }
                        return null;

                    case 11 /* IdentifierName */:
                    case 121 /* QualifiedName */:
                        if (isEntireNameOfModuleDeclaration(ast)) {
                            return ast.parent;
                        }
                        break;

                    default:
                        return null;
                }

                for (ast = ast.parent; ast && ast.kind() === 121 /* QualifiedName */; ast = ast.parent) {
                    if (isEntireNameOfModuleDeclaration(ast)) {
                        return ast.parent;
                    }
                }
            }

            return null;
        }
        ASTHelpers.getModuleDeclarationFromNameAST = getModuleDeclarationFromNameAST;

        function isLastNameOfModule(ast, astName) {
            if (ast) {
                if (ast.stringLiteral) {
                    return astName === ast.stringLiteral;
                } else if (ast.name.kind() === 121 /* QualifiedName */) {
                    return astName === ast.name.right;
                } else {
                    return astName === ast.name;
                }
            }

            return false;
        }
        ASTHelpers.isLastNameOfModule = isLastNameOfModule;

        function getNameOfIdenfierOrQualifiedName(name) {
            if (name.kind() === 11 /* IdentifierName */) {
                return name.text();
            } else {
                TypeScript.Debug.assert(name.kind() == 121 /* QualifiedName */);
                var dotExpr = name;
                return getNameOfIdenfierOrQualifiedName(dotExpr.left) + "." + getNameOfIdenfierOrQualifiedName(dotExpr.right);
            }
        }
        ASTHelpers.getNameOfIdenfierOrQualifiedName = getNameOfIdenfierOrQualifiedName;

        function getModuleNames(name, result) {
            result = result || [];

            if (name.kind() === 121 /* QualifiedName */) {
                getModuleNames(name.left, result);
                result.push(name.right);
            } else {
                result.push(name);
            }

            return result;
        }
        ASTHelpers.getModuleNames = getModuleNames;
    })(TypeScript.ASTHelpers || (TypeScript.ASTHelpers = {}));
    var ASTHelpers = TypeScript.ASTHelpers;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    function walkListChildren(preAst, walker) {
        for (var i = 0, n = preAst.length; i < n; i++) {
            walker.walk(preAst[i]);
        }
    }

    function walkThrowStatementChildren(preAst, walker) {
        walker.walk(preAst.expression);
    }

    function walkPrefixUnaryExpressionChildren(preAst, walker) {
        walker.walk(preAst.operand);
    }

    function walkPostfixUnaryExpressionChildren(preAst, walker) {
        walker.walk(preAst.operand);
    }

    function walkDeleteExpressionChildren(preAst, walker) {
        walker.walk(preAst.expression);
    }

    function walkTypeArgumentListChildren(preAst, walker) {
        walker.walk(preAst.typeArguments);
    }

    function walkTypeOfExpressionChildren(preAst, walker) {
        walker.walk(preAst.expression);
    }

    function walkVoidExpressionChildren(preAst, walker) {
        walker.walk(preAst.expression);
    }

    function walkArgumentListChildren(preAst, walker) {
        walker.walk(preAst.typeArgumentList);
        walker.walk(preAst.arguments);
    }

    function walkArrayLiteralExpressionChildren(preAst, walker) {
        walker.walk(preAst.expressions);
    }

    function walkSimplePropertyAssignmentChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.expression);
    }

    function walkFunctionPropertyAssignmentChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.callSignature);
        walker.walk(preAst.block);
    }

    function walkGetAccessorChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.callSignature);
        walker.walk(preAst.block);
    }

    function walkSeparatedListChildren(preAst, walker) {
        for (var i = 0, n = preAst.length; i < n; i++) {
            walker.walk(preAst[i]);
        }
    }

    function walkSetAccessorChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.callSignature);
        walker.walk(preAst.block);
    }

    function walkObjectLiteralExpressionChildren(preAst, walker) {
        walker.walk(preAst.propertyAssignments);
    }

    function walkCastExpressionChildren(preAst, walker) {
        walker.walk(preAst.type);
        walker.walk(preAst.expression);
    }

    function walkParenthesizedExpressionChildren(preAst, walker) {
        walker.walk(preAst.expression);
    }

    function walkElementAccessExpressionChildren(preAst, walker) {
        walker.walk(preAst.expression);
        walker.walk(preAst.argumentExpression);
    }

    function walkMemberAccessExpressionChildren(preAst, walker) {
        walker.walk(preAst.expression);
        walker.walk(preAst.name);
    }

    function walkQualifiedNameChildren(preAst, walker) {
        walker.walk(preAst.left);
        walker.walk(preAst.right);
    }

    function walkBinaryExpressionChildren(preAst, walker) {
        walker.walk(preAst.left);
        walker.walk(preAst.right);
    }

    function walkEqualsValueClauseChildren(preAst, walker) {
        walker.walk(preAst.value);
    }

    function walkTypeParameterChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.constraint);
    }

    function walkTypeParameterListChildren(preAst, walker) {
        walker.walk(preAst.typeParameters);
    }

    function walkGenericTypeChildren(preAst, walker) {
        walker.walk(preAst.name);
        walker.walk(preAst.typeArgumentList);
    }

    function walkTypeAnnotationChildren(preAst, walker) {
        walker.walk(preAst.type);
    }

    function walkTypeQueryChildren(preAst, walker) {
        walker.walk(preAst.name);
    }

    function walkInvocationExpressionChildren(preAst, walker) {
        walker.walk(preAst.expression);
        walker.walk(preAst.argumentList);
    }

    function walkObjectCreationExpressionChildren(preAst, walker) {
        walker.walk(preAst.expression);
        walker.walk(preAst.argumentList);
    }

    function walkTrinaryExpressionChildren(preAst, walker) {
        walker.walk(preAst.condition);
        walker.walk(preAst.whenTrue);
        walker.walk(preAst.whenFalse);
    }

    function walkFunctionExpressionChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.callSignature);
        walker.walk(preAst.block);
    }

    function walkFunctionTypeChildren(preAst, walker) {
        walker.walk(preAst.typeParameterList);
        walker.walk(preAst.parameterList);
        walker.walk(preAst.type);
    }

    function walkParenthesizedArrowFunctionExpressionChildren(preAst, walker) {
        walker.walk(preAst.callSignature);
        walker.walk(preAst.block);
        walker.walk(preAst.expression);
    }

    function walkSimpleArrowFunctionExpressionChildren(preAst, walker) {
        walker.walk(preAst.parameter);
        walker.walk(preAst.block);
        walker.walk(preAst.expression);
    }

    function walkMemberFunctionDeclarationChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.callSignature);
        walker.walk(preAst.block);
    }

    function walkFuncDeclChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.callSignature);
        walker.walk(preAst.block);
    }

    function walkIndexMemberDeclarationChildren(preAst, walker) {
        walker.walk(preAst.indexSignature);
    }

    function walkIndexSignatureChildren(preAst, walker) {
        walker.walk(preAst.parameters);
        walker.walk(preAst.typeAnnotation);
    }

    function walkCallSignatureChildren(preAst, walker) {
        walker.walk(preAst.typeParameterList);
        walker.walk(preAst.parameterList);
        walker.walk(preAst.typeAnnotation);
    }

    function walkConstraintChildren(preAst, walker) {
        walker.walk(preAst.type);
    }

    function walkConstructorDeclarationChildren(preAst, walker) {
        walker.walk(preAst.callSignature);
        walker.walk(preAst.block);
    }

    function walkConstructorTypeChildren(preAst, walker) {
        walker.walk(preAst.typeParameterList);
        walker.walk(preAst.parameterList);
        walker.walk(preAst.type);
    }

    function walkConstructSignatureChildren(preAst, walker) {
        walker.walk(preAst.callSignature);
    }

    function walkParameterChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.typeAnnotation);
        walker.walk(preAst.equalsValueClause);
    }

    function walkParameterListChildren(preAst, walker) {
        walker.walk(preAst.parameters);
    }

    function walkPropertySignatureChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.typeAnnotation);
    }

    function walkVariableDeclaratorChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.typeAnnotation);
        walker.walk(preAst.equalsValueClause);
    }

    function walkMemberVariableDeclarationChildren(preAst, walker) {
        walker.walk(preAst.variableDeclarator);
    }

    function walkMethodSignatureChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.callSignature);
    }

    function walkReturnStatementChildren(preAst, walker) {
        walker.walk(preAst.expression);
    }

    function walkForStatementChildren(preAst, walker) {
        walker.walk(preAst.variableDeclaration);
        walker.walk(preAst.initializer);
        walker.walk(preAst.condition);
        walker.walk(preAst.incrementor);
        walker.walk(preAst.statement);
    }

    function walkForInStatementChildren(preAst, walker) {
        walker.walk(preAst.variableDeclaration);
        walker.walk(preAst.left);
        walker.walk(preAst.expression);
        walker.walk(preAst.statement);
    }

    function walkIfStatementChildren(preAst, walker) {
        walker.walk(preAst.condition);
        walker.walk(preAst.statement);
        walker.walk(preAst.elseClause);
    }

    function walkElseClauseChildren(preAst, walker) {
        walker.walk(preAst.statement);
    }

    function walkWhileStatementChildren(preAst, walker) {
        walker.walk(preAst.condition);
        walker.walk(preAst.statement);
    }

    function walkDoStatementChildren(preAst, walker) {
        walker.walk(preAst.condition);
        walker.walk(preAst.statement);
    }

    function walkBlockChildren(preAst, walker) {
        walker.walk(preAst.statements);
    }

    function walkVariableDeclarationChildren(preAst, walker) {
        walker.walk(preAst.variableDeclarators);
    }

    function walkCaseSwitchClauseChildren(preAst, walker) {
        walker.walk(preAst.expression);
        walker.walk(preAst.statements);
    }

    function walkDefaultSwitchClauseChildren(preAst, walker) {
        walker.walk(preAst.statements);
    }

    function walkSwitchStatementChildren(preAst, walker) {
        walker.walk(preAst.expression);
        walker.walk(preAst.switchClauses);
    }

    function walkTryStatementChildren(preAst, walker) {
        walker.walk(preAst.block);
        walker.walk(preAst.catchClause);
        walker.walk(preAst.finallyClause);
    }

    function walkCatchClauseChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.typeAnnotation);
        walker.walk(preAst.block);
    }

    function walkExternalModuleReferenceChildren(preAst, walker) {
        walker.walk(preAst.stringLiteral);
    }

    function walkFinallyClauseChildren(preAst, walker) {
        walker.walk(preAst.block);
    }

    function walkClassDeclChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.typeParameterList);
        walker.walk(preAst.heritageClauses);
        walker.walk(preAst.classElements);
    }

    function walkScriptChildren(preAst, walker) {
        walker.walk(preAst.moduleElements);
    }

    function walkHeritageClauseChildren(preAst, walker) {
        walker.walk(preAst.typeNames);
    }

    function walkInterfaceDeclerationChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.typeParameterList);
        walker.walk(preAst.heritageClauses);
        walker.walk(preAst.body);
    }

    function walkObjectTypeChildren(preAst, walker) {
        walker.walk(preAst.typeMembers);
    }

    function walkArrayTypeChildren(preAst, walker) {
        walker.walk(preAst.type);
    }

    function walkModuleDeclarationChildren(preAst, walker) {
        walker.walk(preAst.name);
        walker.walk(preAst.stringLiteral);
        walker.walk(preAst.moduleElements);
    }

    function walkModuleNameModuleReferenceChildren(preAst, walker) {
        walker.walk(preAst.moduleName);
    }

    function walkEnumDeclarationChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.enumElements);
    }

    function walkEnumElementChildren(preAst, walker) {
        walker.walk(preAst.propertyName);
        walker.walk(preAst.equalsValueClause);
    }

    function walkImportDeclarationChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.moduleReference);
    }

    function walkExportAssignmentChildren(preAst, walker) {
        walker.walk(preAst.identifier);
    }

    function walkWithStatementChildren(preAst, walker) {
        walker.walk(preAst.condition);
        walker.walk(preAst.statement);
    }

    function walkExpressionStatementChildren(preAst, walker) {
        walker.walk(preAst.expression);
    }

    function walkLabeledStatementChildren(preAst, walker) {
        walker.walk(preAst.identifier);
        walker.walk(preAst.statement);
    }

    function walkVariableStatementChildren(preAst, walker) {
        walker.walk(preAst.variableDeclaration);
    }

    var childrenWalkers = new Array(TypeScript.SyntaxKind.LastNode + 1);

    for (var i = TypeScript.SyntaxKind.FirstToken, n = TypeScript.SyntaxKind.LastToken; i <= n; i++) {
        childrenWalkers[i] = null;
    }
    for (var i = TypeScript.SyntaxKind.FirstTrivia, n = TypeScript.SyntaxKind.LastTrivia; i <= n; i++) {
        childrenWalkers[i] = null;
    }

    childrenWalkers[175 /* AddAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[208 /* AddExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[180 /* AndAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[60 /* AnyKeyword */] = null;
    childrenWalkers[226 /* ArgumentList */] = walkArgumentListChildren;
    childrenWalkers[214 /* ArrayLiteralExpression */] = walkArrayLiteralExpressionChildren;
    childrenWalkers[124 /* ArrayType */] = walkArrayTypeChildren;
    childrenWalkers[219 /* SimpleArrowFunctionExpression */] = walkSimpleArrowFunctionExpressionChildren;
    childrenWalkers[218 /* ParenthesizedArrowFunctionExpression */] = walkParenthesizedArrowFunctionExpressionChildren;
    childrenWalkers[174 /* AssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[191 /* BitwiseAndExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[190 /* BitwiseExclusiveOrExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[166 /* BitwiseNotExpression */] = walkPrefixUnaryExpressionChildren;
    childrenWalkers[189 /* BitwiseOrExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[146 /* Block */] = walkBlockChildren;
    childrenWalkers[61 /* BooleanKeyword */] = null;
    childrenWalkers[152 /* BreakStatement */] = null;
    childrenWalkers[142 /* CallSignature */] = walkCallSignatureChildren;
    childrenWalkers[233 /* CaseSwitchClause */] = walkCaseSwitchClauseChildren;
    childrenWalkers[220 /* CastExpression */] = walkCastExpressionChildren;
    childrenWalkers[236 /* CatchClause */] = walkCatchClauseChildren;
    childrenWalkers[131 /* ClassDeclaration */] = walkClassDeclChildren;
    childrenWalkers[173 /* CommaExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[186 /* ConditionalExpression */] = walkTrinaryExpressionChildren;
    childrenWalkers[239 /* Constraint */] = walkConstraintChildren;
    childrenWalkers[137 /* ConstructorDeclaration */] = walkConstructorDeclarationChildren;
    childrenWalkers[143 /* ConstructSignature */] = walkConstructSignatureChildren;
    childrenWalkers[153 /* ContinueStatement */] = null;
    childrenWalkers[125 /* ConstructorType */] = walkConstructorTypeChildren;
    childrenWalkers[162 /* DebuggerStatement */] = null;
    childrenWalkers[234 /* DefaultSwitchClause */] = walkDefaultSwitchClauseChildren;
    childrenWalkers[170 /* DeleteExpression */] = walkDeleteExpressionChildren;
    childrenWalkers[178 /* DivideAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[206 /* DivideExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[161 /* DoStatement */] = walkDoStatementChildren;
    childrenWalkers[221 /* ElementAccessExpression */] = walkElementAccessExpressionChildren;
    childrenWalkers[235 /* ElseClause */] = walkElseClauseChildren;
    childrenWalkers[156 /* EmptyStatement */] = null;
    childrenWalkers[132 /* EnumDeclaration */] = walkEnumDeclarationChildren;
    childrenWalkers[243 /* EnumElement */] = walkEnumElementChildren;
    childrenWalkers[194 /* EqualsExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[232 /* EqualsValueClause */] = walkEqualsValueClauseChildren;
    childrenWalkers[192 /* EqualsWithTypeConversionExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[181 /* ExclusiveOrAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[134 /* ExportAssignment */] = walkExportAssignmentChildren;
    childrenWalkers[149 /* ExpressionStatement */] = walkExpressionStatementChildren;
    childrenWalkers[230 /* ExtendsHeritageClause */] = walkHeritageClauseChildren;
    childrenWalkers[245 /* ExternalModuleReference */] = walkExternalModuleReferenceChildren;
    childrenWalkers[24 /* FalseKeyword */] = null;
    childrenWalkers[237 /* FinallyClause */] = walkFinallyClauseChildren;
    childrenWalkers[155 /* ForInStatement */] = walkForInStatementChildren;
    childrenWalkers[154 /* ForStatement */] = walkForStatementChildren;
    childrenWalkers[129 /* FunctionDeclaration */] = walkFuncDeclChildren;
    childrenWalkers[222 /* FunctionExpression */] = walkFunctionExpressionChildren;
    childrenWalkers[241 /* FunctionPropertyAssignment */] = walkFunctionPropertyAssignmentChildren;
    childrenWalkers[123 /* FunctionType */] = walkFunctionTypeChildren;
    childrenWalkers[126 /* GenericType */] = walkGenericTypeChildren;
    childrenWalkers[139 /* GetAccessor */] = walkGetAccessorChildren;
    childrenWalkers[197 /* GreaterThanExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[199 /* GreaterThanOrEqualExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[147 /* IfStatement */] = walkIfStatementChildren;
    childrenWalkers[231 /* ImplementsHeritageClause */] = walkHeritageClauseChildren;
    childrenWalkers[133 /* ImportDeclaration */] = walkImportDeclarationChildren;
    childrenWalkers[138 /* IndexMemberDeclaration */] = walkIndexMemberDeclarationChildren;
    childrenWalkers[144 /* IndexSignature */] = walkIndexSignatureChildren;
    childrenWalkers[201 /* InExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[200 /* InstanceOfExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[128 /* InterfaceDeclaration */] = walkInterfaceDeclerationChildren;
    childrenWalkers[213 /* InvocationExpression */] = walkInvocationExpressionChildren;
    childrenWalkers[160 /* LabeledStatement */] = walkLabeledStatementChildren;
    childrenWalkers[183 /* LeftShiftAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[202 /* LeftShiftExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[196 /* LessThanExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[198 /* LessThanOrEqualExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[1 /* List */] = walkListChildren;
    childrenWalkers[188 /* LogicalAndExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[167 /* LogicalNotExpression */] = walkPrefixUnaryExpressionChildren;
    childrenWalkers[187 /* LogicalOrExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[212 /* MemberAccessExpression */] = walkMemberAccessExpressionChildren;
    childrenWalkers[135 /* MemberFunctionDeclaration */] = walkMemberFunctionDeclarationChildren;
    childrenWalkers[136 /* MemberVariableDeclaration */] = walkMemberVariableDeclarationChildren;
    childrenWalkers[145 /* MethodSignature */] = walkMethodSignatureChildren;
    childrenWalkers[130 /* ModuleDeclaration */] = walkModuleDeclarationChildren;
    childrenWalkers[246 /* ModuleNameModuleReference */] = walkModuleNameModuleReferenceChildren;
    childrenWalkers[179 /* ModuloAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[207 /* ModuloExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[177 /* MultiplyAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[205 /* MultiplyExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[11 /* IdentifierName */] = null;
    childrenWalkers[165 /* NegateExpression */] = walkPrefixUnaryExpressionChildren;
    childrenWalkers[0 /* None */] = null;
    childrenWalkers[195 /* NotEqualsExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[193 /* NotEqualsWithTypeConversionExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[32 /* NullKeyword */] = null;
    childrenWalkers[67 /* NumberKeyword */] = null;
    childrenWalkers[13 /* NumericLiteral */] = null;
    childrenWalkers[216 /* ObjectCreationExpression */] = walkObjectCreationExpressionChildren;
    childrenWalkers[215 /* ObjectLiteralExpression */] = walkObjectLiteralExpressionChildren;
    childrenWalkers[122 /* ObjectType */] = walkObjectTypeChildren;
    childrenWalkers[223 /* OmittedExpression */] = null;
    childrenWalkers[182 /* OrAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[242 /* Parameter */] = walkParameterChildren;
    childrenWalkers[227 /* ParameterList */] = walkParameterListChildren;
    childrenWalkers[217 /* ParenthesizedExpression */] = walkParenthesizedExpressionChildren;
    childrenWalkers[164 /* PlusExpression */] = walkPrefixUnaryExpressionChildren;
    childrenWalkers[211 /* PostDecrementExpression */] = walkPostfixUnaryExpressionChildren;
    childrenWalkers[210 /* PostIncrementExpression */] = walkPostfixUnaryExpressionChildren;
    childrenWalkers[169 /* PreDecrementExpression */] = walkPrefixUnaryExpressionChildren;
    childrenWalkers[168 /* PreIncrementExpression */] = walkPrefixUnaryExpressionChildren;
    childrenWalkers[141 /* PropertySignature */] = walkPropertySignatureChildren;
    childrenWalkers[121 /* QualifiedName */] = walkQualifiedNameChildren;
    childrenWalkers[12 /* RegularExpressionLiteral */] = null;
    childrenWalkers[150 /* ReturnStatement */] = walkReturnStatementChildren;
    childrenWalkers[120 /* SourceUnit */] = walkScriptChildren;
    childrenWalkers[2 /* SeparatedList */] = walkSeparatedListChildren;
    childrenWalkers[140 /* SetAccessor */] = walkSetAccessorChildren;
    childrenWalkers[184 /* SignedRightShiftAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[203 /* SignedRightShiftExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[240 /* SimplePropertyAssignment */] = walkSimplePropertyAssignmentChildren;
    childrenWalkers[14 /* StringLiteral */] = null;
    childrenWalkers[69 /* StringKeyword */] = null;
    childrenWalkers[176 /* SubtractAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[209 /* SubtractExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[50 /* SuperKeyword */] = null;
    childrenWalkers[151 /* SwitchStatement */] = walkSwitchStatementChildren;
    childrenWalkers[35 /* ThisKeyword */] = null;
    childrenWalkers[157 /* ThrowStatement */] = walkThrowStatementChildren;
    childrenWalkers[3 /* TriviaList */] = null;
    childrenWalkers[37 /* TrueKeyword */] = null;
    childrenWalkers[159 /* TryStatement */] = walkTryStatementChildren;
    childrenWalkers[244 /* TypeAnnotation */] = walkTypeAnnotationChildren;
    childrenWalkers[228 /* TypeArgumentList */] = walkTypeArgumentListChildren;
    childrenWalkers[171 /* TypeOfExpression */] = walkTypeOfExpressionChildren;
    childrenWalkers[238 /* TypeParameter */] = walkTypeParameterChildren;
    childrenWalkers[229 /* TypeParameterList */] = walkTypeParameterListChildren;
    childrenWalkers[127 /* TypeQuery */] = walkTypeQueryChildren;
    childrenWalkers[185 /* UnsignedRightShiftAssignmentExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[204 /* UnsignedRightShiftExpression */] = walkBinaryExpressionChildren;
    childrenWalkers[224 /* VariableDeclaration */] = walkVariableDeclarationChildren;
    childrenWalkers[225 /* VariableDeclarator */] = walkVariableDeclaratorChildren;
    childrenWalkers[148 /* VariableStatement */] = walkVariableStatementChildren;
    childrenWalkers[172 /* VoidExpression */] = walkVoidExpressionChildren;
    childrenWalkers[41 /* VoidKeyword */] = null;
    childrenWalkers[158 /* WhileStatement */] = walkWhileStatementChildren;
    childrenWalkers[163 /* WithStatement */] = walkWithStatementChildren;

    for (var e in TypeScript.SyntaxKind) {
        if (TypeScript.SyntaxKind.hasOwnProperty(e) && TypeScript.StringUtilities.isString(TypeScript.SyntaxKind[e])) {
            TypeScript.Debug.assert(childrenWalkers[e] !== undefined, "Fix initWalkers: " + TypeScript.SyntaxKind[e]);
        }
    }

    var AstWalkOptions = (function () {
        function AstWalkOptions() {
            this.goChildren = true;
            this.stopWalking = false;
        }
        return AstWalkOptions;
    })();
    TypeScript.AstWalkOptions = AstWalkOptions;

    var SimplePreAstWalker = (function () {
        function SimplePreAstWalker(pre, state) {
            this.pre = pre;
            this.state = state;
            this.options = new AstWalkOptions();
        }
        SimplePreAstWalker.prototype.walk = function (ast) {
            if (!ast) {
                return;
            }

            this.pre(ast, this.state);

            var walker = childrenWalkers[ast.kind()];
            if (walker) {
                walker(ast, this);
            }
        };
        return SimplePreAstWalker;
    })();

    var SimplePrePostAstWalker = (function () {
        function SimplePrePostAstWalker(pre, post, state) {
            this.pre = pre;
            this.post = post;
            this.state = state;
            this.options = new AstWalkOptions();
        }
        SimplePrePostAstWalker.prototype.walk = function (ast) {
            if (!ast) {
                return;
            }

            this.pre(ast, this.state);

            var walker = childrenWalkers[ast.kind()];
            if (walker) {
                walker(ast, this);
            }

            this.post(ast, this.state);
        };
        return SimplePrePostAstWalker;
    })();

    var NormalAstWalker = (function () {
        function NormalAstWalker(pre, post, state) {
            this.pre = pre;
            this.post = post;
            this.state = state;
            this.options = new AstWalkOptions();
        }
        NormalAstWalker.prototype.walk = function (ast) {
            if (!ast) {
                return;
            }

            // If we're stopping, then bail out immediately.
            if (this.options.stopWalking) {
                return;
            }

            this.pre(ast, this);

            // If we were asked to stop, then stop.
            if (this.options.stopWalking) {
                return;
            }

            if (this.options.goChildren) {
                // Call the "walkChildren" function corresponding to "nodeType".
                var walker = childrenWalkers[ast.kind()];
                if (walker) {
                    walker(ast, this);
                }
            } else {
                // no go only applies to children of node issuing it
                this.options.goChildren = true;
            }

            if (this.post) {
                this.post(ast, this);
            }
        };
        return NormalAstWalker;
    })();

    var AstWalkerFactory = (function () {
        function AstWalkerFactory() {
        }
        AstWalkerFactory.prototype.walk = function (ast, pre, post, state) {
            new NormalAstWalker(pre, post, state).walk(ast);
        };

        AstWalkerFactory.prototype.simpleWalk = function (ast, pre, post, state) {
            if (post) {
                new SimplePrePostAstWalker(pre, post, state).walk(ast);
            } else {
                new SimplePreAstWalker(pre, state).walk(ast);
            }
        };
        return AstWalkerFactory;
    })();
    TypeScript.AstWalkerFactory = AstWalkerFactory;

    var globalAstWalkerFactory = new AstWalkerFactory();

    function getAstWalkerFactory() {
        return globalAstWalkerFactory;
    }
    TypeScript.getAstWalkerFactory = getAstWalkerFactory;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    var Base64Format = (function () {
        function Base64Format() {
        }
        Base64Format.encode = function (inValue) {
            if (inValue < 64) {
                return Base64Format.encodedValues.charAt(inValue);
            }
            throw TypeError(inValue + ": not a 64 based value");
        };

        Base64Format.decodeChar = function (inChar) {
            if (inChar.length === 1) {
                return Base64Format.encodedValues.indexOf(inChar);
            } else {
                throw TypeError('"' + inChar + '" must have length 1');
            }
        };
        Base64Format.encodedValues = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        return Base64Format;
    })();

    var Base64VLQFormat = (function () {
        function Base64VLQFormat() {
        }
        Base64VLQFormat.encode = function (inValue) {
            // Add a new least significant bit that has the sign of the value.
            // if negative number the least significant bit that gets added to the number has value 1
            // else least significant bit value that gets added is 0
            // eg. -1 changes to binary : 01 [1] => 3
            //     +1 changes to binary : 01 [0] => 2
            if (inValue < 0) {
                inValue = ((-inValue) << 1) + 1;
            } else {
                inValue = inValue << 1;
            }

            // Encode 5 bits at a time starting from least significant bits
            var encodedStr = "";
            do {
                var currentDigit = inValue & 31;
                inValue = inValue >> 5;
                if (inValue > 0) {
                    // There are still more digits to decode, set the msb (6th bit)
                    currentDigit = currentDigit | 32;
                }
                encodedStr = encodedStr + Base64Format.encode(currentDigit);
            } while(inValue > 0);

            return encodedStr;
        };

        Base64VLQFormat.decode = function (inString) {
            var result = 0;
            var negative = false;

            var shift = 0;
            for (var i = 0; i < inString.length; i++) {
                var byte = Base64Format.decodeChar(inString[i]);
                if (i === 0) {
                    // Sign bit appears in the LSBit of the first value
                    if ((byte & 1) === 1) {
                        negative = true;
                    }
                    result = (byte >> 1) & 15; // 1111x
                } else {
                    result = result | ((byte & 31) << shift); // 11111
                }

                shift += (i === 0) ? 4 : 5;

                if ((byte & 32) === 32) {
                    // Continue
                } else {
                    return { value: negative ? -(result) : result, rest: inString.substr(i + 1) };
                }
            }

            throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Base64_value_0_finished_with_a_continuation_bit, [inString]));
        };
        return Base64VLQFormat;
    })();
    TypeScript.Base64VLQFormat = Base64VLQFormat;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var SourceMapPosition = (function () {
        function SourceMapPosition() {
        }
        return SourceMapPosition;
    })();
    TypeScript.SourceMapPosition = SourceMapPosition;

    var SourceMapping = (function () {
        function SourceMapping() {
            this.start = new SourceMapPosition();
            this.end = new SourceMapPosition();
            this.nameIndex = -1;
            this.childMappings = [];
        }
        return SourceMapping;
    })();
    TypeScript.SourceMapping = SourceMapping;

    var SourceMapEntry = (function () {
        function SourceMapEntry(emittedFile, emittedLine, emittedColumn, sourceFile, sourceLine, sourceColumn, sourceName) {
            this.emittedFile = emittedFile;
            this.emittedLine = emittedLine;
            this.emittedColumn = emittedColumn;
            this.sourceFile = sourceFile;
            this.sourceLine = sourceLine;
            this.sourceColumn = sourceColumn;
            this.sourceName = sourceName;
            TypeScript.Debug.assert(isFinite(emittedLine));
            TypeScript.Debug.assert(isFinite(emittedColumn));
            TypeScript.Debug.assert(isFinite(sourceColumn));
            TypeScript.Debug.assert(isFinite(sourceLine));
        }
        return SourceMapEntry;
    })();
    TypeScript.SourceMapEntry = SourceMapEntry;

    var SourceMapper = (function () {
        function SourceMapper(jsFile, sourceMapOut, document, jsFilePath, emitOptions, resolvePath) {
            this.jsFile = jsFile;
            this.sourceMapOut = sourceMapOut;
            this.names = [];
            this.mappingLevel = [];
            // Below two arrays represent the information about sourceFile at that index.
            this.tsFilePaths = [];
            this.allSourceMappings = [];
            this.sourceMapEntries = [];
            this.setSourceMapOptions(document, jsFilePath, emitOptions, resolvePath);
            this.setNewSourceFile(document, emitOptions);
        }
        SourceMapper.prototype.getOutputFile = function () {
            var result = this.sourceMapOut.getOutputFile();
            result.sourceMapEntries = this.sourceMapEntries;

            return result;
        };

        SourceMapper.prototype.increaseMappingLevel = function (ast) {
            this.mappingLevel.push(ast);
        };

        SourceMapper.prototype.decreaseMappingLevel = function (ast) {
            TypeScript.Debug.assert(this.mappingLevel.length > 0, "Mapping level should never be less than 0. This suggests a missing start call.");
            var expectedAst = this.mappingLevel.pop();
            if (ast !== expectedAst) {
                var expectedAstInfo = expectedAst.kind ? TypeScript.SyntaxKind[expectedAst.kind] : [expectedAst.start(), expectedAst.end()];
                var astInfo = ast.kind ? TypeScript.SyntaxKind[ast.kind] : [ast.start(), ast.end()];
                TypeScript.Debug.fail("Provided ast is not the expected ISyntaxElement, Expected: " + expectedAstInfo + " Given: " + astInfo);
            }
        };

        SourceMapper.prototype.setNewSourceFile = function (document, emitOptions) {
            // Set new mappings
            var sourceMappings = [];
            this.allSourceMappings.push(sourceMappings);
            this.currentMappings = [sourceMappings];
            this.currentNameIndex = [];

            // Set new source file path
            this.setNewSourceFilePath(document, emitOptions);
        };

        SourceMapper.prototype.setSourceMapOptions = function (document, jsFilePath, emitOptions, resolvePath) {
            // Decode mapRoot and sourceRoot
            // Js File Name = pretty name of js file
            var prettyJsFileName = TypeScript.getPrettyName(jsFilePath, false, true);
            var prettyMapFileName = prettyJsFileName + SourceMapper.MapFileExtension;
            this.jsFileName = prettyJsFileName;

            // Figure out sourceMapPath and sourceMapDirectory
            if (emitOptions.sourceMapRootDirectory()) {
                // Get the sourceMap Directory
                this.sourceMapDirectory = emitOptions.sourceMapRootDirectory();
                if (document.emitToOwnOutputFile()) {
                    // For modules or multiple emit files the mapRoot will have directory structure like the sources
                    // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
                    this.sourceMapDirectory = this.sourceMapDirectory + TypeScript.switchToForwardSlashes(TypeScript.getRootFilePath((document.fileName)).replace(emitOptions.commonDirectoryPath(), ""));
                }

                if (TypeScript.isRelative(this.sourceMapDirectory)) {
                    // The relative paths are relative to the common directory
                    this.sourceMapDirectory = emitOptions.commonDirectoryPath() + this.sourceMapDirectory;
                    this.sourceMapDirectory = TypeScript.convertToDirectoryPath(TypeScript.switchToForwardSlashes(resolvePath(this.sourceMapDirectory)));
                    this.sourceMapPath = TypeScript.getRelativePathToFixedPath(TypeScript.getRootFilePath(jsFilePath), this.sourceMapDirectory + prettyMapFileName);
                } else {
                    this.sourceMapPath = this.sourceMapDirectory + prettyMapFileName;
                }
            } else {
                this.sourceMapPath = prettyMapFileName;
                this.sourceMapDirectory = TypeScript.getRootFilePath(jsFilePath);
            }
            this.sourceRoot = emitOptions.sourceRootDirectory();
        };

        SourceMapper.prototype.setNewSourceFilePath = function (document, emitOptions) {
            var tsFilePath = TypeScript.switchToForwardSlashes(document.fileName);
            if (emitOptions.sourceRootDirectory()) {
                // Use the relative path corresponding to the common directory path
                tsFilePath = TypeScript.getRelativePathToFixedPath(emitOptions.commonDirectoryPath(), tsFilePath);
            } else {
                // Source locations relative to map file location
                tsFilePath = TypeScript.getRelativePathToFixedPath(this.sourceMapDirectory, tsFilePath);
            }
            this.tsFilePaths.push(tsFilePath);
        };

        // Generate source mapping.
        // Creating files can cause exceptions, they will be caught higher up in TypeScriptCompiler.emit
        SourceMapper.prototype.emitSourceMapping = function () {
            var _this = this;
            TypeScript.Debug.assert(this.mappingLevel.length === 0, "Mapping level is not 0. This suggest a missing end call. Value: " + this.mappingLevel.map(function (item) {
                return ['Node of type', TypeScript.SyntaxKind[item.kind], 'at', item.start(), 'to', item.end()].join(' ');
            }).join(', '));

            // Output map file name into the js file
            this.jsFile.WriteLine("//# sourceMappingURL=" + this.sourceMapPath);

            // Now output map file
            var mappingsString = "";

            var prevEmittedColumn = 0;
            var prevEmittedLine = 0;
            var prevSourceColumn = 0;
            var prevSourceLine = 0;
            var prevSourceIndex = 0;
            var prevNameIndex = 0;
            var emitComma = false;

            var recordedPosition = null;
            for (var sourceIndex = 0; sourceIndex < this.tsFilePaths.length; sourceIndex++) {
                var recordSourceMapping = function (mappedPosition, nameIndex) {
                    if (recordedPosition !== null && recordedPosition.emittedColumn === mappedPosition.emittedColumn && recordedPosition.emittedLine === mappedPosition.emittedLine) {
                        // This position is already recorded
                        return;
                    }

                    // Record this position
                    if (prevEmittedLine !== mappedPosition.emittedLine) {
                        while (prevEmittedLine < mappedPosition.emittedLine) {
                            prevEmittedColumn = 0;
                            mappingsString = mappingsString + ";";
                            prevEmittedLine++;
                        }
                        emitComma = false;
                    } else if (emitComma) {
                        mappingsString = mappingsString + ",";
                    }

                    _this.sourceMapEntries.push(new SourceMapEntry(_this.jsFileName, mappedPosition.emittedLine + 1, mappedPosition.emittedColumn + 1, _this.tsFilePaths[sourceIndex], mappedPosition.sourceLine, mappedPosition.sourceColumn + 1, nameIndex >= 0 ? _this.names[nameIndex] : undefined));

                    // 1. Relative Column
                    mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(mappedPosition.emittedColumn - prevEmittedColumn);
                    prevEmittedColumn = mappedPosition.emittedColumn;

                    // 2. Relative sourceIndex
                    mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(sourceIndex - prevSourceIndex);
                    prevSourceIndex = sourceIndex;

                    // 3. Relative sourceLine 0 based
                    mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(mappedPosition.sourceLine - 1 - prevSourceLine);
                    prevSourceLine = mappedPosition.sourceLine - 1;

                    // 4. Relative sourceColumn 0 based
                    mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(mappedPosition.sourceColumn - prevSourceColumn);
                    prevSourceColumn = mappedPosition.sourceColumn;

                    // 5. Relative namePosition 0 based
                    if (nameIndex >= 0) {
                        mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(nameIndex - prevNameIndex);
                        prevNameIndex = nameIndex;
                    }

                    emitComma = true;
                    recordedPosition = mappedPosition;
                };

                // Record starting spans
                var recordSourceMappingSiblings = function (sourceMappings) {
                    for (var i = 0; i < sourceMappings.length; i++) {
                        var sourceMapping = sourceMappings[i];
                        recordSourceMapping(sourceMapping.start, sourceMapping.nameIndex);
                        recordSourceMappingSiblings(sourceMapping.childMappings);
                        recordSourceMapping(sourceMapping.end, sourceMapping.nameIndex);
                    }
                };

                recordSourceMappingSiblings(this.allSourceMappings[sourceIndex]);
            }

            // Write the actual map file
            this.sourceMapOut.Write(JSON.stringify({
                version: 3,
                file: this.jsFileName,
                sourceRoot: this.sourceRoot,
                sources: this.tsFilePaths,
                names: this.names,
                mappings: mappingsString
            }));

            // Closing files could result in exceptions, report them if they occur
            this.sourceMapOut.Close();
        };
        SourceMapper.MapFileExtension = ".map";
        return SourceMapper;
    })();
    TypeScript.SourceMapper = SourceMapper;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (EmitContainer) {
        EmitContainer[EmitContainer["Prog"] = 0] = "Prog";
        EmitContainer[EmitContainer["Module"] = 1] = "Module";
        EmitContainer[EmitContainer["DynamicModule"] = 2] = "DynamicModule";
        EmitContainer[EmitContainer["Class"] = 3] = "Class";
        EmitContainer[EmitContainer["Constructor"] = 4] = "Constructor";
        EmitContainer[EmitContainer["Function"] = 5] = "Function";
        EmitContainer[EmitContainer["Args"] = 6] = "Args";
        EmitContainer[EmitContainer["Interface"] = 7] = "Interface";
    })(TypeScript.EmitContainer || (TypeScript.EmitContainer = {}));
    var EmitContainer = TypeScript.EmitContainer;

    var EmitState = (function () {
        function EmitState() {
            this.column = 0;
            this.line = 0;
            this.container = 0 /* Prog */;
        }
        return EmitState;
    })();
    TypeScript.EmitState = EmitState;

    var EmitOptions = (function () {
        function EmitOptions(compiler, resolvePath) {
            this.resolvePath = resolvePath;
            this._diagnostic = null;
            this._settings = null;
            this._commonDirectoryPath = "";
            this._sharedOutputFile = "";
            this._sourceRootDirectory = "";
            this._sourceMapRootDirectory = "";
            this._outputDirectory = "";
            var settings = compiler.compilationSettings();
            this._settings = settings;

            // If the document is an external module, then report if the the user has not
            // provided the right command line option.
            if (settings.moduleGenTarget() === 0 /* Unspecified */) {
                var fileNames = compiler.fileNames();
                for (var i = 0, n = fileNames.length; i < n; i++) {
                    var document = compiler.getDocument(fileNames[i]);
                    if (!document.isDeclareFile() && document.syntaxTree().isExternalModule()) {
                        var errorSpan = TypeScript.externalModuleIndicatorSpan(document.syntaxTree());
                        this._diagnostic = new TypeScript.Diagnostic(document.fileName, document.lineMap(), errorSpan.start(), errorSpan.length(), TypeScript.DiagnosticCode.Cannot_compile_external_modules_unless_the_module_flag_is_provided);

                        return;
                    }
                }
            }

            if (!settings.mapSourceFiles()) {
                // Error to specify --mapRoot or --sourceRoot without mapSourceFiles
                if (settings.mapRoot()) {
                    if (settings.sourceRoot()) {
                        this._diagnostic = new TypeScript.Diagnostic(null, null, 0, 0, TypeScript.DiagnosticCode.Options_mapRoot_and_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option, null);
                        return;
                    } else {
                        this._diagnostic = new TypeScript.Diagnostic(null, null, 0, 0, TypeScript.DiagnosticCode.Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option, null);
                        return;
                    }
                } else if (settings.sourceRoot()) {
                    this._diagnostic = new TypeScript.Diagnostic(null, null, 0, 0, TypeScript.DiagnosticCode.Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option, null);
                    return;
                }
            }

            this._sourceMapRootDirectory = TypeScript.convertToDirectoryPath(TypeScript.switchToForwardSlashes(settings.mapRoot()));
            this._sourceRootDirectory = TypeScript.convertToDirectoryPath(TypeScript.switchToForwardSlashes(settings.sourceRoot()));

            if (settings.outFileOption() || settings.outDirOption() || settings.mapRoot() || settings.sourceRoot()) {
                if (settings.outFileOption()) {
                    this._sharedOutputFile = TypeScript.switchToForwardSlashes(resolvePath(settings.outFileOption()));
                }

                if (settings.outDirOption()) {
                    this._outputDirectory = TypeScript.convertToDirectoryPath(TypeScript.switchToForwardSlashes(resolvePath(settings.outDirOption())));
                }

                // Parse the directory structure
                if (this._outputDirectory || this._sourceMapRootDirectory || this.sourceRootDirectory) {
                    this.determineCommonDirectoryPath(compiler);
                }
            }
        }
        EmitOptions.prototype.diagnostic = function () {
            return this._diagnostic;
        };

        EmitOptions.prototype.commonDirectoryPath = function () {
            return this._commonDirectoryPath;
        };
        EmitOptions.prototype.sharedOutputFile = function () {
            return this._sharedOutputFile;
        };
        EmitOptions.prototype.sourceRootDirectory = function () {
            return this._sourceRootDirectory;
        };
        EmitOptions.prototype.sourceMapRootDirectory = function () {
            return this._sourceMapRootDirectory;
        };
        EmitOptions.prototype.outputDirectory = function () {
            return this._outputDirectory;
        };

        EmitOptions.prototype.compilationSettings = function () {
            return this._settings;
        };

        EmitOptions.prototype.determineCommonDirectoryPath = function (compiler) {
            var commonComponents = [];
            var commonComponentsLength = -1;

            var fileNames = compiler.fileNames();
            for (var i = 0, len = fileNames.length; i < len; i++) {
                var fileName = fileNames[i];
                var document = compiler.getDocument(fileNames[i]);
                var sourceUnit = document.sourceUnit();

                if (!document.isDeclareFile()) {
                    var fileComponents = TypeScript.filePathComponents(fileName);
                    if (commonComponentsLength === -1) {
                        // First time at finding common path
                        // So common path = directory of file
                        commonComponents = fileComponents;
                        commonComponentsLength = commonComponents.length;
                    } else {
                        var updatedPath = false;
                        for (var j = 0; j < commonComponentsLength && j < fileComponents.length; j++) {
                            if (commonComponents[j] !== fileComponents[j]) {
                                // The new components = 0 ... j -1
                                commonComponentsLength = j;
                                updatedPath = true;

                                if (j === 0) {
                                    var isDynamicModuleCompilation = TypeScript.ArrayUtilities.any(fileNames, function (fileName) {
                                        document = compiler.getDocument(fileName);
                                        return !document.isDeclareFile() && document.syntaxTree().isExternalModule();
                                    });

                                    if (this._outputDirectory || this._sourceRootDirectory || (this._sourceMapRootDirectory && (!this._sharedOutputFile || isDynamicModuleCompilation))) {
                                        // Its error to not have common path
                                        this._diagnostic = new TypeScript.Diagnostic(null, null, 0, 0, TypeScript.DiagnosticCode.Cannot_find_the_common_subdirectory_path_for_the_input_files, null);
                                        return;
                                    }

                                    return;
                                }

                                break;
                            }
                        }

                        // If the fileComponent path completely matched and less than already found update the length
                        if (!updatedPath && fileComponents.length < commonComponentsLength) {
                            commonComponentsLength = fileComponents.length;
                        }
                    }
                }
            }

            this._commonDirectoryPath = commonComponents.slice(0, commonComponentsLength).join("/") + "/";
        };
        return EmitOptions;
    })();
    TypeScript.EmitOptions = EmitOptions;

    var Indenter = (function () {
        function Indenter() {
            this.indentAmt = 0;
        }
        Indenter.prototype.increaseIndent = function () {
            this.indentAmt += Indenter.indentStep;
        };

        Indenter.prototype.decreaseIndent = function () {
            this.indentAmt -= Indenter.indentStep;
        };

        Indenter.prototype.getIndent = function () {
            var indentString = Indenter.indentStrings[this.indentAmt];
            if (indentString === undefined) {
                indentString = "";
                for (var i = 0; i < this.indentAmt; i = i + Indenter.indentStep) {
                    indentString += Indenter.indentStepString;
                }
                Indenter.indentStrings[this.indentAmt] = indentString;
            }
            return indentString;
        };
        Indenter.indentStep = 4;
        Indenter.indentStepString = "    ";
        Indenter.indentStrings = [];
        return Indenter;
    })();
    TypeScript.Indenter = Indenter;

    function lastParameterIsRest(parameters) {
        return parameters.length > 0 && (parameters[parameters.length - 1]).dotDotDotToken !== null;
    }
    TypeScript.lastParameterIsRest = lastParameterIsRest;

    var Emitter = (function () {
        function Emitter(emittingFileName, outfile, emitOptions, semanticInfoChain) {
            this.emittingFileName = emittingFileName;
            this.outfile = outfile;
            this.emitOptions = emitOptions;
            this.semanticInfoChain = semanticInfoChain;
            this.globalThisCapturePrologueEmitted = false;
            this.extendsPrologueEmitted = false;
            this.thisClassNode = null;
            this.inArrowFunction = false;
            this.moduleName = "";
            this.emitState = new EmitState();
            this.indenter = new Indenter();
            this.sourceMapper = null;
            this.captureThisStmtString = "var _this = this;";
            this.declStack = [];
            this.exportAssignment = null;
            this.inWithBlock = false;
            this.document = null;
            // If we choose to detach comments from an element (for example, the Copyright comments),
            // then keep track of that element so that we don't emit all on the comments on it when
            // we visit it.
            this.detachedCommentsElement = null;
        }
        Emitter.prototype.pushDecl = function (decl) {
            if (decl) {
                this.declStack[this.declStack.length] = decl;
            }
        };

        Emitter.prototype.popDecl = function (decl) {
            if (decl) {
                this.declStack.length--;
            }
        };

        Emitter.prototype.getEnclosingDecl = function () {
            var declStackLen = this.declStack.length;
            var enclosingDecl = declStackLen > 0 ? this.declStack[declStackLen - 1] : null;
            return enclosingDecl;
        };

        Emitter.prototype.setExportAssignment = function (exportAssignment) {
            this.exportAssignment = exportAssignment;
        };

        Emitter.prototype.getExportAssignment = function () {
            return this.exportAssignment;
        };

        Emitter.prototype.setDocument = function (document) {
            this.document = document;
        };

        Emitter.prototype.shouldEmitImportDeclaration = function (importDeclAST) {
            var isExternalModuleReference = importDeclAST.moduleReference.kind() === 245 /* ExternalModuleReference */;
            var importDecl = this.semanticInfoChain.getDeclForAST(importDeclAST);
            var isExported = TypeScript.hasFlag(importDecl.flags, 1 /* Exported */);
            var isAmdCodeGen = this.emitOptions.compilationSettings().moduleGenTarget() === 2 /* Asynchronous */;

            // 1) Any internal reference needs to check if the emit can happen
            // 2) External module reference with export modifier always needs to be emitted
            // 3) commonjs needs the var declaration for the import declaration
            if (isExternalModuleReference && !isExported && isAmdCodeGen) {
                return false;
            }

            var importSymbol = importDecl.getSymbol(this.semanticInfoChain);
            if (importSymbol.isUsedAsValue()) {
                return true;
            }

            if (importDeclAST.moduleReference.kind() !== 245 /* ExternalModuleReference */) {
                var canBeUsedExternally = isExported || importSymbol.typeUsedExternally() || importSymbol.isUsedInExportedAlias();
                if (!canBeUsedExternally && !this.document.syntaxTree().isExternalModule()) {
                    // top level import in non-external module are visible across the whole global module
                    canBeUsedExternally = TypeScript.hasFlag(importDecl.getParentDecl().kind, TypeScript.PullElementKind.Script | TypeScript.PullElementKind.DynamicModule);
                }

                if (canBeUsedExternally) {
                    if (importSymbol.getExportAssignedValueSymbol()) {
                        return true;
                    }

                    var containerSymbol = importSymbol.getExportAssignedContainerSymbol();
                    if (containerSymbol && containerSymbol.getInstanceSymbol()) {
                        return true;
                    }
                }
            }

            return false;
        };

        Emitter.prototype.emitImportDeclaration = function (importDeclAST) {
            var isExternalModuleReference = importDeclAST.moduleReference.kind() === 245 /* ExternalModuleReference */;
            var importDecl = this.semanticInfoChain.getDeclForAST(importDeclAST);
            var isExported = TypeScript.hasFlag(importDecl.flags, 1 /* Exported */);
            var isAmdCodeGen = this.emitOptions.compilationSettings().moduleGenTarget() === 2 /* Asynchronous */;

            this.emitComments(importDeclAST, true);

            var importSymbol = importDecl.getSymbol(this.semanticInfoChain);

            var parentSymbol = importSymbol.getContainer();
            var parentKind = parentSymbol ? parentSymbol.kind : 0 /* None */;
            var associatedParentSymbol = parentSymbol ? parentSymbol.getAssociatedContainerType() : null;
            var associatedParentSymbolKind = associatedParentSymbol ? associatedParentSymbol.kind : 0 /* None */;

            var needsPropertyAssignment = false;
            var usePropertyAssignmentInsteadOfVarDecl = false;
            var moduleNamePrefix;

            if (isExported && (parentKind === TypeScript.PullElementKind.Container || parentKind === TypeScript.PullElementKind.DynamicModule || associatedParentSymbolKind === TypeScript.PullElementKind.Container || associatedParentSymbolKind === TypeScript.PullElementKind.DynamicModule)) {
                if (importSymbol.getExportAssignedTypeSymbol() || importSymbol.getExportAssignedContainerSymbol()) {
                    // Type or container assignment that is exported
                    needsPropertyAssignment = true;
                } else {
                    var valueSymbol = importSymbol.getExportAssignedValueSymbol();
                    if (valueSymbol && (valueSymbol.kind === TypeScript.PullElementKind.Method || valueSymbol.kind === TypeScript.PullElementKind.Function)) {
                        needsPropertyAssignment = true;
                    } else {
                        usePropertyAssignmentInsteadOfVarDecl = true;
                    }
                }

                // Calculate what name prefix to use
                if (this.emitState.container === 2 /* DynamicModule */) {
                    moduleNamePrefix = "exports.";
                } else {
                    moduleNamePrefix = this.moduleName + ".";
                }
            }

            if (isAmdCodeGen && isExternalModuleReference) {
                // For amdCode gen of exported external module reference, do not emit var declaration
                // Emit the property assignment since it is exported
                needsPropertyAssignment = true;
            } else {
                this.recordSourceMappingStart(importDeclAST);
                if (usePropertyAssignmentInsteadOfVarDecl) {
                    this.writeToOutput(moduleNamePrefix);
                } else {
                    this.writeToOutput("var ");
                }
                this.writeToOutput(importDeclAST.identifier.text() + " = ");
                var aliasAST = importDeclAST.moduleReference;

                if (isExternalModuleReference) {
                    this.writeToOutput("require(" + aliasAST.stringLiteral.text() + ")");
                } else {
                    this.emitJavascript(aliasAST.moduleName, false);
                }

                this.recordSourceMappingEnd(importDeclAST);
                this.writeToOutput(";");

                if (needsPropertyAssignment) {
                    this.writeLineToOutput("");
                    this.emitIndent();
                }
            }

            if (needsPropertyAssignment) {
                this.writeToOutputWithSourceMapRecord(moduleNamePrefix + importDeclAST.identifier.text() + " = " + importDeclAST.identifier.text(), importDeclAST);
                this.writeToOutput(";");
            }
            this.emitComments(importDeclAST, false);
        };

        Emitter.prototype.createSourceMapper = function (document, jsFileName, jsFile, sourceMapOut, resolvePath) {
            this.sourceMapper = new TypeScript.SourceMapper(jsFile, sourceMapOut, document, jsFileName, this.emitOptions, resolvePath);
        };

        Emitter.prototype.setSourceMapperNewSourceFile = function (document) {
            this.sourceMapper.setNewSourceFile(document, this.emitOptions);
        };

        Emitter.prototype.updateLineAndColumn = function (s) {
            var lineNumbers = TypeScript.TextUtilities.parseLineStarts(s);
            if (lineNumbers.length > 1) {
                // There are new lines in the string, update the line and column number accordingly
                this.emitState.line += lineNumbers.length - 1;
                this.emitState.column = s.length - lineNumbers[lineNumbers.length - 1];
            } else {
                // No new lines in the string
                this.emitState.column += s.length;
            }
        };

        Emitter.prototype.writeToOutputWithSourceMapRecord = function (s, astSpan) {
            if (astSpan) {
                this.recordSourceMappingStart(astSpan);
            }

            this.writeToOutput(s);

            if (astSpan) {
                this.recordSourceMappingEnd(astSpan);
            }
        };

        Emitter.prototype.writeToOutput = function (s) {
            this.outfile.Write(s);
            this.updateLineAndColumn(s);
        };

        Emitter.prototype.writeLineToOutput = function (s, force) {
            if (typeof force === "undefined") { force = false; }
            // No need to print a newline if we're already at the start of the line.
            if (!force && s === "" && this.emitState.column === 0) {
                return;
            }

            this.outfile.WriteLine(s);
            this.updateLineAndColumn(s);
            this.emitState.column = 0;
            this.emitState.line++;
        };

        Emitter.prototype.writeCaptureThisStatement = function (ast) {
            this.emitIndent();
            this.writeToOutputWithSourceMapRecord(this.captureThisStmtString, ast);
            this.writeLineToOutput("");
        };

        Emitter.prototype.setContainer = function (c) {
            var temp = this.emitState.container;
            this.emitState.container = c;
            return temp;
        };

        Emitter.prototype.getIndentString = function () {
            return this.indenter.getIndent();
        };

        Emitter.prototype.emitIndent = function () {
            this.writeToOutput(this.getIndentString());
        };

        Emitter.prototype.emitComment = function (comment, trailing, first, noLeadingSpace) {
            if (typeof noLeadingSpace === "undefined") { noLeadingSpace = false; }
            if (this.emitOptions.compilationSettings().removeComments()) {
                return;
            }

            var text = getTrimmedTextLines(comment);
            var emitColumn = this.emitState.column;

            if (emitColumn === 0) {
                this.emitIndent();
            } else if (trailing && first && !noLeadingSpace) {
                this.writeToOutput(" ");
            }

            if (comment.kind() === 6 /* MultiLineCommentTrivia */) {
                this.recordSourceMappingCommentStart(comment);
                this.writeToOutput(text[0]);

                if (text.length > 1 || comment.endsLine) {
                    for (var i = 1; i < text.length; i++) {
                        this.writeLineToOutput("");
                        this.emitIndent();
                        this.writeToOutput(text[i]);
                    }
                    this.recordSourceMappingCommentEnd(comment);
                    this.writeLineToOutput("");
                    // Fall through
                } else {
                    this.recordSourceMappingCommentEnd(comment);
                    this.writeToOutput(" ");
                    return;
                }
            } else {
                this.recordSourceMappingCommentStart(comment);
                this.writeToOutput(text[0]);
                this.recordSourceMappingCommentEnd(comment);
                this.writeLineToOutput("");
                // Fall through
            }

            if (!trailing && emitColumn !== 0) {
                // If we were indented before, stay indented after.
                this.emitIndent();
            }
        };

        Emitter.prototype.text = function () {
            return this.document.syntaxTree().text;
        };

        Emitter.prototype.emitComments = function (ast, pre, onlyPinnedOrTripleSlashComments) {
            var _this = this;
            if (typeof onlyPinnedOrTripleSlashComments === "undefined") { onlyPinnedOrTripleSlashComments = false; }
            // Emitting the comments for the exprssion inside an arrow function is handled specially
            // in emitFunctionBodyStatements.  We don't want to emit those comments a second time.
            if (ast && !TypeScript.isShared(ast) && ast.kind() !== 146 /* Block */) {
                if (ast.parent.kind() === 219 /* SimpleArrowFunctionExpression */ || ast.parent.kind() === 218 /* ParenthesizedArrowFunctionExpression */) {
                    return;
                }
            }

            if (pre) {
                var preComments = TypeScript.ASTHelpers.preComments(ast, this.text());

                if (preComments && ast === this.detachedCommentsElement) {
                    // We're emitting the comments for the first script element.  Skip any
                    // copyright comments, as we'll already have emitted those.
                    var detachedComments = this.getDetachedComments(ast);
                    preComments = preComments.slice(detachedComments.length);
                    this.detachedCommentsElement = null;
                }

                // We're emitting comments on an elided element.  Only keep the comment if it is
                // a triple slash or pinned comment.
                if (preComments && onlyPinnedOrTripleSlashComments) {
                    preComments = TypeScript.ArrayUtilities.where(preComments, function (c) {
                        return _this.isPinnedOrTripleSlash(c);
                    });
                }

                this.emitCommentsArray(preComments, false);
            } else {
                this.emitCommentsArray(TypeScript.ASTHelpers.postComments(ast, this.text()), true);
            }
        };

        Emitter.prototype.isPinnedOrTripleSlash = function (comment) {
            var fullText = comment.fullText();
            if (fullText.match(TypeScript.tripleSlashReferenceRegExp)) {
                return true;
            } else {
                return fullText.indexOf("/*!") === 0;
            }
        };

        Emitter.prototype.emitCommentsArray = function (comments, trailing, noLeadingSpace) {
            if (typeof noLeadingSpace === "undefined") { noLeadingSpace = false; }
            if (!this.emitOptions.compilationSettings().removeComments() && comments) {
                for (var i = 0, n = comments.length; i < n; i++) {
                    this.emitComment(comments[i], trailing, i === 0, noLeadingSpace);
                }
            }
        };

        Emitter.prototype.emitObjectLiteralExpression = function (objectLiteral) {
            this.recordSourceMappingStart(objectLiteral);

            // Try to preserve the newlines between elements that the user had.
            this.writeToken(objectLiteral.openBraceToken);
            this.emitCommaSeparatedList(objectLiteral, objectLiteral.propertyAssignments, " ", true);
            this.writeToken(objectLiteral.closeBraceToken);

            this.recordSourceMappingEnd(objectLiteral);
        };

        Emitter.prototype.emitArrayLiteralExpression = function (arrayLiteral) {
            this.recordSourceMappingStart(arrayLiteral);

            // Try to preserve the newlines between elements that the user had.
            this.writeToken(arrayLiteral.openBracketToken);
            this.emitCommaSeparatedList(arrayLiteral, arrayLiteral.expressions, "", true);
            this.writeToken(arrayLiteral.closeBracketToken);

            this.recordSourceMappingEnd(arrayLiteral);
        };

        Emitter.prototype.emitObjectCreationExpression = function (objectCreationExpression) {
            this.recordSourceMappingStart(objectCreationExpression);
            this.writeToken(objectCreationExpression.newKeyword);
            this.writeToOutput(" ");
            var target = objectCreationExpression.expression;

            this.emit(target);
            if (objectCreationExpression.argumentList) {
                this.recordSourceMappingStart(objectCreationExpression.argumentList);
                this.writeToken(objectCreationExpression.argumentList.openParenToken);
                this.emitCommaSeparatedList(objectCreationExpression.argumentList, objectCreationExpression.argumentList.arguments, "", false);
                this.writeToken(objectCreationExpression.argumentList.closeParenToken);
                this.recordSourceMappingEnd(objectCreationExpression.argumentList);
            }

            this.recordSourceMappingEnd(objectCreationExpression);
        };

        Emitter.prototype.getConstantDecl = function (dotExpr) {
            var pullSymbol = this.semanticInfoChain.getSymbolForAST(dotExpr);
            if (pullSymbol && pullSymbol.kind === TypeScript.PullElementKind.EnumMember) {
                var pullDecls = pullSymbol.getDeclarations();
                if (pullDecls.length === 1) {
                    var pullDecl = pullDecls[0];
                    if (pullDecl.kind === TypeScript.PullElementKind.EnumMember) {
                        return pullDecl;
                    }
                }
            }

            return null;
        };

        Emitter.prototype.tryEmitConstant = function (dotExpr) {
            var propertyName = dotExpr.name;
            var boundDecl = this.getConstantDecl(dotExpr);
            if (boundDecl) {
                var value = boundDecl.constantValue;
                if (value !== null) {
                    this.recordSourceMappingStart(dotExpr);
                    this.writeToOutput(value.toString());
                    var comment = " /* ";
                    comment += propertyName.text();
                    comment += " */";
                    this.writeToOutput(comment);
                    this.recordSourceMappingEnd(dotExpr);
                    return true;
                }
            }

            return false;
        };

        Emitter.prototype.emitInvocationExpression = function (callNode) {
            this.recordSourceMappingStart(callNode);
            var target = callNode.expression;
            var args = callNode.argumentList.arguments;

            if (target.kind() === 212 /* MemberAccessExpression */ && target.expression.kind() === 50 /* SuperKeyword */) {
                this.emit(target);
                this.writeToOutput(".call");
                this.recordSourceMappingStart(args);
                this.writeToken(callNode.argumentList.openParenToken);
                this.emitThis();
                if (args && args.length > 0) {
                    this.writeToOutput(", ");
                    this.emitCommaSeparatedList(callNode.argumentList, args, "", false);
                }
            } else {
                if (callNode.expression.kind() === 50 /* SuperKeyword */ && this.emitState.container === 4 /* Constructor */) {
                    this.writeToOutput("_super.call");
                } else {
                    this.emitJavascript(target, false);
                }
                this.recordSourceMappingStart(args);
                this.writeToken(callNode.argumentList.openParenToken);
                if (callNode.expression.kind() === 50 /* SuperKeyword */ && this.emitState.container === 4 /* Constructor */) {
                    this.writeToOutput("this");
                    if (args && args.length > 0) {
                        this.writeToOutput(", ");
                    }
                }
                this.emitCommaSeparatedList(callNode.argumentList, args, "", false);
            }

            this.writeToken(callNode.argumentList.closeParenToken);
            this.recordSourceMappingEnd(args);
            this.recordSourceMappingEnd(callNode);
        };

        Emitter.prototype.emitParameterList = function (list) {
            this.writeToken(list.openParenToken);
            this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenTrailingComments(list.openParenToken, this.text()), true, true);
            this.emitFunctionParameters(list.parameters, list.parameters);
            this.writeToken(list.closeParenToken);
        };

        Emitter.prototype.emitFunctionParameters = function (ast, parameters) {
            var argsLen = 0;

            if (parameters) {
                this.emitComments(ast, true);

                var tempContainer = this.setContainer(6 /* Args */);
                argsLen = parameters.length;
                var printLen = argsLen;
                if (lastParameterIsRest(parameters)) {
                    printLen--;
                }
                for (var i = 0; i < printLen; i++) {
                    var arg = parameters[i];
                    this.emit(arg);

                    if (i < (printLen - 1)) {
                        this.writeToOutput(", ");
                        if (parameters) {
                            this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenTrailingComments(parameters.separatorAt(i), this.text()), true, true);
                        }
                    }
                }
                this.setContainer(tempContainer);

                this.emitComments(ast, false);
            }
        };

        Emitter.prototype.emitFunctionBodyStatements = function (name, funcDecl, parameters, block, bodyExpression) {
            this.writeLineToOutput(" {");
            if (name) {
                this.recordSourceMappingNameStart(name);
            }

            this.indenter.increaseIndent();

            if (block) {
                // We want any detached statements at the start of hte block to stay at the start.
                // This is important for features like VSDoc which place their comments inside a
                // block, but can't have them preceded by things like "var _this = this" when we
                // emit.
                this.emitDetachedComments(block.statements);
            }

            // Parameter list parameters with defaults could capture this
            if (this.shouldCaptureThis(funcDecl)) {
                this.writeCaptureThisStatement(funcDecl);
            }

            if (parameters) {
                this.emitDefaultValueAssignments(parameters);
                this.emitRestParameterInitializer(parameters);
            }

            if (block) {
                this.emitList(block.statements);
                this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenLeadingComments(block.closeBraceToken, this.text()), false);
            } else {
                // Copy any comments before the body of the arrow function to the return statement.
                // This is necessary for emitting correctness so we don't emit something like this:
                //
                //      return
                //          // foo
                //          this.foo();
                //
                // Because of ASI, this gets parsed as "return;" which is *not* what we want for
                // proper semantics.
                //var preComments = bodyExpression.preComments();
                //var postComments = bodyExpression.postComments();
                //bodyExpression.setPreComments(null);
                //bodyExpression.setPostComments(null);
                this.emitIndent();
                this.emitCommentsArray(TypeScript.ASTHelpers.preComments(bodyExpression, this.text()), false);
                this.writeToOutput("return ");
                this.emit(bodyExpression);
                this.writeLineToOutput(";");
                this.emitCommentsArray(TypeScript.ASTHelpers.preComments(bodyExpression, this.text()), true);
                //bodyExpression.setPreComments(preComments);
                //bodyExpression.setPostComments(postComments);
            }

            this.indenter.decreaseIndent();
            this.emitIndent();

            if (block) {
                this.writeToken(block.closeBraceToken);
            } else {
                this.writeToOutputWithSourceMapRecord("}", bodyExpression);
            }

            if (name) {
                this.recordSourceMappingNameEnd();
            }
        };

        Emitter.prototype.emitDefaultValueAssignments = function (parameters) {
            var n = parameters.length;
            if (lastParameterIsRest(parameters)) {
                n--;
            }

            for (var i = 0; i < n; i++) {
                var arg = parameters[i];
                var id = arg.identifier;
                var equalsValueClause = arg.equalsValueClause;
                if (equalsValueClause) {
                    this.emitIndent();
                    this.recordSourceMappingStart(arg);
                    this.writeToOutput("if (typeof " + id.text() + " === \"undefined\") { "); //
                    this.writeToken(id);
                    this.emitJavascript(equalsValueClause, false);
                    this.writeLineToOutput("; }");
                    this.recordSourceMappingEnd(arg);
                }
            }
        };

        Emitter.prototype.emitRestParameterInitializer = function (parameters) {
            if (lastParameterIsRest(parameters)) {
                var n = parameters.length;
                var lastArg = parameters[n - 1];
                var id = lastArg.identifier;
                this.emitIndent();
                this.recordSourceMappingStart(lastArg);
                this.writeToOutput("var ");
                this.writeToken(id);
                this.writeLineToOutput(" = [];");
                this.recordSourceMappingEnd(lastArg);
                this.emitIndent();
                this.writeToOutput("for (");
                this.writeToOutputWithSourceMapRecord("var _i = 0;", lastArg);
                this.writeToOutput(" ");
                this.writeToOutputWithSourceMapRecord("_i < (arguments.length - " + (n - 1) + ")", lastArg);
                this.writeToOutput("; ");
                this.writeToOutputWithSourceMapRecord("_i++", lastArg);
                this.writeLineToOutput(") {");
                this.indenter.increaseIndent();
                this.emitIndent();

                this.writeToOutputWithSourceMapRecord(id.text() + "[_i] = arguments[_i + " + (n - 1) + "];", lastArg);
                this.writeLineToOutput("");
                this.indenter.decreaseIndent();
                this.emitIndent();
                this.writeLineToOutput("}");
            }
        };

        Emitter.prototype.getImportDecls = function (fileName) {
            var topLevelDecl = this.semanticInfoChain.topLevelDecl(this.document.fileName);
            var result = [];

            var dynamicModuleDecl = topLevelDecl.getChildDecls()[0];
            var queue = dynamicModuleDecl.getChildDecls();

            for (var i = 0, n = queue.length; i < n; i++) {
                var decl = queue[i];

                if (decl.kind & TypeScript.PullElementKind.TypeAlias) {
                    var importStatementAST = this.semanticInfoChain.getASTForDecl(decl);
                    if (importStatementAST.moduleReference.kind() === 245 /* ExternalModuleReference */) {
                        var symbol = decl.getSymbol(this.semanticInfoChain);
                        var typeSymbol = symbol && symbol.type;
                        if (typeSymbol && typeSymbol !== this.semanticInfoChain.anyTypeSymbol && !typeSymbol.isError()) {
                            result.push(decl);
                        }
                    }
                }
            }

            return result;
        };

        Emitter.prototype.getModuleImportAndDependencyList = function (sourceUnit) {
            var importList = "";
            var dependencyList = "";

            var importDecls = this.getImportDecls(this.document.fileName);

            // all dependencies are quoted
            if (importDecls.length) {
                for (var i = 0; i < importDecls.length; i++) {
                    var importStatementDecl = importDecls[i];
                    var importStatementSymbol = importStatementDecl.getSymbol(this.semanticInfoChain);
                    var importStatementAST = this.semanticInfoChain.getASTForDecl(importStatementDecl);

                    if (importStatementSymbol.isUsedAsValue()) {
                        if (i <= importDecls.length - 1) {
                            dependencyList += ", ";
                            importList += ", ";
                        }

                        importList += importStatementDecl.name;
                        dependencyList += importStatementAST.moduleReference.stringLiteral.text();
                    }
                }
            }

            // emit any potential amd dependencies
            var amdDependencies = this.document.syntaxTree().amdDependencies();
            for (var i = 0; i < amdDependencies.length; i++) {
                dependencyList += ", \"" + amdDependencies[i] + "\"";
            }

            return {
                importList: importList,
                dependencyList: dependencyList
            };
        };

        Emitter.prototype.shouldCaptureThis = function (ast) {
            if (ast.kind() === 120 /* SourceUnit */) {
                var scriptDecl = this.semanticInfoChain.topLevelDecl(this.document.fileName);
                return TypeScript.hasFlag(scriptDecl.flags, TypeScript.PullElementFlags.MustCaptureThis);
            }

            var decl = this.semanticInfoChain.getDeclForAST(ast);
            if (decl) {
                return TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.MustCaptureThis);
            }

            return false;
        };

        Emitter.prototype.emitEnum = function (moduleDecl) {
            var pullDecl = this.semanticInfoChain.getDeclForAST(moduleDecl);
            this.pushDecl(pullDecl);

            var svModuleName = this.moduleName;
            this.moduleName = moduleDecl.identifier.text();

            var temp = this.setContainer(1 /* Module */);
            var isExported = TypeScript.hasFlag(pullDecl.flags, 1 /* Exported */);

            if (!isExported) {
                this.recordSourceMappingStart(moduleDecl);
                this.writeToOutput("var ");
                this.writeToOutputWithSourceMapRecord(this.moduleName, moduleDecl.identifier);
                this.writeLineToOutput(";");
                this.recordSourceMappingEnd(moduleDecl);
                this.emitIndent();
            }

            this.writeToOutput("(");
            this.recordSourceMappingStart(moduleDecl);
            this.writeToOutput("function (");
            this.writeToOutputWithSourceMapRecord(this.moduleName, moduleDecl.identifier);
            this.writeLineToOutput(") {");

            this.recordSourceMappingNameStart(this.moduleName);

            this.indenter.increaseIndent();

            if (this.shouldCaptureThis(moduleDecl)) {
                this.writeCaptureThisStatement(moduleDecl);
            }

            this.emitSeparatedList(moduleDecl.enumElements);
            this.indenter.decreaseIndent();
            this.emitIndent();

            var parentIsDynamic = temp === 2 /* DynamicModule */;
            if (temp === 0 /* Prog */ && isExported) {
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.writeToOutput(")(this." + this.moduleName + " || (this." + this.moduleName + " = {}));");
            } else if (isExported || temp === 0 /* Prog */) {
                var dotMod = svModuleName !== "" ? (parentIsDynamic ? "exports" : svModuleName) + "." : svModuleName;
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.writeToOutput(")(" + dotMod + this.moduleName + " || (" + dotMod + this.moduleName + " = {}));");
            } else if (!isExported && temp !== 0 /* Prog */) {
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.writeToOutput(")(" + this.moduleName + " || (" + this.moduleName + " = {}));");
            } else {
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.writeToOutput(")();");
            }

            this.recordSourceMappingEnd(moduleDecl);
            if (temp !== 0 /* Prog */ && isExported) {
                this.recordSourceMappingStart(moduleDecl);
                if (parentIsDynamic) {
                    this.writeLineToOutput("");
                    this.emitIndent();
                    this.writeToOutput("var " + this.moduleName + " = exports." + this.moduleName + ";");
                } else {
                    this.writeLineToOutput("");
                    this.emitIndent();
                    this.writeToOutput("var " + this.moduleName + " = " + svModuleName + "." + this.moduleName + ";");
                }
                this.recordSourceMappingEnd(moduleDecl);
            }

            this.setContainer(temp);
            this.moduleName = svModuleName;

            this.popDecl(pullDecl);
        };

        Emitter.prototype.getModuleDeclToVerifyChildNameCollision = function (moduleDecl, changeNameIfAnyDeclarationInContext) {
            if (TypeScript.ArrayUtilities.contains(this.declStack, moduleDecl)) {
                // Given decl is in the scope, we would need to check for child name collision
                return moduleDecl;
            } else if (changeNameIfAnyDeclarationInContext) {
                // Check if any other declaration of the given symbol is in scope
                // (eg. when emitting expression of type defined from different declaration in reopened module)
                var symbol = moduleDecl.getSymbol(this.semanticInfoChain);
                if (symbol) {
                    var otherDecls = symbol.getDeclarations();
                    for (var i = 0; i < otherDecls.length; i++) {
                        // If the other decl is in the scope, use this decl to determine which name to display
                        if (TypeScript.ArrayUtilities.contains(this.declStack, otherDecls[i])) {
                            return otherDecls[i];
                        }
                    }
                }
            }

            return null;
        };

        Emitter.prototype.hasChildNameCollision = function (moduleName, parentDecl) {
            var _this = this;
            var childDecls = parentDecl.getChildDecls();
            return TypeScript.ArrayUtilities.any(childDecls, function (childDecl) {
                var childAST = _this.semanticInfoChain.getASTForDecl(childDecl);

                // Enum member it can never conflict with module name as it is property of the enum
                // Only if this child would be emitted we need to look further in
                if (childDecl.kind != TypeScript.PullElementKind.EnumMember && _this.shouldEmit(childAST)) {
                    // same name child
                    if (childDecl.name === moduleName) {
                        // collision if the parent was not class
                        if (parentDecl.kind != TypeScript.PullElementKind.Class) {
                            return true;
                        }

                        // If the parent was class, we would find name collision if this was not a property/method/accessor
                        if (!(childDecl.kind == TypeScript.PullElementKind.Method || childDecl.kind == TypeScript.PullElementKind.Property || childDecl.kind == TypeScript.PullElementKind.SetAccessor || childDecl.kind == TypeScript.PullElementKind.GetAccessor)) {
                            return true;
                        }
                    }

                    // Check if the name collision exists in any of the children
                    if (_this.hasChildNameCollision(moduleName, childDecl)) {
                        return true;
                    }
                }
                return false;
            });
        };

        // Get the moduleName to write in js file
        // If changeNameIfAnyDeclarationInContext is true, verify if any of the declarations for the symbol would need rename.
        Emitter.prototype.getModuleName = function (moduleDecl, changeNameIfAnyDeclarationInContext) {
            var moduleName = moduleDecl.name;
            var moduleDisplayName = moduleDecl.getDisplayName();

            // If the decl is in stack it may need name change in the js file
            moduleDecl = this.getModuleDeclToVerifyChildNameCollision(moduleDecl, changeNameIfAnyDeclarationInContext);
            if (moduleDecl && moduleDecl.kind != TypeScript.PullElementKind.Enum) {
                while (this.hasChildNameCollision(moduleName, moduleDecl)) {
                    // there was name collision with member which could result in faulty codegen, try rename with prepend of '_'
                    moduleName = "_" + moduleName;
                    moduleDisplayName = "_" + moduleDisplayName;
                }
            }

            return moduleDisplayName;
        };

        Emitter.prototype.emitModuleDeclarationWorker = function (moduleDecl) {
            if (moduleDecl.stringLiteral) {
                this.emitSingleModuleDeclaration(moduleDecl, moduleDecl.stringLiteral);
            } else {
                var moduleNames = TypeScript.ASTHelpers.getModuleNames(moduleDecl.name);
                this.emitSingleModuleDeclaration(moduleDecl, moduleNames[0]);
            }
        };

        Emitter.prototype.writeToken = function (token) {
            if (token) {
                this.writeToOutputWithSourceMapRecord(token.text(), token);
            }
        };

        Emitter.prototype.emitSingleModuleDeclaration = function (moduleDecl, moduleName) {
            var isLastName = TypeScript.ASTHelpers.isLastNameOfModule(moduleDecl, moduleName);

            if (isLastName) {
                // Doc Comments on the ast belong to the innermost module being emitted.
                this.emitComments(moduleDecl, true);
            }

            var pullDecl = this.semanticInfoChain.getDeclForAST(moduleName);
            this.pushDecl(pullDecl);

            var svModuleName = this.moduleName;

            if (moduleDecl.stringLiteral) {
                this.moduleName = TypeScript.tokenValueText(moduleDecl.stringLiteral);
                if (TypeScript.isTSFile(this.moduleName)) {
                    this.moduleName = this.moduleName.substring(0, this.moduleName.length - ".ts".length);
                }
            } else {
                this.moduleName = moduleName.text();
            }

            var temp = this.setContainer(1 /* Module */);
            var isExported = TypeScript.hasFlag(pullDecl.flags, 1 /* Exported */);

            // prologue
            if (!isExported) {
                this.recordSourceMappingStart(moduleDecl);
                this.writeToOutput("var ");
                this.writeToOutputWithSourceMapRecord(this.moduleName, moduleName);
                this.writeLineToOutput(";");
                this.recordSourceMappingEnd(moduleDecl);
                this.emitIndent();
            }

            this.writeToOutput("(");
            this.recordSourceMappingStart(moduleDecl);
            this.writeToOutput("function (");

            // Use the name that doesnt conflict with its members,
            // this.moduleName needs to be updated to make sure that export member declaration is emitted correctly
            this.moduleName = this.getModuleName(pullDecl);
            this.writeToOutputWithSourceMapRecord(this.moduleName, moduleName);
            this.writeLineToOutput(") {");

            this.recordSourceMappingNameStart(moduleName.text());

            this.indenter.increaseIndent();

            if (this.shouldCaptureThis(moduleDecl)) {
                this.writeCaptureThisStatement(moduleDecl);
            }

            if (moduleName === moduleDecl.stringLiteral) {
                this.emitList(moduleDecl.moduleElements);
            } else {
                var moduleNames = TypeScript.ASTHelpers.getModuleNames(moduleDecl.name);
                var nameIndex = moduleNames.indexOf(moduleName);

                TypeScript.Debug.assert(nameIndex >= 0);

                if (isLastName) {
                    // If we're on the innermost module, we can emit the module elements.
                    this.emitList(moduleDecl.moduleElements);
                } else {
                    // otherwise, just recurse and emit the next module in the A.B.C module name.
                    this.emitIndent();
                    this.emitSingleModuleDeclaration(moduleDecl, moduleNames[nameIndex + 1]);
                    this.writeLineToOutput("");
                }
            }

            this.moduleName = moduleName.text();
            this.indenter.decreaseIndent();
            this.emitIndent();

            // epilogue
            var parentIsDynamic = temp === 2 /* DynamicModule */;
            this.recordSourceMappingStart(moduleDecl.closeBraceToken);
            if (temp === 0 /* Prog */ && isExported) {
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.recordSourceMappingEnd(moduleDecl.closeBraceToken);
                this.writeToOutput(")(this." + this.moduleName + " || (this." + this.moduleName + " = {}));");
            } else if (isExported || temp === 0 /* Prog */) {
                var dotMod = svModuleName !== "" ? (parentIsDynamic ? "exports" : svModuleName) + "." : svModuleName;
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.recordSourceMappingEnd(moduleDecl.closeBraceToken);
                this.writeToOutput(")(" + dotMod + this.moduleName + " || (" + dotMod + this.moduleName + " = {}));");
            } else if (!isExported && temp !== 0 /* Prog */) {
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.recordSourceMappingEnd(moduleDecl.closeBraceToken);
                this.writeToOutput(")(" + this.moduleName + " || (" + this.moduleName + " = {}));");
            } else {
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.recordSourceMappingEnd(moduleDecl.closeBraceToken);
                this.writeToOutput(")();");
            }

            this.recordSourceMappingEnd(moduleDecl);
            if (temp !== 0 /* Prog */ && isExported) {
                this.recordSourceMappingStart(moduleDecl);
                if (parentIsDynamic) {
                    this.writeLineToOutput("");
                    this.emitIndent();
                    this.writeToOutput("var " + this.moduleName + " = exports." + this.moduleName + ";");
                } else {
                    this.writeLineToOutput("");
                    this.emitIndent();
                    this.writeToOutput("var " + this.moduleName + " = " + svModuleName + "." + this.moduleName + ";");
                }
                this.recordSourceMappingEnd(moduleDecl);
            }

            this.setContainer(temp);
            this.moduleName = svModuleName;

            this.popDecl(pullDecl);

            if (isLastName) {
                // Comments on the module ast belong to the innermost module being emitted.
                this.emitComments(moduleDecl, false);
            }
        };

        Emitter.prototype.emitEnumElement = function (varDecl) {
            // <EnumName>[<EnumName>["<MemberName>"] = <MemberValue>] = "<MemberName>";
            var pullDecl = this.semanticInfoChain.getDeclForAST(varDecl);
            TypeScript.Debug.assert(pullDecl && pullDecl.kind === TypeScript.PullElementKind.EnumMember);

            this.emitComments(varDecl, true);
            this.recordSourceMappingStart(varDecl);

            var representation = (varDecl.propertyName.kind() === 14 /* StringLiteral */) ? varDecl.propertyName.text() : ('"' + TypeScript.tokenValueText(varDecl.propertyName) + '"');

            this.writeToOutput(this.moduleName);
            this.writeToOutput('[');
            this.writeToOutput(this.moduleName);
            this.writeToOutput('[');
            this.writeToOutput(representation);
            this.writeToOutput(']');

            if (varDecl.equalsValueClause) {
                this.emit(varDecl.equalsValueClause);
            } else if (pullDecl.constantValue !== null) {
                this.writeToOutput(' = ');
                this.writeToOutput(pullDecl.constantValue.toString());
            } else {
                this.writeToOutput(' = null');
            }

            this.writeToOutput('] = ');
            this.writeToOutput(representation);
            this.recordSourceMappingEnd(varDecl);
            this.emitComments(varDecl, false);
            this.writeToOutput(';');
        };

        Emitter.prototype.emitElementAccessExpression = function (expression) {
            this.recordSourceMappingStart(expression);
            this.emit(expression.expression);
            this.writeToken(expression.openBracketToken);
            this.emit(expression.argumentExpression);
            this.writeToken(expression.closeBracketToken);
            this.recordSourceMappingEnd(expression);
        };

        Emitter.prototype.emitSimpleArrowFunctionExpression = function (arrowFunction) {
            this.emitAnyArrowFunctionExpression(arrowFunction, arrowFunction.block, arrowFunction.expression);
        };

        Emitter.prototype.emitParenthesizedArrowFunctionExpression = function (arrowFunction) {
            this.emitAnyArrowFunctionExpression(arrowFunction, arrowFunction.block, arrowFunction.expression);
        };

        Emitter.prototype.emitAnyArrowFunctionExpression = function (arrowFunction, block, expression) {
            var savedInArrowFunction = this.inArrowFunction;
            this.inArrowFunction = true;

            var temp = this.setContainer(5 /* Function */);

            this.recordSourceMappingStart(arrowFunction);

            // Start
            var pullDecl = this.semanticInfoChain.getDeclForAST(arrowFunction);
            this.pushDecl(pullDecl);

            this.emitComments(arrowFunction, true);

            this.recordSourceMappingStart(arrowFunction);
            this.writeToOutput("function ");

            var parameters = null;
            if (arrowFunction.kind() === 218 /* ParenthesizedArrowFunctionExpression */) {
                var parenthesizedArrowFunction = arrowFunction;

                parameters = parenthesizedArrowFunction.callSignature.parameterList.parameters;
                this.emitParameterList(parenthesizedArrowFunction.callSignature.parameterList);
            } else {
                var parameter = arrowFunction.parameter;
                parameters = [parameter];
                this.writeToOutput("(");
                this.emitFunctionParameters(parameter, parameters);
                this.writeToOutput(")");
            }

            this.emitFunctionBodyStatements(null, arrowFunction, parameters, block, expression);

            this.recordSourceMappingEnd(arrowFunction);

            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it
            this.recordSourceMappingEnd(arrowFunction);

            this.emitComments(arrowFunction, false);

            this.popDecl(pullDecl);
            this.setContainer(temp);
            this.inArrowFunction = savedInArrowFunction;
        };

        Emitter.prototype.emitConstructor = function (funcDecl) {
            if (!funcDecl.block) {
                return;
            }
            var temp = this.setContainer(4 /* Constructor */);

            this.recordSourceMappingStart(funcDecl);

            var pullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            this.pushDecl(pullDecl);

            this.emitComments(funcDecl, true);

            this.recordSourceMappingStart(funcDecl);
            this.writeToOutput("function ");
            this.writeToOutput(this.thisClassNode.identifier.text());

            this.emitParameterList(funcDecl.callSignature.parameterList);
            this.writeLineToOutput(" {");

            this.recordSourceMappingNameStart("constructor");
            this.indenter.increaseIndent();

            var parameters = funcDecl.callSignature.parameterList.parameters;
            this.emitDefaultValueAssignments(parameters);
            this.emitRestParameterInitializer(parameters);

            if (this.shouldCaptureThis(funcDecl)) {
                this.writeCaptureThisStatement(funcDecl);
            }

            this.emitConstructorStatements(funcDecl);
            this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenLeadingComments(funcDecl.block.closeBraceToken, this.text()), false);

            this.indenter.decreaseIndent();
            this.emitIndent();
            this.writeToken(funcDecl.block.closeBraceToken);

            this.recordSourceMappingNameEnd();
            this.recordSourceMappingEnd(funcDecl);

            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it
            this.recordSourceMappingEnd(funcDecl);

            this.emitComments(funcDecl, false);

            this.popDecl(pullDecl);
            this.setContainer(temp);
        };

        Emitter.prototype.emitGetAccessor = function (accessor) {
            this.recordSourceMappingStart(accessor);
            this.writeToOutput("get ");

            var temp = this.setContainer(5 /* Function */);

            this.recordSourceMappingStart(accessor);

            var pullDecl = this.semanticInfoChain.getDeclForAST(accessor);
            this.pushDecl(pullDecl);

            this.recordSourceMappingStart(accessor);

            var accessorSymbol = TypeScript.PullHelpers.getAccessorSymbol(accessor, this.semanticInfoChain);
            var container = accessorSymbol.getContainer();
            var containerKind = container.kind;

            this.recordSourceMappingNameStart(accessor.propertyName.text());
            this.writeToOutput(accessor.propertyName.text());
            this.emitParameterList(accessor.callSignature.parameterList);

            this.emitFunctionBodyStatements(null, accessor, accessor.callSignature.parameterList.parameters, accessor.block, null);

            this.recordSourceMappingEnd(accessor);

            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it
            this.recordSourceMappingEnd(accessor);

            this.popDecl(pullDecl);
            this.setContainer(temp);
            this.recordSourceMappingEnd(accessor);
        };

        Emitter.prototype.emitSetAccessor = function (accessor) {
            this.recordSourceMappingStart(accessor);
            this.writeToOutput("set ");

            var temp = this.setContainer(5 /* Function */);

            this.recordSourceMappingStart(accessor);

            var pullDecl = this.semanticInfoChain.getDeclForAST(accessor);
            this.pushDecl(pullDecl);

            this.recordSourceMappingStart(accessor);

            var accessorSymbol = TypeScript.PullHelpers.getAccessorSymbol(accessor, this.semanticInfoChain);
            var container = accessorSymbol.getContainer();
            var containerKind = container.kind;

            this.recordSourceMappingNameStart(accessor.propertyName.text());
            this.writeToOutput(accessor.propertyName.text());

            this.emitParameterList(accessor.callSignature.parameterList);

            this.emitFunctionBodyStatements(null, accessor, accessor.callSignature.parameterList.parameters, accessor.block, null);

            this.recordSourceMappingEnd(accessor);

            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it
            this.recordSourceMappingEnd(accessor);

            this.popDecl(pullDecl);
            this.setContainer(temp);
            this.recordSourceMappingEnd(accessor);
        };

        Emitter.prototype.emitFunctionExpression = function (funcDecl) {
            var savedInArrowFunction = this.inArrowFunction;
            this.inArrowFunction = false;

            var temp = this.setContainer(5 /* Function */);

            var funcName = funcDecl.identifier ? funcDecl.identifier.text() : null;

            this.recordSourceMappingStart(funcDecl);

            var pullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            this.pushDecl(pullDecl);

            this.recordSourceMappingStart(funcDecl);
            this.writeToken(funcDecl.functionKeyword);
            this.writeToOutput(" ");

            //var id = funcDecl.getNameText();
            if (funcDecl.identifier) {
                this.writeToOutputWithSourceMapRecord(funcDecl.identifier.text(), funcDecl.identifier);
            }

            this.emitParameterList(funcDecl.callSignature.parameterList);
            this.emitFunctionBodyStatements(funcName, funcDecl, funcDecl.callSignature.parameterList.parameters, funcDecl.block, null);

            this.recordSourceMappingEnd(funcDecl);

            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it
            this.recordSourceMappingEnd(funcDecl);

            this.emitComments(funcDecl, false);

            this.popDecl(pullDecl);

            this.setContainer(temp);
            this.inArrowFunction = savedInArrowFunction;
        };

        Emitter.prototype.emitFunction = function (funcDecl) {
            if (funcDecl.block === null) {
                return;
            }
            var savedInArrowFunction = this.inArrowFunction;
            this.inArrowFunction = false;

            var temp = this.setContainer(5 /* Function */);

            var funcName = funcDecl.identifier.text();

            this.recordSourceMappingStart(funcDecl);

            var printName = funcDecl.identifier !== null;
            var pullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            this.pushDecl(pullDecl);

            this.emitComments(funcDecl, true);

            this.recordSourceMappingStart(funcDecl);
            this.writeToken(funcDecl.functionKeyword);
            this.writeToOutput(" ");

            if (printName) {
                var id = funcDecl.identifier.text();
                if (id) {
                    if (funcDecl.identifier) {
                        this.recordSourceMappingStart(funcDecl.identifier);
                    }
                    this.writeToOutput(id);
                    if (funcDecl.identifier) {
                        this.recordSourceMappingEnd(funcDecl.identifier);
                    }
                }
            }

            this.emitParameterList(funcDecl.callSignature.parameterList);

            var parameters = funcDecl.callSignature.parameterList.parameters;
            this.emitFunctionBodyStatements(funcDecl.identifier.text(), funcDecl, parameters, funcDecl.block, null);

            this.recordSourceMappingEnd(funcDecl);

            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it
            this.recordSourceMappingEnd(funcDecl);

            this.emitComments(funcDecl, false);

            this.popDecl(pullDecl);

            this.setContainer(temp);
            this.inArrowFunction = savedInArrowFunction;

            if (funcDecl.block) {
                var pullFunctionDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
                if ((this.emitState.container === 1 /* Module */ || this.emitState.container === 2 /* DynamicModule */) && pullFunctionDecl && TypeScript.hasFlag(pullFunctionDecl.flags, 1 /* Exported */)) {
                    this.writeLineToOutput("");
                    this.emitIndent();
                    var modName = this.emitState.container === 1 /* Module */ ? this.moduleName : "exports";
                    this.recordSourceMappingStart(funcDecl);
                    this.writeToOutput(modName + "." + funcName + " = " + funcName + ";");
                    this.recordSourceMappingEnd(funcDecl);
                }
            }
        };

        Emitter.prototype.emitAmbientVarDecl = function (varDecl) {
            this.recordSourceMappingStart(this.currentVariableDeclaration);
            if (varDecl.equalsValueClause) {
                this.emitComments(varDecl, true);
                this.recordSourceMappingStart(varDecl);
                this.writeToOutputWithSourceMapRecord(varDecl.propertyName.text(), varDecl.propertyName);
                this.emitJavascript(varDecl.equalsValueClause, false);
                this.recordSourceMappingEnd(varDecl);
                this.emitComments(varDecl, false);
            }
        };

        // Emits "var " if it is allowed
        Emitter.prototype.emitVarDeclVar = function () {
            if (this.currentVariableDeclaration) {
                this.writeToOutput("var ");
            }
        };

        Emitter.prototype.emitVariableDeclaration = function (declaration) {
            var varDecl = declaration.variableDeclarators[0];

            var symbol = this.semanticInfoChain.getSymbolForAST(varDecl);

            var parentSymbol = symbol ? symbol.getContainer() : null;
            var parentKind = parentSymbol ? parentSymbol.kind : 0 /* None */;

            this.emitComments(declaration, true);

            var pullVarDecl = this.semanticInfoChain.getDeclForAST(varDecl);
            var isAmbientWithoutInit = pullVarDecl && TypeScript.hasFlag(pullVarDecl.flags, TypeScript.PullElementFlags.Ambient) && varDecl.equalsValueClause === null;
            if (!isAmbientWithoutInit) {
                var prevVariableDeclaration = this.currentVariableDeclaration;
                this.currentVariableDeclaration = declaration;

                for (var i = 0, n = declaration.variableDeclarators.length; i < n; i++) {
                    var declarator = declaration.variableDeclarators[i];

                    if (i > 0) {
                        this.writeToOutput(", ");
                    }

                    this.emit(declarator);
                }
                this.currentVariableDeclaration = prevVariableDeclaration;

                // Declarator emit would take care of emitting start of the variable declaration start
                this.recordSourceMappingEnd(declaration);
            }

            this.emitComments(declaration, false);
        };

        Emitter.prototype.emitMemberVariableDeclaration = function (varDecl) {
            TypeScript.Debug.assert(!TypeScript.hasModifier(varDecl.modifiers, TypeScript.PullElementFlags.Static) && varDecl.variableDeclarator.equalsValueClause);

            var pullDecl = this.semanticInfoChain.getDeclForAST(varDecl);
            this.pushDecl(pullDecl);

            this.emitComments(varDecl, true);
            this.recordSourceMappingStart(varDecl);

            var varDeclName = varDecl.variableDeclarator.propertyName.text();
            var quotedOrNumber = TypeScript.isQuoted(varDeclName) || varDecl.variableDeclarator.propertyName.kind() !== 11 /* IdentifierName */;

            var symbol = this.semanticInfoChain.getSymbolForAST(varDecl);
            var parentSymbol = symbol ? symbol.getContainer() : null;
            var parentDecl = pullDecl && pullDecl.getParentDecl();

            if (quotedOrNumber) {
                this.writeToOutput("this[");
            } else {
                this.writeToOutput("this.");
            }

            this.writeToOutputWithSourceMapRecord(varDecl.variableDeclarator.propertyName.text(), varDecl.variableDeclarator.propertyName);

            if (quotedOrNumber) {
                this.writeToOutput("]");
            }

            if (varDecl.variableDeclarator.equalsValueClause) {
                // Ensure we have a fresh var list count when recursing into the variable
                // initializer.  We don't want our current list of variables to affect how we
                // emit nested variable lists.
                var prevVariableDeclaration = this.currentVariableDeclaration;
                this.emit(varDecl.variableDeclarator.equalsValueClause);
                this.currentVariableDeclaration = prevVariableDeclaration;
            }

            // class
            if (this.emitState.container !== 6 /* Args */) {
                this.writeToOutput(";");
            }

            this.recordSourceMappingEnd(varDecl);
            this.emitComments(varDecl, false);

            this.popDecl(pullDecl);
        };

        Emitter.prototype.emitVariableDeclarator = function (varDecl) {
            var pullDecl = this.semanticInfoChain.getDeclForAST(varDecl);
            this.pushDecl(pullDecl);
            if (pullDecl && (pullDecl.flags & TypeScript.PullElementFlags.Ambient) === TypeScript.PullElementFlags.Ambient) {
                this.emitAmbientVarDecl(varDecl);
            } else {
                this.emitComments(varDecl, true);
                this.recordSourceMappingStart(this.currentVariableDeclaration);
                this.recordSourceMappingStart(varDecl);

                var varDeclName = varDecl.propertyName.text();

                var symbol = this.semanticInfoChain.getSymbolForAST(varDecl);
                var parentSymbol = symbol ? symbol.getContainer() : null;
                var parentDecl = pullDecl && pullDecl.getParentDecl();
                var parentIsModule = parentDecl && (parentDecl.flags & TypeScript.PullElementFlags.SomeInitializedModule);

                if (parentIsModule) {
                    // module
                    if (!TypeScript.hasFlag(pullDecl.flags, 1 /* Exported */)) {
                        this.emitVarDeclVar();
                    } else {
                        if (this.emitState.container === 2 /* DynamicModule */) {
                            this.writeToOutput("exports.");
                        } else {
                            this.writeToOutput(this.moduleName + ".");
                        }
                    }
                } else {
                    this.emitVarDeclVar();
                }

                this.writeToOutputWithSourceMapRecord(varDecl.propertyName.text(), varDecl.propertyName);

                if (varDecl.equalsValueClause) {
                    // Ensure we have a fresh var list count when recursing into the variable
                    // initializer.  We don't want our current list of variables to affect how we
                    // emit nested variable lists.
                    var prevVariableDeclaration = this.currentVariableDeclaration;
                    this.emit(varDecl.equalsValueClause);
                    this.currentVariableDeclaration = prevVariableDeclaration;
                }

                this.recordSourceMappingEnd(varDecl);
                this.emitComments(varDecl, false);
            }
            this.currentVariableDeclaration = undefined;
            this.popDecl(pullDecl);
        };

        Emitter.prototype.symbolIsUsedInItsEnclosingContainer = function (symbol, dynamic) {
            if (typeof dynamic === "undefined") { dynamic = false; }
            var symDecls = symbol.getDeclarations();

            if (symDecls.length) {
                var enclosingDecl = this.getEnclosingDecl();
                if (enclosingDecl) {
                    var parentDecl = symDecls[0].getParentDecl();
                    if (parentDecl) {
                        var symbolDeclarationEnclosingContainer = parentDecl;
                        var enclosingContainer = enclosingDecl;

                        while (symbolDeclarationEnclosingContainer) {
                            if (symbolDeclarationEnclosingContainer.kind === (dynamic ? TypeScript.PullElementKind.DynamicModule : TypeScript.PullElementKind.Container)) {
                                break;
                            }
                            symbolDeclarationEnclosingContainer = symbolDeclarationEnclosingContainer.getParentDecl();
                        }

                        // if the symbol in question is not a global, compute the nearest
                        // enclosing declaration from the point of usage
                        if (symbolDeclarationEnclosingContainer) {
                            while (enclosingContainer) {
                                if (enclosingContainer.kind === (dynamic ? TypeScript.PullElementKind.DynamicModule : TypeScript.PullElementKind.Container)) {
                                    break;
                                }

                                enclosingContainer = enclosingContainer.getParentDecl();
                            }
                        }

                        if (symbolDeclarationEnclosingContainer && enclosingContainer) {
                            var same = symbolDeclarationEnclosingContainer === enclosingContainer;

                            // initialized module object variables are bound to their parent's decls
                            if (!same && symbol.anyDeclHasFlag(TypeScript.PullElementFlags.InitializedModule)) {
                                same = symbolDeclarationEnclosingContainer === enclosingContainer.getParentDecl();
                            }

                            return same;
                        }
                    }
                }
            }

            return false;
        };

        // In some cases, when emitting a name, the emitter needs to qualify a symbol
        // name by first emitting its parent's name. This generally happens when the
        // name referenced is in scope in TypeScript, but not in Javascript. This is true
        // in any of the following 3 cases:
        // - It is an enum member, even if accessed from within the enum declaration in which it is defined
        // - It is an exported var, even if accessed from within the module declaration in which it is defined
        // - It is an exported member of the current module, but is never defined in this particular module
        // declaration (i.e. it is only defined in other components of the same merged module)
        Emitter.prototype.shouldQualifySymbolNameWithParentName = function (symbol) {
            var enclosingContextDeclPath = this.declStack;
            var symbolDeclarations = symbol.getDeclarations();
            for (var i = 0; i < symbolDeclarations.length; i++) {
                var currentDecl = symbolDeclarations[i];
                var declParent = currentDecl.getParentDecl();

                if (currentDecl.kind === TypeScript.PullElementKind.EnumMember) {
                    return true;
                }

                // All decls of the same symbol must agree on whether they are exported
                // If one decl is not exported, none of them are, and it is safe to
                // assume it is just a local
                if (!TypeScript.hasFlag(currentDecl.flags, 1 /* Exported */)) {
                    return false;
                }

                // Section 10.6:
                // When a variable is exported, all references to the variable in the body of the
                // module are replaced with
                //    <ModuleName>.< VariableName>
                if (currentDecl.kind === TypeScript.PullElementKind.Variable && !TypeScript.hasFlag(currentDecl.flags, TypeScript.PullElementFlags.ImplicitVariable)) {
                    return true;
                }

                if (TypeScript.ArrayUtilities.contains(this.declStack, declParent)) {
                    return false;
                }
            }

            return true;
        };

        // Get the symbol information to be used for emitting the ast
        Emitter.prototype.getSymbolForEmit = function (ast) {
            var pullSymbol = this.semanticInfoChain.getSymbolForAST(ast);
            var pullSymbolAlias = this.semanticInfoChain.getAliasSymbolForAST(ast);
            if (pullSymbol && pullSymbolAlias) {
                var symbolToCompare = TypeScript.isTypesOnlyLocation(ast) ? pullSymbolAlias.getExportAssignedTypeSymbol() : pullSymbolAlias.getExportAssignedValueSymbol();

                if (pullSymbol === symbolToCompare) {
                    pullSymbol = pullSymbolAlias;
                    pullSymbolAlias = null;
                }
            }
            return { symbol: pullSymbol, aliasSymbol: pullSymbolAlias };
        };

        Emitter.prototype.emitName = function (name, addThis) {
            this.emitComments(name, true);
            this.recordSourceMappingStart(name);
            if (name.text().length > 0) {
                var symbolForEmit = this.getSymbolForEmit(name);
                var pullSymbol = symbolForEmit.symbol;
                if (!pullSymbol) {
                    pullSymbol = this.semanticInfoChain.anyTypeSymbol;
                }
                var pullSymbolAlias = symbolForEmit.aliasSymbol;
                var pullSymbolKind = pullSymbol.kind;
                var isLocalAlias = pullSymbolAlias && (pullSymbolAlias.getDeclarations()[0].getParentDecl() === this.getEnclosingDecl());
                if (addThis && (this.emitState.container !== 6 /* Args */) && pullSymbol) {
                    var pullSymbolContainer = pullSymbol.getContainer();

                    if (pullSymbolContainer) {
                        var pullSymbolContainerKind = pullSymbolContainer.kind;

                        if (TypeScript.PullHelpers.symbolIsModule(pullSymbolContainer) || pullSymbolContainerKind === TypeScript.PullElementKind.Enum || pullSymbolContainer.anyDeclHasFlag(TypeScript.PullElementFlags.InitializedModule | TypeScript.PullElementFlags.Enum)) {
                            var needToEmitParentName = this.shouldQualifySymbolNameWithParentName(pullSymbol);
                            if (needToEmitParentName) {
                                var parentDecl = pullSymbol.getDeclarations()[0].getParentDecl();
                                TypeScript.Debug.assert(parentDecl && !parentDecl.isRootDecl());
                                this.writeToOutput(this.getModuleName(parentDecl, true) + ".");
                            }
                        } else if (pullSymbolContainerKind === TypeScript.PullElementKind.DynamicModule || pullSymbolContainer.anyDeclHasFlag(TypeScript.PullElementFlags.InitializedDynamicModule)) {
                            if (pullSymbolKind === TypeScript.PullElementKind.Property) {
                                // If dynamic module
                                this.writeToOutput("exports.");
                            } else if (pullSymbol.anyDeclHasFlag(1 /* Exported */) && !isLocalAlias && !pullSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.ImplicitVariable) && pullSymbol.kind !== TypeScript.PullElementKind.ConstructorMethod && pullSymbol.kind !== TypeScript.PullElementKind.Class && pullSymbol.kind !== TypeScript.PullElementKind.Enum) {
                                this.writeToOutput("exports.");
                            }
                        }
                    }
                }

                this.writeToOutput(name.text());
            }

            this.recordSourceMappingEnd(name);
            this.emitComments(name, false);
        };

        Emitter.prototype.recordSourceMappingNameStart = function (name) {
            if (this.sourceMapper) {
                var nameIndex = -1;
                if (name) {
                    if (this.sourceMapper.currentNameIndex.length > 0) {
                        var parentNameIndex = this.sourceMapper.currentNameIndex[this.sourceMapper.currentNameIndex.length - 1];
                        if (parentNameIndex !== -1) {
                            name = this.sourceMapper.names[parentNameIndex] + "." + name;
                        }
                    }

                    // Look if there already exists name
                    var nameIndex = this.sourceMapper.names.length - 1;
                    for (nameIndex; nameIndex >= 0; nameIndex--) {
                        if (this.sourceMapper.names[nameIndex] === name) {
                            break;
                        }
                    }

                    if (nameIndex === -1) {
                        nameIndex = this.sourceMapper.names.length;
                        this.sourceMapper.names.push(name);
                    }
                }
                this.sourceMapper.currentNameIndex.push(nameIndex);
            }
        };

        Emitter.prototype.recordSourceMappingNameEnd = function () {
            if (this.sourceMapper) {
                this.sourceMapper.currentNameIndex.pop();
            }
        };

        Emitter.prototype.recordSourceMappingStart = function (ast) {
            if (this.sourceMapper && TypeScript.ASTHelpers.isValidAstNode(ast)) {
                var text = this.text();
                this.recordSourceMappingSpanStart(ast, TypeScript.start(ast, text), TypeScript.end(ast, text));
            }
        };

        Emitter.prototype.recordSourceMappingCommentStart = function (comment) {
            this.recordSourceMappingSpanStart(comment, comment.start(), comment.end());
        };

        Emitter.prototype.recordSourceMappingSpanStart = function (ast, start, end) {
            if (this.sourceMapper && ast && start !== -1 && end !== -1) {
                var lineCol = { line: -1, character: -1 };
                var sourceMapping = new TypeScript.SourceMapping();
                sourceMapping.start.emittedColumn = this.emitState.column;
                sourceMapping.start.emittedLine = this.emitState.line;

                // REVIEW: check time consumed by this binary search (about two per leaf statement)
                var lineMap = this.document.lineMap();
                lineMap.fillLineAndCharacterFromPosition(start, lineCol);
                sourceMapping.start.sourceColumn = lineCol.character;
                sourceMapping.start.sourceLine = lineCol.line + 1;
                lineMap.fillLineAndCharacterFromPosition(end, lineCol);
                sourceMapping.end.sourceColumn = lineCol.character;
                sourceMapping.end.sourceLine = lineCol.line + 1;

                TypeScript.Debug.assert(!isNaN(sourceMapping.start.emittedColumn));
                TypeScript.Debug.assert(!isNaN(sourceMapping.start.emittedLine));
                TypeScript.Debug.assert(!isNaN(sourceMapping.start.sourceColumn));
                TypeScript.Debug.assert(!isNaN(sourceMapping.start.sourceLine));
                TypeScript.Debug.assert(!isNaN(sourceMapping.end.sourceColumn));
                TypeScript.Debug.assert(!isNaN(sourceMapping.end.sourceLine));

                if (this.sourceMapper.currentNameIndex.length > 0) {
                    sourceMapping.nameIndex = this.sourceMapper.currentNameIndex[this.sourceMapper.currentNameIndex.length - 1];
                }

                // Set parent and child relationship
                var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];
                siblings.push(sourceMapping);
                this.sourceMapper.currentMappings.push(sourceMapping.childMappings);
                this.sourceMapper.increaseMappingLevel(ast);
            }
        };

        Emitter.prototype.recordSourceMappingEnd = function (ast) {
            if (this.sourceMapper && TypeScript.ASTHelpers.isValidAstNode(ast)) {
                var text = this.text();
                this.recordSourceMappingSpanEnd(ast, TypeScript.start(ast, text), TypeScript.end(ast, text));
            }
        };

        Emitter.prototype.recordSourceMappingCommentEnd = function (ast) {
            if (this.sourceMapper && TypeScript.ASTHelpers.isValidSpan(ast)) {
                this.recordSourceMappingSpanEnd(ast, ast.start(), ast.end());
            }
        };

        Emitter.prototype.recordSourceMappingSpanEnd = function (ast, start, end) {
            if (this.sourceMapper && ast && start !== -1 && end !== -1) {
                // Pop source mapping childs
                this.sourceMapper.currentMappings.pop();

                // Get the last source mapping from sibling list = which is the one we are recording end for
                var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];
                var sourceMapping = siblings[siblings.length - 1];

                sourceMapping.end.emittedColumn = this.emitState.column;
                sourceMapping.end.emittedLine = this.emitState.line;

                TypeScript.Debug.assert(!isNaN(sourceMapping.end.emittedColumn));
                TypeScript.Debug.assert(!isNaN(sourceMapping.end.emittedLine));

                this.sourceMapper.decreaseMappingLevel(ast);
            }
        };

        // Note: may throw exception.
        Emitter.prototype.getOutputFiles = function () {
            // Output a source mapping.  As long as we haven't gotten any errors yet.
            var result = [];
            if (this.sourceMapper !== null) {
                this.sourceMapper.emitSourceMapping();
                result.push(this.sourceMapper.getOutputFile());
            }

            result.push(this.outfile.getOutputFile());
            return result;
        };

        Emitter.prototype.emitParameterPropertyAndMemberVariableAssignments = function () {
            // emit any parameter properties first
            var constructorDecl = getLastConstructor(this.thisClassNode);

            if (constructorDecl) {
                for (var i = 0, n = constructorDecl.callSignature.parameterList.parameters.length; i < n; i++) {
                    var parameter = constructorDecl.callSignature.parameterList.parameters[i];

                    var parameterDecl = this.semanticInfoChain.getDeclForAST(parameter);
                    if (TypeScript.hasFlag(parameterDecl.flags, TypeScript.PullElementFlags.PropertyParameter)) {
                        this.emitIndent();
                        this.recordSourceMappingStart(parameter);
                        this.writeToOutputWithSourceMapRecord("this." + parameter.identifier.text(), parameter.identifier);
                        this.writeToOutput(" = ");
                        this.writeToOutputWithSourceMapRecord(parameter.identifier.text(), parameter.identifier);
                        this.writeLineToOutput(";");
                        this.recordSourceMappingEnd(parameter);
                    }
                }
            }

            for (var i = 0, n = this.thisClassNode.classElements.length; i < n; i++) {
                if (this.thisClassNode.classElements[i].kind() === 136 /* MemberVariableDeclaration */) {
                    var varDecl = this.thisClassNode.classElements[i];
                    if (!TypeScript.hasModifier(varDecl.modifiers, TypeScript.PullElementFlags.Static) && varDecl.variableDeclarator.equalsValueClause) {
                        this.emitIndent();
                        this.emitMemberVariableDeclaration(varDecl);
                        this.writeLineToOutput("");
                    }
                }
            }
        };

        Emitter.prototype.isOnSameLine = function (pos1, pos2) {
            if (pos1 < 0 || pos2 < 0) {
                // Missing element.  Assume it's on the same line as the other element.
                return true;
            }

            var lineMap = this.document.lineMap();
            return lineMap.getLineNumberFromPosition(pos1) === lineMap.getLineNumberFromPosition(pos2);
        };

        Emitter.prototype.emitCommaSeparatedList = function (parent, list, buffer, preserveNewLines) {
            if (list === null || list.length === 0) {
                return;
            }

            // If the first element isn't on hte same line as the parent node, then we need to
            // start with a newline.
            var text = this.text();
            var startLine = preserveNewLines && !this.isOnSameLine(TypeScript.end(parent, text), TypeScript.end(list[0], text));

            if (preserveNewLines) {
                // Any elements on a new line will have to be indented.
                this.indenter.increaseIndent();
            }

            // If we're starting on a newline, then emit an actual newline. Otherwise write out
            // the buffer character before hte first element.
            if (startLine) {
                this.writeLineToOutput("");
            } else {
                this.writeToOutput(buffer);
            }

            for (var i = 0, n = list.length; i < n; i++) {
                var emitNode = list[i];

                // Write out the element, emitting an indent if we're on a new line.
                this.emitJavascript(emitNode, startLine);

                if (i < (n - 1)) {
                    // If the next element start on a different line than this element ended on,
                    // then we want to start on a newline.  Emit the comma with a newline.
                    // Otherwise, emit the comma with the space.
                    startLine = preserveNewLines && !this.isOnSameLine(TypeScript.end(emitNode, text), TypeScript.start(list[i + 1], text));
                    if (startLine) {
                        this.writeLineToOutput(",");
                    } else {
                        this.writeToOutput(", ");
                    }
                }
            }

            if (preserveNewLines) {
                // We're done with all the elements.  Return the indent back to where it was.
                this.indenter.decreaseIndent();
            }

            // If the last element isn't on the same line as the parent, then emit a newline
            // after the last element and emit our indent so the list's terminator will be
            // on the right line.  Otherwise, emit the buffer string between the last value
            // and the terminator.
            if (preserveNewLines && !this.isOnSameLine(TypeScript.end(parent, text), TypeScript.end(list[list.length - 1], text))) {
                this.writeLineToOutput("");
                this.emitIndent();
            } else {
                this.writeToOutput(buffer);
            }
        };

        Emitter.prototype.emitList = function (list, useNewLineSeparator, startInclusive, endExclusive) {
            if (typeof useNewLineSeparator === "undefined") { useNewLineSeparator = true; }
            if (typeof startInclusive === "undefined") { startInclusive = 0; }
            if (typeof endExclusive === "undefined") { endExclusive = list.length; }
            if (list === null) {
                return;
            }

            this.emitComments(list, true);
            var lastEmittedNode = null;

            for (var i = startInclusive; i < endExclusive; i++) {
                var node = list[i];

                if (this.shouldEmit(node)) {
                    this.emitSpaceBetweenConstructs(lastEmittedNode, node);

                    this.emitJavascript(node, true);
                    if (useNewLineSeparator) {
                        this.writeLineToOutput("");
                    }

                    lastEmittedNode = node;
                }
            }

            this.emitComments(list, false);
        };

        Emitter.prototype.emitSeparatedList = function (list, useNewLineSeparator, startInclusive, endExclusive) {
            if (typeof useNewLineSeparator === "undefined") { useNewLineSeparator = true; }
            if (typeof startInclusive === "undefined") { startInclusive = 0; }
            if (typeof endExclusive === "undefined") { endExclusive = list.length; }
            if (list === null) {
                return;
            }

            this.emitComments(list, true);
            var lastEmittedNode = null;

            for (var i = startInclusive; i < endExclusive; i++) {
                var node = list[i];

                if (this.shouldEmit(node)) {
                    this.emitSpaceBetweenConstructs(lastEmittedNode, node);

                    this.emitJavascript(node, true);
                    if (useNewLineSeparator) {
                        this.writeLineToOutput("");
                    }

                    lastEmittedNode = node;
                }
            }

            this.emitComments(list, false);
        };

        Emitter.prototype.isDirectivePrologueElement = function (node) {
            if (node.kind() === 149 /* ExpressionStatement */) {
                var exprStatement = node;
                return exprStatement.expression.kind() === 14 /* StringLiteral */;
            }

            return false;
        };

        // If these two constructs had more than one line between them originally, then emit at
        // least one blank line between them.
        Emitter.prototype.emitSpaceBetweenConstructs = function (node1, node2) {
            if (node1 === null || node2 === null) {
                return;
            }

            var text = this.text();
            if (TypeScript.start(node1, text) === -1 || TypeScript.end(node1, text) === -1 || TypeScript.start(node2, text) === -1 || TypeScript.end(node2, text) === -1) {
                return;
            }

            var lineMap = this.document.lineMap();
            var node1EndLine = lineMap.getLineNumberFromPosition(TypeScript.end(node1, text));
            var node2StartLine = lineMap.getLineNumberFromPosition(TypeScript.start(node2, text));

            if ((node2StartLine - node1EndLine) > 1) {
                this.writeLineToOutput("", true);
            }
        };

        // We consider a sequence of comments to be a detached from an ast if there are no blank lines
        // between them, and there is a blank line after the last one and the node they're attached
        // to.
        Emitter.prototype.getDetachedComments = function (element) {
            var text = this.text();
            var preComments = TypeScript.ASTHelpers.preComments(element, text);
            if (preComments) {
                var lineMap = this.document.lineMap();

                var detachedComments = [];
                var lastComment = null;

                for (var i = 0, n = preComments.length; i < n; i++) {
                    var comment = preComments[i];

                    if (lastComment) {
                        var lastCommentLine = lineMap.getLineNumberFromPosition(lastComment.end());
                        var commentLine = lineMap.getLineNumberFromPosition(comment.start());

                        if (commentLine >= lastCommentLine + 2) {
                            // There was a blank line between the last comment and this comment.  This
                            // comment is not part of the copyright comments.  Return what we have so
                            // far.
                            return detachedComments;
                        }
                    }

                    detachedComments.push(comment);
                    lastComment = comment;
                }

                // All comments look like they could have been part of the copyright header.  Make
                // sure there is at least one blank line between it and the node.  If not, it's not
                // a copyright header.
                var lastCommentLine = lineMap.getLineNumberFromPosition(TypeScript.ArrayUtilities.last(detachedComments).end());
                var astLine = lineMap.getLineNumberFromPosition(TypeScript.start(element, text));
                if (astLine >= lastCommentLine + 2) {
                    return detachedComments;
                }
            }

            // No usable copyright comments found.
            return [];
        };

        Emitter.prototype.emitPossibleCopyrightHeaders = function (script) {
            this.emitDetachedComments(script.moduleElements);
        };

        Emitter.prototype.emitDetachedComments = function (list) {
            if (list.length > 0) {
                var firstElement = TypeScript.childAt(list, 0);

                this.detachedCommentsElement = firstElement;
                this.emitCommentsArray(this.getDetachedComments(this.detachedCommentsElement), false);
            }
        };

        Emitter.prototype.emitScriptElements = function (sourceUnit) {
            var list = sourceUnit.moduleElements;

            this.emitPossibleCopyrightHeaders(sourceUnit);

            for (var i = 0, n = list.length; i < n; i++) {
                var node = list[i];

                if (!this.isDirectivePrologueElement(node)) {
                    break;
                }

                this.emitJavascript(node, true);
                this.writeLineToOutput("");
            }

            // Now emit __extends or a _this capture if necessary.
            this.emitPrologue(sourceUnit);

            var isExternalModule = this.document.syntaxTree().isExternalModule();
            var isNonElidedExternalModule = isExternalModule && !TypeScript.ASTHelpers.scriptIsElided(sourceUnit);
            if (isNonElidedExternalModule) {
                this.recordSourceMappingStart(sourceUnit);

                if (this.emitOptions.compilationSettings().moduleGenTarget() === 2 /* Asynchronous */) {
                    var dependencyList = "[\"require\", \"exports\"";
                    var importList = "require, exports";

                    var importAndDependencyList = this.getModuleImportAndDependencyList(sourceUnit);
                    importList += importAndDependencyList.importList;
                    dependencyList += importAndDependencyList.dependencyList + "]";

                    this.writeLineToOutput("define(" + dependencyList + "," + " function(" + importList + ") {");
                }
            }

            if (isExternalModule) {
                var temp = this.setContainer(2 /* DynamicModule */);

                var svModuleName = this.moduleName;
                this.moduleName = TypeScript.syntaxTree(sourceUnit).fileName();
                if (TypeScript.isTSFile(this.moduleName)) {
                    this.moduleName = this.moduleName.substring(0, this.moduleName.length - ".ts".length);
                }

                // if the external module has an "export =" identifier, we'll
                // set it in the ExportAssignment emit method
                this.setExportAssignment(null);

                if (this.emitOptions.compilationSettings().moduleGenTarget() === 2 /* Asynchronous */) {
                    this.indenter.increaseIndent();
                }

                var externalModule = this.semanticInfoChain.getDeclForAST(this.document.sourceUnit());

                if (TypeScript.hasFlag(externalModule.flags, TypeScript.PullElementFlags.MustCaptureThis)) {
                    this.writeCaptureThisStatement(sourceUnit);
                }

                this.pushDecl(externalModule);
            }

            this.emitList(list, true, i, n);

            if (isExternalModule) {
                if (this.emitOptions.compilationSettings().moduleGenTarget() === 2 /* Asynchronous */) {
                    this.indenter.decreaseIndent();
                }

                if (isNonElidedExternalModule) {
                    var exportAssignment = this.getExportAssignment();
                    var exportAssignmentIdentifierText = exportAssignment ? exportAssignment.identifier.text() : null;
                    var exportAssignmentValueSymbol = externalModule.getSymbol(this.semanticInfoChain).getExportAssignedValueSymbol();

                    if (this.emitOptions.compilationSettings().moduleGenTarget() === 2 /* Asynchronous */) {
                        if (exportAssignmentIdentifierText && exportAssignmentValueSymbol && !(exportAssignmentValueSymbol.kind & TypeScript.PullElementKind.SomeTypeReference)) {
                            // indent was decreased for AMD above
                            this.indenter.increaseIndent();
                            this.emitIndent();
                            this.writeToOutputWithSourceMapRecord("return " + exportAssignmentIdentifierText, exportAssignment);
                            this.writeLineToOutput(";");
                            this.indenter.decreaseIndent();
                        }
                        this.writeToOutput("});");
                    } else if (exportAssignmentIdentifierText && exportAssignmentValueSymbol && !(exportAssignmentValueSymbol.kind & TypeScript.PullElementKind.SomeTypeReference)) {
                        this.emitIndent();
                        this.writeToOutputWithSourceMapRecord("module.exports = " + exportAssignmentIdentifierText, exportAssignment);
                        this.writeToOutput(";");
                    }

                    this.recordSourceMappingEnd(sourceUnit);
                    this.writeLineToOutput("");
                }

                this.setContainer(temp);
                this.moduleName = svModuleName;
                this.popDecl(externalModule);
            }
        };

        Emitter.prototype.emitConstructorStatements = function (funcDecl) {
            var list = funcDecl.block.statements;

            if (list === null) {
                return;
            }

            this.emitComments(list, true);

            var emitPropertyAssignmentsAfterSuperCall = TypeScript.ASTHelpers.getExtendsHeritageClause(this.thisClassNode.heritageClauses) !== null;
            var propertyAssignmentIndex = emitPropertyAssignmentsAfterSuperCall ? 1 : 0;
            var lastEmittedNode = null;

            for (var i = 0, n = list.length; i < n; i++) {
                // In some circumstances, class property initializers must be emitted immediately after the 'super' constructor
                // call which, in these cases, must be the first statement in the constructor body
                if (i === propertyAssignmentIndex) {
                    this.emitParameterPropertyAndMemberVariableAssignments();
                }

                var node = list[i];

                if (this.shouldEmit(node)) {
                    this.emitSpaceBetweenConstructs(lastEmittedNode, node);

                    this.emitJavascript(node, true);
                    this.writeLineToOutput("");

                    lastEmittedNode = node;
                }
            }

            if (i === propertyAssignmentIndex) {
                this.emitParameterPropertyAndMemberVariableAssignments();
            }

            this.emitComments(list, false);
        };

        // tokenId is the id the preceding token
        Emitter.prototype.emitJavascript = function (ast, startLine) {
            if (ast === null) {
                return;
            }

            if (startLine && this.indenter.indentAmt > 0) {
                this.emitIndent();
            }

            this.emit(ast);
        };

        Emitter.prototype.emitAccessorMemberDeclaration = function (funcDecl, name, className, isProto) {
            if (funcDecl.kind() !== 139 /* GetAccessor */) {
                var accessorSymbol = TypeScript.PullHelpers.getAccessorSymbol(funcDecl, this.semanticInfoChain);
                if (accessorSymbol.getGetter()) {
                    return;
                }
            }

            this.emitIndent();
            this.recordSourceMappingStart(funcDecl);

            this.writeToOutput("Object.defineProperty(" + className);
            if (isProto) {
                this.writeToOutput(".prototype, ");
            } else {
                this.writeToOutput(", ");
            }

            var functionName = name.text();
            if (TypeScript.isQuoted(functionName)) {
                this.writeToOutput(functionName);
            } else {
                this.writeToOutput('"' + functionName + '"');
            }

            this.writeLineToOutput(", {");

            this.indenter.increaseIndent();

            var accessors = TypeScript.PullHelpers.getGetterAndSetterFunction(funcDecl, this.semanticInfoChain);
            if (accessors.getter) {
                this.emitIndent();
                this.recordSourceMappingStart(accessors.getter);
                this.emitComments(accessors.getter, true);
                this.writeToOutput("get: ");
                this.emitAccessorBody(accessors.getter, accessors.getter.callSignature.parameterList, accessors.getter.block);
                this.writeLineToOutput(",");
            }

            if (accessors.setter) {
                this.emitIndent();
                this.recordSourceMappingStart(accessors.setter);
                this.emitComments(accessors.setter, true);
                this.writeToOutput("set: ");
                this.emitAccessorBody(accessors.setter, accessors.setter.callSignature.parameterList, accessors.setter.block);
                this.writeLineToOutput(",");
            }

            this.emitIndent();
            this.writeLineToOutput("enumerable: true,");
            this.emitIndent();
            this.writeLineToOutput("configurable: true");
            this.indenter.decreaseIndent();
            this.emitIndent();
            this.writeLineToOutput("});");
            this.recordSourceMappingEnd(funcDecl);
        };

        Emitter.prototype.emitAccessorBody = function (funcDecl, parameterList, block) {
            var pullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            this.pushDecl(pullDecl);

            this.recordSourceMappingStart(funcDecl);
            this.writeToOutput("function ");
            this.emitParameterList(parameterList);

            var parameters = parameterList.parameters;
            this.emitFunctionBodyStatements(null, funcDecl, parameters, block, null);

            this.recordSourceMappingEnd(funcDecl);

            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it
            this.recordSourceMappingEnd(funcDecl);
            this.popDecl(pullDecl);
        };

        Emitter.prototype.emitClass = function (classDecl) {
            var pullDecl = this.semanticInfoChain.getDeclForAST(classDecl);
            this.pushDecl(pullDecl);

            var svClassNode = this.thisClassNode;
            this.thisClassNode = classDecl;
            var className = classDecl.identifier.text();
            this.emitComments(classDecl, true);
            var temp = this.setContainer(3 /* Class */);

            this.recordSourceMappingStart(classDecl);
            this.writeToOutput("var " + className);

            var hasBaseClass = TypeScript.ASTHelpers.getExtendsHeritageClause(classDecl.heritageClauses) !== null;
            var baseTypeReference = null;
            var varDecl = null;

            if (hasBaseClass) {
                this.writeLineToOutput(" = (function (_super) {");
            } else {
                this.writeLineToOutput(" = (function () {");
            }

            this.recordSourceMappingNameStart(className);
            this.indenter.increaseIndent();

            if (hasBaseClass) {
                baseTypeReference = TypeScript.ASTHelpers.getExtendsHeritageClause(classDecl.heritageClauses).typeNames[0];
                this.emitIndent();
                this.writeToOutputWithSourceMapRecord("__extends(" + className + ", _super)", baseTypeReference);
                this.writeLineToOutput(";");
            }

            this.emitIndent();

            var constrDecl = getLastConstructor(classDecl);

            // output constructor
            if (constrDecl) {
                // declared constructor
                this.emit(constrDecl);
                this.writeLineToOutput("");
            } else {
                this.recordSourceMappingStart(classDecl);

                // default constructor
                this.indenter.increaseIndent();
                this.writeLineToOutput("function " + classDecl.identifier.text() + "() {");
                this.recordSourceMappingNameStart("constructor");
                if (hasBaseClass) {
                    this.emitIndent();
                    this.writeToOutputWithSourceMapRecord("_super.apply(this, arguments)", baseTypeReference);
                    this.writeLineToOutput(";");
                }

                if (this.shouldCaptureThis(classDecl)) {
                    this.writeCaptureThisStatement(classDecl);
                }

                this.emitParameterPropertyAndMemberVariableAssignments();

                this.indenter.decreaseIndent();
                this.emitIndent();
                this.writeToken(classDecl.closeBraceToken);
                this.writeLineToOutput("");

                this.recordSourceMappingNameEnd();
                this.recordSourceMappingEnd(classDecl);
            }

            this.emitClassMembers(classDecl);

            this.emitIndent();
            this.writeToOutputWithSourceMapRecord("return " + className + ";", classDecl.closeBraceToken);
            this.writeLineToOutput("");
            this.indenter.decreaseIndent();
            this.emitIndent();
            this.writeToken(classDecl.closeBraceToken);
            this.recordSourceMappingNameEnd();
            this.recordSourceMappingStart(classDecl);
            this.writeToOutput(")(");
            if (hasBaseClass) {
                this.emitJavascript(baseTypeReference, false);
            }
            this.writeToOutput(");");
            this.recordSourceMappingEnd(classDecl);

            if ((temp === 1 /* Module */ || temp === 2 /* DynamicModule */) && TypeScript.hasFlag(pullDecl.flags, 1 /* Exported */)) {
                this.writeLineToOutput("");
                this.emitIndent();
                var modName = temp === 1 /* Module */ ? this.moduleName : "exports";
                this.writeToOutputWithSourceMapRecord(modName + "." + className + " = " + className + ";", classDecl);
            }

            this.recordSourceMappingEnd(classDecl);
            this.emitComments(classDecl, false);
            this.setContainer(temp);
            this.thisClassNode = svClassNode;

            this.popDecl(pullDecl);
        };

        Emitter.prototype.emitClassMembers = function (classDecl) {
            // First, emit all the functions.
            var lastEmittedMember = null;

            for (var i = 0, n = classDecl.classElements.length; i < n; i++) {
                var memberDecl = classDecl.classElements[i];

                if (memberDecl.kind() === 139 /* GetAccessor */) {
                    this.emitSpaceBetweenConstructs(lastEmittedMember, memberDecl);
                    var getter = memberDecl;
                    this.emitAccessorMemberDeclaration(getter, getter.propertyName, classDecl.identifier.text(), !TypeScript.hasModifier(getter.modifiers, TypeScript.PullElementFlags.Static));
                    lastEmittedMember = memberDecl;
                } else if (memberDecl.kind() === 140 /* SetAccessor */) {
                    this.emitSpaceBetweenConstructs(lastEmittedMember, memberDecl);
                    var setter = memberDecl;
                    this.emitAccessorMemberDeclaration(setter, setter.propertyName, classDecl.identifier.text(), !TypeScript.hasModifier(setter.modifiers, TypeScript.PullElementFlags.Static));
                    lastEmittedMember = memberDecl;
                } else if (memberDecl.kind() === 135 /* MemberFunctionDeclaration */) {
                    var memberFunction = memberDecl;

                    if (memberFunction.block) {
                        this.emitSpaceBetweenConstructs(lastEmittedMember, memberDecl);

                        this.emitClassMemberFunctionDeclaration(classDecl, memberFunction);
                        lastEmittedMember = memberDecl;
                    }
                }
            }

            for (var i = 0, n = classDecl.classElements.length; i < n; i++) {
                var memberDecl = classDecl.classElements[i];

                if (memberDecl.kind() === 136 /* MemberVariableDeclaration */) {
                    var varDecl = memberDecl;

                    if (TypeScript.hasModifier(varDecl.modifiers, TypeScript.PullElementFlags.Static) && varDecl.variableDeclarator.equalsValueClause) {
                        this.emitSpaceBetweenConstructs(lastEmittedMember, varDecl);

                        this.emitIndent();
                        this.recordSourceMappingStart(varDecl);

                        this.emitComments(varDecl, true);
                        var varDeclName = varDecl.variableDeclarator.propertyName.text();
                        if (TypeScript.isQuoted(varDeclName) || varDecl.variableDeclarator.propertyName.kind() !== 11 /* IdentifierName */) {
                            this.writeToOutput(classDecl.identifier.text() + "[" + varDeclName + "]");
                        } else {
                            this.writeToOutput(classDecl.identifier.text() + "." + varDeclName);
                        }

                        this.emit(varDecl.variableDeclarator.equalsValueClause);

                        this.recordSourceMappingEnd(varDecl);
                        this.writeLineToOutput(";");

                        lastEmittedMember = varDecl;
                    }
                }
            }
        };

        Emitter.prototype.emitClassMemberFunctionDeclaration = function (classDecl, funcDecl) {
            this.emitIndent();
            this.recordSourceMappingStart(funcDecl);
            this.emitComments(funcDecl, true);
            var functionName = funcDecl.propertyName.text();

            this.writeToOutput(classDecl.identifier.text());

            if (!TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Static)) {
                this.writeToOutput(".prototype");
            }

            if (TypeScript.isQuoted(functionName) || funcDecl.propertyName.kind() !== 11 /* IdentifierName */) {
                this.writeToOutput("[" + functionName + "] = ");
            } else {
                this.writeToOutput("." + functionName + " = ");
            }

            var pullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            this.pushDecl(pullDecl);

            this.recordSourceMappingStart(funcDecl);
            this.writeToOutput("function ");

            this.emitParameterList(funcDecl.callSignature.parameterList);

            var parameters = funcDecl.callSignature.parameterList.parameters;
            this.emitFunctionBodyStatements(funcDecl.propertyName.text(), funcDecl, parameters, funcDecl.block, null);

            this.recordSourceMappingEnd(funcDecl);

            this.emitComments(funcDecl, false);

            this.recordSourceMappingEnd(funcDecl);
            this.popDecl(pullDecl);

            this.writeLineToOutput(";");
        };

        Emitter.prototype.requiresExtendsBlock = function (moduleElements) {
            for (var i = 0, n = moduleElements.length; i < n; i++) {
                var moduleElement = moduleElements[i];

                if (moduleElement.kind() === 130 /* ModuleDeclaration */) {
                    var moduleAST = moduleElement;

                    if (!TypeScript.hasModifier(moduleAST.modifiers, TypeScript.PullElementFlags.Ambient) && this.requiresExtendsBlock(moduleAST.moduleElements)) {
                        return true;
                    }
                } else if (moduleElement.kind() === 131 /* ClassDeclaration */) {
                    var classDeclaration = moduleElement;

                    if (!TypeScript.hasModifier(classDeclaration.modifiers, TypeScript.PullElementFlags.Ambient) && TypeScript.ASTHelpers.getExtendsHeritageClause(classDeclaration.heritageClauses) !== null) {
                        return true;
                    }
                }
            }

            return false;
        };

        Emitter.prototype.emitPrologue = function (sourceUnit) {
            if (!this.extendsPrologueEmitted) {
                if (this.requiresExtendsBlock(sourceUnit.moduleElements)) {
                    this.extendsPrologueEmitted = true;
                    this.writeLineToOutput("var __extends = this.__extends || function (d, b) {");
                    this.writeLineToOutput("    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];");
                    this.writeLineToOutput("    function __() { this.constructor = d; }");
                    this.writeLineToOutput("    __.prototype = b.prototype;");
                    this.writeLineToOutput("    d.prototype = new __();");
                    this.writeLineToOutput("};");
                }
            }

            if (!this.globalThisCapturePrologueEmitted) {
                if (this.shouldCaptureThis(sourceUnit)) {
                    this.globalThisCapturePrologueEmitted = true;
                    this.writeLineToOutput(this.captureThisStmtString);
                }
            }
        };

        Emitter.prototype.emitThis = function () {
            if (!this.inWithBlock && this.inArrowFunction) {
                this.writeToOutput("_this");
            } else {
                this.writeToOutput("this");
            }
        };

        Emitter.prototype.emitBlockOrStatement = function (node) {
            if (node.kind() === 146 /* Block */) {
                this.emit(node);
            } else {
                this.writeLineToOutput("");
                this.indenter.increaseIndent();
                this.emitJavascript(node, true);
                this.indenter.decreaseIndent();
            }
        };

        Emitter.prototype.emitLiteralExpression = function (expression) {
            switch (expression.kind()) {
                case 32 /* NullKeyword */:
                    this.writeToken(expression);
                    break;
                case 24 /* FalseKeyword */:
                    this.writeToken(expression);
                    break;
                case 37 /* TrueKeyword */:
                    this.writeToken(expression);
                    break;
                default:
                    throw TypeScript.Errors.abstract();
            }
        };

        Emitter.prototype.emitThisExpression = function (expression) {
            if (!this.inWithBlock && this.inArrowFunction) {
                this.writeToOutputWithSourceMapRecord("_this", expression);
            } else {
                this.writeToken(expression);
            }
        };

        Emitter.prototype.emitSuperExpression = function (expression) {
            if (TypeScript.PullHelpers.isInStaticMemberContext(expression, this.semanticInfoChain)) {
                this.writeToOutputWithSourceMapRecord("_super", expression);
            } else {
                this.writeToOutputWithSourceMapRecord("_super.prototype", expression);
            }
        };

        Emitter.prototype.hasTrailingComment = function (token) {
            return token.hasTrailingTrivia() && token.trailingTrivia().hasComment();
        };

        Emitter.prototype.emitParenthesizedExpression = function (parenthesizedExpression) {
            var omitParentheses = false;

            if (parenthesizedExpression.expression.kind() === 220 /* CastExpression */ && !this.hasTrailingComment(parenthesizedExpression.openParenToken)) {
                var castedExpression = parenthesizedExpression.expression.expression;

                while (castedExpression.kind() == 220 /* CastExpression */) {
                    castedExpression = castedExpression.expression;
                }

                switch (castedExpression.kind()) {
                    case 217 /* ParenthesizedExpression */:
                    case 11 /* IdentifierName */:
                    case 32 /* NullKeyword */:
                    case 35 /* ThisKeyword */:
                    case 14 /* StringLiteral */:
                    case 13 /* NumericLiteral */:
                    case 12 /* RegularExpressionLiteral */:
                    case 37 /* TrueKeyword */:
                    case 24 /* FalseKeyword */:
                    case 214 /* ArrayLiteralExpression */:
                    case 215 /* ObjectLiteralExpression */:
                    case 212 /* MemberAccessExpression */:
                    case 221 /* ElementAccessExpression */:
                        omitParentheses = true;
                        break;

                    case 213 /* InvocationExpression */:
                        if (parenthesizedExpression.parent.kind() !== 216 /* ObjectCreationExpression */) {
                            omitParentheses = true;
                        }

                        break;
                }
            }

            if (omitParentheses) {
                this.emit(parenthesizedExpression.expression);
            } else {
                this.recordSourceMappingStart(parenthesizedExpression);
                this.writeToken(parenthesizedExpression.openParenToken);
                this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenTrailingComments(parenthesizedExpression.openParenToken, this.text()), false);
                this.emit(parenthesizedExpression.expression);
                this.writeToken(parenthesizedExpression.closeParenToken);
                this.recordSourceMappingEnd(parenthesizedExpression);
            }
        };

        Emitter.prototype.emitCastExpression = function (expression) {
            this.emit(expression.expression);
        };

        Emitter.prototype.emitPrefixUnaryExpression = function (expression) {
            var nodeType = expression.kind();

            this.recordSourceMappingStart(expression);
            switch (nodeType) {
                case 167 /* LogicalNotExpression */:
                    this.writeToken(expression.operatorToken);
                    this.emit(expression.operand);
                    break;
                case 166 /* BitwiseNotExpression */:
                    this.writeToken(expression.operatorToken);
                    this.emit(expression.operand);
                    break;
                case 165 /* NegateExpression */:
                    this.writeToken(expression.operatorToken);
                    if (expression.operand.kind() === 165 /* NegateExpression */ || expression.operand.kind() === 169 /* PreDecrementExpression */) {
                        this.writeToOutput(" ");
                    }
                    this.emit(expression.operand);
                    break;
                case 164 /* PlusExpression */:
                    this.writeToken(expression.operatorToken);
                    if (expression.operand.kind() === 164 /* PlusExpression */ || expression.operand.kind() === 168 /* PreIncrementExpression */) {
                        this.writeToOutput(" ");
                    }
                    this.emit(expression.operand);
                    break;
                case 168 /* PreIncrementExpression */:
                    this.writeToOutputWithSourceMapRecord("++", expression.operatorToken);
                    this.emit(expression.operand);
                    break;
                case 169 /* PreDecrementExpression */:
                    this.writeToOutputWithSourceMapRecord("--", expression.operatorToken);
                    this.emit(expression.operand);
                    break;
                default:
                    throw TypeScript.Errors.abstract();
            }

            this.recordSourceMappingEnd(expression);
        };

        Emitter.prototype.emitPostfixUnaryExpression = function (expression) {
            var nodeType = expression.kind();

            this.recordSourceMappingStart(expression);
            switch (nodeType) {
                case 210 /* PostIncrementExpression */:
                    this.emit(expression.operand);
                    this.writeToOutputWithSourceMapRecord("++", expression.operatorToken);
                    break;
                case 211 /* PostDecrementExpression */:
                    this.emit(expression.operand);
                    this.writeToOutputWithSourceMapRecord("--", expression.operatorToken);
                    break;
                default:
                    throw TypeScript.Errors.abstract();
            }

            this.recordSourceMappingEnd(expression);
        };

        Emitter.prototype.emitTypeOfExpression = function (expression) {
            this.recordSourceMappingStart(expression);
            this.writeToken(expression.typeOfKeyword);
            this.writeToOutput(" ");
            this.emit(expression.expression);
            this.recordSourceMappingEnd(expression);
        };

        Emitter.prototype.emitDeleteExpression = function (expression) {
            this.recordSourceMappingStart(expression);
            this.writeToken(expression.deleteKeyword);
            this.writeToOutput(" ");
            this.emit(expression.expression);
            this.recordSourceMappingEnd(expression);
        };

        Emitter.prototype.emitVoidExpression = function (expression) {
            this.recordSourceMappingStart(expression);
            this.writeToken(expression.voidKeyword);
            this.writeToOutput(" ");
            this.emit(expression.expression);
            this.recordSourceMappingEnd(expression);
        };

        Emitter.prototype.canEmitDottedNameMemberAccessExpression = function (expression) {
            var memberExpressionNodeType = expression.expression.kind();

            // If the memberAccess is of Name or another member access, we could potentially emit the symbol using the this memberAccessSymol
            if (memberExpressionNodeType === 11 /* IdentifierName */ || memberExpressionNodeType == 212 /* MemberAccessExpression */) {
                var memberAccessSymbol = this.getSymbolForEmit(expression).symbol;
                var memberAccessExpressionSymbol = this.getSymbolForEmit(expression.expression).symbol;
                if (memberAccessSymbol && memberAccessExpressionSymbol && !this.semanticInfoChain.getAliasSymbolForAST(expression.expression) && (TypeScript.PullHelpers.symbolIsModule(memberAccessExpressionSymbol) || memberAccessExpressionSymbol.kind === TypeScript.PullElementKind.Enum || memberAccessExpressionSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.InitializedModule | TypeScript.PullElementFlags.Enum))) {
                    // If the memberAccess is in the context of the container, we could use the symbol to emit this expression
                    var memberAccessSymbolKind = memberAccessSymbol.kind;
                    if (memberAccessSymbolKind === TypeScript.PullElementKind.Property || memberAccessSymbolKind === TypeScript.PullElementKind.EnumMember || (memberAccessSymbol.anyDeclHasFlag(1 /* Exported */) && memberAccessSymbolKind === TypeScript.PullElementKind.Variable && !memberAccessSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.InitializedModule | TypeScript.PullElementFlags.Enum)) || ((memberAccessSymbol.anyDeclHasFlag(1 /* Exported */) && !this.symbolIsUsedInItsEnclosingContainer(memberAccessSymbol)))) {
                        // If the expression is member access, we need to verify it as well
                        if (memberExpressionNodeType === 212 /* MemberAccessExpression */) {
                            return this.canEmitDottedNameMemberAccessExpression(expression.expression);
                        }

                        return true;
                    }
                }
            }

            return false;
        };

        // Emit the member access expression using the declPath
        Emitter.prototype.emitDottedNameMemberAccessExpression = function (expression) {
            this.recordSourceMappingStart(expression);
            if (expression.expression.kind() === 212 /* MemberAccessExpression */) {
                // Emit the dotted name access expression
                this.emitDottedNameMemberAccessExpressionRecurse(expression.expression);
            } else {
                this.emitName(expression.expression, true);
            }

            this.writeToken(expression.dotToken);
            this.emitName(expression.name, false);

            this.recordSourceMappingEnd(expression);
        };

        // Set the right indices for the recursive member access expression before emitting it using the decl path
        Emitter.prototype.emitDottedNameMemberAccessExpressionRecurse = function (expression) {
            this.emitComments(expression, true);
            this.emitDottedNameMemberAccessExpression(expression);
            this.emitComments(expression, false);
        };

        Emitter.prototype.emitMemberAccessExpression = function (expression) {
            if (!this.tryEmitConstant(expression)) {
                // If the expression is dotted name of the modules, emit it using decl path so the name could be resolved correctly.
                if (this.canEmitDottedNameMemberAccessExpression(expression)) {
                    this.emitDottedNameMemberAccessExpression(expression);
                } else {
                    this.recordSourceMappingStart(expression);
                    this.emit(expression.expression);
                    this.writeToken(expression.dotToken);
                    this.emitName(expression.name, false);
                    this.recordSourceMappingEnd(expression);
                }
            }
        };

        Emitter.prototype.emitQualifiedName = function (name) {
            this.recordSourceMappingStart(name);

            this.emit(name.left);
            this.writeToken(name.dotToken);
            this.emitName(name.right, false);

            this.recordSourceMappingEnd(name);
        };

        Emitter.prototype.emitBinaryExpression = function (expression) {
            this.recordSourceMappingStart(expression);
            switch (expression.kind()) {
                case 173 /* CommaExpression */:
                    this.emit(expression.left);
                    this.writeToken(expression.operatorToken);
                    this.writeToOutput(" ");
                    this.emit(expression.right);
                    break;
                default: {
                    this.emit(expression.left);
                    var binOp = TypeScript.SyntaxFacts.getText(TypeScript.SyntaxFacts.getOperatorTokenFromBinaryExpression(expression.kind()));
                    this.writeToOutput(" ");
                    this.writeToOutputWithSourceMapRecord(binOp, expression.operatorToken);
                    this.writeToOutput(" ");
                    this.emit(expression.right);
                }
            }
            this.recordSourceMappingEnd(expression);
        };

        Emitter.prototype.emitSimplePropertyAssignment = function (property) {
            this.recordSourceMappingStart(property);
            this.emit(property.propertyName);

            this.writeToken(property.colonToken);
            this.writeToOutput(" ");
            this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenTrailingComments(property.colonToken, this.text()), true, true);

            this.emit(property.expression);
            this.recordSourceMappingEnd(property);
        };

        Emitter.prototype.emitFunctionPropertyAssignment = function (funcProp) {
            this.recordSourceMappingStart(funcProp);

            this.emit(funcProp.propertyName);
            this.writeToOutput(": ");

            var pullFunctionDecl = this.semanticInfoChain.getDeclForAST(funcProp);

            var savedInArrowFunction = this.inArrowFunction;
            this.inArrowFunction = false;

            var temp = this.setContainer(5 /* Function */);
            var funcName = funcProp.propertyName;

            var pullDecl = this.semanticInfoChain.getDeclForAST(funcProp);
            this.pushDecl(pullDecl);

            this.recordSourceMappingStart(funcProp);
            this.writeToOutput("function ");

            //this.recordSourceMappingStart(funcProp.propertyName);
            //this.writeToOutput(funcProp.propertyName.actualText);
            //this.recordSourceMappingEnd(funcProp.propertyName);
            this.emitParameterList(funcProp.callSignature.parameterList);

            this.emitFunctionBodyStatements(funcProp.propertyName.text(), funcProp, funcProp.callSignature.parameterList.parameters, funcProp.block, null);

            this.recordSourceMappingEnd(funcProp);

            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it
            this.recordSourceMappingEnd(funcProp);

            this.emitComments(funcProp, false);

            this.popDecl(pullDecl);

            this.setContainer(temp);
            this.inArrowFunction = savedInArrowFunction;
        };

        Emitter.prototype.emitConditionalExpression = function (expression) {
            this.emit(expression.condition);
            this.writeToOutput(" ");
            this.writeToken(expression.questionToken);
            this.writeToOutput(" ");
            this.emit(expression.whenTrue);
            this.writeToOutput(" ");
            this.writeToken(expression.colonToken);
            this.writeToOutput(" ");
            this.emit(expression.whenFalse);
        };

        Emitter.prototype.emitThrowStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.throwKeyword);
            this.writeToOutput(" ");
            this.emit(statement.expression);
            this.writeToOutputWithSourceMapRecord(";", statement.semicolonToken);
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitExpressionStatement = function (statement) {
            var isArrowExpression = statement.expression.kind() === 219 /* SimpleArrowFunctionExpression */ || statement.expression.kind() === 218 /* ParenthesizedArrowFunctionExpression */;

            this.recordSourceMappingStart(statement);
            if (isArrowExpression) {
                this.writeToOutput("(");
            }

            this.emit(statement.expression);

            if (isArrowExpression) {
                this.writeToOutput(")");
            }

            this.writeToOutputWithSourceMapRecord(";", statement.semicolonToken);
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitLabeledStatement = function (statement) {
            this.writeToOutputWithSourceMapRecord(statement.identifier.text(), statement.identifier);
            this.writeToken(statement.colonToken);
            this.writeLineToOutput("");
            this.emitJavascript(statement.statement, true);
        };

        Emitter.prototype.emitBlock = function (block) {
            this.recordSourceMappingStart(block);
            this.writeLineToOutput(" {");
            this.indenter.increaseIndent();
            if (block.statements) {
                this.emitList(block.statements);
            }
            this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenLeadingComments(block.closeBraceToken, this.text()), false);
            this.indenter.decreaseIndent();
            this.emitIndent();
            this.writeToken(block.closeBraceToken);
            this.recordSourceMappingEnd(block);
        };

        Emitter.prototype.emitBreakStatement = function (jump) {
            this.recordSourceMappingStart(jump);
            this.writeToken(jump.breakKeyword);

            if (jump.identifier) {
                this.writeToOutput(" ");
                this.writeToOutputWithSourceMapRecord(jump.identifier.text(), jump.identifier);
            }

            this.writeToOutputWithSourceMapRecord(";", jump.semicolonToken);
            this.recordSourceMappingEnd(jump);
        };

        Emitter.prototype.emitContinueStatement = function (jump) {
            this.recordSourceMappingStart(jump);
            this.writeToken(jump.continueKeyword);

            if (jump.identifier) {
                this.writeToOutput(" ");
                this.writeToOutputWithSourceMapRecord(jump.identifier.text(), jump.identifier);
            }

            this.writeToOutputWithSourceMapRecord(";", jump.semicolonToken);
            this.recordSourceMappingEnd(jump);
        };

        Emitter.prototype.emitWhileStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.whileKeyword);
            this.writeToOutput(" ");
            this.writeToken(statement.openParenToken);
            this.emit(statement.condition);
            this.writeToken(statement.closeParenToken);
            this.emitBlockOrStatement(statement.statement);
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitDoStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.doKeyword);
            this.emitBlockOrStatement(statement.statement);
            this.writeToOutput(" ");
            this.writeToken(statement.whileKeyword);
            this.writeToken(statement.openParenToken);
            this.emit(statement.condition);
            this.writeToken(statement.closeParenToken);
            this.writeToOutputWithSourceMapRecord(";", statement.semicolonToken);
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitIfStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.ifKeyword);
            this.writeToOutput(" ");
            this.writeToken(statement.openParenToken);
            this.emit(statement.condition);
            this.writeToken(statement.closeParenToken);

            this.emitBlockOrStatement(statement.statement);

            if (statement.elseClause) {
                if (statement.statement.kind() !== 146 /* Block */) {
                    this.writeLineToOutput("");
                    this.emitIndent();
                } else {
                    this.writeToOutput(" ");
                }

                this.emit(statement.elseClause);
            }
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitElseClause = function (elseClause) {
            this.writeToken(elseClause.elseKeyword);
            if (elseClause.statement.kind() === 147 /* IfStatement */) {
                this.writeToOutput(" ");
                this.emit(elseClause.statement);
            } else {
                this.emitBlockOrStatement(elseClause.statement);
            }
        };

        Emitter.prototype.emitReturnStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.returnKeyword);
            if (statement.expression) {
                this.writeToOutput(" ");
                this.emit(statement.expression);
            }

            this.writeToOutputWithSourceMapRecord(";", statement.semicolonToken);
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitForInStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.forKeyword);
            this.writeToOutput(" ");
            this.writeToken(statement.openParenToken);

            if (statement.left) {
                this.emit(statement.left);
            } else {
                this.emit(statement.variableDeclaration);
            }
            this.writeToOutput(" ");
            this.writeToken(statement.inKeyword);
            this.writeToOutput(" ");
            this.emit(statement.expression);
            this.writeToken(statement.closeParenToken);
            this.emitBlockOrStatement(statement.statement);
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitForStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.forKeyword);
            this.writeToOutput(" ");
            this.writeToken(statement.openParenToken);

            if (statement.variableDeclaration) {
                this.emit(statement.variableDeclaration);
            } else if (statement.initializer) {
                this.emit(statement.initializer);
            }

            this.writeToken(statement.firstSemicolonToken);
            this.writeToOutput(" ");
            this.emitJavascript(statement.condition, false);
            this.writeToken(statement.secondSemicolonToken);
            if (statement.incrementor) {
                this.writeToOutput(" ");
                this.emitJavascript(statement.incrementor, false);
            }
            this.writeToken(statement.closeParenToken);
            this.emitBlockOrStatement(statement.statement);
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitWithStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.withKeyword);
            this.writeToOutput(" ");
            this.writeToken(statement.openParenToken);
            if (statement.condition) {
                this.emit(statement.condition);
            }

            this.writeToken(statement.closeParenToken);
            var prevInWithBlock = this.inWithBlock;
            this.inWithBlock = true;
            this.emitBlockOrStatement(statement.statement);
            this.inWithBlock = prevInWithBlock;
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitSwitchStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.switchKeyword);
            this.writeToOutput(" ");
            this.writeToken(statement.openParenToken);
            this.emit(statement.expression);
            this.writeToken(statement.closeParenToken);
            this.writeLineToOutput(" {");
            this.indenter.increaseIndent();
            this.emitList(statement.switchClauses, false);
            this.indenter.decreaseIndent();
            this.emitIndent();
            this.writeToken(statement.closeBraceToken);
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitCaseSwitchClause = function (clause) {
            this.recordSourceMappingStart(clause);
            this.writeToken(clause.caseKeyword);
            this.writeToOutput(" ");
            this.emit(clause.expression);
            this.writeToken(clause.colonToken);

            this.emitSwitchClauseBody(clause.colonToken, clause.statements);
            this.recordSourceMappingEnd(clause);
        };

        Emitter.prototype.emitSwitchClauseBody = function (colonToken, body) {
            var text = this.text();
            if (body.length === 1 && TypeScript.childAt(body, 0).kind() === 146 /* Block */) {
                // The case statement was written with curly braces, so emit it with the appropriate formatting
                this.emit(TypeScript.childAt(body, 0));
                this.writeLineToOutput("");
            } else if (body.length === 1 && this.isOnSameLine(TypeScript.end(colonToken, text), TypeScript.start(body[0], text))) {
                this.writeToOutput(" ");
                this.emit(TypeScript.childAt(body, 0));
                this.writeLineToOutput("");
            } else {
                // No curly braces. Format in the expected way
                this.writeLineToOutput("");
                this.indenter.increaseIndent();
                this.emit(body);
                this.indenter.decreaseIndent();
            }
        };

        Emitter.prototype.emitDefaultSwitchClause = function (clause) {
            this.recordSourceMappingStart(clause);
            this.writeToken(clause.defaultKeyword);
            this.writeToken(clause.colonToken);

            this.emitSwitchClauseBody(clause.colonToken, clause.statements);
            this.recordSourceMappingEnd(clause);
        };

        Emitter.prototype.emitTryStatement = function (statement) {
            this.recordSourceMappingStart(statement);
            this.writeToken(statement.tryKeyword);
            this.writeToOutput(" ");
            this.emit(statement.block);
            this.emitJavascript(statement.catchClause, false);

            if (statement.finallyClause) {
                this.emit(statement.finallyClause);
            }
            this.recordSourceMappingEnd(statement);
        };

        Emitter.prototype.emitCatchClause = function (clause) {
            this.writeToOutput(" ");
            this.recordSourceMappingStart(clause);
            this.writeToken(clause.catchKeyword);
            this.writeToOutput(" ");
            this.writeToken(clause.openParenToken);
            this.emit(clause.identifier);
            this.writeToken(clause.closeParenToken);
            this.emit(clause.block);
            this.recordSourceMappingEnd(clause);
        };

        Emitter.prototype.emitFinallyClause = function (clause) {
            this.writeToOutput(" ");
            this.writeToken(clause.finallyKeyword);
            this.emit(clause.block);
        };

        Emitter.prototype.emitDebuggerStatement = function (statement) {
            this.writeToken(statement.debuggerKeyword);
            this.writeToOutputWithSourceMapRecord(";", statement.semicolonToken);
        };

        Emitter.prototype.emitNumericLiteral = function (literal) {
            this.writeToOutputWithSourceMapRecord(literal.text(), literal);
        };

        Emitter.prototype.emitRegularExpressionLiteral = function (literal) {
            this.writeToOutputWithSourceMapRecord(literal.text(), literal);
        };

        Emitter.prototype.emitStringLiteral = function (literal) {
            this.writeToOutputWithSourceMapRecord(literal.text(), literal);
        };

        Emitter.prototype.emitEqualsValueClause = function (clause) {
            this.writeToOutput(" ");
            this.writeToken(clause.equalsToken);
            this.writeToOutput(" ");
            this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenTrailingComments(clause.equalsToken, this.text()), true, true);

            this.emit(clause.value);
        };

        Emitter.prototype.emitParameter = function (parameter) {
            this.writeToOutputWithSourceMapRecord(parameter.identifier.text(), parameter);
        };

        Emitter.prototype.emitConstructorDeclaration = function (declaration) {
            if (declaration.block) {
                this.emitConstructor(declaration);
            } else {
                this.emitComments(declaration, true, true);
            }
        };

        Emitter.prototype.shouldEmitFunctionDeclaration = function (declaration) {
            return TypeScript.ASTHelpers.preComments(declaration, this.text()) !== null || (!TypeScript.hasModifier(declaration.modifiers, TypeScript.PullElementFlags.Ambient) && declaration.block !== null);
        };

        Emitter.prototype.emitFunctionDeclaration = function (declaration) {
            if (!TypeScript.hasModifier(declaration.modifiers, TypeScript.PullElementFlags.Ambient) && declaration.block !== null) {
                this.emitFunction(declaration);
            } else {
                this.emitComments(declaration, true, true);
            }
        };

        Emitter.prototype.emitSourceUnit = function (sourceUnit) {
            if (!this.document.isDeclareFile()) {
                var pullDecl = this.semanticInfoChain.getDeclForAST(sourceUnit);
                this.pushDecl(pullDecl);
                this.emitScriptElements(sourceUnit);
                this.popDecl(pullDecl);

                this.emitCommentsArray(TypeScript.ASTHelpers.convertTokenLeadingComments(sourceUnit.endOfFileToken, this.text()), false);
            }
        };

        Emitter.prototype.shouldEmitEnumDeclaration = function (declaration) {
            return TypeScript.ASTHelpers.preComments(declaration, this.text()) !== null || !TypeScript.ASTHelpers.enumIsElided(declaration);
        };

        Emitter.prototype.emitEnumDeclaration = function (declaration) {
            if (!TypeScript.ASTHelpers.enumIsElided(declaration)) {
                this.emitComments(declaration, true);
                this.emitEnum(declaration);
                this.emitComments(declaration, false);
            } else {
                this.emitComments(declaration, true, true);
            }
        };

        Emitter.prototype.shouldEmitModuleDeclaration = function (declaration) {
            return TypeScript.ASTHelpers.preComments(declaration, this.text()) !== null || !TypeScript.ASTHelpers.moduleIsElided(declaration);
        };

        Emitter.prototype.emitModuleDeclaration = function (declaration) {
            if (!TypeScript.ASTHelpers.moduleIsElided(declaration)) {
                this.emitModuleDeclarationWorker(declaration);
            } else {
                this.emitComments(declaration, true, true);
            }
        };

        Emitter.prototype.shouldEmitClassDeclaration = function (declaration) {
            return TypeScript.ASTHelpers.preComments(declaration, this.text()) !== null || !TypeScript.hasModifier(declaration.modifiers, TypeScript.PullElementFlags.Ambient);
        };

        Emitter.prototype.emitClassDeclaration = function (declaration) {
            if (!TypeScript.hasModifier(declaration.modifiers, TypeScript.PullElementFlags.Ambient)) {
                this.emitClass(declaration);
            } else {
                this.emitComments(declaration, true, true);
            }
        };

        Emitter.prototype.shouldEmitInterfaceDeclaration = function (declaration) {
            return TypeScript.ASTHelpers.preComments(declaration, this.text()) !== null;
        };

        Emitter.prototype.emitInterfaceDeclaration = function (declaration) {
            this.emitComments(declaration, true, true);
        };

        Emitter.prototype.firstVariableDeclarator = function (statement) {
            return statement.variableDeclaration.variableDeclarators[0];
        };

        Emitter.prototype.isNotAmbientOrHasInitializer = function (variableStatement) {
            return !TypeScript.hasModifier(variableStatement.modifiers, TypeScript.PullElementFlags.Ambient) || this.firstVariableDeclarator(variableStatement).equalsValueClause !== null;
        };

        Emitter.prototype.shouldEmitVariableStatement = function (statement) {
            return TypeScript.ASTHelpers.preComments(statement, this.text()) !== null || this.isNotAmbientOrHasInitializer(statement);
        };

        Emitter.prototype.emitVariableStatement = function (statement) {
            if (this.isNotAmbientOrHasInitializer(statement)) {
                this.emitComments(statement, true);
                this.emit(statement.variableDeclaration);
                this.writeToOutputWithSourceMapRecord(";", statement.semicolonToken);
                this.emitComments(statement, false);
            } else {
                this.emitComments(statement, true, true);
            }
        };

        Emitter.prototype.emitGenericType = function (type) {
            this.emit(type.name);
        };

        Emitter.prototype.shouldEmit = function (ast) {
            if (!ast) {
                return false;
            }

            switch (ast.kind()) {
                case 133 /* ImportDeclaration */:
                    return this.shouldEmitImportDeclaration(ast);
                case 131 /* ClassDeclaration */:
                    return this.shouldEmitClassDeclaration(ast);
                case 128 /* InterfaceDeclaration */:
                    return this.shouldEmitInterfaceDeclaration(ast);
                case 129 /* FunctionDeclaration */:
                    return this.shouldEmitFunctionDeclaration(ast);
                case 130 /* ModuleDeclaration */:
                    return this.shouldEmitModuleDeclaration(ast);
                case 148 /* VariableStatement */:
                    return this.shouldEmitVariableStatement(ast);
                case 223 /* OmittedExpression */:
                    return false;
                case 132 /* EnumDeclaration */:
                    return this.shouldEmitEnumDeclaration(ast);
            }

            return true;
        };

        Emitter.prototype.emit = function (ast) {
            if (!ast) {
                return;
            }

            switch (ast.kind()) {
                case 2 /* SeparatedList */:
                    return this.emitSeparatedList(ast);
                case 1 /* List */:
                    return this.emitList(ast);
                case 120 /* SourceUnit */:
                    return this.emitSourceUnit(ast);
                case 133 /* ImportDeclaration */:
                    return this.emitImportDeclaration(ast);
                case 134 /* ExportAssignment */:
                    return this.setExportAssignment(ast);
                case 131 /* ClassDeclaration */:
                    return this.emitClassDeclaration(ast);
                case 128 /* InterfaceDeclaration */:
                    return this.emitInterfaceDeclaration(ast);
                case 11 /* IdentifierName */:
                    return this.emitName(ast, true);
                case 225 /* VariableDeclarator */:
                    return this.emitVariableDeclarator(ast);
                case 219 /* SimpleArrowFunctionExpression */:
                    return this.emitSimpleArrowFunctionExpression(ast);
                case 218 /* ParenthesizedArrowFunctionExpression */:
                    return this.emitParenthesizedArrowFunctionExpression(ast);
                case 129 /* FunctionDeclaration */:
                    return this.emitFunctionDeclaration(ast);
                case 130 /* ModuleDeclaration */:
                    return this.emitModuleDeclaration(ast);
                case 224 /* VariableDeclaration */:
                    return this.emitVariableDeclaration(ast);
                case 126 /* GenericType */:
                    return this.emitGenericType(ast);
                case 137 /* ConstructorDeclaration */:
                    return this.emitConstructorDeclaration(ast);
                case 132 /* EnumDeclaration */:
                    return this.emitEnumDeclaration(ast);
                case 243 /* EnumElement */:
                    return this.emitEnumElement(ast);
                case 222 /* FunctionExpression */:
                    return this.emitFunctionExpression(ast);
                case 148 /* VariableStatement */:
                    return this.emitVariableStatement(ast);
            }

            this.emitComments(ast, true);
            this.emitWorker(ast);
            this.emitComments(ast, false);
        };

        Emitter.prototype.emitWorker = function (ast) {
            if (!ast) {
                return;
            }

            switch (ast.kind()) {
                case 13 /* NumericLiteral */:
                    return this.emitNumericLiteral(ast);
                case 12 /* RegularExpressionLiteral */:
                    return this.emitRegularExpressionLiteral(ast);
                case 14 /* StringLiteral */:
                    return this.emitStringLiteral(ast);
                case 24 /* FalseKeyword */:
                case 32 /* NullKeyword */:
                case 37 /* TrueKeyword */:
                    return this.emitLiteralExpression(ast);
                case 35 /* ThisKeyword */:
                    return this.emitThisExpression(ast);
                case 50 /* SuperKeyword */:
                    return this.emitSuperExpression(ast);
                case 217 /* ParenthesizedExpression */:
                    return this.emitParenthesizedExpression(ast);
                case 214 /* ArrayLiteralExpression */:
                    return this.emitArrayLiteralExpression(ast);
                case 211 /* PostDecrementExpression */:
                case 210 /* PostIncrementExpression */:
                    return this.emitPostfixUnaryExpression(ast);
                case 167 /* LogicalNotExpression */:
                case 166 /* BitwiseNotExpression */:
                case 165 /* NegateExpression */:
                case 164 /* PlusExpression */:
                case 168 /* PreIncrementExpression */:
                case 169 /* PreDecrementExpression */:
                    return this.emitPrefixUnaryExpression(ast);
                case 213 /* InvocationExpression */:
                    return this.emitInvocationExpression(ast);
                case 221 /* ElementAccessExpression */:
                    return this.emitElementAccessExpression(ast);
                case 212 /* MemberAccessExpression */:
                    return this.emitMemberAccessExpression(ast);
                case 121 /* QualifiedName */:
                    return this.emitQualifiedName(ast);
                case 173 /* CommaExpression */:
                case 174 /* AssignmentExpression */:
                case 175 /* AddAssignmentExpression */:
                case 176 /* SubtractAssignmentExpression */:
                case 177 /* MultiplyAssignmentExpression */:
                case 178 /* DivideAssignmentExpression */:
                case 179 /* ModuloAssignmentExpression */:
                case 180 /* AndAssignmentExpression */:
                case 181 /* ExclusiveOrAssignmentExpression */:
                case 182 /* OrAssignmentExpression */:
                case 183 /* LeftShiftAssignmentExpression */:
                case 184 /* SignedRightShiftAssignmentExpression */:
                case 185 /* UnsignedRightShiftAssignmentExpression */:
                case 187 /* LogicalOrExpression */:
                case 188 /* LogicalAndExpression */:
                case 189 /* BitwiseOrExpression */:
                case 190 /* BitwiseExclusiveOrExpression */:
                case 191 /* BitwiseAndExpression */:
                case 192 /* EqualsWithTypeConversionExpression */:
                case 193 /* NotEqualsWithTypeConversionExpression */:
                case 194 /* EqualsExpression */:
                case 195 /* NotEqualsExpression */:
                case 196 /* LessThanExpression */:
                case 197 /* GreaterThanExpression */:
                case 198 /* LessThanOrEqualExpression */:
                case 199 /* GreaterThanOrEqualExpression */:
                case 200 /* InstanceOfExpression */:
                case 201 /* InExpression */:
                case 202 /* LeftShiftExpression */:
                case 203 /* SignedRightShiftExpression */:
                case 204 /* UnsignedRightShiftExpression */:
                case 205 /* MultiplyExpression */:
                case 206 /* DivideExpression */:
                case 207 /* ModuloExpression */:
                case 208 /* AddExpression */:
                case 209 /* SubtractExpression */:
                    return this.emitBinaryExpression(ast);
                case 186 /* ConditionalExpression */:
                    return this.emitConditionalExpression(ast);
                case 232 /* EqualsValueClause */:
                    return this.emitEqualsValueClause(ast);
                case 242 /* Parameter */:
                    return this.emitParameter(ast);
                case 146 /* Block */:
                    return this.emitBlock(ast);
                case 235 /* ElseClause */:
                    return this.emitElseClause(ast);
                case 147 /* IfStatement */:
                    return this.emitIfStatement(ast);
                case 149 /* ExpressionStatement */:
                    return this.emitExpressionStatement(ast);
                case 139 /* GetAccessor */:
                    return this.emitGetAccessor(ast);
                case 140 /* SetAccessor */:
                    return this.emitSetAccessor(ast);
                case 157 /* ThrowStatement */:
                    return this.emitThrowStatement(ast);
                case 150 /* ReturnStatement */:
                    return this.emitReturnStatement(ast);
                case 216 /* ObjectCreationExpression */:
                    return this.emitObjectCreationExpression(ast);
                case 151 /* SwitchStatement */:
                    return this.emitSwitchStatement(ast);
                case 233 /* CaseSwitchClause */:
                    return this.emitCaseSwitchClause(ast);
                case 234 /* DefaultSwitchClause */:
                    return this.emitDefaultSwitchClause(ast);
                case 152 /* BreakStatement */:
                    return this.emitBreakStatement(ast);
                case 153 /* ContinueStatement */:
                    return this.emitContinueStatement(ast);
                case 154 /* ForStatement */:
                    return this.emitForStatement(ast);
                case 155 /* ForInStatement */:
                    return this.emitForInStatement(ast);
                case 158 /* WhileStatement */:
                    return this.emitWhileStatement(ast);
                case 163 /* WithStatement */:
                    return this.emitWithStatement(ast);
                case 220 /* CastExpression */:
                    return this.emitCastExpression(ast);
                case 215 /* ObjectLiteralExpression */:
                    return this.emitObjectLiteralExpression(ast);
                case 240 /* SimplePropertyAssignment */:
                    return this.emitSimplePropertyAssignment(ast);
                case 241 /* FunctionPropertyAssignment */:
                    return this.emitFunctionPropertyAssignment(ast);
                case 156 /* EmptyStatement */:
                    return this.writeToken(ast.semicolonToken);
                case 159 /* TryStatement */:
                    return this.emitTryStatement(ast);
                case 236 /* CatchClause */:
                    return this.emitCatchClause(ast);
                case 237 /* FinallyClause */:
                    return this.emitFinallyClause(ast);
                case 160 /* LabeledStatement */:
                    return this.emitLabeledStatement(ast);
                case 161 /* DoStatement */:
                    return this.emitDoStatement(ast);
                case 171 /* TypeOfExpression */:
                    return this.emitTypeOfExpression(ast);
                case 170 /* DeleteExpression */:
                    return this.emitDeleteExpression(ast);
                case 172 /* VoidExpression */:
                    return this.emitVoidExpression(ast);
                case 162 /* DebuggerStatement */:
                    return this.emitDebuggerStatement(ast);
            }
        };
        return Emitter;
    })();
    TypeScript.Emitter = Emitter;

    function getLastConstructor(classDecl) {
        for (var i = classDecl.classElements.length - 1; i >= 0; i--) {
            var child = classDecl.classElements[i];

            if (child.kind() === 137 /* ConstructorDeclaration */) {
                return child;
            }
        }

        return null;
    }
    TypeScript.getLastConstructor = getLastConstructor;

    function getTrimmedTextLines(comment) {
        if (comment.kind() === 6 /* MultiLineCommentTrivia */) {
            return comment.fullText().split("\n").map(function (s) {
                return s.trim();
            });
        } else {
            return [comment.fullText().trim()];
        }
    }
    TypeScript.getTrimmedTextLines = getTrimmedTextLines;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var MemberName = (function () {
        function MemberName() {
            this.prefix = "";
            this.suffix = "";
        }
        MemberName.prototype.isString = function () {
            return false;
        };
        MemberName.prototype.isArray = function () {
            return false;
        };
        MemberName.prototype.isMarker = function () {
            return !this.isString() && !this.isArray();
        };

        MemberName.prototype.toString = function () {
            return MemberName.memberNameToString(this);
        };

        MemberName.memberNameToString = function (memberName, markerInfo, markerBaseLength) {
            if (typeof markerBaseLength === "undefined") { markerBaseLength = 0; }
            var result = memberName.prefix;

            if (memberName.isString()) {
                result += memberName.text;
            } else if (memberName.isArray()) {
                var ar = memberName;
                for (var index = 0; index < ar.entries.length; index++) {
                    if (ar.entries[index].isMarker()) {
                        if (markerInfo) {
                            markerInfo.push(markerBaseLength + result.length);
                        }
                        continue;
                    }

                    result += MemberName.memberNameToString(ar.entries[index], markerInfo, markerBaseLength + result.length);
                    result += ar.delim;
                }
            }

            result += memberName.suffix;
            return result;
        };

        MemberName.create = function (arg1, arg2, arg3) {
            if (typeof arg1 === "string") {
                return new MemberNameString(arg1);
            } else {
                var result = new MemberNameArray();
                if (arg2)
                    result.prefix = arg2;
                if (arg3)
                    result.suffix = arg3;
                result.entries.push(arg1);
                return result;
            }
        };
        return MemberName;
    })();
    TypeScript.MemberName = MemberName;

    var MemberNameString = (function (_super) {
        __extends(MemberNameString, _super);
        function MemberNameString(text) {
            _super.call(this);
            this.text = text;
        }
        MemberNameString.prototype.isString = function () {
            return true;
        };
        return MemberNameString;
    })(MemberName);
    TypeScript.MemberNameString = MemberNameString;

    var MemberNameArray = (function (_super) {
        __extends(MemberNameArray, _super);
        function MemberNameArray() {
            _super.call(this);
            this.delim = "";
            this.entries = [];
        }
        MemberNameArray.prototype.isArray = function () {
            return true;
        };

        MemberNameArray.prototype.add = function (entry) {
            this.entries.push(entry);
        };

        MemberNameArray.prototype.addAll = function (entries) {
            for (var i = 0; i < entries.length; i++) {
                this.entries.push(entries[i]);
            }
        };
        return MemberNameArray;
    })(MemberName);
    TypeScript.MemberNameArray = MemberNameArray;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    function stripStartAndEndQuotes(str) {
        var firstCharCode = str && str.charCodeAt(0);
        if (str && str.length >= 2 && firstCharCode === str.charCodeAt(str.length - 1) && (firstCharCode === 39 /* singleQuote */ || firstCharCode === 34 /* doubleQuote */)) {
            return str.substring(1, str.length - 1);
        }

        return str;
    }
    TypeScript.stripStartAndEndQuotes = stripStartAndEndQuotes;

    function isSingleQuoted(str) {
        return str && str.length >= 2 && str.charCodeAt(0) === str.charCodeAt(str.length - 1) && str.charCodeAt(0) === 39 /* singleQuote */;
    }
    TypeScript.isSingleQuoted = isSingleQuoted;

    function isDoubleQuoted(str) {
        return str && str.length >= 2 && str.charCodeAt(0) === str.charCodeAt(str.length - 1) && str.charCodeAt(0) === 34 /* doubleQuote */;
    }
    TypeScript.isDoubleQuoted = isDoubleQuoted;

    function isQuoted(str) {
        return isDoubleQuoted(str) || isSingleQuoted(str);
    }
    TypeScript.isQuoted = isQuoted;

    function quoteStr(str) {
        return "\"" + str + "\"";
    }
    TypeScript.quoteStr = quoteStr;

    var switchToForwardSlashesRegEx = /\\/g;
    function switchToForwardSlashes(path) {
        return path.replace(switchToForwardSlashesRegEx, "/");
    }
    TypeScript.switchToForwardSlashes = switchToForwardSlashes;

    function trimModName(modName) {
        // in case's it's a declare file...
        if (modName.length > 5 && modName.substring(modName.length - 5, modName.length) === ".d.ts") {
            return modName.substring(0, modName.length - 5);
        }
        if (modName.length > 3 && modName.substring(modName.length - 3, modName.length) === ".ts") {
            return modName.substring(0, modName.length - 3);
        }

        // in case's it's a .js file
        if (modName.length > 3 && modName.substring(modName.length - 3, modName.length) === ".js") {
            return modName.substring(0, modName.length - 3);
        }

        return modName;
    }
    TypeScript.trimModName = trimModName;

    function getDeclareFilePath(fname) {
        return isTSFile(fname) ? changePathToDTS(fname) : changePathToDTS(fname);
    }
    TypeScript.getDeclareFilePath = getDeclareFilePath;

    function isFileOfExtension(fname, ext) {
        var invariantFname = fname.toLocaleUpperCase();
        var invariantExt = ext.toLocaleUpperCase();
        var extLength = invariantExt.length;
        return invariantFname.length > extLength && invariantFname.substring(invariantFname.length - extLength, invariantFname.length) === invariantExt;
    }

    function isTSFile(fname) {
        return isFileOfExtension(fname, ".ts");
    }
    TypeScript.isTSFile = isTSFile;

    function isDTSFile(fname) {
        return isFileOfExtension(fname, ".d.ts");
    }
    TypeScript.isDTSFile = isDTSFile;

    function getPrettyName(modPath, quote, treatAsFileName) {
        if (typeof quote === "undefined") { quote = true; }
        if (typeof treatAsFileName === "undefined") { treatAsFileName = false; }
        var modName = treatAsFileName ? switchToForwardSlashes(modPath) : trimModName(stripStartAndEndQuotes(modPath));
        var components = this.getPathComponents(modName);
        return components.length ? (quote ? quoteStr(components[components.length - 1]) : components[components.length - 1]) : modPath;
    }
    TypeScript.getPrettyName = getPrettyName;

    function getPathComponents(path) {
        return path.split("/");
    }
    TypeScript.getPathComponents = getPathComponents;

    function getRelativePathToFixedPath(fixedModFilePath, absoluteModPath, isAbsoultePathURL) {
        if (typeof isAbsoultePathURL === "undefined") { isAbsoultePathURL = true; }
        absoluteModPath = switchToForwardSlashes(absoluteModPath);

        var modComponents = this.getPathComponents(absoluteModPath);
        var fixedModComponents = this.getPathComponents(fixedModFilePath);

        // Find the component that differs
        var joinStartIndex = 0;
        for (; joinStartIndex < modComponents.length && joinStartIndex < fixedModComponents.length; joinStartIndex++) {
            if (fixedModComponents[joinStartIndex] !== modComponents[joinStartIndex]) {
                break;
            }
        }

        // Get the relative path
        if (joinStartIndex !== 0) {
            var relativePath = "";
            var relativePathComponents = modComponents.slice(joinStartIndex, modComponents.length);
            for (; joinStartIndex < fixedModComponents.length; joinStartIndex++) {
                if (fixedModComponents[joinStartIndex] !== "") {
                    relativePath = relativePath + "../";
                }
            }

            return relativePath + relativePathComponents.join("/");
        }

        if (isAbsoultePathURL && absoluteModPath.indexOf("://") === -1) {
            absoluteModPath = "file:///" + absoluteModPath;
        }

        return absoluteModPath;
    }
    TypeScript.getRelativePathToFixedPath = getRelativePathToFixedPath;

    function changePathToDTS(modPath) {
        return trimModName(stripStartAndEndQuotes(modPath)) + ".d.ts";
    }
    TypeScript.changePathToDTS = changePathToDTS;

    function isRelative(path) {
        return path.length > 0 && path.charAt(0) === ".";
    }
    TypeScript.isRelative = isRelative;
    function isRooted(path) {
        return path.length > 0 && (path.charAt(0) === "\\" || path.charAt(0) === "/" || (path.indexOf(":\\") !== -1) || (path.indexOf(":/") !== -1));
    }
    TypeScript.isRooted = isRooted;

    function getRootFilePath(outFname) {
        if (outFname === "") {
            return outFname;
        } else {
            var isPath = outFname.indexOf("/") !== -1;
            return isPath ? filePath(outFname) : "";
        }
    }
    TypeScript.getRootFilePath = getRootFilePath;

    function filePathComponents(fullPath) {
        fullPath = switchToForwardSlashes(fullPath);
        var components = getPathComponents(fullPath);
        return components.slice(0, components.length - 1);
    }
    TypeScript.filePathComponents = filePathComponents;

    function filePath(fullPath) {
        var path = filePathComponents(fullPath);
        return path.join("/") + "/";
    }
    TypeScript.filePath = filePath;

    function convertToDirectoryPath(dirPath) {
        if (dirPath && dirPath.charAt(dirPath.length - 1) !== "/") {
            dirPath += "/";
        }

        return dirPath;
    }
    TypeScript.convertToDirectoryPath = convertToDirectoryPath;

    var normalizePathRegEx = /^\\\\[^\\]/;
    function normalizePath(path) {
        // If it's a UNC style path (i.e. \\server\share), convert to a URI style (i.e. file://server/share)
        if (normalizePathRegEx.test(path)) {
            path = "file:" + path;
        }
        var parts = this.getPathComponents(switchToForwardSlashes(path));
        var normalizedParts = [];

        for (var i = 0; i < parts.length; i++) {
            var part = parts[i];
            if (part === ".") {
                continue;
            }

            if (normalizedParts.length > 0 && TypeScript.ArrayUtilities.last(normalizedParts) !== ".." && part === "..") {
                normalizedParts.pop();
                continue;
            }

            normalizedParts.push(part);
        }

        return normalizedParts.join("/");
    }
    TypeScript.normalizePath = normalizePath;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    

    function isNoDefaultLibMatch(comment) {
        var isNoDefaultLibRegex = /^(\/\/\/\s*<reference\s+no-default-lib=)('|")(.+?)\2\s*\/>/gim;
        return isNoDefaultLibRegex.exec(comment);
    }

    TypeScript.tripleSlashReferenceRegExp = /^(\/\/\/\s*<reference\s+path=)('|")(.+?)\2\s*(static=('|")(.+?)\2\s*)*\/>/;

    function getFileReferenceFromReferencePath(fileName, text, position, comment, diagnostics) {
        // First, just see if they've written: /// <reference\s+
        // If so, then we'll consider this a reference directive and we'll report errors if it's
        // malformed.  Otherwise, we'll completely ignore this.
        var lineMap = text.lineMap();

        var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
        if (simpleReferenceRegEx.exec(comment)) {
            var isNoDefaultLib = isNoDefaultLibMatch(comment);

            if (!isNoDefaultLib) {
                var fullReferenceRegEx = TypeScript.tripleSlashReferenceRegExp;
                var fullReference = fullReferenceRegEx.exec(comment);

                if (!fullReference) {
                    // It matched the start of a reference directive, but wasn't well formed.  Report
                    // an appropriate error to the user.
                    diagnostics.push(new TypeScript.Diagnostic(fileName, lineMap, position, comment.length, TypeScript.DiagnosticCode.Invalid_reference_directive_syntax));
                } else {
                    var path = TypeScript.normalizePath(fullReference[3]);
                    var adjustedPath = TypeScript.normalizePath(path);

                    var isResident = fullReference.length >= 7 && fullReference[6] === "true";
                    return {
                        line: 0,
                        character: 0,
                        position: 0,
                        length: 0,
                        path: TypeScript.switchToForwardSlashes(adjustedPath),
                        isResident: isResident
                    };
                }
            }
        }

        return null;
    }

    var reportDiagnostic = function () {
    };

    function processImports(text, scanner, token, importedFiles) {
        var lineChar = { line: -1, character: -1 };

        var lineMap = text.lineMap();
        var start = new Date().getTime();

        while (token.kind() !== 10 /* EndOfFileToken */) {
            if (token.kind() === 49 /* ImportKeyword */) {
                var importToken = token;
                token = scanner.scan(false);

                if (TypeScript.SyntaxFacts.isIdentifierNameOrAnyKeyword(token)) {
                    token = scanner.scan(false);

                    if (token.kind() === 107 /* EqualsToken */) {
                        token = scanner.scan(false);

                        if (token.kind() === 65 /* ModuleKeyword */ || token.kind() === 66 /* RequireKeyword */) {
                            token = scanner.scan(false);

                            if (token.kind() === 72 /* OpenParenToken */) {
                                token = scanner.scan(false);

                                lineMap.fillLineAndCharacterFromPosition(TypeScript.start(importToken, text), lineChar);

                                if (token.kind() === 14 /* StringLiteral */) {
                                    var ref = {
                                        line: lineChar.line,
                                        character: lineChar.character,
                                        position: TypeScript.start(token, text),
                                        length: TypeScript.width(token),
                                        path: TypeScript.stripStartAndEndQuotes(TypeScript.switchToForwardSlashes(token.text())),
                                        isResident: false
                                    };
                                    importedFiles.push(ref);
                                }
                            }
                        }
                    }
                }
            }

            token = scanner.scan(false);
        }

        var totalTime = new Date().getTime() - start;
        TypeScript.fileResolutionScanImportsTime += totalTime;
    }

    function processTripleSlashDirectives(fileName, text, firstToken) {
        var leadingTrivia = firstToken.leadingTrivia(text);

        var position = 0;
        var lineChar = { line: -1, character: -1 };
        var noDefaultLib = false;
        var diagnostics = [];
        var referencedFiles = [];
        var lineMap = text.lineMap();

        for (var i = 0, n = leadingTrivia.count(); i < n; i++) {
            var trivia = leadingTrivia.syntaxTriviaAt(i);

            if (trivia.kind() === 7 /* SingleLineCommentTrivia */) {
                var triviaText = trivia.fullText();
                var referencedCode = getFileReferenceFromReferencePath(fileName, text, position, triviaText, diagnostics);

                if (referencedCode) {
                    lineMap.fillLineAndCharacterFromPosition(position, lineChar);
                    referencedCode.position = position;
                    referencedCode.length = trivia.fullWidth();
                    referencedCode.line = lineChar.line;
                    referencedCode.character = lineChar.character;

                    referencedFiles.push(referencedCode);
                }

                // is it a lib file?
                var isNoDefaultLib = isNoDefaultLibMatch(triviaText);
                if (isNoDefaultLib) {
                    noDefaultLib = isNoDefaultLib[3] === "true";
                }
            }

            position += trivia.fullWidth();
        }

        return { noDefaultLib: noDefaultLib, diagnostics: diagnostics, referencedFiles: referencedFiles };
    }

    function preProcessFile(fileName, sourceText, readImportFiles) {
        if (typeof readImportFiles === "undefined") { readImportFiles = true; }
        var text = TypeScript.SimpleText.fromScriptSnapshot(sourceText);
        var scanner = TypeScript.Scanner.createScanner(1 /* EcmaScript5 */, text, reportDiagnostic);

        var firstToken = scanner.scan(false);

        // only search out dynamic mods
        // if you find a dynamic mod, ignore every other mod inside, until you balance rcurlies
        // var position
        var importedFiles = [];
        if (readImportFiles) {
            processImports(text, scanner, firstToken, importedFiles);
        }

        var properties = processTripleSlashDirectives(fileName, text, firstToken);

        return { referencedFiles: properties.referencedFiles, importedFiles: importedFiles, isLibFile: properties.noDefaultLib, diagnostics: properties.diagnostics };
    }
    TypeScript.preProcessFile = preProcessFile;

    function getReferencedFiles(fileName, sourceText) {
        return preProcessFile(fileName, sourceText, false).referencedFiles;
    }
    TypeScript.getReferencedFiles = getReferencedFiles;
})(TypeScript || (TypeScript = {})); // Tools
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var ReferenceResolutionResult = (function () {
        function ReferenceResolutionResult() {
            this.resolvedFiles = [];
            this.diagnostics = [];
            this.seenNoDefaultLibTag = false;
        }
        return ReferenceResolutionResult;
    })();
    TypeScript.ReferenceResolutionResult = ReferenceResolutionResult;

    var ReferenceLocation = (function () {
        function ReferenceLocation(filePath, lineMap, position, length, isImported) {
            this.filePath = filePath;
            this.lineMap = lineMap;
            this.position = position;
            this.length = length;
            this.isImported = isImported;
        }
        return ReferenceLocation;
    })();

    var ReferenceResolver = (function () {
        function ReferenceResolver(inputFileNames, host, useCaseSensitiveFileResolution) {
            this.useCaseSensitiveFileResolution = useCaseSensitiveFileResolution;
            this.inputFileNames = inputFileNames;
            this.host = host;
            this.visited = {};
        }
        ReferenceResolver.resolve = function (inputFileNames, host, useCaseSensitiveFileResolution) {
            var resolver = new ReferenceResolver(inputFileNames, host, useCaseSensitiveFileResolution);
            return resolver.resolveInputFiles();
        };

        ReferenceResolver.prototype.resolveInputFiles = function () {
            var _this = this;
            var result = new ReferenceResolutionResult();

            if (!this.inputFileNames || this.inputFileNames.length <= 0) {
                // Nothing to do.
                return result;
            }

            // Loop over the files and extract references
            var referenceLocation = new ReferenceLocation(null, null, 0, 0, false);
            this.inputFileNames.forEach(function (fileName) {
                return _this.resolveIncludedFile(fileName, referenceLocation, result);
            });

            return result;
        };

        ReferenceResolver.prototype.resolveIncludedFile = function (path, referenceLocation, resolutionResult) {
            var normalizedPath = this.getNormalizedFilePath(path, referenceLocation.filePath);

            if (this.isSameFile(normalizedPath, referenceLocation.filePath)) {
                // Cannot reference self
                if (!referenceLocation.isImported) {
                    resolutionResult.diagnostics.push(new TypeScript.Diagnostic(referenceLocation.filePath, referenceLocation.lineMap, referenceLocation.position, referenceLocation.length, TypeScript.DiagnosticCode.A_file_cannot_have_a_reference_to_itself, null));
                }

                return normalizedPath;
            }

            if (!TypeScript.isTSFile(normalizedPath) && !TypeScript.isDTSFile(normalizedPath)) {
                var dtsFile = normalizedPath + ".d.ts";
                var tsFile = normalizedPath + ".ts";

                if (this.host.fileExists(tsFile)) {
                    normalizedPath = tsFile;
                } else {
                    normalizedPath = dtsFile;
                }
            }

            if (!this.host.fileExists(normalizedPath)) {
                if (!referenceLocation.isImported) {
                    resolutionResult.diagnostics.push(new TypeScript.Diagnostic(referenceLocation.filePath, referenceLocation.lineMap, referenceLocation.position, referenceLocation.length, TypeScript.DiagnosticCode.Cannot_resolve_referenced_file_0, [path]));
                }

                return normalizedPath;
            }

            // Preprocess the file and resolve its imports/references
            return this.resolveFile(normalizedPath, resolutionResult);
        };

        ReferenceResolver.prototype.resolveImportedFile = function (path, referenceLocation, resolutionResult) {
            var isRelativePath = TypeScript.isRelative(path);
            var isRootedPath = isRelativePath ? false : TypeScript.isRooted(path);

            if (isRelativePath || isRootedPath) {
                // Handle as a normal include file
                return this.resolveIncludedFile(path, referenceLocation, resolutionResult);
            } else {
                // Search for the file
                var parentDirectory = this.host.getParentDirectory(referenceLocation.filePath);
                var searchFilePath = null;
                var dtsFileName = path + ".d.ts";
                var tsFilePath = path + ".ts";

                var start = new Date().getTime();

                do {
                    // Search for ".ts" file first
                    currentFilePath = this.host.resolveRelativePath(tsFilePath, parentDirectory);
                    if (this.host.fileExists(currentFilePath)) {
                        // Found the file
                        searchFilePath = currentFilePath;
                        break;
                    }

                    // Search for ".d.ts" file
                    var currentFilePath = this.host.resolveRelativePath(dtsFileName, parentDirectory);
                    if (this.host.fileExists(currentFilePath)) {
                        // Found the file
                        searchFilePath = currentFilePath;
                        break;
                    }

                    parentDirectory = this.host.getParentDirectory(parentDirectory);
                } while(parentDirectory);

                TypeScript.fileResolutionImportFileSearchTime += new Date().getTime() - start;

                if (!searchFilePath) {
                    // Cannot find file import, do not reprot an error, the typeChecker will report it later on
                    return path;
                }

                // Preprocess the file and resolve its imports/references
                return this.resolveFile(searchFilePath, resolutionResult);
            }
        };

        ReferenceResolver.prototype.resolveFile = function (normalizedPath, resolutionResult) {
            var _this = this;
            // If we have processed this file before, skip it
            var visitedPath = this.isVisited(normalizedPath);
            if (!visitedPath) {
                // Record that we have seen it
                this.recordVisitedFile(normalizedPath);

                // Preprocess the file
                var start = new Date().getTime();
                var scriptSnapshot = this.host.getScriptSnapshot(normalizedPath);
                var totalTime = new Date().getTime() - start;
                TypeScript.fileResolutionIOTime += totalTime;

                var lineMap = TypeScript.LineMap1.fromScriptSnapshot(scriptSnapshot);
                var preprocessedFileInformation = TypeScript.preProcessFile(normalizedPath, scriptSnapshot);
                resolutionResult.diagnostics.push.apply(resolutionResult.diagnostics, preprocessedFileInformation.diagnostics);

                // If this file has a "no-default-lib = 'true'" tag
                if (preprocessedFileInformation.isLibFile) {
                    resolutionResult.seenNoDefaultLibTag = true;
                }

                // Resolve explicit references
                var normalizedReferencePaths = [];
                preprocessedFileInformation.referencedFiles.forEach(function (fileReference) {
                    var currentReferenceLocation = new ReferenceLocation(normalizedPath, lineMap, fileReference.position, fileReference.length, false);
                    var normalizedReferencePath = _this.resolveIncludedFile(fileReference.path, currentReferenceLocation, resolutionResult);
                    normalizedReferencePaths.push(normalizedReferencePath);
                });

                // Resolve imports
                var normalizedImportPaths = [];
                for (var i = 0; i < preprocessedFileInformation.importedFiles.length; i++) {
                    var fileImport = preprocessedFileInformation.importedFiles[i];
                    var currentReferenceLocation = new ReferenceLocation(normalizedPath, lineMap, fileImport.position, fileImport.length, true);
                    var normalizedImportPath = this.resolveImportedFile(fileImport.path, currentReferenceLocation, resolutionResult);
                    normalizedImportPaths.push(normalizedImportPath);
                }

                // Add the file to the result list
                resolutionResult.resolvedFiles.push({
                    path: normalizedPath,
                    referencedFiles: normalizedReferencePaths,
                    importedFiles: normalizedImportPaths
                });
            } else {
                normalizedPath = visitedPath;
            }

            return normalizedPath;
        };

        ReferenceResolver.prototype.getNormalizedFilePath = function (path, parentFilePath) {
            var parentFileDirectory = parentFilePath ? this.host.getParentDirectory(parentFilePath) : "";
            var normalizedPath = this.host.resolveRelativePath(path, parentFileDirectory);
            return normalizedPath;
        };

        ReferenceResolver.prototype.getUniqueFileId = function (filePath) {
            return this.useCaseSensitiveFileResolution ? filePath : filePath.toLocaleUpperCase();
        };

        ReferenceResolver.prototype.recordVisitedFile = function (filePath) {
            this.visited[this.getUniqueFileId(filePath)] = filePath;
        };

        ReferenceResolver.prototype.isVisited = function (filePath) {
            return this.visited[this.getUniqueFileId(filePath)];
        };

        ReferenceResolver.prototype.isSameFile = function (filePath1, filePath2) {
            if (!filePath1 || !filePath2) {
                return false;
            }

            if (this.useCaseSensitiveFileResolution) {
                return filePath1 === filePath2;
            } else {
                return filePath1.toLocaleUpperCase() === filePath2.toLocaleUpperCase();
            }
        };
        return ReferenceResolver;
    })();
    TypeScript.ReferenceResolver = ReferenceResolver;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    var TextWriter = (function () {
        function TextWriter(name, writeByteOrderMark, outputFileType) {
            this.name = name;
            this.writeByteOrderMark = writeByteOrderMark;
            this.outputFileType = outputFileType;
            this.contents = "";
            this.onNewLine = true;
        }
        TextWriter.prototype.Write = function (s) {
            this.contents += s;
            this.onNewLine = false;
        };

        TextWriter.prototype.WriteLine = function (s) {
            this.contents += s;
            this.contents += TypeScript.newLine();
            this.onNewLine = true;
        };

        TextWriter.prototype.Close = function () {
        };

        TextWriter.prototype.getOutputFile = function () {
            return new TypeScript.OutputFile(this.name, this.writeByteOrderMark, this.contents, this.outputFileType);
        };
        return TextWriter;
    })();
    TypeScript.TextWriter = TextWriter;

    var DeclarationEmitter = (function () {
        function DeclarationEmitter(emittingFileName, document, compiler, emitOptions, semanticInfoChain) {
            this.emittingFileName = emittingFileName;
            this.document = document;
            this.compiler = compiler;
            this.emitOptions = emitOptions;
            this.semanticInfoChain = semanticInfoChain;
            this.declFile = null;
            this.indenter = new TypeScript.Indenter();
            this.emittedReferencePaths = false;
            this.declFile = new TextWriter(emittingFileName, this.document.byteOrderMark !== 0 /* None */, 2 /* Declaration */);
        }
        DeclarationEmitter.prototype.getOutputFile = function () {
            return this.declFile.getOutputFile();
        };

        DeclarationEmitter.prototype.emitDeclarations = function (sourceUnit) {
            this.emitDeclarationsForSourceUnit(sourceUnit);
        };

        DeclarationEmitter.prototype.emitDeclarationsForList = function (list) {
            for (var i = 0, n = list.length; i < n; i++) {
                this.emitDeclarationsForAST(list[i]);
            }
        };

        DeclarationEmitter.prototype.emitSeparatedList = function (list) {
            for (var i = 0, n = list.length; i < n; i++) {
                this.emitDeclarationsForAST(list[i]);
            }
        };

        DeclarationEmitter.prototype.emitDeclarationsForAST = function (ast) {
            switch (ast.kind()) {
                case 148 /* VariableStatement */:
                    return this.emitDeclarationsForVariableStatement(ast);
                case 141 /* PropertySignature */:
                    return this.emitPropertySignature(ast);
                case 225 /* VariableDeclarator */:
                    return this.emitVariableDeclarator(ast, true, true);
                case 136 /* MemberVariableDeclaration */:
                    return this.emitDeclarationsForMemberVariableDeclaration(ast);
                case 137 /* ConstructorDeclaration */:
                    return this.emitDeclarationsForConstructorDeclaration(ast);
                case 139 /* GetAccessor */:
                    return this.emitDeclarationsForGetAccessor(ast);
                case 140 /* SetAccessor */:
                    return this.emitDeclarationsForSetAccessor(ast);
                case 138 /* IndexMemberDeclaration */:
                    return this.emitIndexMemberDeclaration(ast);
                case 144 /* IndexSignature */:
                    return this.emitIndexSignature(ast);
                case 142 /* CallSignature */:
                    return this.emitCallSignature(ast);
                case 143 /* ConstructSignature */:
                    return this.emitConstructSignature(ast);
                case 145 /* MethodSignature */:
                    return this.emitMethodSignature(ast);
                case 129 /* FunctionDeclaration */:
                    return this.emitDeclarationsForFunctionDeclaration(ast);
                case 135 /* MemberFunctionDeclaration */:
                    return this.emitMemberFunctionDeclaration(ast);
                case 131 /* ClassDeclaration */:
                    return this.emitDeclarationsForClassDeclaration(ast);
                case 128 /* InterfaceDeclaration */:
                    return this.emitDeclarationsForInterfaceDeclaration(ast);
                case 133 /* ImportDeclaration */:
                    return this.emitDeclarationsForImportDeclaration(ast);
                case 130 /* ModuleDeclaration */:
                    return this.emitDeclarationsForModuleDeclaration(ast);
                case 132 /* EnumDeclaration */:
                    return this.emitDeclarationsForEnumDeclaration(ast);
                case 134 /* ExportAssignment */:
                    return this.emitDeclarationsForExportAssignment(ast);
            }
        };

        DeclarationEmitter.prototype.getIndentString = function (declIndent) {
            if (typeof declIndent === "undefined") { declIndent = false; }
            return this.indenter.getIndent();
        };

        DeclarationEmitter.prototype.emitIndent = function () {
            this.declFile.Write(this.getIndentString());
        };

        DeclarationEmitter.prototype.canEmitDeclarations = function (declAST) {
            var container = DeclarationEmitter.getEnclosingContainer(declAST);
            if (container.kind() === 130 /* ModuleDeclaration */ || container.kind() === 120 /* SourceUnit */) {
                var pullDecl = this.semanticInfoChain.getDeclForAST(declAST);
                if (!TypeScript.hasFlag(pullDecl.flags, 1 /* Exported */)) {
                    var start = new Date().getTime();
                    var declSymbol = this.semanticInfoChain.getSymbolForAST(declAST);
                    var result = declSymbol && declSymbol.isExternallyVisible();
                    TypeScript.declarationEmitIsExternallyVisibleTime += new Date().getTime() - start;

                    return result;
                }
            }

            return true;
        };

        DeclarationEmitter.prototype.getDeclFlagsString = function (pullDecl, typeString) {
            var result = this.getIndentString();
            var pullFlags = pullDecl.flags;

            // Static/public/private/global declare
            if (TypeScript.hasFlag(pullFlags, TypeScript.PullElementFlags.Static)) {
                if (TypeScript.hasFlag(pullFlags, TypeScript.PullElementFlags.Private)) {
                    result += "private ";
                }
                result += "static ";
            } else {
                if (TypeScript.hasFlag(pullFlags, TypeScript.PullElementFlags.Private)) {
                    result += "private ";
                } else if (TypeScript.hasFlag(pullFlags, TypeScript.PullElementFlags.Public)) {
                    result += "public ";
                } else {
                    var emitDeclare = !TypeScript.hasFlag(pullFlags, 1 /* Exported */);

                    var declAST = this.semanticInfoChain.getASTForDecl(pullDecl);
                    var container = DeclarationEmitter.getEnclosingContainer(declAST);

                    var isExternalModule = container.kind() === 120 /* SourceUnit */ && this.document.syntaxTree().isExternalModule();

                    // Emit export only for global export statements.
                    // The container for this would be dynamic module which is whole file
                    if (isExternalModule && TypeScript.hasFlag(pullFlags, 1 /* Exported */)) {
                        result += "export ";
                        emitDeclare = true;
                    }

                    // Emit declare only in global context
                    if (isExternalModule || container.kind() === 120 /* SourceUnit */) {
                        // Emit declare if not interface declaration or import declaration && is not from module
                        if (emitDeclare && typeString !== "interface" && typeString !== "import") {
                            result += "declare ";
                        }
                    }

                    result += typeString + " ";
                }
            }

            return result;
        };

        DeclarationEmitter.prototype.emitDeclFlags = function (declarationAST, typeString) {
            this.declFile.Write(this.getDeclFlagsString(this.semanticInfoChain.getDeclForAST(declarationAST), typeString));
        };

        DeclarationEmitter.prototype.emitTypeNamesMember = function (memberName, emitIndent) {
            if (typeof emitIndent === "undefined") { emitIndent = false; }
            if (memberName.prefix === "{ ") {
                if (emitIndent) {
                    this.emitIndent();
                }

                this.declFile.WriteLine("{");
                this.indenter.increaseIndent();
                emitIndent = true;
            } else if (memberName.prefix !== "") {
                if (emitIndent) {
                    this.emitIndent();
                }

                this.declFile.Write(memberName.prefix);
                emitIndent = false;
            }

            if (memberName.isString()) {
                if (emitIndent) {
                    this.emitIndent();
                }

                this.declFile.Write(memberName.text);
            } else if (memberName.isArray()) {
                var ar = memberName;
                for (var index = 0; index < ar.entries.length; index++) {
                    this.emitTypeNamesMember(ar.entries[index], emitIndent);
                    if (ar.delim === "; ") {
                        this.declFile.WriteLine(";");
                    }
                }
            }

            if (memberName.suffix === "}") {
                this.indenter.decreaseIndent();
                this.emitIndent();
                this.declFile.Write(memberName.suffix);
            } else {
                this.declFile.Write(memberName.suffix);
            }
        };

        DeclarationEmitter.prototype.emitTypeSignature = function (ast, type) {
            var declarationContainerAst = DeclarationEmitter.getEnclosingContainer(ast);

            var start = new Date().getTime();
            var declarationContainerDecl = this.semanticInfoChain.getDeclForAST(declarationContainerAst);

            var declarationPullSymbol = declarationContainerDecl.getSymbol(this.semanticInfoChain);
            TypeScript.declarationEmitTypeSignatureTime += new Date().getTime() - start;

            var isNotAGenericType = ast.kind() !== 126 /* GenericType */;

            var typeNameMembers = type.getScopedNameEx(declarationPullSymbol, false, false, false, false, false, isNotAGenericType);
            this.emitTypeNamesMember(typeNameMembers);
        };

        DeclarationEmitter.prototype.emitComment = function (comment) {
            var text = TypeScript.getTrimmedTextLines(comment);
            if (this.declFile.onNewLine) {
                this.emitIndent();
            } else if (comment.kind() !== 6 /* MultiLineCommentTrivia */) {
                this.declFile.WriteLine("");
                this.emitIndent();
            }

            this.declFile.Write(text[0]);

            for (var i = 1; i < text.length; i++) {
                this.declFile.WriteLine("");
                this.emitIndent();
                this.declFile.Write(text[i]);
            }

            if (comment.endsLine || comment.kind() !== 6 /* MultiLineCommentTrivia */) {
                this.declFile.WriteLine("");
            } else {
                this.declFile.Write(" ");
            }
        };

        DeclarationEmitter.prototype.text = function () {
            return this.document.syntaxTree().text;
        };

        DeclarationEmitter.prototype.emitDeclarationComments = function (astOrSymbol, endLine) {
            if (typeof endLine === "undefined") { endLine = true; }
            if (this.emitOptions.compilationSettings().removeComments()) {
                return;
            }

            var declComments = astOrSymbol.docComments ? astOrSymbol.docComments() : TypeScript.ASTHelpers.docComments(astOrSymbol, this.text());
            this.writeDeclarationComments(declComments, endLine);
        };

        DeclarationEmitter.prototype.writeDeclarationComments = function (declComments, endLine) {
            if (typeof endLine === "undefined") { endLine = true; }
            if (declComments) {
                var wroteComment = false;
                for (var i = 0; i < declComments.length; i++) {
                    if (TypeScript.ASTHelpers.isDocComment(declComments[i])) {
                        this.emitComment(declComments[i]);
                        wroteComment = true;
                    }
                }

                if (wroteComment) {
                    if (endLine) {
                        if (!this.declFile.onNewLine) {
                            this.declFile.WriteLine("");
                        }
                    } else {
                        if (this.declFile.onNewLine) {
                            this.emitIndent();
                        }
                    }
                }
            }
        };

        DeclarationEmitter.prototype.emitTypeOfVariableDeclaratorOrParameter = function (boundDecl) {
            var start = new Date().getTime();
            var decl = this.semanticInfoChain.getDeclForAST(boundDecl);
            var pullSymbol = decl.getSymbol(this.semanticInfoChain);
            TypeScript.declarationEmitGetBoundDeclTypeTime += new Date().getTime() - start;

            var type = pullSymbol.type;
            TypeScript.Debug.assert(type);

            this.declFile.Write(": ");
            this.emitTypeSignature(boundDecl, type);
        };

        DeclarationEmitter.prototype.emitPropertySignature = function (varDecl) {
            this.emitDeclarationComments(varDecl);
            this.emitIndent();
            this.declFile.Write(varDecl.propertyName.text());
            if (varDecl.questionToken) {
                this.declFile.Write("?");
            }

            this.emitTypeOfVariableDeclaratorOrParameter(varDecl);

            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitVariableDeclarator = function (varDecl, isFirstVarInList, isLastVarInList) {
            if (this.canEmitDeclarations(varDecl)) {
                this.emitDeclarationComments(varDecl);

                // If it is var list of form var a, b, c = emit it only if count > 0 - which will be when emitting first var
                // If it is var list of form  var a = varList count will be 0
                if (isFirstVarInList) {
                    this.emitDeclFlags(varDecl, "var");
                }

                this.declFile.Write(varDecl.propertyName.text());

                if (!TypeScript.hasModifier(TypeScript.ASTHelpers.getVariableDeclaratorModifiers(varDecl), TypeScript.PullElementFlags.Private)) {
                    this.emitTypeOfVariableDeclaratorOrParameter(varDecl);
                }

                // Write ; or ,
                if (isLastVarInList) {
                    this.declFile.WriteLine(";");
                } else {
                    this.declFile.Write(", ");
                }
            }
        };

        DeclarationEmitter.prototype.emitClassElementModifiers = function (modifiers) {
            if (TypeScript.hasModifier(modifiers, TypeScript.PullElementFlags.Static)) {
                if (TypeScript.hasModifier(modifiers, TypeScript.PullElementFlags.Private)) {
                    this.declFile.Write("private ");
                }
                this.declFile.Write("static ");
            } else {
                if (TypeScript.hasModifier(modifiers, TypeScript.PullElementFlags.Private)) {
                    this.declFile.Write("private ");
                } else {
                    this.declFile.Write("public ");
                }
            }
        };

        DeclarationEmitter.prototype.emitDeclarationsForMemberVariableDeclaration = function (varDecl) {
            if (this.canEmitDeclarations(varDecl)) {
                this.emitDeclarationComments(varDecl);

                this.declFile.Write(this.getIndentString());
                this.emitClassElementModifiers(varDecl.modifiers);
                ;

                this.declFile.Write(varDecl.variableDeclarator.propertyName.text());

                if (!TypeScript.hasModifier(varDecl.modifiers, TypeScript.PullElementFlags.Private)) {
                    this.emitTypeOfVariableDeclaratorOrParameter(varDecl);
                }

                this.declFile.WriteLine(";");
            }
        };

        DeclarationEmitter.prototype.emitDeclarationsForVariableStatement = function (variableStatement) {
            this.emitDeclarationsForVariableDeclaration(variableStatement.variableDeclaration);
        };

        DeclarationEmitter.prototype.emitDeclarationsForVariableDeclaration = function (variableDeclaration) {
            var varListCount = variableDeclaration.variableDeclarators.length;
            for (var i = 0; i < varListCount; i++) {
                this.emitVariableDeclarator(variableDeclaration.variableDeclarators[i], i === 0, i === varListCount - 1);
            }
        };

        DeclarationEmitter.prototype.parameterIsOptional = function (parameter) {
            return parameter.questionToken !== null || parameter.equalsValueClause !== null;
        };

        DeclarationEmitter.prototype.emitParameter = function (argDecl, isPrivate) {
            this.indenter.increaseIndent();

            this.emitDeclarationComments(argDecl, false);
            this.declFile.Write(argDecl.identifier.text());
            if (this.parameterIsOptional(argDecl)) {
                this.declFile.Write("?");
            }

            this.indenter.decreaseIndent();

            if (!isPrivate) {
                this.emitTypeOfVariableDeclaratorOrParameter(argDecl);
            }
        };

        DeclarationEmitter.prototype.isOverloadedCallSignature = function (funcDecl) {
            var start = new Date().getTime();
            var functionDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            var funcSymbol = functionDecl.getSymbol(this.semanticInfoChain);
            TypeScript.declarationEmitIsOverloadedCallSignatureTime += new Date().getTime() - start;

            var funcTypeSymbol = funcSymbol.type;
            var signatures = funcTypeSymbol.getCallSignatures();
            var result = signatures && signatures.length > 1;

            return result;
        };

        DeclarationEmitter.prototype.emitDeclarationsForConstructorDeclaration = function (funcDecl) {
            var start = new Date().getTime();
            var funcSymbol = this.semanticInfoChain.getSymbolForAST(funcDecl);

            TypeScript.declarationEmitFunctionDeclarationGetSymbolTime += new Date().getTime() - start;

            var funcTypeSymbol = funcSymbol.type;
            if (funcDecl.block) {
                var constructSignatures = funcTypeSymbol.getConstructSignatures();
                if (constructSignatures && constructSignatures.length > 1) {
                    return;
                }
                //else if (this.isOverloadedCallSignature(funcDecl)) {
                //    // This means its implementation of overload signature. do not emit
                //    return;
                //}
            }

            var funcPullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            var funcSignature = funcPullDecl.getSignatureSymbol(this.semanticInfoChain);
            this.emitDeclarationComments(funcDecl);

            this.emitIndent();
            this.declFile.Write("constructor");

            this.emitParameterList(false, funcDecl.callSignature.parameterList);

            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitParameterList = function (isPrivate, parameterList) {
            this.declFile.Write("(");
            this.emitParameters(isPrivate, parameterList.parameters);
            this.declFile.Write(")");
        };

        DeclarationEmitter.prototype.emitParameters = function (isPrivate, parameterList) {
            var hasLastParameterRestParameter = TypeScript.lastParameterIsRest(parameterList);
            var argsLen = parameterList.length;
            if (hasLastParameterRestParameter) {
                argsLen--;
            }

            for (var i = 0; i < argsLen; i++) {
                this.emitParameter(parameterList[i], isPrivate);
                if (i < (argsLen - 1)) {
                    this.declFile.Write(", ");
                }
            }

            if (hasLastParameterRestParameter) {
                if (parameterList.length > 1) {
                    this.declFile.Write(", ...");
                } else {
                    this.declFile.Write("...");
                }

                var index = parameterList.length - 1;
                this.emitParameter(parameterList[index], isPrivate);
            }
        };

        DeclarationEmitter.prototype.emitMemberFunctionDeclaration = function (funcDecl) {
            var start = new Date().getTime();
            var funcSymbol = this.semanticInfoChain.getSymbolForAST(funcDecl);

            TypeScript.declarationEmitFunctionDeclarationGetSymbolTime += new Date().getTime() - start;

            var funcTypeSymbol = funcSymbol.type;
            if (funcDecl.block) {
                var constructSignatures = funcTypeSymbol.getConstructSignatures();
                if (constructSignatures && constructSignatures.length > 1) {
                    return;
                } else if (this.isOverloadedCallSignature(funcDecl)) {
                    // This means its implementation of overload signature. do not emit
                    return;
                }
            } else if (TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Private) && this.isOverloadedCallSignature(funcDecl)) {
                // Print only first overload of private function
                var callSignatures = funcTypeSymbol.getCallSignatures();
                TypeScript.Debug.assert(callSignatures && callSignatures.length > 1);
                var firstSignature = callSignatures[0].isDefinition() ? callSignatures[1] : callSignatures[0];
                var firstSignatureDecl = firstSignature.getDeclarations()[0];
                var firstFuncDecl = this.semanticInfoChain.getASTForDecl(firstSignatureDecl);
                if (firstFuncDecl !== funcDecl) {
                    return;
                }
            }

            if (!this.canEmitDeclarations(funcDecl)) {
                return;
            }

            var funcPullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            var funcSignature = funcPullDecl.getSignatureSymbol(this.semanticInfoChain);
            this.emitDeclarationComments(funcDecl);

            this.emitDeclFlags(funcDecl, "function");
            var id = funcDecl.propertyName.text();
            this.declFile.Write(id);
            this.emitTypeParameters(funcDecl.callSignature.typeParameterList, funcSignature);

            var isPrivate = TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Private);

            this.emitParameterList(isPrivate, funcDecl.callSignature.parameterList);

            if (!isPrivate) {
                var returnType = funcSignature.returnType;
                this.declFile.Write(": ");
                this.emitTypeSignature(funcDecl, returnType);
            }

            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitCallSignature = function (funcDecl) {
            var funcPullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);

            this.emitDeclarationComments(funcDecl);

            var funcSignature = funcPullDecl.getSignatureSymbol(this.semanticInfoChain);
            this.emitTypeParameters(funcDecl.typeParameterList, funcSignature);

            this.emitIndent();

            this.emitParameterList(false, funcDecl.parameterList);

            var returnType = funcSignature.returnType;
            this.declFile.Write(": ");
            if (returnType) {
                this.emitTypeSignature(funcDecl, returnType);
            } else {
                this.declFile.Write("any");
            }

            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitConstructSignature = function (funcDecl) {
            var funcPullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);

            var start = new Date().getTime();
            var funcSymbol = this.semanticInfoChain.getSymbolForAST(funcDecl);

            TypeScript.declarationEmitFunctionDeclarationGetSymbolTime += new Date().getTime() - start;

            this.emitDeclarationComments(funcDecl);

            this.emitIndent();
            this.declFile.Write("new");

            var funcSignature = funcPullDecl.getSignatureSymbol(this.semanticInfoChain);
            this.emitTypeParameters(funcDecl.callSignature.typeParameterList, funcSignature);

            this.emitParameterList(false, funcDecl.callSignature.parameterList);

            var returnType = funcSignature.returnType;
            this.declFile.Write(": ");
            if (returnType) {
                this.emitTypeSignature(funcDecl, returnType);
            } else {
                this.declFile.Write("any");
            }

            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitMethodSignature = function (funcDecl) {
            var funcPullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);

            var start = new Date().getTime();
            var funcSymbol = this.semanticInfoChain.getSymbolForAST(funcDecl);

            TypeScript.declarationEmitFunctionDeclarationGetSymbolTime += new Date().getTime() - start;

            this.emitDeclarationComments(funcDecl);

            this.emitIndent();
            this.declFile.Write(funcDecl.propertyName.text());
            if (funcDecl.questionToken) {
                this.declFile.Write("? ");
            }

            var funcSignature = funcPullDecl.getSignatureSymbol(this.semanticInfoChain);
            this.emitTypeParameters(funcDecl.callSignature.typeParameterList, funcSignature);

            this.emitParameterList(false, funcDecl.callSignature.parameterList);

            var returnType = funcSignature.returnType;
            this.declFile.Write(": ");
            if (returnType) {
                this.emitTypeSignature(funcDecl, returnType);
            } else {
                this.declFile.Write("any");
            }

            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitDeclarationsForFunctionDeclaration = function (funcDecl) {
            var funcPullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);

            var start = new Date().getTime();
            var funcSymbol = this.semanticInfoChain.getSymbolForAST(funcDecl);

            TypeScript.declarationEmitFunctionDeclarationGetSymbolTime += new Date().getTime() - start;

            if (funcDecl.block) {
                var funcTypeSymbol = funcSymbol.type;
                var constructSignatures = funcTypeSymbol.getConstructSignatures();
                if (constructSignatures && constructSignatures.length > 1) {
                    return;
                } else if (this.isOverloadedCallSignature(funcDecl)) {
                    // This means its implementation of overload signature. do not emit
                    return;
                }
            }

            if (!this.canEmitDeclarations(funcDecl)) {
                return;
            }

            this.emitDeclarationComments(funcDecl);

            var id = funcDecl.identifier.text();
            this.emitDeclFlags(funcDecl, "function");
            if (id !== "" || !funcDecl.identifier || funcDecl.identifier.text().length > 0) {
                this.declFile.Write(id);
            } else if (funcPullDecl.kind === TypeScript.PullElementKind.ConstructSignature) {
                this.declFile.Write("new");
            }

            var funcSignature = funcPullDecl.getSignatureSymbol(this.semanticInfoChain);
            this.emitTypeParameters(funcDecl.callSignature.typeParameterList, funcSignature);

            this.emitParameterList(false, funcDecl.callSignature.parameterList);

            var returnType = funcSignature.returnType;
            this.declFile.Write(": ");
            if (returnType) {
                this.emitTypeSignature(funcDecl, returnType);
            } else {
                this.declFile.Write("any");
            }

            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitIndexMemberDeclaration = function (funcDecl) {
            this.emitDeclarationsForAST(funcDecl.indexSignature);
        };

        DeclarationEmitter.prototype.emitIndexSignature = function (funcDecl) {
            if (!this.canEmitDeclarations(funcDecl)) {
                return;
            }

            this.emitDeclarationComments(funcDecl);

            this.emitIndent();
            this.declFile.Write("[");
            this.emitParameters(false, funcDecl.parameters);
            this.declFile.Write("]");

            var funcPullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
            var funcSignature = funcPullDecl.getSignatureSymbol(this.semanticInfoChain);
            var returnType = funcSignature.returnType;
            this.declFile.Write(": ");
            this.emitTypeSignature(funcDecl, returnType);

            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitBaseList = function (bases, useExtendsList) {
            if (bases && (bases.length > 0)) {
                var qual = useExtendsList ? "extends" : "implements";
                this.declFile.Write(" " + qual + " ");
                var basesLen = bases.length;
                for (var i = 0; i < basesLen; i++) {
                    if (i > 0) {
                        this.declFile.Write(", ");
                    }
                    var base = bases[i];
                    var baseType = this.semanticInfoChain.getSymbolForAST(base);
                    this.emitTypeSignature(base, baseType);
                }
            }
        };

        DeclarationEmitter.prototype.emitAccessorDeclarationComments = function (funcDecl) {
            if (this.emitOptions.compilationSettings().removeComments()) {
                return;
            }

            var start = new Date().getTime();
            var accessors = TypeScript.PullHelpers.getGetterAndSetterFunction(funcDecl, this.semanticInfoChain);
            TypeScript.declarationEmitGetAccessorFunctionTime += new Date().getTime();

            var comments = [];
            if (accessors.getter) {
                comments = comments.concat(TypeScript.ASTHelpers.docComments(accessors.getter, this.text()));
            }
            if (accessors.setter) {
                comments = comments.concat(TypeScript.ASTHelpers.docComments(accessors.setter, this.text()));
            }

            this.writeDeclarationComments(comments);
        };

        DeclarationEmitter.prototype.emitDeclarationsForGetAccessor = function (funcDecl) {
            this.emitMemberAccessorDeclaration(funcDecl, funcDecl.modifiers, funcDecl.propertyName);
        };

        DeclarationEmitter.prototype.emitDeclarationsForSetAccessor = function (funcDecl) {
            this.emitMemberAccessorDeclaration(funcDecl, funcDecl.modifiers, funcDecl.propertyName);
        };

        DeclarationEmitter.prototype.emitMemberAccessorDeclaration = function (funcDecl, modifiers, name) {
            var start = new Date().getTime();
            var accessorSymbol = TypeScript.PullHelpers.getAccessorSymbol(funcDecl, this.semanticInfoChain);
            TypeScript.declarationEmitGetAccessorFunctionTime += new Date().getTime();

            if (funcDecl.kind() === 140 /* SetAccessor */ && accessorSymbol.getGetter()) {
                // Setter is being used to emit the type info.
                return;
            }

            var isPrivate = TypeScript.hasModifier(modifiers, TypeScript.PullElementFlags.Private);
            this.emitAccessorDeclarationComments(funcDecl);
            this.declFile.Write(this.getIndentString());
            this.emitClassElementModifiers(modifiers);
            this.declFile.Write(name.text());
            if (!isPrivate) {
                this.declFile.Write(" : ");
                var type = accessorSymbol.type;
                this.emitTypeSignature(funcDecl, type);
            }
            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.emitClassMembersFromConstructorDefinition = function (funcDecl) {
            var argsLen = funcDecl.callSignature.parameterList.parameters.length;
            if (TypeScript.lastParameterIsRest(funcDecl.callSignature.parameterList.parameters)) {
                argsLen--;
            }

            for (var i = 0; i < argsLen; i++) {
                var parameter = funcDecl.callSignature.parameterList.parameters[i];
                var parameterDecl = this.semanticInfoChain.getDeclForAST(parameter);
                if (TypeScript.hasFlag(parameterDecl.flags, TypeScript.PullElementFlags.PropertyParameter)) {
                    var funcPullDecl = this.semanticInfoChain.getDeclForAST(funcDecl);
                    this.emitDeclarationComments(parameter);
                    this.declFile.Write(this.getIndentString());
                    this.emitClassElementModifiers(parameter.modifiers);
                    this.declFile.Write(parameter.identifier.text());

                    if (!TypeScript.hasModifier(parameter.modifiers, TypeScript.PullElementFlags.Private)) {
                        this.emitTypeOfVariableDeclaratorOrParameter(parameter);
                    }
                    this.declFile.WriteLine(";");
                }
            }
        };

        DeclarationEmitter.prototype.emitDeclarationsForClassDeclaration = function (classDecl) {
            if (!this.canEmitDeclarations(classDecl)) {
                return;
            }

            var className = classDecl.identifier.text();
            this.emitDeclarationComments(classDecl);
            var classPullDecl = this.semanticInfoChain.getDeclForAST(classDecl);
            this.emitDeclFlags(classDecl, "class");
            this.declFile.Write(className);

            this.emitTypeParameters(classDecl.typeParameterList);
            this.emitHeritageClauses(classDecl.heritageClauses);
            this.declFile.WriteLine(" {");

            this.indenter.increaseIndent();
            var constructorDecl = TypeScript.getLastConstructor(classDecl);
            if (constructorDecl) {
                this.emitClassMembersFromConstructorDefinition(constructorDecl);
            }

            this.emitDeclarationsForList(classDecl.classElements);

            this.indenter.decreaseIndent();

            this.emitIndent();
            this.declFile.WriteLine("}");
        };

        DeclarationEmitter.prototype.emitHeritageClauses = function (clauses) {
            if (clauses) {
                for (var i = 0, n = clauses.length; i < n; i++) {
                    this.emitHeritageClause(clauses[i]);
                }
            }
        };

        DeclarationEmitter.prototype.emitHeritageClause = function (clause) {
            this.emitBaseList(clause.typeNames, clause.kind() === 230 /* ExtendsHeritageClause */);
        };

        DeclarationEmitter.getEnclosingContainer = function (ast) {
            // If the passed in as is the 'name' portion of an module declaration.
            // If so, we want the actual container of *that* module declaration.
            var enclosingModule = TypeScript.ASTHelpers.getModuleDeclarationFromNameAST(ast);
            ast = enclosingModule || ast;

            ast = ast.parent;
            while (ast) {
                if (ast.kind() === 131 /* ClassDeclaration */ || ast.kind() === 128 /* InterfaceDeclaration */ || ast.kind() === 130 /* ModuleDeclaration */ || ast.kind() === 120 /* SourceUnit */) {
                    return ast;
                }

                ast = ast.parent;
            }

            return null;
        };

        DeclarationEmitter.prototype.emitTypeParameters = function (typeParams, funcSignature) {
            if (!typeParams || !typeParams.typeParameters.length) {
                return;
            }

            this.declFile.Write("<");
            var containerAst = DeclarationEmitter.getEnclosingContainer(typeParams);

            var start = new Date().getTime();
            var containerDecl = this.semanticInfoChain.getDeclForAST(containerAst);
            var containerSymbol = containerDecl.getSymbol(this.semanticInfoChain);
            TypeScript.declarationEmitGetTypeParameterSymbolTime += new Date().getTime() - start;

            var typars;
            if (funcSignature) {
                typars = funcSignature.getTypeParameters();
            } else {
                typars = containerSymbol.getTypeArgumentsOrTypeParameters();
            }

            for (var i = 0; i < typars.length; i++) {
                if (i) {
                    this.declFile.Write(", ");
                }

                var memberName = typars[i].getScopedNameEx(containerSymbol, false, true);
                this.emitTypeNamesMember(memberName);
            }

            this.declFile.Write(">");
        };

        DeclarationEmitter.prototype.emitDeclarationsForInterfaceDeclaration = function (interfaceDecl) {
            if (!this.canEmitDeclarations(interfaceDecl)) {
                return;
            }

            var interfaceName = interfaceDecl.identifier.text();
            this.emitDeclarationComments(interfaceDecl);
            var interfacePullDecl = this.semanticInfoChain.getDeclForAST(interfaceDecl);
            this.emitDeclFlags(interfaceDecl, "interface");
            this.declFile.Write(interfaceName);

            this.emitTypeParameters(interfaceDecl.typeParameterList);
            this.emitHeritageClauses(interfaceDecl.heritageClauses);
            this.declFile.WriteLine(" {");

            this.indenter.increaseIndent();

            this.emitSeparatedList(interfaceDecl.body.typeMembers);

            this.indenter.decreaseIndent();

            this.emitIndent();
            this.declFile.WriteLine("}");
        };

        DeclarationEmitter.prototype.emitDeclarationsForImportDeclaration = function (importDeclAST) {
            var importDecl = this.semanticInfoChain.getDeclForAST(importDeclAST);
            var importSymbol = importDecl.getSymbol(this.semanticInfoChain);
            var isExportedImportDecl = TypeScript.hasModifier(importDeclAST.modifiers, 1 /* Exported */);

            if (isExportedImportDecl || importSymbol.typeUsedExternally() || TypeScript.PullContainerSymbol.usedAsSymbol(importSymbol.getContainer(), importSymbol)) {
                this.emitDeclarationComments(importDeclAST);
                this.emitIndent();
                if (isExportedImportDecl) {
                    this.declFile.Write("export ");
                }
                this.declFile.Write("import ");
                this.declFile.Write(importDeclAST.identifier.text() + " = ");
                if (importDeclAST.moduleReference.kind() === 245 /* ExternalModuleReference */) {
                    this.declFile.WriteLine("require(" + importDeclAST.moduleReference.stringLiteral.text() + ");");
                } else {
                    this.declFile.WriteLine(TypeScript.ASTHelpers.getNameOfIdenfierOrQualifiedName(importDeclAST.moduleReference.moduleName) + ";");
                }
            }
        };

        DeclarationEmitter.prototype.emitDeclarationsForEnumDeclaration = function (moduleDecl) {
            if (!this.canEmitDeclarations(moduleDecl)) {
                return;
            }

            this.emitDeclarationComments(moduleDecl);
            var modulePullDecl = this.semanticInfoChain.getDeclForAST(moduleDecl);
            this.emitDeclFlags(moduleDecl, "enum");
            this.declFile.WriteLine(moduleDecl.identifier.text() + " {");

            this.indenter.increaseIndent();
            var membersLen = moduleDecl.enumElements.length;
            for (var j = 0; j < membersLen; j++) {
                var enumElement = moduleDecl.enumElements[j];
                var enumElementDecl = this.semanticInfoChain.getDeclForAST(enumElement);
                this.emitDeclarationComments(enumElement);
                this.emitIndent();
                this.declFile.Write(enumElement.propertyName.text());
                if (enumElementDecl.constantValue !== null) {
                    this.declFile.Write(" = " + enumElementDecl.constantValue);
                }
                this.declFile.WriteLine(",");
            }
            this.indenter.decreaseIndent();

            this.emitIndent();
            this.declFile.WriteLine("}");
        };

        DeclarationEmitter.prototype.emitDeclarationsForModuleDeclaration = function (moduleDecl) {
            // If module is defined as A.B.C
            // The whole moduleDecl will have the pullDecl corresponding to innermost
            // Which would always be exported and hence would need to be emitted
            // But we really want to check if module A needs to be emitted and hence use
            // the leftmost name to determine if this needs to be emitted
            // Since the module name will have the correct decl, it is always used to determine
            // if this ast needs to be emitted or not
            var name = moduleDecl.stringLiteral || TypeScript.ArrayUtilities.first(TypeScript.ASTHelpers.getModuleNames(moduleDecl.name));
            if (!this.canEmitDeclarations(name)) {
                return;
            }

            this.emitDeclarationComments(moduleDecl);
            this.emitDeclFlags(name, "module");

            if (moduleDecl.stringLiteral) {
                this.declFile.Write(moduleDecl.stringLiteral.text());
            } else {
                this.declFile.Write(TypeScript.ASTHelpers.getNameOfIdenfierOrQualifiedName(moduleDecl.name));
            }

            this.declFile.WriteLine(" {");
            this.indenter.increaseIndent();

            this.emitDeclarationsForList(moduleDecl.moduleElements);

            this.indenter.decreaseIndent();
            this.emitIndent();
            this.declFile.WriteLine("}");
        };

        DeclarationEmitter.prototype.emitDeclarationsForExportAssignment = function (ast) {
            this.emitIndent();
            this.declFile.Write("export = ");
            this.declFile.Write(ast.identifier.text());
            this.declFile.WriteLine(";");
        };

        DeclarationEmitter.prototype.resolveScriptReference = function (document, reference) {
            if (!this.emitOptions.compilationSettings().noResolve() || TypeScript.isRooted(reference)) {
                return reference;
            }

            var documentDir = TypeScript.convertToDirectoryPath(TypeScript.switchToForwardSlashes(TypeScript.getRootFilePath(document.fileName)));
            var resolvedReferencePath = this.emitOptions.resolvePath(documentDir + reference);
            return resolvedReferencePath;
        };

        DeclarationEmitter.prototype.emitReferencePaths = function (sourceUnit) {
            // In case of shared handler we collect all the references and emit them
            if (this.emittedReferencePaths) {
                return;
            }

            // Collect all the documents that need to be emitted as reference
            var documents = [];
            if (this.document.emitToOwnOutputFile()) {
                // Emit only from this file
                var scriptReferences = this.document.referencedFiles;
                var addedGlobalDocument = false;
                for (var j = 0; j < scriptReferences.length; j++) {
                    var currentReference = this.resolveScriptReference(this.document, scriptReferences[j]);
                    var document = this.compiler.getDocument(currentReference);

                    // All the references that are not going to be part of same file
                    if (document && (document.emitToOwnOutputFile() || document.isDeclareFile() || !addedGlobalDocument)) {
                        documents = documents.concat(document);

                        if (!document.isDeclareFile() && document.syntaxTree().isExternalModule()) {
                            addedGlobalDocument = true;
                        }
                    }
                }
            } else {
                // Collect from all the references and emit
                var fileNames = this.compiler.fileNames();
                for (var i = 0; i < fileNames.length; i++) {
                    var doc = this.compiler.getDocument(fileNames[i]);
                    if (!doc.isDeclareFile() && !doc.syntaxTree().isExternalModule()) {
                        // Check what references need to be added
                        var scriptReferences = doc.referencedFiles;
                        for (var j = 0; j < scriptReferences.length; j++) {
                            var currentReference = this.resolveScriptReference(doc, scriptReferences[j]);
                            var document = this.compiler.getDocument(currentReference);

                            // All the references that are not going to be part of same file
                            if (document && (document.isDeclareFile() || document.syntaxTree().isExternalModule())) {
                                for (var k = 0; k < documents.length; k++) {
                                    if (documents[k] === document) {
                                        break;
                                    }
                                }

                                if (k === documents.length) {
                                    documents = documents.concat(document);
                                }
                            }
                        }
                    }
                }
            }

            // Emit the references
            var emittingFilePath = documents.length ? TypeScript.getRootFilePath(this.emittingFileName) : null;
            for (var i = 0; i < documents.length; i++) {
                var document = documents[i];
                var declFileName;
                if (document.isDeclareFile()) {
                    declFileName = document.fileName;
                } else {
                    declFileName = this.compiler.mapOutputFileName(document, this.emitOptions, TypeScript.TypeScriptCompiler.mapToDTSFileName);
                }

                // Get the relative path
                declFileName = TypeScript.getRelativePathToFixedPath(emittingFilePath, declFileName, false);
                this.declFile.WriteLine('/// <reference path="' + declFileName + '" />');
            }

            this.emittedReferencePaths = true;
        };

        DeclarationEmitter.prototype.emitDeclarationsForSourceUnit = function (sourceUnit) {
            this.emitReferencePaths(sourceUnit);
            this.emitDeclarationsForList(sourceUnit.moduleElements);
        };
        return DeclarationEmitter;
    })();
    TypeScript.DeclarationEmitter = DeclarationEmitter;
})(TypeScript || (TypeScript = {}));
///<reference path='core\integerUtilities.ts' />
var TypeScript;
(function (TypeScript) {
    var BloomFilter = (function () {
        /*
        * From the bloom filter calculator here: http://hur.st/bloomfilter?n=4&p=1.0E-20
        *
        * 1) n  = Number of items in the filter
        *
        * 2) p = Probability of false positives, (a double between 0 and 1).
        *
        * 3) m = Number of bits in the filter
        *
        * 4) k = Number of hash functions
        *
        * m = ceil((n * log(p)) / log(1.0 / (pow(2.0, log(2.0)))))
        *
        * k = round(log(2.0) * m / n)
        *
        */
        function BloomFilter(expectedCount) {
            var m = Math.max(1, BloomFilter.computeM(expectedCount));
            var k = Math.max(1, BloomFilter.computeK(expectedCount));
            ;

            // We must have size in even bytes, so that when we deserialize from bytes we get a bit array with the same count.
            // The count is used by the hash functions.
            var sizeInEvenBytes = (m + 7) & ~7;

            this.bitArray = [];
            for (var i = 0, len = sizeInEvenBytes; i < len; i++) {
                this.bitArray[i] = false;
            }
            this.hashFunctionCount = k;
        }
        // m = ceil((n * log(p)) / log(1.0 / (pow(2.0, log(2.0)))))
        BloomFilter.computeM = function (expectedCount) {
            var p = BloomFilter.falsePositiveProbability;
            var n = expectedCount;

            var numerator = n * Math.log(p);
            var denominator = Math.log(1.0 / Math.pow(2.0, Math.log(2.0)));
            return Math.ceil(numerator / denominator);
        };

        // k = round(log(2.0) * m / n)
        BloomFilter.computeK = function (expectedCount) {
            var n = expectedCount;
            var m = BloomFilter.computeM(expectedCount);

            var temp = Math.log(2.0) * m / n;
            return Math.round(temp);
        };

        /** Modification of the murmurhash2 algorithm.  Code is simpler because it operates over
        * strings instead of byte arrays.  Because each string character is two bytes, it is known
        * that the input will be an even number of bytes (though not necessarily a multiple of 4).
        *
        * This is needed over the normal 'string.GetHashCode()' because we need to be able to generate
        * 'k' different well distributed hashes for any given string s.  Also, we want to be able to
        * generate these hashes without allocating any memory.  My ideal solution would be to use an
        * MD5 hash.  However, there appears to be no way to do MD5 in .Net where you can:
        *
        * a) feed it individual values instead of a byte[]
        *
        * b) have the hash computed into a byte[] you provide instead of a newly allocated one
        *
        * Generating 'k' pieces of garbage on each insert and lookup seems very wasteful.  So,
        * instead, we use murmur hash since it provides well distributed values, allows for a
        * seed, and allocates no memory.
        *
        * Murmur hash is public domain.  Actual code is included below as reference.
        */
        BloomFilter.prototype.computeHash = function (key, seed) {
            return TypeScript.Hash.computeMurmur2StringHashCode(key, seed);
        };

        BloomFilter.prototype.addKeys = function (keys) {
            for (var name in keys) {
                if (keys[name]) {
                    this.add(name);
                }
            }
        };

        BloomFilter.prototype.add = function (value) {
            for (var i = 0; i < this.hashFunctionCount; i++) {
                var hash = this.computeHash(value, i);
                hash = hash % this.bitArray.length;
                this.bitArray[Math.abs(hash)] = true;
            }
        };

        BloomFilter.prototype.probablyContains = function (value) {
            for (var i = 0; i < this.hashFunctionCount; i++) {
                var hash = this.computeHash(value, i);
                hash = hash % this.bitArray.length;
                if (!this.bitArray[Math.abs(hash)]) {
                    return false;
                }
            }

            return true;
        };

        BloomFilter.prototype.isEquivalent = function (filter) {
            return BloomFilter.isEquivalent(this.bitArray, filter.bitArray) && this.hashFunctionCount === filter.hashFunctionCount;
        };

        BloomFilter.isEquivalent = function (array1, array2) {
            if (array1.length !== array2.length) {
                return false;
            }

            for (var i = 0; i < array1.length; i++) {
                if (array1[i] !== array2[i]) {
                    return false;
                }
            }

            return true;
        };
        BloomFilter.falsePositiveProbability = 0.0001;
        return BloomFilter;
    })();
    TypeScript.BloomFilter = BloomFilter;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var IdentifierWalker = (function (_super) {
        __extends(IdentifierWalker, _super);
        function IdentifierWalker(list) {
            _super.call(this);
            this.list = list;
        }
        IdentifierWalker.prototype.visitToken = function (token) {
            this.list[token.text()] = true;
        };
        return IdentifierWalker;
    })(TypeScript.SyntaxWalker);
    TypeScript.IdentifierWalker = IdentifierWalker;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    /// Compiler settings
    var CompilationSettings = (function () {
        function CompilationSettings() {
            this.propagateEnumConstants = false;
            this.removeComments = false;
            this.watch = false;
            this.noResolve = false;
            this.allowAutomaticSemicolonInsertion = true;
            this.noImplicitAny = false;
            this.noLib = false;
            this.codeGenTarget = 0 /* EcmaScript3 */;
            this.moduleGenTarget = 0 /* Unspecified */;
            this.outFileOption = "";
            this.outDirOption = "";
            this.mapSourceFiles = false;
            this.mapRoot = "";
            this.sourceRoot = "";
            this.generateDeclarationFiles = false;
            this.useCaseSensitiveFileResolution = false;
            this.gatherDiagnostics = false;
            this.codepage = null;
        }
        return CompilationSettings;
    })();
    TypeScript.CompilationSettings = CompilationSettings;

    var ImmutableCompilationSettings = (function () {
        function ImmutableCompilationSettings(propagateEnumConstants, removeComments, watch, noResolve, allowAutomaticSemicolonInsertion, noImplicitAny, noLib, codeGenTarget, moduleGenTarget, outFileOption, outDirOption, mapSourceFiles, mapRoot, sourceRoot, generateDeclarationFiles, useCaseSensitiveFileResolution, gatherDiagnostics, codepage) {
            this._propagateEnumConstants = propagateEnumConstants;
            this._removeComments = removeComments;
            this._watch = watch;
            this._noResolve = noResolve;
            this._allowAutomaticSemicolonInsertion = allowAutomaticSemicolonInsertion;
            this._noImplicitAny = noImplicitAny;
            this._noLib = noLib;
            this._codeGenTarget = codeGenTarget;
            this._moduleGenTarget = moduleGenTarget;
            this._outFileOption = outFileOption;
            this._outDirOption = outDirOption;
            this._mapSourceFiles = mapSourceFiles;
            this._mapRoot = mapRoot;
            this._sourceRoot = sourceRoot;
            this._generateDeclarationFiles = generateDeclarationFiles;
            this._useCaseSensitiveFileResolution = useCaseSensitiveFileResolution;
            this._gatherDiagnostics = gatherDiagnostics;
            this._codepage = codepage;
        }
        ImmutableCompilationSettings.prototype.propagateEnumConstants = function () {
            return this._propagateEnumConstants;
        };
        ImmutableCompilationSettings.prototype.removeComments = function () {
            return this._removeComments;
        };
        ImmutableCompilationSettings.prototype.watch = function () {
            return this._watch;
        };
        ImmutableCompilationSettings.prototype.noResolve = function () {
            return this._noResolve;
        };
        ImmutableCompilationSettings.prototype.allowAutomaticSemicolonInsertion = function () {
            return this._allowAutomaticSemicolonInsertion;
        };
        ImmutableCompilationSettings.prototype.noImplicitAny = function () {
            return this._noImplicitAny;
        };
        ImmutableCompilationSettings.prototype.noLib = function () {
            return this._noLib;
        };
        ImmutableCompilationSettings.prototype.codeGenTarget = function () {
            return this._codeGenTarget;
        };
        ImmutableCompilationSettings.prototype.moduleGenTarget = function () {
            return this._moduleGenTarget;
        };
        ImmutableCompilationSettings.prototype.outFileOption = function () {
            return this._outFileOption;
        };
        ImmutableCompilationSettings.prototype.outDirOption = function () {
            return this._outDirOption;
        };
        ImmutableCompilationSettings.prototype.mapSourceFiles = function () {
            return this._mapSourceFiles;
        };
        ImmutableCompilationSettings.prototype.mapRoot = function () {
            return this._mapRoot;
        };
        ImmutableCompilationSettings.prototype.sourceRoot = function () {
            return this._sourceRoot;
        };
        ImmutableCompilationSettings.prototype.generateDeclarationFiles = function () {
            return this._generateDeclarationFiles;
        };
        ImmutableCompilationSettings.prototype.useCaseSensitiveFileResolution = function () {
            return this._useCaseSensitiveFileResolution;
        };
        ImmutableCompilationSettings.prototype.gatherDiagnostics = function () {
            return this._gatherDiagnostics;
        };
        ImmutableCompilationSettings.prototype.codepage = function () {
            return this._codepage;
        };

        ImmutableCompilationSettings.defaultSettings = function () {
            if (!ImmutableCompilationSettings._defaultSettings) {
                ImmutableCompilationSettings._defaultSettings = ImmutableCompilationSettings.fromCompilationSettings(new CompilationSettings());
            }

            return ImmutableCompilationSettings._defaultSettings;
        };

        ImmutableCompilationSettings.fromCompilationSettings = function (settings) {
            return new ImmutableCompilationSettings(settings.propagateEnumConstants, settings.removeComments, settings.watch, settings.noResolve, settings.allowAutomaticSemicolonInsertion, settings.noImplicitAny, settings.noLib, settings.codeGenTarget, settings.moduleGenTarget, settings.outFileOption, settings.outDirOption, settings.mapSourceFiles, settings.mapRoot, settings.sourceRoot, settings.generateDeclarationFiles, settings.useCaseSensitiveFileResolution, settings.gatherDiagnostics, settings.codepage);
        };

        ImmutableCompilationSettings.prototype.toCompilationSettings = function () {
            var result = new CompilationSettings();

            var thisAsIndexable = this;
            var resultAsIndexable = result;
            for (var name in this) {
                if (this.hasOwnProperty(name) && TypeScript.StringUtilities.startsWith(name, "_")) {
                    resultAsIndexable[name.substr(1)] = thisAsIndexable[name];
                }
            }

            return result;
        };
        return ImmutableCompilationSettings;
    })();
    TypeScript.ImmutableCompilationSettings = ImmutableCompilationSettings;

    function settingsChangeAffectsSyntax(before, after) {
        // If the automatic semicolon insertion option has changed, then we have to dump all
        // syntax trees in order to reparse them with the new option.
        //
        // If the language version changed, then that affects what types of things we parse. So
        // we have to dump all syntax trees.
        //
        // If propagateEnumConstants changes, then that affects the constant value data we've
        // stored in the ISyntaxElement.
        return before.allowAutomaticSemicolonInsertion() !== after.allowAutomaticSemicolonInsertion() || before.codeGenTarget() !== after.codeGenTarget() || before.propagateEnumConstants() !== after.propagateEnumConstants();
    }
    TypeScript.settingsChangeAffectsSyntax = settingsChangeAffectsSyntax;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (PullElementFlags) {
        PullElementFlags[PullElementFlags["None"] = 0] = "None";
        PullElementFlags[PullElementFlags["Exported"] = 1] = "Exported";
        PullElementFlags[PullElementFlags["Private"] = 1 << 1] = "Private";
        PullElementFlags[PullElementFlags["Public"] = 1 << 2] = "Public";
        PullElementFlags[PullElementFlags["Ambient"] = 1 << 3] = "Ambient";
        PullElementFlags[PullElementFlags["Static"] = 1 << 4] = "Static";
        PullElementFlags[PullElementFlags["Optional"] = 1 << 7] = "Optional";
        PullElementFlags[PullElementFlags["Signature"] = 1 << 11] = "Signature";
        PullElementFlags[PullElementFlags["Enum"] = 1 << 12] = "Enum";
        PullElementFlags[PullElementFlags["ArrowFunction"] = 1 << 13] = "ArrowFunction";

        PullElementFlags[PullElementFlags["ClassConstructorVariable"] = 1 << 14] = "ClassConstructorVariable";
        PullElementFlags[PullElementFlags["InitializedModule"] = 1 << 15] = "InitializedModule";
        PullElementFlags[PullElementFlags["InitializedDynamicModule"] = 1 << 16] = "InitializedDynamicModule";

        PullElementFlags[PullElementFlags["MustCaptureThis"] = 1 << 18] = "MustCaptureThis";

        PullElementFlags[PullElementFlags["DeclaredInAWithBlock"] = 1 << 21] = "DeclaredInAWithBlock";

        PullElementFlags[PullElementFlags["HasReturnStatement"] = 1 << 22] = "HasReturnStatement";

        PullElementFlags[PullElementFlags["PropertyParameter"] = 1 << 23] = "PropertyParameter";

        PullElementFlags[PullElementFlags["IsAnnotatedWithAny"] = 1 << 24] = "IsAnnotatedWithAny";

        PullElementFlags[PullElementFlags["HasDefaultArgs"] = 1 << 25] = "HasDefaultArgs";

        PullElementFlags[PullElementFlags["ConstructorParameter"] = 1 << 26] = "ConstructorParameter";

        PullElementFlags[PullElementFlags["ImplicitVariable"] = PullElementFlags.ClassConstructorVariable | PullElementFlags.InitializedModule | PullElementFlags.InitializedDynamicModule | PullElementFlags.Enum] = "ImplicitVariable";
        PullElementFlags[PullElementFlags["SomeInitializedModule"] = PullElementFlags.InitializedModule | PullElementFlags.InitializedDynamicModule | PullElementFlags.Enum] = "SomeInitializedModule";
    })(TypeScript.PullElementFlags || (TypeScript.PullElementFlags = {}));
    var PullElementFlags = TypeScript.PullElementFlags;

    function mapFlagToTokenKind(flag) {
        switch (flag) {
            case PullElementFlags.Ambient:
                return 63 /* DeclareKeyword */;
            case 1 /* Exported */:
                return 47 /* ExportKeyword */;
            case PullElementFlags.Public:
                return 57 /* PublicKeyword */;
            case PullElementFlags.Private:
                return 55 /* PrivateKeyword */;
            case PullElementFlags.Static:
                return 58 /* StaticKeyword */;
            default:
                throw TypeScript.Errors.invalidOperation();
        }
    }

    function hasModifier(modifiers, flag) {
        var kind = mapFlagToTokenKind(flag);

        for (var i = 0, n = modifiers.length; i < n; i++) {
            var modifier = modifiers[i];

            if (modifier.kind() === kind) {
                return true;
            }
        }

        return false;
    }
    TypeScript.hasModifier = hasModifier;

    (function (PullElementKind) {
        PullElementKind[PullElementKind["None"] = 0] = "None";
        PullElementKind[PullElementKind["Global"] = 0] = "Global";

        PullElementKind[PullElementKind["Script"] = 1 << 0] = "Script";
        PullElementKind[PullElementKind["Primitive"] = 1 << 1] = "Primitive";

        PullElementKind[PullElementKind["Container"] = 1 << 2] = "Container";
        PullElementKind[PullElementKind["Class"] = 1 << 3] = "Class";
        PullElementKind[PullElementKind["Interface"] = 1 << 4] = "Interface";
        PullElementKind[PullElementKind["DynamicModule"] = 1 << 5] = "DynamicModule";
        PullElementKind[PullElementKind["Enum"] = 1 << 6] = "Enum";
        PullElementKind[PullElementKind["TypeAlias"] = 1 << 7] = "TypeAlias";
        PullElementKind[PullElementKind["ObjectLiteral"] = 1 << 8] = "ObjectLiteral";

        PullElementKind[PullElementKind["Variable"] = 1 << 9] = "Variable";
        PullElementKind[PullElementKind["CatchVariable"] = 1 << 10] = "CatchVariable";
        PullElementKind[PullElementKind["Parameter"] = 1 << 11] = "Parameter";
        PullElementKind[PullElementKind["Property"] = 1 << 12] = "Property";
        PullElementKind[PullElementKind["TypeParameter"] = 1 << 13] = "TypeParameter";

        PullElementKind[PullElementKind["Function"] = 1 << 14] = "Function";
        PullElementKind[PullElementKind["ConstructorMethod"] = 1 << 15] = "ConstructorMethod";
        PullElementKind[PullElementKind["Method"] = 1 << 16] = "Method";
        PullElementKind[PullElementKind["FunctionExpression"] = 1 << 17] = "FunctionExpression";

        PullElementKind[PullElementKind["GetAccessor"] = 1 << 18] = "GetAccessor";
        PullElementKind[PullElementKind["SetAccessor"] = 1 << 19] = "SetAccessor";

        PullElementKind[PullElementKind["CallSignature"] = 1 << 20] = "CallSignature";
        PullElementKind[PullElementKind["ConstructSignature"] = 1 << 21] = "ConstructSignature";
        PullElementKind[PullElementKind["IndexSignature"] = 1 << 22] = "IndexSignature";

        PullElementKind[PullElementKind["ObjectType"] = 1 << 23] = "ObjectType";
        PullElementKind[PullElementKind["FunctionType"] = 1 << 24] = "FunctionType";
        PullElementKind[PullElementKind["ConstructorType"] = 1 << 25] = "ConstructorType";

        PullElementKind[PullElementKind["EnumMember"] = 1 << 26] = "EnumMember";

        PullElementKind[PullElementKind["WithBlock"] = 1 << 27] = "WithBlock";
        PullElementKind[PullElementKind["CatchBlock"] = 1 << 28] = "CatchBlock";

        // WARNING: To prevent JS VMs from wrapping these values as floats, we don't want to utilize more than the 31 bits above.  (Doing so would
        // seriously slow down bitwise operations
        PullElementKind[PullElementKind["All"] = PullElementKind.Script | PullElementKind.Global | PullElementKind.Primitive | PullElementKind.Container | PullElementKind.Class | PullElementKind.Interface | PullElementKind.DynamicModule | PullElementKind.Enum | PullElementKind.TypeAlias | PullElementKind.ObjectLiteral | PullElementKind.Variable | PullElementKind.Parameter | PullElementKind.Property | PullElementKind.TypeParameter | PullElementKind.Function | PullElementKind.ConstructorMethod | PullElementKind.Method | PullElementKind.FunctionExpression | PullElementKind.GetAccessor | PullElementKind.SetAccessor | PullElementKind.CallSignature | PullElementKind.ConstructSignature | PullElementKind.IndexSignature | PullElementKind.ObjectType | PullElementKind.FunctionType | PullElementKind.ConstructorType | PullElementKind.EnumMember | PullElementKind.WithBlock | PullElementKind.CatchBlock] = "All";

        PullElementKind[PullElementKind["SomeFunction"] = PullElementKind.Function | PullElementKind.ConstructorMethod | PullElementKind.Method | PullElementKind.FunctionExpression | PullElementKind.GetAccessor | PullElementKind.SetAccessor] = "SomeFunction";

        // Warning: SomeValue and SomeType (along with their constituents) must be disjoint
        PullElementKind[PullElementKind["SomeValue"] = PullElementKind.Variable | PullElementKind.Parameter | PullElementKind.Property | PullElementKind.EnumMember | PullElementKind.SomeFunction] = "SomeValue";

        PullElementKind[PullElementKind["SomeType"] = PullElementKind.Script | PullElementKind.Global | PullElementKind.Primitive | PullElementKind.Class | PullElementKind.Interface | PullElementKind.Enum | PullElementKind.ObjectLiteral | PullElementKind.ObjectType | PullElementKind.FunctionType | PullElementKind.ConstructorType | PullElementKind.TypeParameter] = "SomeType";

        PullElementKind[PullElementKind["AcceptableAlias"] = PullElementKind.Variable | PullElementKind.SomeFunction | PullElementKind.Class | PullElementKind.Interface | PullElementKind.Enum | PullElementKind.Container | PullElementKind.ObjectType | PullElementKind.FunctionType | PullElementKind.ConstructorType] = "AcceptableAlias";

        PullElementKind[PullElementKind["SomeContainer"] = PullElementKind.Container | PullElementKind.DynamicModule | PullElementKind.TypeAlias] = "SomeContainer";

        PullElementKind[PullElementKind["SomeSignature"] = PullElementKind.CallSignature | PullElementKind.ConstructSignature | PullElementKind.IndexSignature] = "SomeSignature";

        PullElementKind[PullElementKind["SomeTypeReference"] = PullElementKind.Interface | PullElementKind.ObjectType | PullElementKind.FunctionType | PullElementKind.ConstructorType] = "SomeTypeReference";

        PullElementKind[PullElementKind["SomeInstantiatableType"] = PullElementKind.Class | PullElementKind.Interface | PullElementKind.TypeParameter] = "SomeInstantiatableType";
    })(TypeScript.PullElementKind || (TypeScript.PullElementKind = {}));
    var PullElementKind = TypeScript.PullElementKind;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    var pullDeclID = 0;
    var sentinelEmptyPullDeclArray = [];

    var PullDecl = (function () {
        function PullDecl(declName, displayName, kind, declFlags) {
            this.declID = pullDeclID++;
            this.flags = 0 /* None */;
            this.declGroups = null;
            // Child decls
            this.childDecls = null;
            this.typeParameters = null;
            // In the case of classes, initialized modules and enums, we need to track the implicit
            // value set to the constructor or instance type.  We can use this field to make sure that on
            // edits and updates we don't leak the val decl or symbol
            this.synthesizedValDecl = null;
            // backreference from the value decl back to non-value part
            this.containerDecl = null;
            // Caches
            // Mappings from names to decls.  Public only for diffing purposes.
            this.childDeclTypeCache = null;
            this.childDeclValueCache = null;
            this.childDeclNamespaceCache = null;
            this.childDeclTypeParameterCache = null;
            this.name = declName;
            this.kind = kind;
            this.flags = declFlags;

            if (displayName !== this.name) {
                this.declDisplayName = displayName;
            }
        }
        PullDecl.prototype.getASTForDeclMap = function () {
            throw TypeScript.Errors.abstract();
        };

        PullDecl.prototype.fileName = function () {
            throw TypeScript.Errors.abstract();
        };

        PullDecl.prototype.getParentPath = function () {
            throw TypeScript.Errors.abstract();
        };

        PullDecl.prototype.getParentDecl = function () {
            throw TypeScript.Errors.abstract();
        };

        PullDecl.prototype.isExternalModule = function () {
            throw TypeScript.Errors.abstract();
        };

        // The enclosing decl is different from the parent decl. It is a syntactic ancestor decl
        // that introduces the scope in which this decl is defined.
        // Call this to get the enclosing decl of *this* decl
        PullDecl.prototype.getEnclosingDecl = function () {
            throw TypeScript.Errors.abstract();
        };

        // Note: Call this on the *parent* decl of the decl whose enclosing decl you want.
        // This will assume you have already skipped the current decl on your way to the
        // enclosing decl.
        PullDecl.prototype._getEnclosingDeclFromParentDecl = function () {
            // Skip over the decls that cannot introduce a scope
            var decl = this;
            while (decl) {
                switch (decl.kind) {
                    default:
                        return decl;
                    case TypeScript.PullElementKind.Variable:
                    case TypeScript.PullElementKind.TypeParameter:
                    case TypeScript.PullElementKind.Parameter:
                    case TypeScript.PullElementKind.TypeAlias:
                    case TypeScript.PullElementKind.EnumMember:
                }

                decl = decl.getParentDecl();
            }

            TypeScript.Debug.fail();
        };

        /** Use getName for type checking purposes, and getDisplayName to report an error or display info to the user.
        * They will differ when the identifier is an escaped unicode character or the identifier "__proto__".
        */
        PullDecl.prototype.getDisplayName = function () {
            return this.declDisplayName === undefined ? this.name : this.declDisplayName;
        };

        PullDecl.prototype.setSymbol = function (symbol, semanticInfoChain) {
            semanticInfoChain.setSymbolForDecl(this, symbol);
        };

        PullDecl.prototype.ensureSymbolIsBound = function (semanticInfoChain) {
            if (!this.hasBeenBound(semanticInfoChain) && this.kind !== TypeScript.PullElementKind.Script) {
                var binder = semanticInfoChain.getBinder();
                binder.bindDeclToPullSymbol(this);
            }
        };

        PullDecl.prototype.getSymbol = function (semanticInfoChain) {
            if (this.kind === TypeScript.PullElementKind.Script) {
                return null;
            }

            this.ensureSymbolIsBound(semanticInfoChain);

            return semanticInfoChain.getSymbolForDecl(this);
        };

        PullDecl.prototype.hasSymbol = function (semanticInfoChain) {
            var symbol = semanticInfoChain.getSymbolForDecl(this);
            return !!symbol;
        };

        PullDecl.prototype.setSignatureSymbol = function (signatureSymbol, semanticInfoChain) {
            semanticInfoChain.setSignatureSymbolForDecl(this, signatureSymbol);
        };

        PullDecl.prototype.getSignatureSymbol = function (semanticInfoChain) {
            this.ensureSymbolIsBound(semanticInfoChain);
            return semanticInfoChain.getSignatureSymbolForDecl(this);
        };

        PullDecl.prototype.hasSignatureSymbol = function (semanticInfoChain) {
            var signatureSymbol = semanticInfoChain.getSignatureSymbolForDecl(this);
            return !!signatureSymbol;
        };

        PullDecl.prototype.setFlags = function (flags) {
            this.flags = flags;
        };

        PullDecl.prototype.setFlag = function (flags) {
            this.flags |= flags;
        };

        PullDecl.prototype.setValueDecl = function (valDecl) {
            this.synthesizedValDecl = valDecl;
            valDecl.containerDecl = this;
        };

        PullDecl.prototype.getValueDecl = function () {
            return this.synthesizedValDecl;
        };

        PullDecl.prototype.getContainerDecl = function () {
            return this.containerDecl;
        };

        PullDecl.prototype.getChildDeclCache = function (declKind) {
            if (declKind === TypeScript.PullElementKind.TypeParameter) {
                if (!this.childDeclTypeParameterCache) {
                    this.childDeclTypeParameterCache = TypeScript.createIntrinsicsObject();
                }

                return this.childDeclTypeParameterCache;
            } else if (TypeScript.hasFlag(declKind, TypeScript.PullElementKind.SomeContainer)) {
                if (!this.childDeclNamespaceCache) {
                    this.childDeclNamespaceCache = TypeScript.createIntrinsicsObject();
                }

                return this.childDeclNamespaceCache;
            } else if (TypeScript.hasFlag(declKind, TypeScript.PullElementKind.SomeType)) {
                if (!this.childDeclTypeCache) {
                    this.childDeclTypeCache = TypeScript.createIntrinsicsObject();
                }

                return this.childDeclTypeCache;
            } else {
                if (!this.childDeclValueCache) {
                    this.childDeclValueCache = TypeScript.createIntrinsicsObject();
                }

                return this.childDeclValueCache;
            }
        };

        // Should only be called by subclasses.
        PullDecl.prototype.addChildDecl = function (childDecl) {
            if (childDecl.kind === TypeScript.PullElementKind.TypeParameter) {
                if (!this.typeParameters) {
                    this.typeParameters = [];
                }
                this.typeParameters[this.typeParameters.length] = childDecl;
            } else {
                if (!this.childDecls) {
                    this.childDecls = [];
                }
                this.childDecls[this.childDecls.length] = childDecl;
            }

            // add to the appropriate cache
            var declName = childDecl.name;

            if (!(childDecl.kind & TypeScript.PullElementKind.SomeSignature)) {
                var cache = this.getChildDeclCache(childDecl.kind);
                var childrenOfName = cache[declName];
                if (!childrenOfName) {
                    childrenOfName = [];
                }

                childrenOfName.push(childDecl);
                cache[declName] = childrenOfName;
            }
        };

        // Search for a child decl with the given name.  'isType' is used to specify whether or
        // not child types or child values are returned.
        PullDecl.prototype.searchChildDecls = function (declName, searchKind) {
            // find the decl with the optional type
            // if necessary, cache the decl
            // may be wise to return a chain of decls, or take a parent decl as a parameter
            var cacheVal = null;

            if (searchKind & TypeScript.PullElementKind.SomeType) {
                cacheVal = this.childDeclTypeCache ? this.childDeclTypeCache[declName] : null;
            } else if (searchKind & TypeScript.PullElementKind.SomeContainer) {
                cacheVal = this.childDeclNamespaceCache ? this.childDeclNamespaceCache[declName] : null;
            } else {
                cacheVal = this.childDeclValueCache ? this.childDeclValueCache[declName] : null;
            }

            if (cacheVal) {
                return cacheVal;
            } else {
                // If we didn't find it, and they were searching for types, then also check the
                // type parameter cache.
                if (searchKind & TypeScript.PullElementKind.SomeType) {
                    cacheVal = this.childDeclTypeParameterCache ? this.childDeclTypeParameterCache[declName] : null;

                    if (cacheVal) {
                        return cacheVal;
                    }
                }

                return sentinelEmptyPullDeclArray;
            }
        };

        PullDecl.prototype.getChildDecls = function () {
            return this.childDecls || sentinelEmptyPullDeclArray;
        };

        PullDecl.prototype.getTypeParameters = function () {
            return this.typeParameters || sentinelEmptyPullDeclArray;
        };

        PullDecl.prototype.addVariableDeclToGroup = function (decl) {
            if (!this.declGroups) {
                this.declGroups = TypeScript.createIntrinsicsObject();
            }

            var declGroup = this.declGroups[decl.name];
            if (declGroup) {
                declGroup.addDecl(decl);
            } else {
                declGroup = new PullDeclGroup(decl.name);
                declGroup.addDecl(decl);
                this.declGroups[decl.name] = declGroup;
            }
        };

        PullDecl.prototype.getVariableDeclGroups = function () {
            var declGroups = null;

            if (this.declGroups) {
                for (var declName in this.declGroups) {
                    if (this.declGroups[declName]) {
                        if (declGroups === null) {
                            declGroups = [];
                        }

                        declGroups.push(this.declGroups[declName].getDecls());
                    }
                }
            }

            return declGroups || sentinelEmptyPullDeclArray;
        };

        PullDecl.prototype.hasBeenBound = function (semanticInfoChain) {
            return this.hasSymbol(semanticInfoChain) || this.hasSignatureSymbol(semanticInfoChain);
        };

        PullDecl.prototype.isSynthesized = function () {
            return false;
        };

        PullDecl.prototype.ast = function () {
            return this.isSynthesized() ? null : this.getASTForDeclMap()._getASTForDecl(this);
        };

        PullDecl.prototype.isRootDecl = function () {
            throw TypeScript.Errors.abstract();
        };
        return PullDecl;
    })();
    TypeScript.PullDecl = PullDecl;

    // A root decl represents the top level decl for a file.  By specializing this decl, we
    // provide a location, per file, to store data that all decls in the file would otherwise
    // have to duplicate.  For example, there is no need to store the 'fileName' in each decl.
    // Instead, only the root decl needs to store this data.  Decls underneath it can determine
    // the file name by queryign their parent.  In other words, a Root Decl allows us to trade
    // space for logarithmic speed.
    var RootPullDecl = (function (_super) {
        __extends(RootPullDecl, _super);
        function RootPullDecl(astToDeclMap, name, fileName, kind, declFlags, isExternalModule) {
            _super.call(this, name, name, kind, declFlags);
            this.astToDeclMap = astToDeclMap;
            this._isExternalModule = isExternalModule;
            this._fileName = fileName;
        }
        RootPullDecl.prototype.fileName = function () {
            return this._fileName;
        };

        RootPullDecl.prototype.getASTForDeclMap = function () {
            return this.astToDeclMap;
        };

        RootPullDecl.prototype.getParentPath = function () {
            return [this];
        };

        RootPullDecl.prototype.getParentDecl = function () {
            return null;
        };

        RootPullDecl.prototype.isExternalModule = function () {
            return this._isExternalModule;
        };

        // We never want the enclosing decl to be null, so if we are at a top level decl, return it
        RootPullDecl.prototype.getEnclosingDecl = function () {
            return this;
        };

        RootPullDecl.prototype.isRootDecl = function () {
            return true;
        };
        return RootPullDecl;
    })(PullDecl);
    TypeScript.RootPullDecl = RootPullDecl;

    var NormalPullDecl = (function (_super) {
        __extends(NormalPullDecl, _super);
        function NormalPullDecl(declName, displayName, kind, declFlags, parentDecl, addToParent) {
            if (typeof addToParent === "undefined") { addToParent = true; }
            _super.call(this, declName, displayName, kind, declFlags);
            this.parentDecl = null;
            this.parentPath = null;

            // Link to parent
            this.parentDecl = parentDecl;
            if (addToParent) {
                parentDecl.addChildDecl(this);
            }

            if (this.parentDecl) {
                if (this.parentDecl.isRootDecl()) {
                    this._rootDecl = this.parentDecl;
                } else {
                    this._rootDecl = this.parentDecl._rootDecl;
                }
            } else {
                // Synthetic
                TypeScript.Debug.assert(this.isSynthesized());
                this._rootDecl = null;
            }
            //if (!parentDecl && !this.isSynthesized() && kind !== PullElementKind.Primitive) {
            //    throw Errors.invalidOperation("Orphaned decl " + PullElementKind[kind]);
            //}
        }
        NormalPullDecl.prototype.fileName = function () {
            return this._rootDecl.fileName();
        };

        NormalPullDecl.prototype.getASTForDeclMap = function () {
            return this._rootDecl.getASTForDeclMap();
        };

        NormalPullDecl.prototype.getParentDecl = function () {
            return this.parentDecl;
        };

        NormalPullDecl.prototype.getParentPath = function () {
            if (!this.parentPath) {
                var path = [this];
                var parentDecl = this.parentDecl;

                while (parentDecl) {
                    if (parentDecl && path[path.length - 1] !== parentDecl && !(parentDecl.kind & (TypeScript.PullElementKind.ObjectLiteral | TypeScript.PullElementKind.ObjectType))) {
                        path.unshift(parentDecl);
                    }

                    parentDecl = parentDecl.getParentDecl();
                }

                this.parentPath = path;
            }

            return this.parentPath;
        };

        NormalPullDecl.prototype.isExternalModule = function () {
            return false;
        };

        NormalPullDecl.prototype.getEnclosingDecl = function () {
            return this.parentDecl && this.parentDecl._getEnclosingDeclFromParentDecl();
        };

        NormalPullDecl.prototype.isRootDecl = function () {
            return false;
        };
        return NormalPullDecl;
    })(PullDecl);
    TypeScript.NormalPullDecl = NormalPullDecl;

    var PullEnumElementDecl = (function (_super) {
        __extends(PullEnumElementDecl, _super);
        function PullEnumElementDecl(declName, displayName, parentDecl) {
            _super.call(this, declName, displayName, TypeScript.PullElementKind.EnumMember, TypeScript.PullElementFlags.Public, parentDecl);
            this.constantValue = null;
        }
        return PullEnumElementDecl;
    })(NormalPullDecl);
    TypeScript.PullEnumElementDecl = PullEnumElementDecl;

    var PullFunctionExpressionDecl = (function (_super) {
        __extends(PullFunctionExpressionDecl, _super);
        function PullFunctionExpressionDecl(expressionName, declFlags, parentDecl, displayName) {
            if (typeof displayName === "undefined") { displayName = ""; }
            _super.call(this, "", displayName, TypeScript.PullElementKind.FunctionExpression, declFlags, parentDecl);
            this.functionExpressionName = expressionName;
        }
        PullFunctionExpressionDecl.prototype.getFunctionExpressionName = function () {
            return this.functionExpressionName;
        };
        return PullFunctionExpressionDecl;
    })(NormalPullDecl);
    TypeScript.PullFunctionExpressionDecl = PullFunctionExpressionDecl;

    var PullSynthesizedDecl = (function (_super) {
        __extends(PullSynthesizedDecl, _super);
        // This is a synthesized decl; its life time should match that of the symbol using it, and
        // not that of its parent decl. To enforce this we are not making it reachable from its
        // parent, but will set the parent link.
        function PullSynthesizedDecl(declName, displayName, kind, declFlags, parentDecl) {
            _super.call(this, declName, displayName, kind, declFlags, parentDecl, false);
        }
        PullSynthesizedDecl.prototype.isSynthesized = function () {
            return true;
        };

        PullSynthesizedDecl.prototype.fileName = function () {
            return this._rootDecl ? this._rootDecl.fileName() : "";
        };
        return PullSynthesizedDecl;
    })(NormalPullDecl);
    TypeScript.PullSynthesizedDecl = PullSynthesizedDecl;

    var PullDeclGroup = (function () {
        function PullDeclGroup(name) {
            this.name = name;
            this._decls = [];
        }
        PullDeclGroup.prototype.addDecl = function (decl) {
            if (decl.name === this.name) {
                this._decls[this._decls.length] = decl;
            }
        };

        PullDeclGroup.prototype.getDecls = function () {
            return this._decls;
        };
        return PullDeclGroup;
    })();
    TypeScript.PullDeclGroup = PullDeclGroup;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    TypeScript.pullSymbolID = 0;
    TypeScript.sentinelEmptyArray = [];

    var PullSymbol = (function () {
        function PullSymbol(name, declKind, semanticInfoChain) {
            this.semanticInfoChain = semanticInfoChain;
            // private state
            // The symbol ids start with 1 and not 0 as 0 is reserved to detect false conditions eg. in determining
            // wrappingTypeParameterID
            this.pullSymbolID = ++TypeScript.pullSymbolID;
            this._container = null;
            this.type = null;
            // We cache the declarations to improve look-up speed
            // (but we re-create on edits because deletion from the linked list is
            // much faster)
            this._declarations = null;
            this.isResolved = false;
            this.isOptional = false;
            this.inResolution = false;
            this.isSynthesized = false;
            this.isVarArg = false;
            this.rootSymbol = null;
            this._enclosingSignature = null;
            this._docComments = null;
            this.isPrinting = false;
            this.name = name;
            this.kind = declKind;
        }
        PullSymbol.prototype.isAny = function () {
            return false;
        };

        PullSymbol.prototype.isType = function () {
            return (this.kind & TypeScript.PullElementKind.SomeType) !== 0;
        };

        PullSymbol.prototype.isTypeReference = function () {
            return false;
        };

        PullSymbol.prototype.isSignature = function () {
            return (this.kind & TypeScript.PullElementKind.SomeSignature) !== 0;
        };

        PullSymbol.prototype.isArrayNamedTypeReference = function () {
            return false;
        };

        PullSymbol.prototype.isPrimitive = function () {
            return this.kind === TypeScript.PullElementKind.Primitive;
        };

        PullSymbol.prototype.isAccessor = function () {
            return false;
        };

        PullSymbol.prototype.isError = function () {
            return false;
        };

        PullSymbol.prototype.isInterface = function () {
            return this.kind === TypeScript.PullElementKind.Interface;
        };

        PullSymbol.prototype.isMethod = function () {
            return this.kind === TypeScript.PullElementKind.Method;
        };

        PullSymbol.prototype.isProperty = function () {
            return this.kind === TypeScript.PullElementKind.Property;
        };

        PullSymbol.prototype.isAlias = function () {
            return false;
        };

        PullSymbol.prototype.isContainer = function () {
            return false;
        };

        // Finds alias if present representing this symbol
        PullSymbol.prototype.findAliasedTypeSymbols = function (scopeSymbol, skipScopeSymbolAliasesLookIn, lookIntoOnlyExportedAlias, aliasSymbols, visitedScopeDeclarations) {
            if (typeof aliasSymbols === "undefined") { aliasSymbols = []; }
            if (typeof visitedScopeDeclarations === "undefined") { visitedScopeDeclarations = []; }
            var scopeDeclarations = scopeSymbol.getDeclarations();
            var scopeSymbolAliasesToLookIn = [];

            for (var i = 0; i < scopeDeclarations.length; i++) {
                var scopeDecl = scopeDeclarations[i];
                if (!TypeScript.ArrayUtilities.contains(visitedScopeDeclarations, scopeDecl)) {
                    visitedScopeDeclarations.push(scopeDecl);

                    var childDecls = scopeDecl.getChildDecls();
                    for (var j = 0; j < childDecls.length; j++) {
                        var childDecl = childDecls[j];
                        if (childDecl.kind === TypeScript.PullElementKind.TypeAlias && (!lookIntoOnlyExportedAlias || (childDecl.flags & 1 /* Exported */))) {
                            var symbol = childDecl.getSymbol(this.semanticInfoChain);

                            if (PullContainerSymbol.usedAsSymbol(symbol, this) || (this.rootSymbol && PullContainerSymbol.usedAsSymbol(symbol, this.rootSymbol))) {
                                aliasSymbols.push(symbol);
                                return aliasSymbols;
                            }

                            if (!skipScopeSymbolAliasesLookIn && PullSymbol._isExternalModuleReferenceAlias(symbol) && (!symbol.assignedContainer().hasExportAssignment() || (symbol.assignedContainer().getExportAssignedContainerSymbol() && symbol.assignedContainer().getExportAssignedContainerSymbol().kind === TypeScript.PullElementKind.DynamicModule))) {
                                scopeSymbolAliasesToLookIn.push(symbol);
                            }
                        }
                    }
                }
            }

            for (var i = 0; i < scopeSymbolAliasesToLookIn.length; i++) {
                var scopeSymbolAlias = scopeSymbolAliasesToLookIn[i];

                aliasSymbols.push(scopeSymbolAlias);
                var result = this.findAliasedTypeSymbols(scopeSymbolAlias.assignedContainer().hasExportAssignment() ? scopeSymbolAlias.assignedContainer().getExportAssignedContainerSymbol() : scopeSymbolAlias.assignedContainer(), false, true, aliasSymbols, visitedScopeDeclarations);
                if (result) {
                    return result;
                }

                aliasSymbols.pop();
            }

            return null;
        };

        // Gets alias with external module reference if present representing this symbol
        PullSymbol.prototype.getExternalAliasedSymbols = function (scopeSymbol) {
            if (!scopeSymbol) {
                return null;
            }

            var scopePath = scopeSymbol.pathToRoot();
            if (scopePath.length && scopePath[scopePath.length - 1].kind === TypeScript.PullElementKind.DynamicModule) {
                var symbols = this.findAliasedTypeSymbols(scopePath[scopePath.length - 1]);
                return symbols;
            }

            return null;
        };

        PullSymbol._isExternalModuleReferenceAlias = function (aliasSymbol) {
            if (aliasSymbol) {
                // Has value symbol
                if (aliasSymbol.assignedValue()) {
                    return false;
                }

                // Has type that is not same as container
                if (aliasSymbol.assignedType() && aliasSymbol.assignedType() !== aliasSymbol.assignedContainer()) {
                    return false;
                }

                // Its internal module
                if (aliasSymbol.assignedContainer() && aliasSymbol.assignedContainer().kind !== TypeScript.PullElementKind.DynamicModule) {
                    return false;
                }

                return true;
            }

            return false;
        };

        // Gets exported alias with internal module reference if present representing this symbol
        PullSymbol.prototype.getExportedInternalAliasSymbol = function (scopeSymbol) {
            if (scopeSymbol) {
                if (this.kind !== TypeScript.PullElementKind.TypeAlias) {
                    var scopePath = scopeSymbol.pathToRoot();
                    for (var i = 0; i < scopePath.length; i++) {
                        var internalAliases = this.findAliasedTypeSymbols(scopeSymbol, true, true);
                        if (internalAliases) {
                            TypeScript.Debug.assert(internalAliases.length === 1);
                            return internalAliases[0];
                        }
                    }
                }
            }

            return null;
        };

        // Get alias Name using the name getter methods
        PullSymbol.prototype.getAliasSymbolName = function (scopeSymbol, aliasNameGetter, // get the name for the alias
aliasPartsNameGetter, // get the name of parts of the alias
skipInternalAlias) {
            if (!skipInternalAlias) {
                var internalAlias = this.getExportedInternalAliasSymbol(scopeSymbol);
                if (internalAlias) {
                    return aliasNameGetter(internalAlias);
                }
            }

            var externalAliases = this.getExternalAliasedSymbols(scopeSymbol);

            // Use only alias symbols to the dynamic module and it isnt expressed in terms of this symbol itself
            if (externalAliases && externalAliases[0] != this && PullSymbol._isExternalModuleReferenceAlias(externalAliases[externalAliases.length - 1])) {
                var aliasFullName = aliasNameGetter(externalAliases[0]);
                if (!aliasFullName) {
                    return null;
                }
                for (var i = 1, symbolsLen = externalAliases.length; i < symbolsLen; i++) {
                    aliasFullName = aliasFullName + "." + aliasPartsNameGetter(externalAliases[i]);
                }
                return aliasFullName;
            }

            return null;
        };

        PullSymbol.prototype._getResolver = function () {
            return this.semanticInfoChain.getResolver();
        };

        PullSymbol.prototype._resolveDeclaredSymbol = function () {
            return this._getResolver().resolveDeclaredSymbol(this);
        };

        /** Use getName for type checking purposes, and getDisplayName to report an error or display info to the user.
        * They will differ when the identifier is an escaped unicode character or the identifier "__proto__".
        */
        PullSymbol.prototype.getName = function (scopeSymbol, useConstraintInName) {
            var aliasName = this.getAliasSymbolName(scopeSymbol, function (symbol) {
                return symbol.getName(scopeSymbol, useConstraintInName);
            }, function (symbol) {
                return symbol.getName();
            });
            return aliasName || this.name;
        };

        PullSymbol.prototype.getDisplayName = function (scopeSymbol, useConstraintInName, skipInternalAliasName) {
            var aliasDisplayName = this.getAliasSymbolName(scopeSymbol, function (symbol) {
                return symbol.getDisplayName(scopeSymbol, useConstraintInName);
            }, function (symbol) {
                return symbol.getDisplayName();
            }, skipInternalAliasName);
            if (aliasDisplayName) {
                return aliasDisplayName;
            }

            // Get the actual name associated with a declaration for this symbol
            var decls = this.getDeclarations();
            var name = decls.length && decls[0].getDisplayName();

            // In case the decl does not have a name like in the case of named function expression
            return (name && name.length) ? name : this.name;
        };

        PullSymbol.prototype.getIsSpecialized = function () {
            return false;
        };

        PullSymbol.prototype.getRootSymbol = function () {
            if (!this.rootSymbol) {
                return this;
            }
            return this.rootSymbol;
        };
        PullSymbol.prototype.setRootSymbol = function (symbol) {
            this.rootSymbol = symbol;
        };

        PullSymbol.prototype.isRootSymbol = function () {
            return !this.rootSymbol;
        };

        PullSymbol.prototype.setIsSynthesized = function (value) {
            if (typeof value === "undefined") { value = true; }
            TypeScript.Debug.assert(this.rootSymbol == null);
            this.isSynthesized = value;
        };

        PullSymbol.prototype.getIsSynthesized = function () {
            if (this.rootSymbol) {
                return this.rootSymbol.getIsSynthesized();
            }
            return this.isSynthesized;
        };

        PullSymbol.prototype.setEnclosingSignature = function (signature) {
            this._enclosingSignature = signature;
        };

        PullSymbol.prototype.getEnclosingSignature = function () {
            return this._enclosingSignature;
        };

        // declaration methods
        PullSymbol.prototype.addDeclaration = function (decl) {
            TypeScript.Debug.assert(!!decl);

            if (this.rootSymbol) {
                return;
            }

            if (!this._declarations) {
                this._declarations = [decl];
            } else {
                this._declarations[this._declarations.length] = decl;
            }
        };

        PullSymbol.prototype.getDeclarations = function () {
            if (this.rootSymbol) {
                return this.rootSymbol.getDeclarations();
            }

            if (!this._declarations) {
                this._declarations = [];
            }

            return this._declarations;
        };

        PullSymbol.prototype.hasDeclaration = function (decl) {
            if (!this._declarations) {
                return false;
            }

            return TypeScript.ArrayUtilities.any(this._declarations, function (eachDecl) {
                return eachDecl === decl;
            });
        };

        // link methods
        PullSymbol.prototype.setContainer = function (containerSymbol) {
            if (this.rootSymbol) {
                return;
            }

            this._container = containerSymbol;
        };

        PullSymbol.prototype.getContainer = function () {
            if (this.rootSymbol) {
                return this.rootSymbol.getContainer();
            }

            return this._container;
        };

        PullSymbol.prototype.setResolved = function () {
            this.isResolved = true;
            this.inResolution = false;
        };

        PullSymbol.prototype.startResolving = function () {
            this.inResolution = true;
        };

        PullSymbol.prototype.setUnresolved = function () {
            this.isResolved = false;
            this.inResolution = false;
        };

        PullSymbol.prototype.anyDeclHasFlag = function (flag) {
            var declarations = this.getDeclarations();
            for (var i = 0, n = declarations.length; i < n; i++) {
                if (TypeScript.hasFlag(declarations[i].flags, flag)) {
                    return true;
                }
            }
            return false;
        };

        PullSymbol.prototype.allDeclsHaveFlag = function (flag) {
            var declarations = this.getDeclarations();
            for (var i = 0, n = declarations.length; i < n; i++) {
                if (!TypeScript.hasFlag(declarations[i].flags, flag)) {
                    return false;
                }
            }
            return true;
        };

        PullSymbol.prototype.pathToRoot = function () {
            var path = [];
            var node = this;
            while (node) {
                if (node.isType()) {
                    var associatedContainerSymbol = node.getAssociatedContainerType();
                    if (associatedContainerSymbol) {
                        node = associatedContainerSymbol;
                    }
                }
                path[path.length] = node;
                var nodeKind = node.kind;
                if (nodeKind === TypeScript.PullElementKind.Parameter) {
                    break;
                } else {
                    node = node.getContainer();
                }
            }
            return path;
        };

        PullSymbol.unqualifiedNameReferencesDifferentSymbolInScope = function (symbol, scopePath, endScopePathIndex) {
            // Declaration path is reverse of symbol path
            // That is for symbol A.B.C.W the symbolPath = W C B A
            // while declPath = A B C W
            var declPath = scopePath[0].getDeclarations()[0].getParentPath();
            for (var i = 0, declIndex = declPath.length - 1; i <= endScopePathIndex; i++, declIndex--) {
                // We should be doing this for all that is type/namespace/value kinds but for now we do this only for
                // containers and types in another container
                if (scopePath[i].isContainer()) {
                    var scopeContainer = scopePath[i];
                    if (symbol.isContainer()) {
                        // Non exported container
                        var memberSymbol = scopeContainer.findContainedNonMemberContainer(symbol.name, TypeScript.PullElementKind.SomeContainer);
                        if (memberSymbol && memberSymbol != symbol && memberSymbol.getDeclarations()[0].getParentDecl() == declPath[declIndex]) {
                            // If we found different non exported symbol that is originating in same parent
                            // So symbol with this name would refer to the memberSymbol instead of symbol
                            return true;
                        }

                        // Exported container
                        var memberSymbol = scopeContainer.findNestedContainer(symbol.name, TypeScript.PullElementKind.SomeContainer);
                        if (memberSymbol && memberSymbol != symbol) {
                            return true;
                        }
                    } else if (symbol.isType()) {
                        // Non exported type
                        var memberSymbol = scopeContainer.findContainedNonMemberType(symbol.name, TypeScript.PullElementKind.SomeType);
                        var symbolRootType = TypeScript.PullHelpers.getRootType(symbol);
                        if (memberSymbol && TypeScript.PullHelpers.getRootType(memberSymbol) != symbolRootType && memberSymbol.getDeclarations()[0].getParentDecl() == declPath[declIndex]) {
                            // If we found different non exported symbol that is originating in same parent
                            // So symbol with this name would refer to the memberSymbol instead of symbol
                            return true;
                        }

                        // Exported type
                        var memberSymbol = scopeContainer.findNestedType(symbol.name, TypeScript.PullElementKind.SomeType);
                        if (memberSymbol && TypeScript.PullHelpers.getRootType(memberSymbol) != symbolRootType) {
                            return true;
                        }
                    }
                }
            }

            return false;
        };

        // Find the path of this symbol in common ancestor of this symbol and b Symbol
        PullSymbol.prototype.findQualifyingSymbolPathInScopeSymbol = function (scopeSymbol) {
            var thisPath = this.pathToRoot();
            if (thisPath.length === 1) {
                // Global symbol
                return thisPath;
            }

            var scopeSymbolPath;
            if (scopeSymbol) {
                scopeSymbolPath = scopeSymbol.pathToRoot();
            } else {
                // If scopeSymbol wasnt provided, then the path is full path
                return thisPath;
            }

            var thisCommonAncestorIndex = TypeScript.ArrayUtilities.indexOf(thisPath, function (thisNode) {
                return TypeScript.ArrayUtilities.contains(scopeSymbolPath, thisNode);
            });
            if (thisCommonAncestorIndex > 0) {
                // If the symbols matched that does not mean we can use the symbol before the common ancestor directly.
                // e.g
                //module A.C {
                //    export interface Z {
                //    }
                //}
                //module A.B.C {
                //    export class W implements A.C.Z /*This*/ {
                //    }
                //}
                // When trying to get Name of A.C.Z in the context A.B.C.W
                // We find that thisPath = [Z C A] and scopeSymbolPath = [W C B A]
                // thisCommonAncestorIndex = 2
                // But we cant use (thisCommonAncestorIndex - 1)C of C.Z as the reference path because
                // C in A.B.C.W references A.B.C rather than A.C
                var thisCommonAncestor = thisPath[thisCommonAncestorIndex];
                var scopeCommonAncestorIndex = TypeScript.ArrayUtilities.indexOf(scopeSymbolPath, function (scopeNode) {
                    return scopeNode === thisCommonAncestor;
                });
                TypeScript.Debug.assert(thisPath.length - thisCommonAncestorIndex === scopeSymbolPath.length - scopeCommonAncestorIndex);

                for (; thisCommonAncestorIndex < thisPath.length; thisCommonAncestorIndex++, scopeCommonAncestorIndex++) {
                    if (!PullSymbol.unqualifiedNameReferencesDifferentSymbolInScope(thisPath[thisCommonAncestorIndex - 1], scopeSymbolPath, scopeCommonAncestorIndex)) {
                        break;
                    }
                }
            }

            if (thisCommonAncestorIndex >= 0 && thisCommonAncestorIndex < thisPath.length) {
                return thisPath.slice(0, thisCommonAncestorIndex);
            } else {
                return thisPath;
            }
        };

        PullSymbol.prototype.toString = function (scopeSymbol, useConstraintInName) {
            var str = this.getNameAndTypeName(scopeSymbol);
            return str;
        };

        PullSymbol.prototype.getNamePartForFullName = function () {
            return this.getDisplayName(null, true);
        };

        PullSymbol.prototype.fullName = function (scopeSymbol) {
            var _this = this;
            var path = this.pathToRoot();
            var fullName = "";

            var aliasFullName = this.getAliasSymbolName(scopeSymbol, function (symbol) {
                return symbol.fullName(scopeSymbol);
            }, function (symbol) {
                return symbol.getNamePartForFullName();
            });
            if (aliasFullName) {
                return aliasFullName;
            }

            for (var i = 1; i < path.length; i++) {
                var aliasFullName = path[i].getAliasSymbolName(scopeSymbol, function (symbol) {
                    return symbol === _this ? null : symbol.fullName(scopeSymbol);
                }, function (symbol) {
                    return symbol.getNamePartForFullName();
                });
                if (aliasFullName) {
                    fullName = aliasFullName + "." + fullName;
                    break;
                }

                var scopedName = path[i].getNamePartForFullName();
                if (path[i].kind === TypeScript.PullElementKind.DynamicModule && !TypeScript.isQuoted(scopedName)) {
                    break;
                }

                if (scopedName === "") {
                    break;
                }

                fullName = scopedName + "." + fullName;
            }

            fullName = fullName + this.getNamePartForFullName();
            return fullName;
        };

        PullSymbol.prototype.getScopedName = function (scopeSymbol, skipTypeParametersInName, useConstraintInName, skipInternalAliasName) {
            var path = this.findQualifyingSymbolPathInScopeSymbol(scopeSymbol);
            var fullName = "";

            var aliasFullName = this.getAliasSymbolName(scopeSymbol, function (symbol) {
                return symbol.getScopedName(scopeSymbol, skipTypeParametersInName, useConstraintInName, skipInternalAliasName);
            }, function (symbol) {
                return symbol.getNamePartForFullName();
            }, skipInternalAliasName);
            if (aliasFullName) {
                return aliasFullName;
            }

            for (var i = 1; i < path.length; i++) {
                var kind = path[i].kind;
                if (kind === TypeScript.PullElementKind.Container || kind === TypeScript.PullElementKind.DynamicModule) {
                    var aliasFullName = path[i].getAliasSymbolName(scopeSymbol, function (symbol) {
                        return symbol.getScopedName(scopeSymbol, skipTypeParametersInName, false, skipInternalAliasName);
                    }, function (symbol) {
                        return symbol.getNamePartForFullName();
                    }, skipInternalAliasName);
                    if (aliasFullName) {
                        fullName = aliasFullName + "." + fullName;
                        break;
                    }

                    if (kind === TypeScript.PullElementKind.Container) {
                        fullName = path[i].getDisplayName() + "." + fullName;
                    } else {
                        // Dynamic module
                        var displayName = path[i].getDisplayName();
                        if (TypeScript.isQuoted(displayName)) {
                            fullName = displayName + "." + fullName;
                        }
                        break;
                    }
                } else {
                    break;
                }
            }
            fullName = fullName + this.getDisplayName(scopeSymbol, useConstraintInName, skipInternalAliasName);
            return fullName;
        };

        PullSymbol.prototype.getScopedNameEx = function (scopeSymbol, skipTypeParametersInName, useConstraintInName, getPrettyTypeName, getTypeParamMarkerInfo, skipInternalAliasName) {
            var name = this.getScopedName(scopeSymbol, skipTypeParametersInName, useConstraintInName, skipInternalAliasName);
            return TypeScript.MemberName.create(name);
        };

        PullSymbol.prototype.getTypeName = function (scopeSymbol, getPrettyTypeName) {
            var memberName = this.getTypeNameEx(scopeSymbol, getPrettyTypeName);
            return memberName.toString();
        };

        PullSymbol.prototype.getTypeNameEx = function (scopeSymbol, getPrettyTypeName) {
            var type = this.type;
            if (type) {
                var memberName = getPrettyTypeName ? this.getTypeNameForFunctionSignature("", scopeSymbol, getPrettyTypeName) : null;
                if (!memberName) {
                    memberName = type.getScopedNameEx(scopeSymbol, false, true, getPrettyTypeName);
                }

                return memberName;
            }
            return TypeScript.MemberName.create("");
        };

        PullSymbol.prototype.getTypeNameForFunctionSignature = function (prefix, scopeSymbol, getPrettyTypeName) {
            var type = this.type;
            if (type && !type.isNamedTypeSymbol() && this.kind !== TypeScript.PullElementKind.Property && this.kind !== TypeScript.PullElementKind.Variable && this.kind !== TypeScript.PullElementKind.Parameter) {
                var signatures = type.getCallSignatures();
                if (signatures.length === 1 || (getPrettyTypeName && signatures.length)) {
                    var typeName = new TypeScript.MemberNameArray();
                    var signatureName = PullSignatureSymbol.getSignaturesTypeNameEx(signatures, prefix, false, false, scopeSymbol, getPrettyTypeName);
                    typeName.addAll(signatureName);
                    return typeName;
                }
            }

            return null;
        };

        PullSymbol.prototype.getNameAndTypeName = function (scopeSymbol) {
            var nameAndTypeName = this.getNameAndTypeNameEx(scopeSymbol);
            return nameAndTypeName.toString();
        };

        PullSymbol.prototype.getNameAndTypeNameEx = function (scopeSymbol) {
            var type = this.type;
            var nameStr = this.getDisplayName(scopeSymbol);
            if (type) {
                nameStr = nameStr + (this.isOptional ? "?" : "");
                var memberName = this.getTypeNameForFunctionSignature(nameStr, scopeSymbol);
                if (!memberName) {
                    var typeNameEx = type.getScopedNameEx(scopeSymbol);
                    memberName = TypeScript.MemberName.create(typeNameEx, nameStr + ": ", "");
                }
                return memberName;
            }
            return TypeScript.MemberName.create(nameStr);
        };

        PullSymbol.getTypeParameterString = function (typars, scopeSymbol, useConstraintInName) {
            return PullSymbol.getTypeParameterStringEx(typars, scopeSymbol, undefined, useConstraintInName).toString();
        };

        PullSymbol.getTypeParameterStringEx = function (typeParameters, scopeSymbol, getTypeParamMarkerInfo, useConstraintInName) {
            var builder = new TypeScript.MemberNameArray();
            builder.prefix = "";

            if (typeParameters && typeParameters.length) {
                builder.add(TypeScript.MemberName.create("<"));

                for (var i = 0; i < typeParameters.length; i++) {
                    if (i) {
                        builder.add(TypeScript.MemberName.create(", "));
                    }

                    if (getTypeParamMarkerInfo) {
                        builder.add(new TypeScript.MemberName());
                    }

                    builder.add(typeParameters[i].getScopedNameEx(scopeSymbol, false, useConstraintInName));

                    if (getTypeParamMarkerInfo) {
                        builder.add(new TypeScript.MemberName());
                    }
                }

                builder.add(TypeScript.MemberName.create(">"));
            }

            return builder;
        };

        PullSymbol.getIsExternallyVisible = function (symbol, fromIsExternallyVisibleSymbol, inIsExternallyVisibleSymbols) {
            if (inIsExternallyVisibleSymbols) {
                for (var i = 0; i < inIsExternallyVisibleSymbols.length; i++) {
                    if (inIsExternallyVisibleSymbols[i] === symbol) {
                        return true;
                    }
                }
            } else {
                inIsExternallyVisibleSymbols = [];
            }

            if (fromIsExternallyVisibleSymbol === symbol) {
                return true;
            }

            inIsExternallyVisibleSymbols.push(fromIsExternallyVisibleSymbol);

            var result = symbol.isExternallyVisible(inIsExternallyVisibleSymbols);

            TypeScript.Debug.assert(TypeScript.ArrayUtilities.last(inIsExternallyVisibleSymbols) === fromIsExternallyVisibleSymbol);
            inIsExternallyVisibleSymbols.pop();

            return result;
        };

        PullSymbol.prototype.isExternallyVisible = function (inIsExternallyVisibleSymbols) {
            // Primitive
            var kind = this.kind;
            if (kind === TypeScript.PullElementKind.Primitive) {
                return true;
            }

            if (this.rootSymbol) {
                return PullSymbol.getIsExternallyVisible(this.rootSymbol, this, inIsExternallyVisibleSymbols);
            }

            // Type - use container to determine privacy info
            if (this.isType()) {
                var associatedContainerSymbol = this.getAssociatedContainerType();
                if (associatedContainerSymbol) {
                    return PullSymbol.getIsExternallyVisible(associatedContainerSymbol, this, inIsExternallyVisibleSymbols);
                }
            }

            // Private member
            if (this.anyDeclHasFlag(TypeScript.PullElementFlags.Private)) {
                return false;
            }

            // If the container for this symbol is null, then this symbol is visible
            var container = this.getContainer();
            if (container === null) {
                var decls = this.getDeclarations();
                if (decls.length) {
                    var parentDecl = decls[0].getParentDecl();
                    if (parentDecl) {
                        var parentSymbol = parentDecl.getSymbol(this.semanticInfoChain);
                        if (!parentSymbol || parentDecl.kind === TypeScript.PullElementKind.Script) {
                            return true;
                        }

                        return PullSymbol.getIsExternallyVisible(parentSymbol, this, inIsExternallyVisibleSymbols);
                    }
                }

                return true;
            }

            // If export assignment check if this is the symbol that is exported
            if (container.kind === TypeScript.PullElementKind.DynamicModule || (container.getAssociatedContainerType() && container.getAssociatedContainerType().kind === TypeScript.PullElementKind.DynamicModule)) {
                var containerSymbol = container.kind === TypeScript.PullElementKind.DynamicModule ? container : container.getAssociatedContainerType();
                if (PullContainerSymbol.usedAsSymbol(containerSymbol, this)) {
                    return true;
                }
            }

            // If non exported member and is not class properties and method, it is not visible
            if (!this.anyDeclHasFlag(1 /* Exported */) && kind !== TypeScript.PullElementKind.Property && kind !== TypeScript.PullElementKind.Method) {
                return false;
            }

            // Visible if parent is visible
            return PullSymbol.getIsExternallyVisible(container, this, inIsExternallyVisibleSymbols);
        };

        PullSymbol.prototype.getDocCommentsOfDecl = function (decl) {
            var ast = decl.ast();

            if (ast) {
                var enclosingModuleDeclaration = TypeScript.ASTHelpers.getModuleDeclarationFromNameAST(ast);
                if (TypeScript.ASTHelpers.isLastNameOfModule(enclosingModuleDeclaration, ast)) {
                    return TypeScript.ASTHelpers.docComments(enclosingModuleDeclaration, TypeScript.syntaxTree(ast).text);
                }

                if (ast.kind() !== 130 /* ModuleDeclaration */ || decl.kind !== TypeScript.PullElementKind.Variable) {
                    return TypeScript.ASTHelpers.docComments(ast, TypeScript.syntaxTree(ast).text);
                }
            }

            return [];
        };

        PullSymbol.prototype.getDocCommentArray = function (symbol) {
            var docComments = [];
            if (!symbol) {
                return docComments;
            }

            var isParameter = symbol.kind === TypeScript.PullElementKind.Parameter;
            var decls = symbol.getDeclarations();
            for (var i = 0; i < decls.length; i++) {
                if (isParameter && decls[i].kind === TypeScript.PullElementKind.Property) {
                    continue;
                }
                docComments = docComments.concat(this.getDocCommentsOfDecl(decls[i]));
            }
            return docComments;
        };

        PullSymbol.getDefaultConstructorSymbolForDocComments = function (classSymbol) {
            if (classSymbol.getHasDefaultConstructor()) {
                // get from parent if possible
                var extendedTypes = classSymbol.getExtendedTypes();
                if (extendedTypes.length) {
                    return PullSymbol.getDefaultConstructorSymbolForDocComments(extendedTypes[0]);
                }
            }

            return classSymbol.type.getConstructSignatures()[0];
        };

        PullSymbol.prototype.getDocCommentText = function (comments) {
            var docCommentText = new Array();
            for (var c = 0; c < comments.length; c++) {
                var commentText = this.getDocCommentTextValue(comments[c]);
                if (commentText !== "") {
                    docCommentText.push(commentText);
                }
            }
            return docCommentText.join("\n");
        };

        PullSymbol.prototype.getDocCommentTextValue = function (comment) {
            return this.cleanJSDocComment(comment.fullText());
        };

        PullSymbol.prototype.docComments = function (useConstructorAsClass) {
            var decls = this.getDeclarations();
            if (useConstructorAsClass && decls.length && decls[0].kind === TypeScript.PullElementKind.ConstructorMethod) {
                var classDecl = decls[0].getParentDecl();
                return this.getDocCommentText(this.getDocCommentsOfDecl(classDecl));
            }

            if (this._docComments === null) {
                var docComments = "";
                if (!useConstructorAsClass && this.kind === TypeScript.PullElementKind.ConstructSignature && decls.length && decls[0].kind === TypeScript.PullElementKind.Class) {
                    var classSymbol = this.returnType;
                    var extendedTypes = classSymbol.getExtendedTypes();
                    if (extendedTypes.length) {
                        docComments = extendedTypes[0].getConstructorMethod().docComments();
                    } else {
                        docComments = "";
                    }
                } else if (this.kind === TypeScript.PullElementKind.Parameter) {
                    var parameterComments = [];

                    var funcContainer = this.getEnclosingSignature();
                    var funcDocComments = this.getDocCommentArray(funcContainer);
                    var paramComment = this.getParameterDocCommentText(this.getDisplayName(), funcDocComments);
                    if (paramComment != "") {
                        parameterComments.push(paramComment);
                    }

                    var paramSelfComment = this.getDocCommentText(this.getDocCommentArray(this));
                    if (paramSelfComment != "") {
                        parameterComments.push(paramSelfComment);
                    }
                    docComments = parameterComments.join("\n");
                } else {
                    var getSymbolComments = true;
                    if (this.kind === TypeScript.PullElementKind.FunctionType) {
                        var functionSymbol = this.getFunctionSymbol();

                        if (functionSymbol) {
                            docComments = functionSymbol._docComments || "";
                            getSymbolComments = false;
                        } else {
                            var declarationList = this.getDeclarations();
                            if (declarationList.length > 0) {
                                docComments = declarationList[0].getSymbol(this.semanticInfoChain)._docComments || "";
                                getSymbolComments = false;
                            }
                        }
                    }
                    if (getSymbolComments) {
                        docComments = this.getDocCommentText(this.getDocCommentArray(this));
                        if (docComments === "") {
                            if (this.kind === TypeScript.PullElementKind.CallSignature) {
                                var callTypeSymbol = this.functionType;
                                if (callTypeSymbol && callTypeSymbol.getCallSignatures().length === 1) {
                                    docComments = callTypeSymbol.docComments();
                                }
                            }
                        }
                    }
                }

                this._docComments = docComments;
            }

            return this._docComments;
        };

        PullSymbol.prototype.getParameterDocCommentText = function (param, fncDocComments) {
            if (fncDocComments.length === 0 || fncDocComments[0].kind() !== 6 /* MultiLineCommentTrivia */) {
                // there were no fnc doc comments and the comment is not block comment then it cannot have
                // @param comment that can be parsed
                return "";
            }

            for (var i = 0; i < fncDocComments.length; i++) {
                var commentContents = fncDocComments[i].fullText();
                for (var j = commentContents.indexOf("@param", 0); 0 <= j; j = commentContents.indexOf("@param", j)) {
                    j += 6;
                    if (!this.isSpaceChar(commentContents, j)) {
                        continue;
                    }

                    // This is param tag. Check if it is what we are looking for
                    j = this.consumeLeadingSpace(commentContents, j);
                    if (j === -1) {
                        break;
                    }

                    // Ignore the type expression
                    if (commentContents.charCodeAt(j) === 123 /* openBrace */) {
                        j++;

                        // Consume the type
                        var charCode = 0;
                        for (var curlies = 1; j < commentContents.length; j++) {
                            charCode = commentContents.charCodeAt(j);

                            // { character means we need to find another } to match the found one
                            if (charCode === 123 /* openBrace */) {
                                curlies++;
                                continue;
                            }

                            // } char
                            if (charCode === 125 /* closeBrace */) {
                                curlies--;
                                if (curlies === 0) {
                                    break;
                                } else {
                                    continue;
                                }
                            }

                            // Found start of another tag
                            if (charCode === 64 /* at */) {
                                break;
                            }
                        }

                        // End of the comment
                        if (j === commentContents.length) {
                            break;
                        }

                        // End of the tag, go onto looking for next tag
                        if (charCode === 64 /* at */) {
                            continue;
                        }

                        j = this.consumeLeadingSpace(commentContents, j + 1);
                        if (j === -1) {
                            break;
                        }
                    }

                    // Parameter name
                    if (param !== commentContents.substr(j, param.length) || !this.isSpaceChar(commentContents, j + param.length)) {
                        continue;
                    }

                    // Found the parameter we were looking for
                    j = this.consumeLeadingSpace(commentContents, j + param.length);
                    if (j === -1) {
                        return "";
                    }

                    var endOfParam = commentContents.indexOf("@", j);
                    var paramHelpString = commentContents.substring(j, endOfParam < 0 ? commentContents.length : endOfParam);

                    // Find alignement spaces to remove
                    var paramSpacesToRemove = undefined;
                    var paramLineIndex = commentContents.substring(0, j).lastIndexOf("\n") + 1;
                    if (paramLineIndex !== 0) {
                        if (paramLineIndex < j && commentContents.charAt(paramLineIndex + 1) === "\r") {
                            paramLineIndex++;
                        }
                    }
                    var startSpaceRemovalIndex = this.consumeLeadingSpace(commentContents, paramLineIndex);
                    if (startSpaceRemovalIndex !== j && commentContents.charAt(startSpaceRemovalIndex) === "*") {
                        paramSpacesToRemove = j - startSpaceRemovalIndex - 1;
                    }

                    // Clean jsDocComment and return
                    return this.cleanJSDocComment(paramHelpString, paramSpacesToRemove);
                }
            }

            return "";
        };

        PullSymbol.prototype.cleanJSDocComment = function (content, spacesToRemove) {
            var docCommentLines = new Array();
            content = content.replace("/**", ""); // remove /**
            if (content.length >= 2 && content.charAt(content.length - 1) === "/" && content.charAt(content.length - 2) === "*") {
                content = content.substring(0, content.length - 2); // remove last */
            }
            var lines = content.split("\n");
            var inParamTag = false;
            for (var l = 0; l < lines.length; l++) {
                var line = lines[l];
                var cleanLinePos = this.cleanDocCommentLine(line, true, spacesToRemove);
                if (!cleanLinePos) {
                    continue;
                }

                var docCommentText = "";
                var prevPos = cleanLinePos.start;
                for (var i = line.indexOf("@", cleanLinePos.start); 0 <= i && i < cleanLinePos.end; i = line.indexOf("@", i + 1)) {
                    // We have encoutered @.
                    // If we were omitting param comment, we dont have to do anything
                    // other wise the content of the text till @ tag goes as doc comment
                    var wasInParamtag = inParamTag;

                    // Parse contents next to @
                    if (line.indexOf("param", i + 1) === i + 1 && this.isSpaceChar(line, i + 6)) {
                        // It is param tag.
                        // If we were not in param tag earlier, push the contents from prev pos of the tag this tag start as docComment
                        if (!wasInParamtag) {
                            docCommentText += line.substring(prevPos, i);
                        }

                        // New start of contents
                        prevPos = i;
                        inParamTag = true;
                    } else if (wasInParamtag) {
                        // Non param tag start
                        prevPos = i;
                        inParamTag = false;
                    }
                }

                if (!inParamTag) {
                    docCommentText += line.substring(prevPos, cleanLinePos.end);
                }

                // Add line to comment text if it is not only white space line
                var newCleanPos = this.cleanDocCommentLine(docCommentText, false);
                if (newCleanPos) {
                    if (spacesToRemove === undefined) {
                        spacesToRemove = cleanLinePos.jsDocSpacesRemoved;
                    }
                    docCommentLines.push(docCommentText);
                }
            }

            return docCommentLines.join("\n");
        };

        PullSymbol.prototype.consumeLeadingSpace = function (line, startIndex, maxSpacesToRemove) {
            var endIndex = line.length;
            if (maxSpacesToRemove !== undefined) {
                endIndex = Math.min(startIndex + maxSpacesToRemove, endIndex);
            }

            for (; startIndex < endIndex; startIndex++) {
                var charCode = line.charCodeAt(startIndex);
                if (charCode !== 32 /* space */ && charCode !== 9 /* tab */) {
                    return startIndex;
                }
            }

            if (endIndex !== line.length) {
                return endIndex;
            }

            return -1;
        };

        PullSymbol.prototype.isSpaceChar = function (line, index) {
            var length = line.length;
            if (index < length) {
                var charCode = line.charCodeAt(index);

                // If the character is space
                return charCode === 32 /* space */ || charCode === 9 /* tab */;
            }

            // If the index is end of the line it is space
            return index === length;
        };

        PullSymbol.prototype.cleanDocCommentLine = function (line, jsDocStyleComment, jsDocLineSpaceToRemove) {
            var nonSpaceIndex = this.consumeLeadingSpace(line, 0);
            if (nonSpaceIndex !== -1) {
                var jsDocSpacesRemoved = nonSpaceIndex;
                if (jsDocStyleComment && line.charAt(nonSpaceIndex) === '*') {
                    var startIndex = nonSpaceIndex + 1;
                    nonSpaceIndex = this.consumeLeadingSpace(line, startIndex, jsDocLineSpaceToRemove);

                    if (nonSpaceIndex !== -1) {
                        jsDocSpacesRemoved = nonSpaceIndex - startIndex;
                    } else {
                        return null;
                    }
                }

                return {
                    start: nonSpaceIndex,
                    end: line.charAt(line.length - 1) === "\r" ? line.length - 1 : line.length,
                    jsDocSpacesRemoved: jsDocSpacesRemoved
                };
            }

            return null;
        };
        return PullSymbol;
    })();
    TypeScript.PullSymbol = PullSymbol;

    

    var PullSignatureSymbol = (function (_super) {
        __extends(PullSignatureSymbol, _super);
        function PullSignatureSymbol(kind, semanticInfoChain, _isDefinition) {
            if (typeof _isDefinition === "undefined") { _isDefinition = false; }
            _super.call(this, "", kind, semanticInfoChain);
            this._isDefinition = _isDefinition;
            this._memberTypeParameterNameCache = null;
            this._stringConstantOverload = undefined;
            this.parameters = TypeScript.sentinelEmptyArray;
            this._typeParameters = null;
            this.returnType = null;
            this.functionType = null;
            this.hasOptionalParam = false;
            this.nonOptionalParamCount = 0;
            this.hasVarArgs = false;
            this._allowedToReferenceTypeParameters = null;
            this._instantiationCache = null;
            this.hasBeenChecked = false;
            this.inWrapCheck = false;
            this.inWrapInfiniteExpandingReferenceCheck = false;
        }
        PullSignatureSymbol.prototype.isDefinition = function () {
            return this._isDefinition;
        };

        // GTODO
        PullSignatureSymbol.prototype.isGeneric = function () {
            var typeParameters = this.getTypeParameters();
            return !!typeParameters && typeParameters.length !== 0;
        };

        PullSignatureSymbol.prototype.addParameter = function (parameter, isOptional) {
            if (typeof isOptional === "undefined") { isOptional = false; }
            if (this.parameters === TypeScript.sentinelEmptyArray) {
                this.parameters = [];
            }

            this.parameters[this.parameters.length] = parameter;
            this.hasOptionalParam = isOptional;

            if (!parameter.getEnclosingSignature()) {
                parameter.setEnclosingSignature(this);
            }

            if (!isOptional) {
                this.nonOptionalParamCount++;
            }
        };

        PullSignatureSymbol.prototype.addTypeParameter = function (typeParameter) {
            if (!this._typeParameters) {
                this._typeParameters = [];
            }

            if (!this._memberTypeParameterNameCache) {
                this._memberTypeParameterNameCache = TypeScript.createIntrinsicsObject();
            }

            this._typeParameters[this._typeParameters.length] = typeParameter;

            this._memberTypeParameterNameCache[typeParameter.getName()] = typeParameter;
        };

        PullSignatureSymbol.prototype.addTypeParametersFromReturnType = function () {
            var typeParameters = this.returnType.getTypeParameters();
            for (var i = 0; i < typeParameters.length; i++) {
                this.addTypeParameter(typeParameters[i]);
            }
        };

        PullSignatureSymbol.prototype.getTypeParameters = function () {
            if (!this._typeParameters) {
                this._typeParameters = [];
            }

            return this._typeParameters;
        };

        PullSignatureSymbol.prototype.findTypeParameter = function (name) {
            var memberSymbol;

            if (!this._memberTypeParameterNameCache) {
                this._memberTypeParameterNameCache = TypeScript.createIntrinsicsObject();

                for (var i = 0; i < this.getTypeParameters().length; i++) {
                    this._memberTypeParameterNameCache[this._typeParameters[i].getName()] = this._typeParameters[i];
                }
            }

            memberSymbol = this._memberTypeParameterNameCache[name];

            return memberSymbol;
        };

        PullSignatureSymbol.prototype.getTypeParameterSubstitutionMap = function () {
            return null;
        };

        PullSignatureSymbol.prototype.getAllowedToReferenceTypeParameters = function () {
            TypeScript.Debug.assert(this.getRootSymbol() == this);
            if (!this._allowedToReferenceTypeParameters) {
                // If the type is not named, it cannot have its own type parameters
                // But it can refer to typeParameters from enclosing type
                this._allowedToReferenceTypeParameters = TypeScript.PullInstantiationHelpers.getAllowedToReferenceTypeParametersFromDecl(this.getDeclarations()[0], this.semanticInfoChain);
            }

            return this._allowedToReferenceTypeParameters;
        };

        PullSignatureSymbol.prototype.getIsInstantiated = function () {
            return false;
        };

        PullSignatureSymbol.prototype.addSpecialization = function (specializedVersionOfThisSignature, typeArgumentMap) {
            TypeScript.Debug.assert(this.getRootSymbol() == this);
            if (!this._instantiationCache) {
                this._instantiationCache = TypeScript.createIntrinsicsObject();
            }

            this._instantiationCache[getIDForTypeSubstitutions(this, typeArgumentMap)] = specializedVersionOfThisSignature;
        };

        PullSignatureSymbol.prototype.getSpecialization = function (typeArgumentMap) {
            TypeScript.Debug.assert(this.getRootSymbol() == this);
            if (!this._instantiationCache) {
                return null;
            }

            var result = this._instantiationCache[getIDForTypeSubstitutions(this, typeArgumentMap)];
            return result || null;
        };

        PullSignatureSymbol.prototype.isStringConstantOverloadSignature = function () {
            if (this._stringConstantOverload === undefined) {
                var params = this.parameters;
                this._stringConstantOverload = false;
                for (var i = 0; i < params.length; i++) {
                    var paramType = params[i].type;
                    if (paramType && paramType.isPrimitive() && paramType.isStringConstant()) {
                        this._stringConstantOverload = true;
                    }
                }
            }

            return this._stringConstantOverload;
        };

        // Gets the type of parameter at given index
        PullSignatureSymbol.prototype.getParameterTypeAtIndex = function (iParam) {
            if (iParam < this.parameters.length - 1 || (iParam < this.parameters.length && !this.hasVarArgs)) {
                return this.parameters[iParam].type;
            } else if (this.hasVarArgs) {
                var paramType = this.parameters[this.parameters.length - 1].type;
                if (paramType.isArrayNamedTypeReference()) {
                    paramType = paramType.getElementType();
                }
                return paramType;
            }

            return null;
        };

        PullSignatureSymbol.getSignatureTypeMemberName = function (candidateSignature, signatures, scopeSymbol) {
            var allMemberNames = new TypeScript.MemberNameArray();
            var signatureMemberName = PullSignatureSymbol.getSignaturesTypeNameEx(signatures, "", false, false, scopeSymbol, true, candidateSignature);
            allMemberNames.addAll(signatureMemberName);
            return allMemberNames;
        };

        PullSignatureSymbol.getSignaturesTypeNameEx = function (signatures, prefix, shortform, brackets, scopeSymbol, getPrettyTypeName, candidateSignature) {
            var result = [];
            if (!signatures) {
                return result;
            }

            var len = signatures.length;
            if (!getPrettyTypeName && len > 1) {
                shortform = false;
            }

            var foundDefinition = false;
            if (candidateSignature && candidateSignature.isDefinition() && len > 1) {
                // Overloaded signature with candidateSignature = definition - cannot be used.
                candidateSignature = null;
            }

            for (var i = 0; i < len; i++) {
                // the definition signature shouldn't be printed if there are overloads
                if (len > 1 && signatures[i].isDefinition()) {
                    foundDefinition = true;
                    continue;
                }

                var signature = signatures[i];
                if (getPrettyTypeName && candidateSignature) {
                    signature = candidateSignature;
                }

                result.push(signature.getSignatureTypeNameEx(prefix, shortform, brackets, scopeSymbol));
                if (getPrettyTypeName) {
                    break;
                }
            }

            if (getPrettyTypeName && result.length && len > 1) {
                var lastMemberName = result[result.length - 1];
                for (var i = i + 1; i < len; i++) {
                    if (signatures[i].isDefinition()) {
                        foundDefinition = true;
                        break;
                    }
                }
                var overloadString = TypeScript.getLocalizedText(TypeScript.DiagnosticCode._0_overload_s, [foundDefinition ? len - 2 : len - 1]);
                lastMemberName.add(TypeScript.MemberName.create(overloadString));
            }

            return result;
        };

        PullSignatureSymbol.prototype.toString = function (scopeSymbol, useConstraintInName) {
            var s = this.getSignatureTypeNameEx(this.getScopedNameEx().toString(), false, false, scopeSymbol, undefined, useConstraintInName).toString();
            return s;
        };

        PullSignatureSymbol.prototype.getSignatureTypeNameEx = function (prefix, shortform, brackets, scopeSymbol, getParamMarkerInfo, getTypeParamMarkerInfo) {
            var typeParamterBuilder = new TypeScript.MemberNameArray();

            typeParamterBuilder.add(PullSymbol.getTypeParameterStringEx(this.getTypeParameters(), scopeSymbol, getTypeParamMarkerInfo, true));

            if (brackets) {
                typeParamterBuilder.add(TypeScript.MemberName.create("["));
            } else {
                typeParamterBuilder.add(TypeScript.MemberName.create("("));
            }

            var builder = new TypeScript.MemberNameArray();
            builder.prefix = prefix;

            if (getTypeParamMarkerInfo) {
                builder.prefix = prefix;
                builder.addAll(typeParamterBuilder.entries);
            } else {
                builder.prefix = prefix + typeParamterBuilder.toString();
            }

            var params = this.parameters;
            var paramLen = params.length;
            for (var i = 0; i < paramLen; i++) {
                var paramType = params[i].type;
                var typeString = paramType ? ": " : "";
                var paramIsVarArg = params[i].isVarArg;
                var varArgPrefix = paramIsVarArg ? "..." : "";
                var optionalString = (!paramIsVarArg && params[i].isOptional) ? "?" : "";
                if (getParamMarkerInfo) {
                    builder.add(new TypeScript.MemberName());
                }
                builder.add(TypeScript.MemberName.create(varArgPrefix + params[i].getScopedNameEx(scopeSymbol).toString() + optionalString + typeString));
                if (paramType) {
                    builder.add(paramType.getScopedNameEx(scopeSymbol));
                }
                if (getParamMarkerInfo) {
                    builder.add(new TypeScript.MemberName());
                }
                if (i < paramLen - 1) {
                    builder.add(TypeScript.MemberName.create(", "));
                }
            }

            if (shortform) {
                if (brackets) {
                    builder.add(TypeScript.MemberName.create("] => "));
                } else {
                    builder.add(TypeScript.MemberName.create(") => "));
                }
            } else {
                if (brackets) {
                    builder.add(TypeScript.MemberName.create("]: "));
                } else {
                    builder.add(TypeScript.MemberName.create("): "));
                }
            }

            if (this.returnType) {
                builder.add(this.returnType.getScopedNameEx(scopeSymbol));
            } else {
                builder.add(TypeScript.MemberName.create("any"));
            }

            return builder;
        };

        PullSignatureSymbol.prototype.forAllParameterTypes = function (length, predicate) {
            if (this.parameters.length < length && !this.hasVarArgs) {
                length = this.parameters.length;
            }

            for (var i = 0; i < length; i++) {
                var paramType = this.getParameterTypeAtIndex(i);
                if (!predicate(paramType, i)) {
                    return false;
                }
            }

            return true;
        };

        PullSignatureSymbol.prototype.forAllCorrespondingParameterTypesInThisAndOtherSignature = function (otherSignature, predicate) {
            // First determine the length
            var length;
            if (this.hasVarArgs) {
                length = otherSignature.hasVarArgs ? Math.max(this.parameters.length, otherSignature.parameters.length) : otherSignature.parameters.length;
            } else {
                length = otherSignature.hasVarArgs ? this.parameters.length : Math.min(this.parameters.length, otherSignature.parameters.length);
            }

            for (var i = 0; i < length; i++) {
                // Finally, call the callback using the knowledge of whether each param is a rest param
                var thisParamType = this.getParameterTypeAtIndex(i);
                var otherParamType = otherSignature.getParameterTypeAtIndex(i);
                if (!predicate(thisParamType, otherParamType, i)) {
                    return false;
                }
            }

            return true;
        };

        PullSignatureSymbol.prototype.wrapsSomeTypeParameter = function (typeParameterArgumentMap) {
            return this.getWrappingTypeParameterID(typeParameterArgumentMap) !== 0;
        };

        // 0 means there was no type parameter ID wrapping
        // otherwise typeParameterID that was wrapped
        //
        // While it would be intuitive to return a boolean, this actually doesn't work
        // for the WrapsTypeParameterCache. See the comment at the top of the WrapsTypeParameterCache
        // class for an explanation.
        PullSignatureSymbol.prototype.getWrappingTypeParameterID = function (typeParameterArgumentMap) {
            if (this.inWrapCheck) {
                return 0;
            }

            // Find result from cache
            this._wrapsTypeParameterCache = this._wrapsTypeParameterCache || new TypeScript.WrapsTypeParameterCache();

            var wrappingTypeParameterID = this._wrapsTypeParameterCache.getWrapsTypeParameter(typeParameterArgumentMap);
            if (wrappingTypeParameterID === undefined) {
                this.inWrapCheck = true;
                wrappingTypeParameterID = this.getWrappingTypeParameterIDWorker(typeParameterArgumentMap);
                this.inWrapCheck = false;
                this._wrapsTypeParameterCache.setWrapsTypeParameter(typeParameterArgumentMap, wrappingTypeParameterID);
            }

            return wrappingTypeParameterID;
        };

        // A signature wraps a type parameter if any of the following are true:
        // 1. Return type wraps the type parameter
        // 2. Some parameter type wraps the type parameter
        // 3. Some constraint wraps the type parameter
        PullSignatureSymbol.prototype.getWrappingTypeParameterIDWorker = function (typeParameterArgumentMap) {
            TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(this);
            var wrappingTypeParameterID = 0;
            if (this.returnType) {
                wrappingTypeParameterID = this.returnType.getWrappingTypeParameterID(typeParameterArgumentMap);
                if (wrappingTypeParameterID !== 0) {
                    return wrappingTypeParameterID;
                }
            }

            // Continue iterating over parameter types to find if they wrap type parameter,
            // only until we find the first wrapping Type parameter
            var parameters = this.parameters;
            for (var i = 0; i < parameters.length; i++) {
                TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(parameters[i]);
                wrappingTypeParameterID = parameters[i].type.getWrappingTypeParameterID(typeParameterArgumentMap);
                if (wrappingTypeParameterID !== 0) {
                    return wrappingTypeParameterID;
                }
            }

            var typeParameters = this.getTypeParameters();
            for (var i = 0; i < typeParameters.length; i++) {
                TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(typeParameters[i]);
                var constraint = typeParameters[i].getConstraint();
                if (constraint) {
                    wrappingTypeParameterID = constraint.getWrappingTypeParameterID(typeParameterArgumentMap);
                    if (wrappingTypeParameterID !== 0) {
                        return wrappingTypeParameterID;
                    }
                }
            }

            return 0;
        };

        PullSignatureSymbol.prototype._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReference = function (enclosingType, knownWrapMap) {
            var wrapsIntoInfinitelyExpandingTypeReference = knownWrapMap.valueAt(this.pullSymbolID, enclosingType.pullSymbolID);
            if (wrapsIntoInfinitelyExpandingTypeReference != undefined) {
                return wrapsIntoInfinitelyExpandingTypeReference;
            }

            if (this.inWrapInfiniteExpandingReferenceCheck) {
                return false;
            }

            this.inWrapInfiniteExpandingReferenceCheck = true;
            wrapsIntoInfinitelyExpandingTypeReference = this._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceWorker(enclosingType, knownWrapMap);
            knownWrapMap.setValueAt(this.pullSymbolID, enclosingType.pullSymbolID, wrapsIntoInfinitelyExpandingTypeReference);
            this.inWrapInfiniteExpandingReferenceCheck = false;

            return wrapsIntoInfinitelyExpandingTypeReference;
        };

        PullSignatureSymbol.prototype._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceWorker = function (enclosingType, knownWrapMap) {
            if (this.returnType && this.returnType._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceRecurse(enclosingType, knownWrapMap)) {
                return true;
            }

            var parameters = this.parameters;

            for (var i = 0; i < parameters.length; i++) {
                if (parameters[i].type && parameters[i].type._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceRecurse(enclosingType, knownWrapMap)) {
                    return true;
                }
            }

            return false;
        };
        return PullSignatureSymbol;
    })(PullSymbol);
    TypeScript.PullSignatureSymbol = PullSignatureSymbol;

    var PullTypeSymbol = (function (_super) {
        __extends(PullTypeSymbol, _super);
        function PullTypeSymbol(name, kind, semanticInfoChain) {
            _super.call(this, name, kind, semanticInfoChain);
            this._members = TypeScript.sentinelEmptyArray;
            this._enclosedMemberTypes = null;
            this._enclosedMemberContainers = null;
            this._typeParameters = null;
            this._allowedToReferenceTypeParameters = null;
            this._specializedVersionsOfThisType = null;
            this._arrayVersionOfThisType = null;
            this._implementedTypes = null;
            this._extendedTypes = null;
            this._typesThatExplicitlyImplementThisType = null;
            this._typesThatExtendThisType = null;
            this._callSignatures = null;
            this._allCallSignatures = null;
            this._constructSignatures = null;
            this._allConstructSignatures = null;
            this._indexSignatures = null;
            this._allIndexSignatures = null;
            this._allIndexSignaturesOfAugmentedType = null;
            this._memberNameCache = null;
            this._enclosedTypeNameCache = null;
            this._enclosedContainerCache = null;
            this._typeParameterNameCache = null;
            this._containedNonMemberNameCache = null;
            this._containedNonMemberTypeNameCache = null;
            this._containedNonMemberContainerCache = null;
            // The instanatiation cache we use when we are instantiating this type with a single
            // non-object type.
            this._simpleInstantiationCache = null;
            // The instantiation cache we use in all other circumstances.  i.e. instantiating with
            // multiple types, or instantiating with object types.
            this._complexInstantiationCache = null;
            // GTODO
            this._hasGenericSignature = false;
            this._hasGenericMember = false;
            this._hasBaseTypeConflict = false;
            this._knownBaseTypeCount = 0;
            this._associatedContainerTypeSymbol = null;
            this._constructorMethod = null;
            this._hasDefaultConstructor = false;
            // TODO: Really only used to track doc comments...
            this._functionSymbol = null;
            this._inMemberTypeNameEx = false;
            this.inSymbolPrivacyCheck = false;
            this.inWrapCheck = false;
            this.inWrapInfiniteExpandingReferenceCheck = false;
            this.typeReference = null;
            this._widenedType = null;
            // Returns true if this is type reference to Array<T>.  Note that because this is a type
            // reference, it will have type arguments, not type parameters.
            this._isArrayNamedTypeReference = undefined;
            this.type = this;
        }
        PullTypeSymbol.prototype.isArrayNamedTypeReference = function () {
            if (this._isArrayNamedTypeReference === undefined) {
                this._isArrayNamedTypeReference = this.computeIsArrayNamedTypeReference();
            }

            return this._isArrayNamedTypeReference;
        };

        PullTypeSymbol.prototype.computeIsArrayNamedTypeReference = function () {
            var typeArgs = this.getTypeArguments();
            if (typeArgs && this.getTypeArguments().length === 1 && this.name === "Array") {
                var declaration = this.getDeclarations()[0];

                // If we're a child of the global module (i.e. we have a parent decl, but our
                // parent has no parent), then we're the Array<T> type.
                if (declaration && declaration.getParentDecl() && declaration.getParentDecl().getParentDecl() === null) {
                    return true;
                }
            }

            return false;
        };

        PullTypeSymbol.prototype.isType = function () {
            return true;
        };
        PullTypeSymbol.prototype.isClass = function () {
            return this.kind === TypeScript.PullElementKind.Class || (this._constructorMethod !== null);
        };
        PullTypeSymbol.prototype.isFunction = function () {
            return (this.kind & (TypeScript.PullElementKind.ConstructorType | TypeScript.PullElementKind.FunctionType)) !== 0;
        };
        PullTypeSymbol.prototype.isConstructor = function () {
            return this.kind === TypeScript.PullElementKind.ConstructorType || (this._associatedContainerTypeSymbol && this._associatedContainerTypeSymbol.isClass());
        };
        PullTypeSymbol.prototype.isTypeParameter = function () {
            return false;
        };
        PullTypeSymbol.prototype.isTypeVariable = function () {
            return false;
        };
        PullTypeSymbol.prototype.isError = function () {
            return false;
        };
        PullTypeSymbol.prototype.isEnum = function () {
            return this.kind === TypeScript.PullElementKind.Enum;
        };

        PullTypeSymbol.prototype.getTypeParameterSubstitutionMap = function () {
            return null;
        };

        PullTypeSymbol.prototype.isObject = function () {
            return TypeScript.hasFlag(this.kind, TypeScript.PullElementKind.Class | TypeScript.PullElementKind.ConstructorType | TypeScript.PullElementKind.Enum | TypeScript.PullElementKind.FunctionType | TypeScript.PullElementKind.Interface | TypeScript.PullElementKind.ObjectType | TypeScript.PullElementKind.ObjectLiteral);
        };

        PullTypeSymbol.prototype.isFunctionType = function () {
            return this.getCallSignatures().length > 0 || this.getConstructSignatures().length > 0;
        };

        PullTypeSymbol.prototype.getKnownBaseTypeCount = function () {
            return this._knownBaseTypeCount;
        };
        PullTypeSymbol.prototype.resetKnownBaseTypeCount = function () {
            this._knownBaseTypeCount = 0;
        };
        PullTypeSymbol.prototype.incrementKnownBaseCount = function () {
            this._knownBaseTypeCount++;
        };

        PullTypeSymbol.prototype.setHasBaseTypeConflict = function () {
            this._hasBaseTypeConflict = true;
        };
        PullTypeSymbol.prototype.hasBaseTypeConflict = function () {
            return this._hasBaseTypeConflict;
        };

        PullTypeSymbol.prototype.hasMembers = function () {
            if (this._members !== TypeScript.sentinelEmptyArray) {
                return true;
            }

            var parents = this.getExtendedTypes();

            for (var i = 0; i < parents.length; i++) {
                if (parents[i].hasMembers()) {
                    return true;
                }
            }

            return false;
        };

        // GTODO
        PullTypeSymbol.prototype.setHasGenericSignature = function () {
            this._hasGenericSignature = true;
        };
        PullTypeSymbol.prototype.getHasGenericSignature = function () {
            return this._hasGenericSignature;
        };

        // GTODO
        PullTypeSymbol.prototype.setHasGenericMember = function () {
            this._hasGenericMember = true;
        };
        PullTypeSymbol.prototype.getHasGenericMember = function () {
            return this._hasGenericMember;
        };

        PullTypeSymbol.prototype.setAssociatedContainerType = function (type) {
            this._associatedContainerTypeSymbol = type;
        };

        PullTypeSymbol.prototype.getAssociatedContainerType = function () {
            return this._associatedContainerTypeSymbol;
        };

        // REVIEW
        PullTypeSymbol.prototype.getArrayType = function () {
            return this._arrayVersionOfThisType;
        };

        PullTypeSymbol.prototype.getElementType = function () {
            return null;
        };

        PullTypeSymbol.prototype.setArrayType = function (arrayType) {
            this._arrayVersionOfThisType = arrayType;
        };

        PullTypeSymbol.prototype.getFunctionSymbol = function () {
            return this._functionSymbol;
        };

        PullTypeSymbol.prototype.setFunctionSymbol = function (symbol) {
            if (symbol) {
                this._functionSymbol = symbol;
            }
        };

        // TODO: This seems to conflate exposed members with private non-Members
        PullTypeSymbol.prototype.findContainedNonMember = function (name) {
            if (!this._containedNonMemberNameCache) {
                return null;
            }

            return this._containedNonMemberNameCache[name];
        };

        PullTypeSymbol.prototype.findContainedNonMemberType = function (typeName, kind) {
            if (typeof kind === "undefined") { kind = 0 /* None */; }
            if (!this._containedNonMemberTypeNameCache) {
                return null;
            }

            var nonMemberSymbol = this._containedNonMemberTypeNameCache[typeName];

            if (nonMemberSymbol && kind !== 0 /* None */) {
                nonMemberSymbol = TypeScript.hasFlag(nonMemberSymbol.kind, kind) ? nonMemberSymbol : null;
            }

            return nonMemberSymbol;
        };

        PullTypeSymbol.prototype.findContainedNonMemberContainer = function (containerName, kind) {
            if (typeof kind === "undefined") { kind = 0 /* None */; }
            if (!this._containedNonMemberContainerCache) {
                return null;
            }

            var nonMemberSymbol = this._containedNonMemberContainerCache[containerName];

            if (nonMemberSymbol && kind !== 0 /* None */) {
                nonMemberSymbol = TypeScript.hasFlag(nonMemberSymbol.kind, kind) ? nonMemberSymbol : null;
            }

            return nonMemberSymbol;
        };

        PullTypeSymbol.prototype.addMember = function (memberSymbol) {
            if (!memberSymbol) {
                return;
            }

            memberSymbol.setContainer(this);

            if (!this._memberNameCache) {
                this._memberNameCache = TypeScript.createIntrinsicsObject();
            }

            if (this._members === TypeScript.sentinelEmptyArray) {
                this._members = [];
            }

            this._members.push(memberSymbol);
            this._memberNameCache[memberSymbol.name] = memberSymbol;
        };

        PullTypeSymbol.prototype.addEnclosedMemberType = function (enclosedType) {
            if (!enclosedType) {
                return;
            }

            enclosedType.setContainer(this);

            if (!this._enclosedTypeNameCache) {
                this._enclosedTypeNameCache = TypeScript.createIntrinsicsObject();
            }

            if (!this._enclosedMemberTypes) {
                this._enclosedMemberTypes = [];
            }

            this._enclosedMemberTypes[this._enclosedMemberTypes.length] = enclosedType;
            this._enclosedTypeNameCache[enclosedType.name] = enclosedType;
        };

        PullTypeSymbol.prototype.addEnclosedMemberContainer = function (enclosedContainer) {
            if (!enclosedContainer) {
                return;
            }

            enclosedContainer.setContainer(this);

            if (!this._enclosedContainerCache) {
                this._enclosedContainerCache = TypeScript.createIntrinsicsObject();
            }

            if (!this._enclosedMemberContainers) {
                this._enclosedMemberContainers = [];
            }

            this._enclosedMemberContainers[this._enclosedMemberContainers.length] = enclosedContainer;
            this._enclosedContainerCache[enclosedContainer.name] = enclosedContainer;
        };

        PullTypeSymbol.prototype.addEnclosedNonMember = function (enclosedNonMember) {
            if (!enclosedNonMember) {
                return;
            }

            enclosedNonMember.setContainer(this);

            if (!this._containedNonMemberNameCache) {
                this._containedNonMemberNameCache = TypeScript.createIntrinsicsObject();
            }

            this._containedNonMemberNameCache[enclosedNonMember.name] = enclosedNonMember;
        };

        PullTypeSymbol.prototype.addEnclosedNonMemberType = function (enclosedNonMemberType) {
            if (!enclosedNonMemberType) {
                return;
            }

            enclosedNonMemberType.setContainer(this);

            if (!this._containedNonMemberTypeNameCache) {
                this._containedNonMemberTypeNameCache = TypeScript.createIntrinsicsObject();
            }

            this._containedNonMemberTypeNameCache[enclosedNonMemberType.name] = enclosedNonMemberType;
        };

        PullTypeSymbol.prototype.addEnclosedNonMemberContainer = function (enclosedNonMemberContainer) {
            if (!enclosedNonMemberContainer) {
                return;
            }

            enclosedNonMemberContainer.setContainer(this);

            if (!this._containedNonMemberContainerCache) {
                this._containedNonMemberContainerCache = TypeScript.createIntrinsicsObject();
            }

            this._containedNonMemberContainerCache[enclosedNonMemberContainer.name] = enclosedNonMemberContainer;
        };

        PullTypeSymbol.prototype.addTypeParameter = function (typeParameter) {
            if (!typeParameter) {
                return;
            }

            if (!typeParameter.getContainer()) {
                typeParameter.setContainer(this);
            }

            if (!this._typeParameterNameCache) {
                this._typeParameterNameCache = TypeScript.createIntrinsicsObject();
            }

            if (!this._typeParameters) {
                this._typeParameters = [];
            }

            this._typeParameters[this._typeParameters.length] = typeParameter;
            this._typeParameterNameCache[typeParameter.getName()] = typeParameter;
        };

        PullTypeSymbol.prototype.getMembers = function () {
            return this._members;
        };

        PullTypeSymbol.prototype.setHasDefaultConstructor = function (hasOne) {
            if (typeof hasOne === "undefined") { hasOne = true; }
            this._hasDefaultConstructor = hasOne;
        };

        PullTypeSymbol.prototype.getHasDefaultConstructor = function () {
            return this._hasDefaultConstructor;
        };

        PullTypeSymbol.prototype.getConstructorMethod = function () {
            return this._constructorMethod;
        };

        PullTypeSymbol.prototype.setConstructorMethod = function (constructorMethod) {
            this._constructorMethod = constructorMethod;
        };

        PullTypeSymbol.prototype.getTypeParameters = function () {
            if (!this._typeParameters) {
                return TypeScript.sentinelEmptyArray;
            }

            return this._typeParameters;
        };

        PullTypeSymbol.prototype.getAllowedToReferenceTypeParameters = function () {
            if (!!(this.kind && TypeScript.PullElementKind.SomeInstantiatableType) && this.isNamedTypeSymbol() && !this.isTypeParameter()) {
                return this.getTypeParameters();
            }

            if (!this._allowedToReferenceTypeParameters) {
                // If the type is not named, it cannot have its own type parameters
                // But it can refer to typeParameters from enclosing type
                this._allowedToReferenceTypeParameters = TypeScript.PullInstantiationHelpers.getAllowedToReferenceTypeParametersFromDecl(this.getDeclarations()[0], this.semanticInfoChain);
            }

            return this._allowedToReferenceTypeParameters;
        };

        // GTODO
        PullTypeSymbol.prototype.isGeneric = function () {
            return (this._typeParameters && this._typeParameters.length > 0) || this._hasGenericSignature || this._hasGenericMember || this.isArrayNamedTypeReference();
        };

        PullTypeSymbol.prototype.canUseSimpleInstantiationCache = function (typeArgumentMap) {
            if (this.isTypeParameter()) {
                return true;
            }

            var typeParameters = this.getTypeParameters();
            return typeArgumentMap && this.isNamedTypeSymbol() && typeParameters.length === 1 && typeArgumentMap[typeParameters[0].pullSymbolID].kind !== TypeScript.PullElementKind.ObjectType;
        };

        PullTypeSymbol.prototype.getSimpleInstantiationCacheId = function (typeArgumentMap) {
            return typeArgumentMap[this.getTypeParameters()[0].pullSymbolID].pullSymbolID;
        };

        PullTypeSymbol.prototype.addSpecialization = function (specializedVersionOfThisType, typeArgumentMap) {
            if (this.canUseSimpleInstantiationCache(typeArgumentMap)) {
                if (!this._simpleInstantiationCache) {
                    this._simpleInstantiationCache = [];
                }

                this._simpleInstantiationCache[this.getSimpleInstantiationCacheId(typeArgumentMap)] = specializedVersionOfThisType;
            } else {
                if (!this._complexInstantiationCache) {
                    this._complexInstantiationCache = TypeScript.createIntrinsicsObject();
                }

                this._complexInstantiationCache[getIDForTypeSubstitutions(this, typeArgumentMap)] = specializedVersionOfThisType;
            }

            if (!this._specializedVersionsOfThisType) {
                this._specializedVersionsOfThisType = [];
            }

            this._specializedVersionsOfThisType.push(specializedVersionOfThisType);
        };

        PullTypeSymbol.prototype.getSpecialization = function (typeArgumentMap) {
            if (this.canUseSimpleInstantiationCache(typeArgumentMap)) {
                if (!this._simpleInstantiationCache) {
                    return null;
                }

                var result = this._simpleInstantiationCache[this.getSimpleInstantiationCacheId(typeArgumentMap)];
                return result || null;
            } else {
                if (!this._complexInstantiationCache) {
                    return null;
                }

                if (this.getAllowedToReferenceTypeParameters().length == 0) {
                    return this;
                }

                var result = this._complexInstantiationCache[getIDForTypeSubstitutions(this, typeArgumentMap)];
                return result || null;
            }
        };

        PullTypeSymbol.prototype.getKnownSpecializations = function () {
            if (!this._specializedVersionsOfThisType) {
                return TypeScript.sentinelEmptyArray;
            }

            return this._specializedVersionsOfThisType;
        };

        // GTODO
        PullTypeSymbol.prototype.getTypeArguments = function () {
            return null;
        };

        PullTypeSymbol.prototype.getTypeArgumentsOrTypeParameters = function () {
            return this.getTypeParameters();
        };

        PullTypeSymbol.prototype.addCallOrConstructSignaturePrerequisiteBase = function (signature) {
            if (signature.isGeneric()) {
                this._hasGenericSignature = true;
            }

            signature.functionType = this;
        };

        PullTypeSymbol.prototype.addCallSignaturePrerequisite = function (callSignature) {
            if (!this._callSignatures) {
                this._callSignatures = [];
            }

            this.addCallOrConstructSignaturePrerequisiteBase(callSignature);
        };

        PullTypeSymbol.prototype.appendCallSignature = function (callSignature) {
            this.addCallSignaturePrerequisite(callSignature);
            this._callSignatures.push(callSignature);
        };

        PullTypeSymbol.prototype.insertCallSignatureAtIndex = function (callSignature, index) {
            this.addCallSignaturePrerequisite(callSignature);
            TypeScript.Debug.assert(index <= this._callSignatures.length);
            if (index === this._callSignatures.length) {
                this._callSignatures.push(callSignature);
            } else {
                this._callSignatures.splice(index, 0, callSignature);
            }
        };

        PullTypeSymbol.prototype.addConstructSignaturePrerequisite = function (constructSignature) {
            if (!this._constructSignatures) {
                this._constructSignatures = [];
            }

            this.addCallOrConstructSignaturePrerequisiteBase(constructSignature);
        };

        PullTypeSymbol.prototype.appendConstructSignature = function (constructSignature) {
            this.addConstructSignaturePrerequisite(constructSignature);
            this._constructSignatures.push(constructSignature);
        };

        PullTypeSymbol.prototype.insertConstructSignatureAtIndex = function (constructSignature, index) {
            this.addConstructSignaturePrerequisite(constructSignature);
            TypeScript.Debug.assert(index <= this._constructSignatures.length);
            if (index === this._constructSignatures.length) {
                this._constructSignatures.push(constructSignature);
            } else {
                this._constructSignatures.splice(index, 0, constructSignature);
            }
        };

        PullTypeSymbol.prototype.addIndexSignature = function (indexSignature) {
            if (!this._indexSignatures) {
                this._indexSignatures = [];
            }

            this._indexSignatures[this._indexSignatures.length] = indexSignature;

            if (indexSignature.isGeneric()) {
                this._hasGenericSignature = true;
            }

            indexSignature.functionType = this;
        };

        PullTypeSymbol.prototype.hasOwnCallSignatures = function () {
            return this._callSignatures !== null;
        };

        PullTypeSymbol.prototype.getOwnCallSignatures = function () {
            return this._callSignatures || TypeScript.sentinelEmptyArray;
        };

        PullTypeSymbol.prototype.getCallSignatures = function () {
            if (this._allCallSignatures) {
                return this._allCallSignatures;
            }

            var signatures = [];

            if (this._callSignatures) {
                signatures = signatures.concat(this._callSignatures);
            }

            // Check for inherited call signatures
            // Only interfaces can inherit call signatures
            if (this._extendedTypes && this.kind === TypeScript.PullElementKind.Interface) {
                for (var i = 0; i < this._extendedTypes.length; i++) {
                    if (this._extendedTypes[i].hasBase(this)) {
                        continue;
                    }

                    // October 16, 2013: Section 7.1:
                    // A call signature declaration hides a base type call signature that is
                    // identical when return types are ignored.
                    this._getResolver()._addUnhiddenSignaturesFromBaseType(this._callSignatures, this._extendedTypes[i].getCallSignatures(), signatures);
                }
            }

            this._allCallSignatures = signatures;

            return signatures;
        };

        PullTypeSymbol.prototype.hasOwnConstructSignatures = function () {
            return this._constructSignatures !== null;
        };

        PullTypeSymbol.prototype.getOwnDeclaredConstructSignatures = function () {
            return this._constructSignatures || TypeScript.sentinelEmptyArray;
        };

        PullTypeSymbol.prototype.getConstructSignatures = function () {
            if (this._allConstructSignatures) {
                return this._allConstructSignatures;
            }

            var signatures = [];

            if (this._constructSignatures) {
                signatures = signatures.concat(this._constructSignatures);
            } else if (this.isConstructor()) {
                if (this._extendedTypes && this._extendedTypes.length > 0) {
                    signatures = this.getBaseClassConstructSignatures(this._extendedTypes[0]);
                } else {
                    signatures = [this.getDefaultClassConstructSignature()];
                }
            }

            // If it's a constructor type, we don't inherit construct signatures
            // (E.g., we'd be looking at the statics on a class, where we want
            // to inherit members, but not construct signatures
            if (this._extendedTypes && this.kind === TypeScript.PullElementKind.Interface) {
                for (var i = 0; i < this._extendedTypes.length; i++) {
                    if (this._extendedTypes[i].hasBase(this)) {
                        continue;
                    }

                    // October 16, 2013: Section 7.1:
                    // A construct signature declaration hides a base type construct signature that is
                    // identical when return types are ignored.
                    this._getResolver()._addUnhiddenSignaturesFromBaseType(this._constructSignatures, this._extendedTypes[i].getConstructSignatures(), signatures);
                }
            }

            this._allConstructSignatures = signatures;

            return signatures;
        };

        PullTypeSymbol.prototype.hasOwnIndexSignatures = function () {
            return this._indexSignatures !== null;
        };

        PullTypeSymbol.prototype.getOwnIndexSignatures = function () {
            return this._indexSignatures || TypeScript.sentinelEmptyArray;
        };

        PullTypeSymbol.prototype.getIndexSignatures = function () {
            if (this._allIndexSignatures) {
                return this._allIndexSignatures;
            }

            var signatures = [];

            if (this._indexSignatures) {
                signatures = signatures.concat(this._indexSignatures);
            }

            if (this._extendedTypes) {
                for (var i = 0; i < this._extendedTypes.length; i++) {
                    if (this._extendedTypes[i].hasBase(this)) {
                        continue;
                    }

                    // October 16, 2013: Section 7.1:
                    // A string index signature declaration hides a base type string index signature.
                    // A numeric index signature declaration hides a base type numeric index signature.
                    this._getResolver()._addUnhiddenSignaturesFromBaseType(this._indexSignatures, this._extendedTypes[i].getIndexSignatures(), signatures);
                }
            }

            this._allIndexSignatures = signatures;

            return signatures;
        };

        // The augmented form of an object type T adds to T those members of the global interface
        // type 'Object' that aren't hidden by members in T. Furthermore, if T has one or more call
        // or construct signatures, the augmented form of T adds to T the members of the global
        // interface type 'Function' that aren't hidden by members in T. Members in T hide 'Object'
        // or 'Function' interface members in the following manner:
        // ...
        // An index signature hides an 'Object' or 'Function' index signature with the same parameter type.
        PullTypeSymbol.prototype.getIndexSignaturesOfAugmentedType = function (resolver, globalFunctionInterface, globalObjectInterface) {
            if (!this._allIndexSignaturesOfAugmentedType) {
                // Start with the types own and inherited index signatures
                var initialIndexSignatures = this.getIndexSignatures();
                var shouldAddFunctionSignatures = false;
                var shouldAddObjectSignatures = false;

                if (globalFunctionInterface && this.isFunctionType() && this !== globalFunctionInterface) {
                    var functionIndexSignatures = globalFunctionInterface.getIndexSignatures();
                    if (functionIndexSignatures.length) {
                        shouldAddFunctionSignatures = true;
                    }
                }

                if (globalObjectInterface && this !== globalObjectInterface) {
                    var objectIndexSignatures = globalObjectInterface.getIndexSignatures();
                    if (objectIndexSignatures.length) {
                        shouldAddObjectSignatures = true;
                    }
                }

                // The 'then' block of this conditional should almost never be entered, since
                // Object and Function in lib.d.ts have no index signatures. This could only
                // happen if the user has added index signatures to Object or Function.
                if (shouldAddFunctionSignatures || shouldAddObjectSignatures) {
                    // First, copy the existing signatures into a new array
                    // .slice(0) is an idiom for copying
                    this._allIndexSignaturesOfAugmentedType = initialIndexSignatures.slice(0);
                    if (shouldAddFunctionSignatures) {
                        // The following call mutates this._allIndexSignaturesOfAugmentedType
                        resolver._addUnhiddenSignaturesFromBaseType(initialIndexSignatures, functionIndexSignatures, this._allIndexSignaturesOfAugmentedType);
                    }
                    if (shouldAddObjectSignatures) {
                        if (shouldAddFunctionSignatures) {
                            // Concat function index signatures to make sure we don't add object signatures
                            // hidden by function signatures.
                            initialIndexSignatures = initialIndexSignatures.concat(functionIndexSignatures);
                        }
                        resolver._addUnhiddenSignaturesFromBaseType(initialIndexSignatures, objectIndexSignatures, this._allIndexSignaturesOfAugmentedType);
                    }
                } else {
                    this._allIndexSignaturesOfAugmentedType = initialIndexSignatures;
                }
            }

            return this._allIndexSignaturesOfAugmentedType;
        };

        PullTypeSymbol.prototype.getBaseClassConstructSignatures = function (baseType) {
            TypeScript.Debug.assert(this.isConstructor() && baseType.isConstructor());
            var instanceTypeSymbol = this.getAssociatedContainerType();
            TypeScript.Debug.assert(instanceTypeSymbol.getDeclarations().length === 1);
            if (baseType.hasBase(this)) {
                return null;
            }

            var baseConstructSignatures = baseType.getConstructSignatures();
            var signatures = [];
            for (var i = 0; i < baseConstructSignatures.length; i++) {
                var baseSignature = baseConstructSignatures[i];

                // Make sure the base signature is resolved, so that the parameter symbols from the new
                // siganture are used, they will have the type associated with them.
                baseSignature._resolveDeclaredSymbol();
                var currentSignature = new PullSignatureSymbol(TypeScript.PullElementKind.ConstructSignature, this.semanticInfoChain, baseSignature.isDefinition());
                currentSignature.returnType = instanceTypeSymbol;
                currentSignature.addTypeParametersFromReturnType();
                for (var j = 0; j < baseSignature.parameters.length; j++) {
                    currentSignature.addParameter(baseSignature.parameters[j], baseSignature.parameters[j].isOptional);
                }
                if (baseSignature.parameters.length > 0) {
                    currentSignature.hasVarArgs = baseSignature.parameters[baseSignature.parameters.length - 1].isVarArg;
                }

                // Assume the class has only one decl, since it can't mix with anything
                currentSignature.addDeclaration(instanceTypeSymbol.getDeclarations()[0]);
                this.addCallOrConstructSignaturePrerequisiteBase(currentSignature);
                signatures.push(currentSignature);
            }

            return signatures;
        };

        PullTypeSymbol.prototype.getDefaultClassConstructSignature = function () {
            TypeScript.Debug.assert(this.isConstructor());
            var instanceTypeSymbol = this.getAssociatedContainerType();
            TypeScript.Debug.assert(instanceTypeSymbol.getDeclarations().length == 1);
            var signature = new PullSignatureSymbol(TypeScript.PullElementKind.ConstructSignature, this.semanticInfoChain, true);
            signature.returnType = instanceTypeSymbol;
            signature.addTypeParametersFromReturnType();
            signature.addDeclaration(instanceTypeSymbol.getDeclarations()[0]);
            this.addCallOrConstructSignaturePrerequisiteBase(signature);

            return signature;
        };

        PullTypeSymbol.prototype.addImplementedType = function (implementedType) {
            if (!implementedType) {
                return;
            }

            if (!this._implementedTypes) {
                this._implementedTypes = [];
            }

            this._implementedTypes[this._implementedTypes.length] = implementedType;

            implementedType.addTypeThatExplicitlyImplementsThisType(this);
        };

        PullTypeSymbol.prototype.getImplementedTypes = function () {
            if (!this._implementedTypes) {
                return TypeScript.sentinelEmptyArray;
            }

            return this._implementedTypes;
        };

        PullTypeSymbol.prototype.addExtendedType = function (extendedType) {
            if (!extendedType) {
                return;
            }

            if (!this._extendedTypes) {
                this._extendedTypes = [];
            }

            this._extendedTypes[this._extendedTypes.length] = extendedType;

            extendedType.addTypeThatExtendsThisType(this);
        };

        PullTypeSymbol.prototype.getExtendedTypes = function () {
            if (!this._extendedTypes) {
                return TypeScript.sentinelEmptyArray;
            }

            return this._extendedTypes;
        };

        PullTypeSymbol.prototype.addTypeThatExtendsThisType = function (type) {
            if (!type) {
                return;
            }

            if (!this._typesThatExtendThisType) {
                this._typesThatExtendThisType = [];
            }

            this._typesThatExtendThisType[this._typesThatExtendThisType.length] = type;
        };

        PullTypeSymbol.prototype.getTypesThatExtendThisType = function () {
            if (!this._typesThatExtendThisType) {
                this._typesThatExtendThisType = [];
            }

            return this._typesThatExtendThisType;
        };

        PullTypeSymbol.prototype.addTypeThatExplicitlyImplementsThisType = function (type) {
            if (!type) {
                return;
            }

            if (!this._typesThatExplicitlyImplementThisType) {
                this._typesThatExplicitlyImplementThisType = [];
            }

            this._typesThatExplicitlyImplementThisType[this._typesThatExplicitlyImplementThisType.length] = type;
        };

        PullTypeSymbol.prototype.getTypesThatExplicitlyImplementThisType = function () {
            if (!this._typesThatExplicitlyImplementThisType) {
                this._typesThatExplicitlyImplementThisType = [];
            }

            return this._typesThatExplicitlyImplementThisType;
        };

        PullTypeSymbol.prototype.hasBase = function (potentialBase, visited) {
            if (typeof visited === "undefined") { visited = []; }
            // Check if this is the potential base:
            //      A extends A  => this === potentialBase
            //      A<T> extends A<T>  => this.getRootSymbol() === potentialBase
            //      A<T> extends A<string> => this === potentialBase.getRootSymbol()
            if (this === potentialBase || this.getRootSymbol() === potentialBase || this === potentialBase.getRootSymbol()) {
                return true;
            }

            if (TypeScript.ArrayUtilities.contains(visited, this)) {
                return true;
            }

            visited.push(this);

            var extendedTypes = this.getExtendedTypes();

            for (var i = 0; i < extendedTypes.length; i++) {
                if (extendedTypes[i].hasBase(potentialBase, visited)) {
                    return true;
                }
            }

            var implementedTypes = this.getImplementedTypes();

            for (var i = 0; i < implementedTypes.length; i++) {
                if (implementedTypes[i].hasBase(potentialBase, visited)) {
                    return true;
                }
            }

            // Clean the list if we are returning false to ensure we are not leaving symbols that
            // were not in the path. No need to do that if we return true, as that will short circuit
            // the search
            visited.pop();

            return false;
        };

        PullTypeSymbol.prototype.isValidBaseKind = function (baseType, isExtendedType) {
            // Error type symbol is invalid base kind
            if (baseType.isError()) {
                return false;
            }

            var thisIsClass = this.isClass();
            if (isExtendedType) {
                if (thisIsClass) {
                    // Class extending non class Type is invalid
                    return baseType.kind === TypeScript.PullElementKind.Class;
                }
            } else {
                if (!thisIsClass) {
                    // Interface implementing baseType is invalid
                    return false;
                }
            }

            // Interface extending non interface or class
            // or class implementing non interface or class - are invalid
            return !!(baseType.kind & (TypeScript.PullElementKind.Interface | TypeScript.PullElementKind.Class));
        };

        PullTypeSymbol.prototype.findMember = function (name, lookInParent) {
            var memberSymbol = null;

            if (this._memberNameCache) {
                memberSymbol = this._memberNameCache[name];
            }

            if (memberSymbol || !lookInParent) {
                return memberSymbol;
            }

            // check parents
            if (this._extendedTypes) {
                for (var i = 0; i < this._extendedTypes.length; i++) {
                    memberSymbol = this._extendedTypes[i].findMember(name, lookInParent);

                    if (memberSymbol) {
                        return memberSymbol;
                    }
                }
            }

            return null;
        };

        PullTypeSymbol.prototype.findNestedType = function (name, kind) {
            if (typeof kind === "undefined") { kind = 0 /* None */; }
            var memberSymbol;

            if (!this._enclosedTypeNameCache) {
                return null;
            }

            memberSymbol = this._enclosedTypeNameCache[name];

            if (memberSymbol && kind !== 0 /* None */) {
                memberSymbol = TypeScript.hasFlag(memberSymbol.kind, kind) ? memberSymbol : null;
            }

            return memberSymbol;
        };

        PullTypeSymbol.prototype.findNestedContainer = function (name, kind) {
            if (typeof kind === "undefined") { kind = 0 /* None */; }
            var memberSymbol;

            if (!this._enclosedContainerCache) {
                return null;
            }

            memberSymbol = this._enclosedContainerCache[name];

            if (memberSymbol && kind !== 0 /* None */) {
                memberSymbol = TypeScript.hasFlag(memberSymbol.kind, kind) ? memberSymbol : null;
            }

            return memberSymbol;
        };

        PullTypeSymbol.prototype.getAllMembers = function (searchDeclKind, memberVisiblity) {
            var allMembers = [];

            // Add members
            if (this._members !== TypeScript.sentinelEmptyArray) {
                for (var i = 0, n = this._members.length; i < n; i++) {
                    var member = this._members[i];
                    if ((member.kind & searchDeclKind) && (memberVisiblity !== 2 /* externallyVisible */ || !member.anyDeclHasFlag(TypeScript.PullElementFlags.Private))) {
                        allMembers[allMembers.length] = member;
                    }
                }
            }

            // Add parent members
            if (this._extendedTypes) {
                // Do not look for the parent's private members unless we need to enumerate all members
                var extenedMembersVisibility = memberVisiblity !== 0 /* all */ ? 2 /* externallyVisible */ : 0 /* all */;

                for (var i = 0, n = this._extendedTypes.length; i < n; i++) {
                    var extendedMembers = this._extendedTypes[i].getAllMembers(searchDeclKind, extenedMembersVisibility);

                    for (var j = 0, m = extendedMembers.length; j < m; j++) {
                        var extendedMember = extendedMembers[j];
                        if (!(this._memberNameCache && this._memberNameCache[extendedMember.name])) {
                            allMembers[allMembers.length] = extendedMember;
                        }
                    }
                }
            }

            if (this.isContainer()) {
                if (this._enclosedMemberTypes) {
                    for (var i = 0; i < this._enclosedMemberTypes.length; i++) {
                        allMembers[allMembers.length] = this._enclosedMemberTypes[i];
                    }
                }
                if (this._enclosedMemberContainers) {
                    for (var i = 0; i < this._enclosedMemberContainers.length; i++) {
                        allMembers[allMembers.length] = this._enclosedMemberContainers[i];
                    }
                }
            }

            return allMembers;
        };

        PullTypeSymbol.prototype.findTypeParameter = function (name) {
            if (!this._typeParameterNameCache) {
                return null;
            }

            return this._typeParameterNameCache[name];
        };

        PullTypeSymbol.prototype.setResolved = function () {
            _super.prototype.setResolved.call(this);
        };

        PullTypeSymbol.prototype.getNamePartForFullName = function () {
            var name = _super.prototype.getNamePartForFullName.call(this);

            var typars = this.getTypeArgumentsOrTypeParameters();
            var typarString = PullSymbol.getTypeParameterString(typars, this, true);
            return name + typarString;
        };

        PullTypeSymbol.prototype.getScopedName = function (scopeSymbol, skipTypeParametersInName, useConstraintInName, skipInternalAliasName) {
            return this.getScopedNameEx(scopeSymbol, skipTypeParametersInName, useConstraintInName, false, false, skipInternalAliasName).toString();
        };

        PullTypeSymbol.prototype.isNamedTypeSymbol = function () {
            var kind = this.kind;
            if (kind === TypeScript.PullElementKind.Primitive || kind === TypeScript.PullElementKind.Class || kind === TypeScript.PullElementKind.Container || kind === TypeScript.PullElementKind.DynamicModule || kind === TypeScript.PullElementKind.TypeAlias || kind === TypeScript.PullElementKind.Enum || kind === TypeScript.PullElementKind.TypeParameter || ((kind === TypeScript.PullElementKind.Interface || kind === TypeScript.PullElementKind.ObjectType) && this.name !== "")) {
                return true;
            }

            return false;
        };

        PullTypeSymbol.prototype.toString = function (scopeSymbol, useConstraintInName) {
            var s = this.getScopedNameEx(scopeSymbol, false, useConstraintInName).toString();
            return s;
        };

        PullTypeSymbol.prototype.getScopedNameEx = function (scopeSymbol, skipTypeParametersInName, useConstraintInName, getPrettyTypeName, getTypeParamMarkerInfo, skipInternalAliasName, shouldAllowArrayType) {
            if (typeof shouldAllowArrayType === "undefined") { shouldAllowArrayType = true; }
            if (this.isArrayNamedTypeReference() && shouldAllowArrayType) {
                var elementType = this.getElementType();
                var elementMemberName = elementType ? (elementType.isArrayNamedTypeReference() || elementType.isNamedTypeSymbol() ? elementType.getScopedNameEx(scopeSymbol, false, false, getPrettyTypeName, getTypeParamMarkerInfo, skipInternalAliasName) : elementType.getMemberTypeNameEx(false, scopeSymbol, getPrettyTypeName)) : TypeScript.MemberName.create("any");
                return TypeScript.MemberName.create(elementMemberName, "", "[]");
            }

            if (!this.isNamedTypeSymbol()) {
                return this.getMemberTypeNameEx(true, scopeSymbol, getPrettyTypeName);
            }

            if (skipTypeParametersInName) {
                return TypeScript.MemberName.create(_super.prototype.getScopedName.call(this, scopeSymbol, skipTypeParametersInName, useConstraintInName, skipInternalAliasName));
            } else {
                var builder = new TypeScript.MemberNameArray();
                builder.prefix = _super.prototype.getScopedName.call(this, scopeSymbol, skipTypeParametersInName, useConstraintInName, skipInternalAliasName);

                var typars = this.getTypeArgumentsOrTypeParameters();
                builder.add(PullSymbol.getTypeParameterStringEx(typars, scopeSymbol, getTypeParamMarkerInfo, useConstraintInName));

                return builder;
            }
        };

        PullTypeSymbol.prototype.hasOnlyOverloadCallSignatures = function () {
            var members = this.getMembers();
            var callSignatures = this.getCallSignatures();
            var constructSignatures = this.getConstructSignatures();
            return members.length === 0 && constructSignatures.length === 0 && callSignatures.length > 1;
        };

        PullTypeSymbol.prototype.getTypeOfSymbol = function () {
            // typeof Module/Class/Enum
            var associatedContainerType = this.getAssociatedContainerType();
            if (associatedContainerType && associatedContainerType.isNamedTypeSymbol()) {
                return associatedContainerType;
            }

            // typeof Function
            var functionSymbol = this.getFunctionSymbol();
            if (functionSymbol && functionSymbol.kind === TypeScript.PullElementKind.Function && !TypeScript.PullHelpers.isSymbolLocal(functionSymbol)) {
                // workaround for missing 'bindAllDeclsInOrder' for classes: do not return typeof symbol for functions defined in module part of clodules (they are considered non-local)
                return TypeScript.PullHelpers.isExportedSymbolInClodule(functionSymbol) ? null : functionSymbol;
            }

            return null;
        };

        PullTypeSymbol.prototype.getMemberTypeNameEx = function (topLevel, scopeSymbol, getPrettyTypeName) {
            var members = this.getMembers();
            var callSignatures = this.getCallSignatures();
            var constructSignatures = this.getConstructSignatures();
            var indexSignatures = this.getIndexSignatures();

            var typeOfSymbol = this.getTypeOfSymbol();
            if (typeOfSymbol) {
                var nameForTypeOf = typeOfSymbol.getScopedNameEx(scopeSymbol, true);
                return TypeScript.MemberName.create(nameForTypeOf, "typeof ", "");
            }

            if (members.length > 0 || callSignatures.length > 0 || constructSignatures.length > 0 || indexSignatures.length > 0) {
                if (this._inMemberTypeNameEx) {
                    // If recursive without type name possible if function expression type
                    return TypeScript.MemberName.create("any");
                }

                this._inMemberTypeNameEx = true;

                var allMemberNames = new TypeScript.MemberNameArray();
                var curlies = !topLevel || indexSignatures.length !== 0;
                var delim = "; ";
                for (var i = 0; i < members.length; i++) {
                    if (members[i].kind === TypeScript.PullElementKind.Method && members[i].type.hasOnlyOverloadCallSignatures()) {
                        // Add all Call signatures of the method
                        var methodCallSignatures = members[i].type.getCallSignatures();
                        var nameStr = members[i].getDisplayName(scopeSymbol) + (members[i].isOptional ? "?" : "");
                        ;
                        var methodMemberNames = PullSignatureSymbol.getSignaturesTypeNameEx(methodCallSignatures, nameStr, false, false, scopeSymbol);
                        allMemberNames.addAll(methodMemberNames);
                    } else {
                        var memberTypeName = members[i].getNameAndTypeNameEx(scopeSymbol);
                        if (memberTypeName.isArray() && memberTypeName.delim === delim) {
                            allMemberNames.addAll(memberTypeName.entries);
                        } else {
                            allMemberNames.add(memberTypeName);
                        }
                    }
                    curlies = true;
                }

                // Use pretty Function overload signature if this is just a call overload
                var getPrettyFunctionOverload = getPrettyTypeName && !curlies && this.hasOnlyOverloadCallSignatures();

                var signatureCount = callSignatures.length + constructSignatures.length + indexSignatures.length;
                var useShortFormSignature = !curlies && (signatureCount === 1);
                var signatureMemberName;

                if (callSignatures.length > 0) {
                    signatureMemberName = PullSignatureSymbol.getSignaturesTypeNameEx(callSignatures, "", useShortFormSignature, false, scopeSymbol, getPrettyFunctionOverload);
                    allMemberNames.addAll(signatureMemberName);
                }

                if (constructSignatures.length > 0) {
                    signatureMemberName = PullSignatureSymbol.getSignaturesTypeNameEx(constructSignatures, "new", useShortFormSignature, false, scopeSymbol);
                    allMemberNames.addAll(signatureMemberName);
                }

                if (indexSignatures.length > 0) {
                    signatureMemberName = PullSignatureSymbol.getSignaturesTypeNameEx(indexSignatures, "", useShortFormSignature, true, scopeSymbol);
                    allMemberNames.addAll(signatureMemberName);
                }

                if ((curlies) || (!getPrettyFunctionOverload && (signatureCount > 1) && topLevel)) {
                    allMemberNames.prefix = "{ ";
                    allMemberNames.suffix = "}";
                    allMemberNames.delim = delim;
                } else if (allMemberNames.entries.length > 1) {
                    allMemberNames.delim = delim;
                }

                this._inMemberTypeNameEx = false;

                return allMemberNames;
            }

            return TypeScript.MemberName.create("{}");
        };

        PullTypeSymbol.prototype.getGenerativeTypeClassification = function (enclosingType) {
            return 2 /* Closed */;
        };

        PullTypeSymbol.prototype.wrapsSomeTypeParameter = function (typeParameterArgumentMap, skipTypeArgumentCheck) {
            return this.getWrappingTypeParameterID(typeParameterArgumentMap, skipTypeArgumentCheck) != 0;
        };

        // 0 means there was no type parameter ID wrapping
        // otherwise typeParameterID that was wrapped
        //
        // While it would be intuitive to return a boolean, this actually doesn't work
        // for the WrapsTypeParameterCache. See the comment at the top of the WrapsTypeParameterCache
        // class for an explanation.
        PullTypeSymbol.prototype.getWrappingTypeParameterID = function (typeParameterArgumentMap, skipTypeArgumentCheck) {
            // if we encounter a type parameter, we're obviously wrapping
            if (this.isTypeParameter()) {
                if (typeParameterArgumentMap[this.pullSymbolID] || typeParameterArgumentMap[this.getRootSymbol().pullSymbolID]) {
                    return this.pullSymbolID;
                }
            }

            // Note here that we do NOT check the type parameter's constraint. If we did, we would
            // think that any reference to the type parameter wraps something if its constraint does.
            // Instead, the containing signature is responsible for checking if the constraint wraps.
            // For example, consider the following type:
            //
            // interface A<S> {
            //     foo: S;
            // }
            //
            // interface B<T> {
            //     <U extends T>(x: A<U>);
            // }
            //
            // The type reference A<U> does not wrap T. If we checked the constraint here, we would
            // return true for that. However, the signature <U extends T>(x: A<U>); does indeed wrap
            // T.
            if (this.inWrapCheck) {
                return 0;
            }

            // Find result from cache
            this._wrapsTypeParameterCache = this._wrapsTypeParameterCache || new TypeScript.WrapsTypeParameterCache();
            var wrappingTypeParameterID = this._wrapsTypeParameterCache.getWrapsTypeParameter(typeParameterArgumentMap);
            if (wrappingTypeParameterID === undefined) {
                this.inWrapCheck = true;
                wrappingTypeParameterID = this.getWrappingTypeParameterIDWorker(typeParameterArgumentMap, skipTypeArgumentCheck);
                this.inWrapCheck = false;

                // Update the cache
                this._wrapsTypeParameterCache.setWrapsTypeParameter(typeParameterArgumentMap, wrappingTypeParameterID);
            }
            return wrappingTypeParameterID;
        };

        PullTypeSymbol.prototype.getWrappingTypeParameterIDWorker = function (typeParameterArgumentMap, skipTypeArgumentCheck) {
            var wrappingTypeParameterID = 0;

            if (!skipTypeArgumentCheck) {
                var typeArguments = this.getTypeArguments();

                // If there are no type arguments, we could be instantiating the 'root' type
                // declaration
                if (this.isGeneric() && !typeArguments) {
                    typeArguments = this.getTypeParameters();
                }

                // if it's a generic type, scan the type arguments to see which may wrap type parameters
                if (typeArguments) {
                    for (var i = 0; !wrappingTypeParameterID && i < typeArguments.length; i++) {
                        wrappingTypeParameterID = typeArguments[i].getWrappingTypeParameterID(typeParameterArgumentMap);
                        if (wrappingTypeParameterID !== 0) {
                            return wrappingTypeParameterID;
                        }
                    }
                }
            }

            // if it's not a named type, we'll need to introspect its member list
            if (skipTypeArgumentCheck || !(this.kind & TypeScript.PullElementKind.SomeInstantiatableType) || !this.name) {
                // otherwise, walk the member list and signatures, checking for wraps
                var members = this.getAllMembers(TypeScript.PullElementKind.SomeValue, 0 /* all */);
                for (var i = 0; i < members.length; i++) {
                    TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(members[i]);
                    wrappingTypeParameterID = members[i].type.getWrappingTypeParameterID(typeParameterArgumentMap);
                    if (wrappingTypeParameterID !== 0) {
                        return wrappingTypeParameterID;
                    }
                }

                // We are ORing numbers here, which means that if any invocation returns 0, we will proceed to the next
                // signature group.
                return this.getWrappingTypeParameterIDFromSignatures(this.getCallSignatures(), typeParameterArgumentMap) || this.getWrappingTypeParameterIDFromSignatures(this.getConstructSignatures(), typeParameterArgumentMap) || this.getWrappingTypeParameterIDFromSignatures(this.getIndexSignatures(), typeParameterArgumentMap);
            }

            return 0;
        };

        PullTypeSymbol.prototype.getWrappingTypeParameterIDFromSignatures = function (signatures, typeParameterArgumentMap) {
            for (var i = 0; i < signatures.length; i++) {
                var wrappingTypeParameterID = signatures[i].getWrappingTypeParameterID(typeParameterArgumentMap);
                if (wrappingTypeParameterID !== 0) {
                    return wrappingTypeParameterID;
                }
            }

            return 0;
        };

        // Detect if a type parameter is wrapped in a wrapped form that generates infinite expansion.  E.g., for 'T'
        //  class C<T> {
        //      p1: T; <- no
        //      p2: C<T>; <- no
        //      p3: C<C<T>> <- yes
        //  }
        PullTypeSymbol.prototype.wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReference = function (enclosingType) {
            // Only named types can form infinite expansion
            TypeScript.Debug.assert(this.isNamedTypeSymbol());
            TypeScript.Debug.assert(TypeScript.PullHelpers.getRootType(enclosingType) == enclosingType); // Enclosing type passed has to be the root symbol
            var knownWrapMap = TypeScript.BitMatrix.getBitMatrix(true);
            var wrapsIntoInfinitelyExpandingTypeReference = this._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceRecurse(enclosingType, knownWrapMap);
            knownWrapMap.release();
            return wrapsIntoInfinitelyExpandingTypeReference;
        };

        PullTypeSymbol.prototype._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceRecurse = function (enclosingType, knownWrapMap) {
            var wrapsIntoInfinitelyExpandingTypeReference = knownWrapMap.valueAt(this.pullSymbolID, enclosingType.pullSymbolID);
            if (wrapsIntoInfinitelyExpandingTypeReference != undefined) {
                return wrapsIntoInfinitelyExpandingTypeReference;
            }

            if (this.inWrapInfiniteExpandingReferenceCheck) {
                return false;
            }

            this.inWrapInfiniteExpandingReferenceCheck = true;
            wrapsIntoInfinitelyExpandingTypeReference = this._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceWorker(enclosingType, knownWrapMap);
            knownWrapMap.setValueAt(this.pullSymbolID, enclosingType.pullSymbolID, wrapsIntoInfinitelyExpandingTypeReference);
            this.inWrapInfiniteExpandingReferenceCheck = false;

            return wrapsIntoInfinitelyExpandingTypeReference;
        };

        PullTypeSymbol.prototype._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceWorker = function (enclosingType, knownWrapMap) {
            var thisRootType = TypeScript.PullHelpers.getRootType(this);

            if (thisRootType != enclosingType) {
                var thisIsNamedType = this.isNamedTypeSymbol();

                if (thisIsNamedType) {
                    if (thisRootType.inWrapInfiniteExpandingReferenceCheck) {
                        // No need to iterating members of the type again if we are checking members of some
                        // version of this type
                        return false;
                    }

                    thisRootType.inWrapInfiniteExpandingReferenceCheck = true;
                }

                var wrapsIntoInfinitelyExpandingTypeReference = this._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceStructure(enclosingType, knownWrapMap);

                if (thisIsNamedType) {
                    thisRootType.inWrapInfiniteExpandingReferenceCheck = false;
                }

                return wrapsIntoInfinitelyExpandingTypeReference;
            }

            // Spec section 3.8.7: Recursive Types
            // A type reference which, directly or indirectly, references G through open type references and
            // which contains a wrapped form of any of G’s type parameters in one or more type arguments is classified
            // as an infinitely expanding type reference.A type is said to wrap a type parameter if it references
            // the type parameter but isn’t simply the type parameter itself.
            var enclosingTypeParameters = enclosingType.getTypeParameters();
            var typeArguments = this.getTypeArguments();
            for (var i = 0; i < typeArguments.length; i++) {
                if (TypeScript.ArrayUtilities.contains(enclosingTypeParameters, typeArguments[i])) {
                    continue;
                }

                // Type arguments wraps type parameter
                if (typeArguments[i].wrapsSomeTypeParameter(this.getTypeParameterSubstitutionMap())) {
                    return true;
                }
            }

            return false;
        };

        PullTypeSymbol.prototype._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceStructure = function (enclosingType, knownWrapMap) {
            var members = this.getAllMembers(TypeScript.PullElementKind.SomeValue, 0 /* all */);
            for (var i = 0; i < members.length; i++) {
                if (members[i].type && members[i].type._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReferenceRecurse(enclosingType, knownWrapMap)) {
                    return true;
                }
            }

            var sigs = this.getCallSignatures();
            for (var i = 0; i < sigs.length; i++) {
                if (sigs[i]._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReference(enclosingType, knownWrapMap)) {
                    return true;
                }
            }

            sigs = this.getConstructSignatures();
            for (var i = 0; i < sigs.length; i++) {
                if (sigs[i]._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReference(enclosingType, knownWrapMap)) {
                    return true;
                }
            }

            sigs = this.getIndexSignatures();
            for (var i = 0; i < sigs.length; i++) {
                if (sigs[i]._wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReference(enclosingType, knownWrapMap)) {
                    return true;
                }
            }

            return false;
        };

        // This is the same signature as PullTypeResolver.widenType (except that the positions
        // of the resolver are switched). This method just returns the cached value of the widened
        // type, otherwise, calls into the resolver.
        PullTypeSymbol.prototype.widenedType = function (resolver, ast, context) {
            if (!this._widenedType) {
                this._widenedType = resolver.widenType(this, ast, context);
            }
            return this._widenedType;
        };
        return PullTypeSymbol;
    })(PullSymbol);
    TypeScript.PullTypeSymbol = PullTypeSymbol;

    var PullPrimitiveTypeSymbol = (function (_super) {
        __extends(PullPrimitiveTypeSymbol, _super);
        function PullPrimitiveTypeSymbol(name, semanticInfoChain) {
            _super.call(this, name, TypeScript.PullElementKind.Primitive, semanticInfoChain);

            this.isResolved = true;
        }
        PullPrimitiveTypeSymbol.prototype.isAny = function () {
            return !this.isStringConstant() && this.name === "any";
        };

        PullPrimitiveTypeSymbol.prototype.isNull = function () {
            return !this.isStringConstant() && this.name === "null";
        };

        PullPrimitiveTypeSymbol.prototype.isUndefined = function () {
            return !this.isStringConstant() && this.name === "undefined";
        };

        PullPrimitiveTypeSymbol.prototype.isStringConstant = function () {
            return false;
        };

        PullPrimitiveTypeSymbol.prototype.setUnresolved = function () {
            // do nothing...
        };

        // Overrides the PullSymbol.getDisplayName to give the appearance of widening. The spec
        // doesn't say anything about displaying types, but we should leave no trace of undefined
        // or null.
        PullPrimitiveTypeSymbol.prototype.getDisplayName = function () {
            if (this.isNull() || this.isUndefined()) {
                return "any";
            } else {
                return _super.prototype.getDisplayName.call(this);
            }
        };
        return PullPrimitiveTypeSymbol;
    })(PullTypeSymbol);
    TypeScript.PullPrimitiveTypeSymbol = PullPrimitiveTypeSymbol;

    var PullStringConstantTypeSymbol = (function (_super) {
        __extends(PullStringConstantTypeSymbol, _super);
        function PullStringConstantTypeSymbol(name, semanticInfoChain) {
            _super.call(this, name, semanticInfoChain);
        }
        PullStringConstantTypeSymbol.prototype.isStringConstant = function () {
            return true;
        };
        return PullStringConstantTypeSymbol;
    })(PullPrimitiveTypeSymbol);
    TypeScript.PullStringConstantTypeSymbol = PullStringConstantTypeSymbol;

    var PullErrorTypeSymbol = (function (_super) {
        __extends(PullErrorTypeSymbol, _super);
        function PullErrorTypeSymbol(_anyType, name, semanticInfoChain) {
            _super.call(this, name, semanticInfoChain);
            this._anyType = _anyType;

            TypeScript.Debug.assert(this._anyType);
            this.isResolved = true;
        }
        PullErrorTypeSymbol.prototype.isError = function () {
            return true;
        };

        PullErrorTypeSymbol.prototype._getResolver = function () {
            return this._anyType._getResolver();
        };

        PullErrorTypeSymbol.prototype.getName = function (scopeSymbol, useConstraintInName) {
            return this._anyType.getName(scopeSymbol, useConstraintInName);
        };

        PullErrorTypeSymbol.prototype.getDisplayName = function (scopeSymbol, useConstraintInName, skipInternalAliasName) {
            return this._anyType.getName(scopeSymbol, useConstraintInName);
        };

        PullErrorTypeSymbol.prototype.toString = function (scopeSymbol, useConstraintInName) {
            return this._anyType.getName(scopeSymbol, useConstraintInName);
        };
        return PullErrorTypeSymbol;
    })(PullPrimitiveTypeSymbol);
    TypeScript.PullErrorTypeSymbol = PullErrorTypeSymbol;

    // represents the module "namespace" type
    var PullContainerSymbol = (function (_super) {
        __extends(PullContainerSymbol, _super);
        function PullContainerSymbol(name, kind, semanticInfoChain) {
            _super.call(this, name, kind, semanticInfoChain);
            this.instanceSymbol = null;
            this.assignedValue = null;
            this.assignedType = null;
            this.assignedContainer = null;
        }
        PullContainerSymbol.prototype.isContainer = function () {
            return true;
        };

        PullContainerSymbol.prototype.setInstanceSymbol = function (symbol) {
            this.instanceSymbol = symbol;
        };

        PullContainerSymbol.prototype.getInstanceSymbol = function () {
            return this.instanceSymbol;
        };

        PullContainerSymbol.prototype.setExportAssignedValueSymbol = function (symbol) {
            this.assignedValue = symbol;
        };

        PullContainerSymbol.prototype.getExportAssignedValueSymbol = function () {
            return this.assignedValue;
        };

        PullContainerSymbol.prototype.setExportAssignedTypeSymbol = function (type) {
            this.assignedType = type;
        };

        PullContainerSymbol.prototype.getExportAssignedTypeSymbol = function () {
            return this.assignedType;
        };

        PullContainerSymbol.prototype.setExportAssignedContainerSymbol = function (container) {
            this.assignedContainer = container;
        };

        PullContainerSymbol.prototype.getExportAssignedContainerSymbol = function () {
            return this.assignedContainer;
        };

        PullContainerSymbol.prototype.hasExportAssignment = function () {
            return !!this.assignedValue || !!this.assignedType || !!this.assignedContainer;
        };

        // Determine if 'symbol' is used as containerSymbol
        PullContainerSymbol.usedAsSymbol = function (containerSymbol, symbol) {
            if (!containerSymbol || !containerSymbol.isContainer()) {
                return false;
            }

            if (!containerSymbol.isAlias() && containerSymbol.type === symbol) {
                return true;
            }

            var moduleSymbol = containerSymbol;
            var valueExportSymbol = moduleSymbol.getExportAssignedValueSymbol();
            var typeExportSymbol = moduleSymbol.getExportAssignedTypeSymbol();
            var containerExportSymbol = moduleSymbol.getExportAssignedContainerSymbol();
            if (valueExportSymbol || typeExportSymbol || containerExportSymbol) {
                // If the container symbol has export assignment then 'symbol' is used as containerSymbol if
                // any of export assigned symbol is same as 'symbol'
                if (valueExportSymbol === symbol || typeExportSymbol == symbol || containerExportSymbol == symbol) {
                    return true;
                }

                // If the container symbol doesnt export itself, check if export assigned container symbol is used as 'symbol'
                if (containerExportSymbol != containerSymbol) {
                    return PullContainerSymbol.usedAsSymbol(containerExportSymbol, symbol);
                }
            }

            return false;
        };

        PullContainerSymbol.prototype.getInstanceType = function () {
            return this.instanceSymbol ? this.instanceSymbol.type : null;
        };
        return PullContainerSymbol;
    })(PullTypeSymbol);
    TypeScript.PullContainerSymbol = PullContainerSymbol;

    var PullTypeAliasSymbol = (function (_super) {
        __extends(PullTypeAliasSymbol, _super);
        function PullTypeAliasSymbol(name, semanticInfoChain) {
            _super.call(this, name, TypeScript.PullElementKind.TypeAlias, semanticInfoChain);
            this._assignedValue = null;
            this._assignedType = null;
            this._assignedContainer = null;
            this._isUsedAsValue = false;
            this._typeUsedExternally = false;
            this._isUsedInExportAlias = false;
            this.retrievingExportAssignment = false;
            this.linkedAliasSymbols = null;
        }
        PullTypeAliasSymbol.prototype.isUsedInExportedAlias = function () {
            this._resolveDeclaredSymbol();
            return this._isUsedInExportAlias;
        };

        PullTypeAliasSymbol.prototype.typeUsedExternally = function () {
            this._resolveDeclaredSymbol();
            return this._typeUsedExternally;
        };

        PullTypeAliasSymbol.prototype.isUsedAsValue = function () {
            this._resolveDeclaredSymbol();
            return this._isUsedAsValue;
        };

        PullTypeAliasSymbol.prototype.setTypeUsedExternally = function () {
            this._typeUsedExternally = true;
        };

        PullTypeAliasSymbol.prototype.setIsUsedInExportedAlias = function () {
            this._isUsedInExportAlias = true;
            if (this.linkedAliasSymbols) {
                this.linkedAliasSymbols.forEach(function (s) {
                    return s.setIsUsedInExportedAlias();
                });
            }
        };

        PullTypeAliasSymbol.prototype.addLinkedAliasSymbol = function (contingentValueSymbol) {
            if (!this.linkedAliasSymbols) {
                this.linkedAliasSymbols = [contingentValueSymbol];
            } else {
                this.linkedAliasSymbols.push(contingentValueSymbol);
            }
        };

        PullTypeAliasSymbol.prototype.setIsUsedAsValue = function () {
            this._isUsedAsValue = true;
            if (this.linkedAliasSymbols) {
                this.linkedAliasSymbols.forEach(function (s) {
                    return s.setIsUsedAsValue();
                });
            }
        };

        PullTypeAliasSymbol.prototype.assignedValue = function () {
            this._resolveDeclaredSymbol();
            return this._assignedValue;
        };

        PullTypeAliasSymbol.prototype.assignedType = function () {
            this._resolveDeclaredSymbol();
            return this._assignedType;
        };

        PullTypeAliasSymbol.prototype.assignedContainer = function () {
            this._resolveDeclaredSymbol();
            return this._assignedContainer;
        };

        PullTypeAliasSymbol.prototype.isAlias = function () {
            return true;
        };
        PullTypeAliasSymbol.prototype.isContainer = function () {
            return true;
        };

        PullTypeAliasSymbol.prototype.setAssignedValueSymbol = function (symbol) {
            this._assignedValue = symbol;
        };

        PullTypeAliasSymbol.prototype.getExportAssignedValueSymbol = function () {
            if (this._assignedValue) {
                return this._assignedValue;
            }

            if (this.retrievingExportAssignment) {
                return null;
            }

            if (this._assignedContainer) {
                if (this._assignedContainer.hasExportAssignment()) {
                    this.retrievingExportAssignment = true;
                    var sym = this._assignedContainer.getExportAssignedValueSymbol();
                    this.retrievingExportAssignment = false;
                    return sym;
                }

                return this._assignedContainer.getInstanceSymbol();
            }

            return null;
        };

        PullTypeAliasSymbol.prototype.setAssignedTypeSymbol = function (type) {
            this._assignedType = type;
        };

        PullTypeAliasSymbol.prototype.getExportAssignedTypeSymbol = function () {
            if (this.retrievingExportAssignment) {
                return null;
            }

            if (this._assignedType) {
                if (this._assignedType.isAlias()) {
                    this.retrievingExportAssignment = true;
                    var sym = this._assignedType.getExportAssignedTypeSymbol();
                    this.retrievingExportAssignment = false;
                } else if (this._assignedType !== this._assignedContainer) {
                    return this._assignedType;
                }
            }

            if (this._assignedContainer) {
                this.retrievingExportAssignment = true;
                var sym = this._assignedContainer.getExportAssignedTypeSymbol();
                this.retrievingExportAssignment = false;
                if (sym) {
                    return sym;
                }
            }

            return this._assignedContainer;
        };

        PullTypeAliasSymbol.prototype.setAssignedContainerSymbol = function (container) {
            this._assignedContainer = container;
        };

        PullTypeAliasSymbol.prototype.getExportAssignedContainerSymbol = function () {
            if (this.retrievingExportAssignment) {
                return null;
            }

            if (this._assignedContainer) {
                this.retrievingExportAssignment = true;
                var sym = this._assignedContainer.getExportAssignedContainerSymbol();
                this.retrievingExportAssignment = false;
                if (sym) {
                    return sym;
                }
            }

            return this._assignedContainer;
        };

        PullTypeAliasSymbol.prototype.getMembers = function () {
            if (this._assignedType) {
                return this._assignedType.getMembers();
            }

            return TypeScript.sentinelEmptyArray;
        };

        PullTypeAliasSymbol.prototype.getCallSignatures = function () {
            if (this._assignedType) {
                return this._assignedType.getCallSignatures();
            }

            return TypeScript.sentinelEmptyArray;
        };

        PullTypeAliasSymbol.prototype.getConstructSignatures = function () {
            if (this._assignedType) {
                return this._assignedType.getConstructSignatures();
            }

            return TypeScript.sentinelEmptyArray;
        };

        PullTypeAliasSymbol.prototype.getIndexSignatures = function () {
            if (this._assignedType) {
                return this._assignedType.getIndexSignatures();
            }

            return TypeScript.sentinelEmptyArray;
        };

        PullTypeAliasSymbol.prototype.findMember = function (name) {
            if (this._assignedType) {
                return this._assignedType.findMember(name, true);
            }

            return null;
        };

        PullTypeAliasSymbol.prototype.findNestedType = function (name) {
            if (this._assignedType) {
                return this._assignedType.findNestedType(name);
            }

            return null;
        };

        PullTypeAliasSymbol.prototype.findNestedContainer = function (name) {
            if (this._assignedType) {
                return this._assignedType.findNestedContainer(name);
            }

            return null;
        };

        PullTypeAliasSymbol.prototype.getAllMembers = function (searchDeclKind, memberVisibility) {
            if (this._assignedType) {
                return this._assignedType.getAllMembers(searchDeclKind, memberVisibility);
            }

            return TypeScript.sentinelEmptyArray;
        };
        return PullTypeAliasSymbol;
    })(PullTypeSymbol);
    TypeScript.PullTypeAliasSymbol = PullTypeAliasSymbol;

    var PullTypeParameterSymbol = (function (_super) {
        __extends(PullTypeParameterSymbol, _super);
        function PullTypeParameterSymbol(name, semanticInfoChain) {
            _super.call(this, name, TypeScript.PullElementKind.TypeParameter, semanticInfoChain);
            this._constraint = null;
        }
        PullTypeParameterSymbol.prototype.isTypeParameter = function () {
            return true;
        };

        PullTypeParameterSymbol.prototype.setConstraint = function (constraintType) {
            this._constraint = constraintType;
        };

        PullTypeParameterSymbol.prototype.getConstraint = function () {
            return this._constraint;
        };

        // Section 3.4.1 (November 18, 2013):
        // The base constraint of a type parameter T is defined as follows:
        //  If T has no declared constraint, T's base constraint is the empty object type {}
        //  If T's declared constraint is a type parameter, T's base constraint is that of the type parameter.
        //  Otherwise, T's base constraint is T's declared constraint.
        PullTypeParameterSymbol.prototype.getBaseConstraint = function (semanticInfoChain) {
            var preBaseConstraint = this.getConstraintRecursively({});
            TypeScript.Debug.assert(preBaseConstraint === null || !preBaseConstraint.isTypeParameter());
            return preBaseConstraint || semanticInfoChain.emptyTypeSymbol;
        };

        // Returns null if you hit a cycle or no constraint
        // The visitedTypeParameters bag is for catching cycles
        PullTypeParameterSymbol.prototype.getConstraintRecursively = function (visitedTypeParameters) {
            var constraint = this.getConstraint();

            if (constraint) {
                if (constraint.isTypeParameter()) {
                    var constraintAsTypeParameter = constraint;
                    if (!visitedTypeParameters[constraintAsTypeParameter.pullSymbolID]) {
                        visitedTypeParameters[constraintAsTypeParameter.pullSymbolID] = constraintAsTypeParameter;
                        return constraintAsTypeParameter.getConstraintRecursively(visitedTypeParameters);
                    }
                } else {
                    return constraint;
                }
            }

            return null;
        };

        // The default constraint is just like the base constraint, but without recursively traversing
        // type parameters.
        PullTypeParameterSymbol.prototype.getDefaultConstraint = function (semanticInfoChain) {
            return this._constraint || semanticInfoChain.emptyTypeSymbol;
        };

        // Note: This is a deviation from the spec. Using the constraint to get signatures is only
        // warranted when we explicitly ask for an apparent type.
        PullTypeParameterSymbol.prototype.getCallSignatures = function () {
            if (this._constraint) {
                return this._constraint.getCallSignatures();
            }

            return _super.prototype.getCallSignatures.call(this);
        };

        PullTypeParameterSymbol.prototype.getConstructSignatures = function () {
            if (this._constraint) {
                return this._constraint.getConstructSignatures();
            }

            return _super.prototype.getConstructSignatures.call(this);
        };

        PullTypeParameterSymbol.prototype.getIndexSignatures = function () {
            if (this._constraint) {
                return this._constraint.getIndexSignatures();
            }

            return _super.prototype.getIndexSignatures.call(this);
        };

        PullTypeParameterSymbol.prototype.isGeneric = function () {
            return true;
        };

        PullTypeParameterSymbol.prototype.fullName = function (scopeSymbol) {
            var name = this.getDisplayName(scopeSymbol);
            var container = this.getContainer();
            if (container) {
                var containerName = container.fullName(scopeSymbol);
                name = name + " in " + containerName;
            }

            return name;
        };

        PullTypeParameterSymbol.prototype.getName = function (scopeSymbol, useConstraintInName) {
            var name = _super.prototype.getName.call(this, scopeSymbol);

            if (this.isPrinting) {
                return name;
            }

            this.isPrinting = true;

            if (useConstraintInName && this._constraint) {
                name += " extends " + this._constraint.toString(scopeSymbol);
            }

            this.isPrinting = false;

            return name;
        };

        PullTypeParameterSymbol.prototype.getDisplayName = function (scopeSymbol, useConstraintInName, skipInternalAliasName) {
            var name = _super.prototype.getDisplayName.call(this, scopeSymbol, useConstraintInName, skipInternalAliasName);

            if (this.isPrinting) {
                return name;
            }

            this.isPrinting = true;

            if (useConstraintInName && this._constraint) {
                name += " extends " + this._constraint.toString(scopeSymbol);
            }

            this.isPrinting = false;

            return name;
        };

        PullTypeParameterSymbol.prototype.isExternallyVisible = function (inIsExternallyVisibleSymbols) {
            return true;
        };
        return PullTypeParameterSymbol;
    })(PullTypeSymbol);
    TypeScript.PullTypeParameterSymbol = PullTypeParameterSymbol;

    var PullAccessorSymbol = (function (_super) {
        __extends(PullAccessorSymbol, _super);
        function PullAccessorSymbol(name, semanticInfoChain) {
            _super.call(this, name, TypeScript.PullElementKind.Property, semanticInfoChain);
            this._getterSymbol = null;
            this._setterSymbol = null;
        }
        PullAccessorSymbol.prototype.isAccessor = function () {
            return true;
        };

        PullAccessorSymbol.prototype.setSetter = function (setter) {
            if (!setter) {
                return;
            }

            this._setterSymbol = setter;
        };

        PullAccessorSymbol.prototype.getSetter = function () {
            return this._setterSymbol;
        };

        PullAccessorSymbol.prototype.setGetter = function (getter) {
            if (!getter) {
                return;
            }

            this._getterSymbol = getter;
        };

        PullAccessorSymbol.prototype.getGetter = function () {
            return this._getterSymbol;
        };
        return PullAccessorSymbol;
    })(PullSymbol);
    TypeScript.PullAccessorSymbol = PullAccessorSymbol;

    function getIDForTypeSubstitutions(instantiatingTypeOrSignature, typeArgumentMap) {
        var substitution = "";
        var members = null;

        var allowedToReferenceTypeParameters = instantiatingTypeOrSignature.getAllowedToReferenceTypeParameters();
        for (var i = 0; i < allowedToReferenceTypeParameters.length; i++) {
            var typeParameter = allowedToReferenceTypeParameters[i];
            var typeParameterID = typeParameter.pullSymbolID;
            var typeArg = typeArgumentMap[typeParameterID];
            if (!typeArg) {
                typeArg = typeParameter;
            }
            substitution += typeParameterID + ":" + getIDForTypeSubstitutionsOfType(typeArg);
        }

        return substitution;
    }
    TypeScript.getIDForTypeSubstitutions = getIDForTypeSubstitutions;

    function getIDForTypeSubstitutionsOfType(type) {
        var structure;
        if (type.isError()) {
            structure = "E" + getIDForTypeSubstitutionsOfType(type._anyType);
        } else if (!type.isNamedTypeSymbol()) {
            structure = getIDForTypeSubstitutionsFromObjectType(type);
        }

        if (!structure) {
            structure = type.pullSymbolID + "#";
        }

        return structure;
    }

    function getIDForTypeSubstitutionsFromObjectType(type) {
        if (type.isResolved) {
            var getIDForTypeSubStitutionWalker = new GetIDForTypeSubStitutionWalker();
            TypeScript.PullHelpers.walkPullTypeSymbolStructure(type, getIDForTypeSubStitutionWalker);
        }

        return null;
    }

    var GetIDForTypeSubStitutionWalker = (function () {
        function GetIDForTypeSubStitutionWalker() {
            this.structure = "";
        }
        GetIDForTypeSubStitutionWalker.prototype.memberSymbolWalk = function (memberSymbol) {
            this.structure += memberSymbol.name + "@" + getIDForTypeSubstitutionsOfType(memberSymbol.type);
            return true;
        };
        GetIDForTypeSubStitutionWalker.prototype.callSignatureWalk = function (signatureSymbol) {
            this.structure += "(";
            return true;
        };
        GetIDForTypeSubStitutionWalker.prototype.constructSignatureWalk = function (signatureSymbol) {
            this.structure += "new(";
            return true;
        };
        GetIDForTypeSubStitutionWalker.prototype.indexSignatureWalk = function (signatureSymbol) {
            this.structure += "[](";
            return true;
        };
        GetIDForTypeSubStitutionWalker.prototype.signatureParameterWalk = function (parameterSymbol) {
            this.structure += parameterSymbol.name + "@" + getIDForTypeSubstitutionsOfType(parameterSymbol.type);
            return true;
        };
        GetIDForTypeSubStitutionWalker.prototype.signatureReturnTypeWalk = function (returnType) {
            this.structure += ")" + getIDForTypeSubstitutionsOfType(returnType);
            return true;
        };
        return GetIDForTypeSubStitutionWalker;
    })();

    (function (GetAllMembersVisiblity) {
        // All properties of the type regardless of their accessibility level
        GetAllMembersVisiblity[GetAllMembersVisiblity["all"] = 0] = "all";

        // Only properties that are accessible on a class instance, i.e. public and private members of
        // the current class, and only public members of any bases it extends
        GetAllMembersVisiblity[GetAllMembersVisiblity["internallyVisible"] = 1] = "internallyVisible";

        // Only public members of classes
        GetAllMembersVisiblity[GetAllMembersVisiblity["externallyVisible"] = 2] = "externallyVisible";
    })(TypeScript.GetAllMembersVisiblity || (TypeScript.GetAllMembersVisiblity = {}));
    var GetAllMembersVisiblity = TypeScript.GetAllMembersVisiblity;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    // This represents the state of the enclosing type walker that is a flag indicating if we are walking enclosingType
    // and the list of symbols walked of a generic type. It is represented as these two things because even when
    // we are in the enclosing type that is not generic, we have set enclosing type, but there wont be any need of relevant
    // signature and type reference symbols as they wont be needed to determine if the typereference in this enclosing type
    // would be infinitely recursive. Having set the flag that we have already set enclosing type, would help in
    // perf because we wouldnt keep calculating enclosing type again and again on any of the inner traversals when not necessary
    var EnclosingTypeWalkerState = (function () {
        function EnclosingTypeWalkerState() {
        }
        // Gets thye default enclosing type walker state
        // Default state is enclosing type walker isnt walking any enclosing type and hence hasSetEnclosingType = false and no current symbols
        EnclosingTypeWalkerState.getDefaultEnclosingTypeWalkerState = function () {
            var defaultEnclosingTypeWalkerState = new EnclosingTypeWalkerState();
            defaultEnclosingTypeWalkerState._hasSetEnclosingType = false;
            return defaultEnclosingTypeWalkerState;
        };

        // Gets the enclosing type walker state when enclosingType is non generic
        // In this case, the hasSetEnclosingType is true but the currentSymbols is not set because it doesnt need those symbols
        // to evaluate if typeReference would be infinitely expanding
        EnclosingTypeWalkerState.getNonGenericEnclosingTypeWalkerState = function () {
            var defaultEnclosingTypeWalkerState = new EnclosingTypeWalkerState();
            defaultEnclosingTypeWalkerState._hasSetEnclosingType = true;
            return defaultEnclosingTypeWalkerState;
        };

        // Gets the enclosing type walker state when enclosingType is generic
        EnclosingTypeWalkerState.getGenericEnclosingTypeWalkerState = function (genericEnclosingType) {
            var defaultEnclosingTypeWalkerState = new EnclosingTypeWalkerState();
            defaultEnclosingTypeWalkerState._hasSetEnclosingType = true;
            defaultEnclosingTypeWalkerState._currentSymbols = [TypeScript.PullHelpers.getRootType(genericEnclosingType)];
            return defaultEnclosingTypeWalkerState;
        };
        return EnclosingTypeWalkerState;
    })();
    TypeScript.EnclosingTypeWalkerState = EnclosingTypeWalkerState;

    // This is the walker that walks the type and type reference associated with the declaration.
    // This will make sure that any time, generative classification is asked, we have the right type of the declaration
    // and we can evaluate it in the correct context
    // interface IList<T> {
    //     owner: IList<IList<T>>;
    //     owner2: IList<IList<string>>;
    // }
    // class List<U> implements IList<U> {
    //     owner: List<List<U>>;
    // }
    // In the above example, when checking if owner of List<U> is subtype of owner of IList<U>
    // we want to traverse IList<T> to make sure when generative classification is asked we know exactly
    // which type parameters and which type need to be checked for infinite wrapping
    // This also is essential so that we dont incorrectly think owner2's type reference as infinitely expanding when
    // checking members of IList<string>
    var PullTypeEnclosingTypeWalker = (function () {
        function PullTypeEnclosingTypeWalker(semanticInfoChain) {
            this.semanticInfoChain = semanticInfoChain;
            this.setDefaultTypeWalkerState();
        }
        PullTypeEnclosingTypeWalker.prototype.setDefaultTypeWalkerState = function () {
            this.enclosingTypeWalkerState = PullTypeEnclosingTypeWalker._defaultEnclosingTypeWalkerState;
        };

        PullTypeEnclosingTypeWalker.prototype.setNonGenericEnclosingTypeWalkerState = function () {
            this.enclosingTypeWalkerState = PullTypeEnclosingTypeWalker._nonGenericEnclosingTypeWalkerState;
        };

        PullTypeEnclosingTypeWalker.prototype.canSymbolOrDeclBeUsedAsEnclosingTypeHelper = function (name, kind) {
            return name && (kind === TypeScript.PullElementKind.Class || kind === TypeScript.PullElementKind.Interface);
        };

        PullTypeEnclosingTypeWalker.prototype.canDeclBeUsedAsEnclosingType = function (decl) {
            return this.canSymbolOrDeclBeUsedAsEnclosingTypeHelper(decl.name, decl.kind);
        };

        PullTypeEnclosingTypeWalker.prototype.canSymbolBeUsedAsEnclosingType = function (symbol) {
            return this.canSymbolOrDeclBeUsedAsEnclosingTypeHelper(symbol.name, symbol.kind);
        };

        // Enclosing type is the first symbol in the symbols visited
        PullTypeEnclosingTypeWalker.prototype.getEnclosingType = function () {
            var currentSymbols = this.enclosingTypeWalkerState._currentSymbols;
            if (currentSymbols) {
                // We dont allocate current symbols as empty list any more
                TypeScript.Debug.assert(currentSymbols.length > 0);
                return currentSymbols[0];
            }

            return null;
        };

        // We can/should walk the structure only if the enclosing type is generic
        PullTypeEnclosingTypeWalker.prototype._canWalkStructure = function () {
            var enclosingType = this.getEnclosingType();
            TypeScript.Debug.assert(!enclosingType || enclosingType.isGeneric());
            return !!enclosingType;
        };

        // Current symbol is the last symbol in the current symbols list
        PullTypeEnclosingTypeWalker.prototype._getCurrentSymbol = function () {
            var currentSymbols = this.enclosingTypeWalkerState._currentSymbols;
            if (currentSymbols && currentSymbols.length) {
                return currentSymbols[currentSymbols.length - 1];
            }

            return null;
        };

        // Gets the generative classification of the current symbol in the enclosing type
        PullTypeEnclosingTypeWalker.prototype.getGenerativeClassification = function () {
            if (this._canWalkStructure()) {
                var currentType = this._getCurrentSymbol();
                if (!currentType) {
                    // This may occur if we are trying to walk type parameter in the original declaration
                    return 0 /* Unknown */;
                }

                var variableNeededToFixNodeJitterBug = this.getEnclosingType();

                return currentType.getGenerativeTypeClassification(variableNeededToFixNodeJitterBug);
            }

            return 2 /* Closed */;
        };

        PullTypeEnclosingTypeWalker.prototype._pushSymbol = function (symbol) {
            return this.enclosingTypeWalkerState._currentSymbols.push(symbol);
        };

        PullTypeEnclosingTypeWalker.prototype._popSymbol = function () {
            return this.enclosingTypeWalkerState._currentSymbols.pop();
        };

        PullTypeEnclosingTypeWalker.prototype.setSymbolAsEnclosingType = function (type) {
            if (type.isGeneric()) {
                // Set the state of the new generic type
                this.enclosingTypeWalkerState = EnclosingTypeWalkerState.getGenericEnclosingTypeWalkerState(type);
            } else {
                // Non generic Type
                this.setNonGenericEnclosingTypeWalkerState();
            }
        };

        // Sets the enclosing type along with parent declaration symbols
        PullTypeEnclosingTypeWalker.prototype._setEnclosingTypeOfParentDecl = function (decl, setSignature) {
            var parentDecl = decl.getParentDecl();

            // If we are already at module/script, we are done walking up the parent
            if (parentDecl && !(parentDecl.kind & (TypeScript.PullElementKind.SomeContainer | TypeScript.PullElementKind.Script))) {
                // Always set signatures in parents
                if (this.canDeclBeUsedAsEnclosingType(parentDecl)) {
                    this.setSymbolAsEnclosingType(parentDecl.getSymbol(this.semanticInfoChain));
                } else {
                    this._setEnclosingTypeOfParentDecl(parentDecl, true);
                }

                if (this._canWalkStructure()) {
                    // Update the current decl in the
                    var symbol = decl.getSymbol(this.semanticInfoChain);
                    if (symbol) {
                        // If symbol is raw PullSymbol (not a type or a signature, but
                        // rather a variable, function, etc), use its type instead
                        if (!symbol.isType() && !symbol.isSignature()) {
                            symbol = symbol.type;
                        }

                        this._pushSymbol(symbol);
                    }

                    // Set signature symbol if asked
                    if (setSignature) {
                        var signature = decl.getSignatureSymbol(this.semanticInfoChain);
                        if (signature) {
                            this._pushSymbol(signature);
                        }
                    }
                }
            }
        };

        PullTypeEnclosingTypeWalker.prototype.setEnclosingTypeForSymbol = function (symbol) {
            var currentEnclosingTypeWalkerState = this.enclosingTypeWalkerState;
            if (this.canSymbolBeUsedAsEnclosingType(symbol)) {
                this.setSymbolAsEnclosingType(symbol);
            } else {
                // We are going to walk declarations, so first set the default type walker state,
                // So the walker doesnt incorrectly assume us already in enclosingTypeWalker state
                this.setDefaultTypeWalkerState();

                // Walk the decls and its parents to set the enclosing type
                var decls = symbol.getDeclarations();
                for (var i = 0; i < decls.length; i++) {
                    var decl = decls[i];
                    this._setEnclosingTypeOfParentDecl(decl, symbol.isSignature());

                    // If the parent was able to set the enclosing type, we are done, no need to walk more decls
                    if (this.enclosingTypeWalkerState._hasSetEnclosingType) {
                        break;
                    }
                }

                if (!this.enclosingTypeWalkerState._hasSetEnclosingType) {
                    // We have started walking enclosing type, but this symbol might be a symbol with declaration that doesnt
                    // have parentDecl, eg. SyntheticDecl of emptyObjectType, in that case we wouldnt have set the flag
                    // _hasSetEnclosingType as path of walking its decls,
                    // so set it now to indicate we have started walking the enclosing type, its not a generic type
                    this.setNonGenericEnclosingTypeWalkerState();
                }
            }
            return currentEnclosingTypeWalkerState;
        };

        // Start walking type
        PullTypeEnclosingTypeWalker.prototype.startWalkingType = function (symbol) {
            var currentState = this.enclosingTypeWalkerState;

            // We want to set the new enclosing type using symbol if we arent already walking any enclosing Type
            // or the symbol itself can be used as new enclosing type as then we want to be walking in the new enclosingType and not the old one.
            // We dont need to set new enclosing type if we are walking signature because they dont declare new enclosing type as the enclosing type
            // can only be class or interface and in case of signature we would have either set it earlier, or would do when we are actually
            // using type reference from parameter/return types
            var setEnclosingTypeForSymbol = !this.enclosingTypeWalkerState._hasSetEnclosingType || this.canSymbolBeUsedAsEnclosingType(symbol);
            if (setEnclosingTypeForSymbol) {
                this.setEnclosingTypeForSymbol(symbol);
            }
            return currentState;
        };

        // Finish walking type
        PullTypeEnclosingTypeWalker.prototype.endWalkingType = function (stateWhenStartedWalkingTypes) {
            this.enclosingTypeWalkerState = stateWhenStartedWalkingTypes;
        };

        // Walk members
        PullTypeEnclosingTypeWalker.prototype.walkMemberType = function (memberName, resolver) {
            if (this._canWalkStructure()) {
                var currentType = this._getCurrentSymbol();
                var memberSymbol = currentType ? resolver._getNamedPropertySymbolOfAugmentedType(memberName, currentType) : null;
                this._pushSymbol(memberSymbol ? memberSymbol.type : null);
            }
        };

        PullTypeEnclosingTypeWalker.prototype.postWalkMemberType = function () {
            if (this._canWalkStructure()) {
                this._popSymbol();
            }
        };

        // Walk signature
        PullTypeEnclosingTypeWalker.prototype.walkSignature = function (kind, index) {
            if (this._canWalkStructure()) {
                var currentType = this._getCurrentSymbol();
                var signatures;
                if (currentType) {
                    if (kind == TypeScript.PullElementKind.CallSignature) {
                        signatures = currentType.getCallSignatures();
                    } else if (kind == TypeScript.PullElementKind.ConstructSignature) {
                        signatures = currentType.getConstructSignatures();
                    } else {
                        signatures = currentType.getIndexSignatures();
                    }
                }

                this._pushSymbol(signatures ? signatures[index] : null);
            }
        };

        PullTypeEnclosingTypeWalker.prototype.postWalkSignature = function () {
            if (this._canWalkStructure()) {
                this._popSymbol();
            }
        };

        PullTypeEnclosingTypeWalker.prototype.walkTypeArgument = function (index) {
            if (this._canWalkStructure()) {
                var typeArgument = null;
                var currentType = this._getCurrentSymbol();
                if (currentType) {
                    var typeArguments = currentType.getTypeArguments();
                    typeArgument = typeArguments ? typeArguments[index] : null;
                }
                this._pushSymbol(typeArgument);
            }
        };

        PullTypeEnclosingTypeWalker.prototype.postWalkTypeArgument = function () {
            if (this._canWalkStructure()) {
                this._popSymbol();
            }
        };

        // Walk type parameter constraint
        PullTypeEnclosingTypeWalker.prototype.walkTypeParameterConstraint = function (index) {
            if (this._canWalkStructure()) {
                var typeParameters;
                var currentSymbol = this._getCurrentSymbol();
                if (currentSymbol) {
                    if (currentSymbol.isSignature()) {
                        typeParameters = currentSymbol.getTypeParameters();
                    } else {
                        TypeScript.Debug.assert(currentSymbol.isType());
                        typeParameters = currentSymbol.getTypeParameters();
                    }
                }
                this._pushSymbol(typeParameters ? typeParameters[index].getConstraint() : null);
            }
        };

        PullTypeEnclosingTypeWalker.prototype.postWalkTypeParameterConstraint = function () {
            if (this._canWalkStructure()) {
                this._popSymbol();
            }
        };

        // Walk return type
        PullTypeEnclosingTypeWalker.prototype.walkReturnType = function () {
            if (this._canWalkStructure()) {
                var currentSignature = this._getCurrentSymbol();
                this._pushSymbol(currentSignature ? currentSignature.returnType : null);
            }
        };

        PullTypeEnclosingTypeWalker.prototype.postWalkReturnType = function () {
            if (this._canWalkStructure()) {
                this._popSymbol();
            }
        };

        // Walk parameter type
        PullTypeEnclosingTypeWalker.prototype.walkParameterType = function (iParam) {
            if (this._canWalkStructure()) {
                var currentSignature = this._getCurrentSymbol();
                this._pushSymbol(currentSignature ? currentSignature.getParameterTypeAtIndex(iParam) : null);
            }
        };
        PullTypeEnclosingTypeWalker.prototype.postWalkParameterType = function () {
            if (this._canWalkStructure()) {
                this._popSymbol();
            }
        };

        // Get both kind of index signatures
        PullTypeEnclosingTypeWalker.prototype.getBothKindOfIndexSignatures = function (resolver, context, includeAugmentedType) {
            if (this._canWalkStructure()) {
                var currentType = this._getCurrentSymbol();
                if (currentType) {
                    return resolver._getBothKindsOfIndexSignatures(currentType, context, includeAugmentedType);
                }
            }
            return null;
        };

        // Walk index signature return type
        PullTypeEnclosingTypeWalker.prototype.walkIndexSignatureReturnType = function (indexSigInfo, useStringIndexSignature, onlySignature) {
            if (this._canWalkStructure()) {
                var indexSig = indexSigInfo ? (useStringIndexSignature ? indexSigInfo.stringSignature : indexSigInfo.numericSignature) : null;
                this._pushSymbol(indexSig);
                if (!onlySignature) {
                    this._pushSymbol(indexSig ? indexSig.returnType : null);
                }
            }
        };

        PullTypeEnclosingTypeWalker.prototype.postWalkIndexSignatureReturnType = function (onlySignature) {
            if (this._canWalkStructure()) {
                if (!onlySignature) {
                    this._popSymbol(); // return type
                }
                this._popSymbol(); // index signature type
            }
        };

        // Reset the state of the enclosing type walker
        PullTypeEnclosingTypeWalker.prototype.resetEnclosingTypeWalkerState = function () {
            var currentState = this.enclosingTypeWalkerState;
            this.setDefaultTypeWalkerState();
            return currentState;
        };

        // Set new state of the enclosing type walker
        PullTypeEnclosingTypeWalker.prototype.setEnclosingTypeWalkerState = function (enclosingTypeWalkerState) {
            if (enclosingTypeWalkerState) {
                this.enclosingTypeWalkerState = enclosingTypeWalkerState;
            } else {
                // This could happend when the context didnt have existing type walker and hence resetEnclosingTypeWalkerState would have
                // saved the state as null, but now that we have walker, we want to set the state as default that is it isnt walking any enclosing type
                this.setDefaultTypeWalkerState();
            }
        };
        // Default state of the enclosingTypeWalker, so we dont end up creating empty states again and again
        PullTypeEnclosingTypeWalker._defaultEnclosingTypeWalkerState = EnclosingTypeWalkerState.getDefaultEnclosingTypeWalkerState();

        // Default state for non genericEnclosingTypeWalker
        PullTypeEnclosingTypeWalker._nonGenericEnclosingTypeWalkerState = EnclosingTypeWalkerState.getNonGenericEnclosingTypeWalkerState();
        return PullTypeEnclosingTypeWalker;
    })();
    TypeScript.PullTypeEnclosingTypeWalker = PullTypeEnclosingTypeWalker;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    var CandidateInferenceInfo = (function () {
        function CandidateInferenceInfo() {
            this.typeParameter = null;
            this._inferredTypeAfterFixing = null;
            this.inferenceCandidates = [];
        }
        CandidateInferenceInfo.prototype.addCandidate = function (candidate) {
            if (!this._inferredTypeAfterFixing) {
                this.inferenceCandidates[this.inferenceCandidates.length] = candidate;
            }
        };

        CandidateInferenceInfo.prototype.isFixed = function () {
            return !!this._inferredTypeAfterFixing;
        };

        CandidateInferenceInfo.prototype.fixTypeParameter = function (resolver, context) {
            var _this = this;
            if (!this._inferredTypeAfterFixing) {
                // November 18, 2013: Section 4.12.2:
                // The inferred type argument for a particular type parameter is the widened form
                // (section 3.9) of the best common type(section 3.10) of a set of candidate types.
                var collection = {
                    getLength: function () {
                        return _this.inferenceCandidates.length;
                    },
                    getTypeAtIndex: function (index) {
                        return _this.inferenceCandidates[index].type;
                    }
                };

                var bestCommonType = resolver.findBestCommonType(null, collection, context);

                // Now widen (per the spec citation above)
                this._inferredTypeAfterFixing = bestCommonType.widenedType(resolver, null, context);
            }
        };
        return CandidateInferenceInfo;
    })();
    TypeScript.CandidateInferenceInfo = CandidateInferenceInfo;

    var TypeArgumentInferenceContext = (function () {
        function TypeArgumentInferenceContext(resolver, context, signatureBeingInferred) {
            this.resolver = resolver;
            this.context = context;
            this.signatureBeingInferred = signatureBeingInferred;
            this.inferenceCache = TypeScript.BitMatrix.getBitMatrix(false);
            this.candidateCache = [];
            var typeParameters = signatureBeingInferred.getTypeParameters();
            for (var i = 0; i < typeParameters.length; i++) {
                this.addInferenceRoot(typeParameters[i]);
            }
        }
        TypeArgumentInferenceContext.prototype.alreadyRelatingTypes = function (objectType, parameterType) {
            if (this.inferenceCache.valueAt(objectType.pullSymbolID, parameterType.pullSymbolID)) {
                return true;
            } else {
                this.inferenceCache.setValueAt(objectType.pullSymbolID, parameterType.pullSymbolID, true);
                return false;
            }
        };

        TypeArgumentInferenceContext.prototype.resetRelationshipCache = function () {
            this.inferenceCache.release();
            this.inferenceCache = TypeScript.BitMatrix.getBitMatrix(false);
        };

        TypeArgumentInferenceContext.prototype.addInferenceRoot = function (param) {
            var info = this.candidateCache[param.pullSymbolID];

            if (!info) {
                info = new CandidateInferenceInfo();
                info.typeParameter = param;
                this.candidateCache[param.pullSymbolID] = info;
            }
        };

        TypeArgumentInferenceContext.prototype.getInferenceInfo = function (param) {
            return this.candidateCache[param.pullSymbolID];
        };

        TypeArgumentInferenceContext.prototype.addCandidateForInference = function (param, candidate) {
            var info = this.getInferenceInfo(param);

            // Add the candidate to the CandidateInferenceInfo for this type parameter
            // only if the candidate is not already present.
            if (info && candidate && info.inferenceCandidates.indexOf(candidate) < 0) {
                info.addCandidate(candidate);
            }
        };

        TypeArgumentInferenceContext.prototype.inferTypeArguments = function () {
            throw TypeScript.Errors.abstract();
        };

        TypeArgumentInferenceContext.prototype.fixTypeParameter = function (typeParameter) {
            var candidateInfo = this.candidateCache[typeParameter.pullSymbolID];
            if (candidateInfo) {
                candidateInfo.fixTypeParameter(this.resolver, this.context);
            }
        };

        TypeArgumentInferenceContext.prototype._finalizeInferredTypeArguments = function () {
            var results = [];
            var typeParameters = this.signatureBeingInferred.getTypeParameters();
            for (var i = 0; i < typeParameters.length; i++) {
                var info = this.candidateCache[typeParameters[i].pullSymbolID];

                info.fixTypeParameter(this.resolver, this.context);

                for (var i = 0; i < results.length; i++) {
                    if (results[i].type === info.typeParameter) {
                        results[i].type = info._inferredTypeAfterFixing;
                    }
                }

                results.push(info._inferredTypeAfterFixing);
            }

            return results;
        };

        TypeArgumentInferenceContext.prototype.isInvocationInferenceContext = function () {
            throw TypeScript.Errors.abstract();
        };
        return TypeArgumentInferenceContext;
    })();
    TypeScript.TypeArgumentInferenceContext = TypeArgumentInferenceContext;

    var InvocationTypeArgumentInferenceContext = (function (_super) {
        __extends(InvocationTypeArgumentInferenceContext, _super);
        function InvocationTypeArgumentInferenceContext(resolver, context, signatureBeingInferred, argumentList) {
            _super.call(this, resolver, context, signatureBeingInferred);
            this.argumentList = argumentList;
        }
        InvocationTypeArgumentInferenceContext.prototype.isInvocationInferenceContext = function () {
            return true;
        };

        InvocationTypeArgumentInferenceContext.prototype.inferTypeArguments = function () {
            var _this = this;
            // Resolve all of the argument ASTs in the callback
            this.signatureBeingInferred.forAllParameterTypes(this.argumentList.arguments.length, function (parameterType, argumentIndex) {
                var argumentAST = _this.argumentList.arguments[argumentIndex];

                _this.context.pushInferentialType(parameterType, _this);
                var argumentType = _this.resolver.resolveAST(argumentAST, true, _this.context).type;
                _this.resolver.relateTypeToTypeParametersWithNewEnclosingTypes(argumentType, parameterType, _this, _this.context);
                _this.context.popAnyContextualType();

                return true;
            });

            return this._finalizeInferredTypeArguments();
        };
        return InvocationTypeArgumentInferenceContext;
    })(TypeArgumentInferenceContext);
    TypeScript.InvocationTypeArgumentInferenceContext = InvocationTypeArgumentInferenceContext;

    var ContextualSignatureInstantiationTypeArgumentInferenceContext = (function (_super) {
        __extends(ContextualSignatureInstantiationTypeArgumentInferenceContext, _super);
        // for the shouldFixContextualSignatureParameterTypes flag, pass true during inferential typing
        // and false during signature relation checking
        function ContextualSignatureInstantiationTypeArgumentInferenceContext(resolver, context, signatureBeingInferred, contextualSignature, shouldFixContextualSignatureParameterTypes) {
            _super.call(this, resolver, context, signatureBeingInferred);
            this.contextualSignature = contextualSignature;
            this.shouldFixContextualSignatureParameterTypes = shouldFixContextualSignatureParameterTypes;
        }
        ContextualSignatureInstantiationTypeArgumentInferenceContext.prototype.isInvocationInferenceContext = function () {
            return false;
        };

        ContextualSignatureInstantiationTypeArgumentInferenceContext.prototype.inferTypeArguments = function () {
            var _this = this;
            // We are in contextual signature instantiation. This callback will be executed
            // for each parameter we are trying to relate in order to infer type arguments.
            var relateTypesCallback = function (parameterTypeBeingInferred, contextualParameterType) {
                if (_this.shouldFixContextualSignatureParameterTypes) {
                    // Need to modify the callback to cause fixing. Per spec section 4.12.2
                    // 4th bullet of inferential typing:
                    // ... then any inferences made for type parameters referenced by the
                    // parameters of T's call signature are fixed
                    // (T here is the contextual signature)
                    contextualParameterType = _this.context.fixAllTypeParametersReferencedByType(contextualParameterType, _this.resolver, _this);
                }
                _this.resolver.relateTypeToTypeParametersWithNewEnclosingTypes(contextualParameterType, parameterTypeBeingInferred, _this, _this.context);

                return true;
            };

            this.signatureBeingInferred.forAllCorrespondingParameterTypesInThisAndOtherSignature(this.contextualSignature, relateTypesCallback);

            return this._finalizeInferredTypeArguments();
        };
        return ContextualSignatureInstantiationTypeArgumentInferenceContext;
    })(TypeArgumentInferenceContext);
    TypeScript.ContextualSignatureInstantiationTypeArgumentInferenceContext = ContextualSignatureInstantiationTypeArgumentInferenceContext;

    var PullContextualTypeContext = (function () {
        function PullContextualTypeContext(contextualType, provisional, isInferentiallyTyping, typeArgumentInferenceContext) {
            this.contextualType = contextualType;
            this.provisional = provisional;
            this.isInferentiallyTyping = isInferentiallyTyping;
            this.typeArgumentInferenceContext = typeArgumentInferenceContext;
            this.provisionallyTypedSymbols = [];
            this.hasProvisionalErrors = false;
            this.astSymbolMap = [];
        }
        PullContextualTypeContext.prototype.recordProvisionallyTypedSymbol = function (symbol) {
            this.provisionallyTypedSymbols[this.provisionallyTypedSymbols.length] = symbol;
        };

        PullContextualTypeContext.prototype.invalidateProvisionallyTypedSymbols = function () {
            for (var i = 0; i < this.provisionallyTypedSymbols.length; i++) {
                this.provisionallyTypedSymbols[i].setUnresolved();
            }
        };

        PullContextualTypeContext.prototype.setSymbolForAST = function (ast, symbol) {
            TypeScript.Debug.assert(!TypeScript.isShared(ast));
            this.astSymbolMap[TypeScript.syntaxID(ast)] = symbol;
        };

        PullContextualTypeContext.prototype.getSymbolForAST = function (ast) {
            return TypeScript.isShared(ast) ? null : this.astSymbolMap[TypeScript.syntaxID(ast)];
        };
        return PullContextualTypeContext;
    })();
    TypeScript.PullContextualTypeContext = PullContextualTypeContext;

    var PullTypeResolutionContext = (function () {
        function PullTypeResolutionContext(resolver, inTypeCheck, fileName) {
            if (typeof inTypeCheck === "undefined") { inTypeCheck = false; }
            if (typeof fileName === "undefined") { fileName = null; }
            this.resolver = resolver;
            this.inTypeCheck = inTypeCheck;
            this.fileName = fileName;
            this.contextStack = [];
            this.typeCheckedNodes = null;
            this.enclosingTypeWalker1 = null;
            this.enclosingTypeWalker2 = null;
            this.inBaseTypeResolution = false;
            if (inTypeCheck) {
                TypeScript.Debug.assert(fileName, "A file name must be provided if you are typechecking");
                this.typeCheckedNodes = TypeScript.BitVector.getBitVector(false);
            }
        }
        PullTypeResolutionContext.prototype.setTypeChecked = function (ast) {
            if (!this.inProvisionalResolution()) {
                this.typeCheckedNodes.setValueAt(TypeScript.syntaxID(ast), true);
            }
        };

        PullTypeResolutionContext.prototype.canTypeCheckAST = function (ast) {
            // If we're in a context where we're type checking, and the ast we're typechecking
            // hasn't been typechecked in this phase yet, *and* the ast is from the file we're
            // currently typechecking, then we can typecheck.
            //
            // If the ast has been typechecked in this phase, then there's no need to typecheck
            // it again.  Also, if it's from another file, there's no need to typecheck it since
            // whatever host we're in will eventually get around to typechecking it.  This is
            // also important as it's very possible to stack overflow when typechecking if we
            // keep jumping around to ISyntaxElement nodes all around a large project.
            return !TypeScript.isShared(ast) && this.typeCheck() && !this.typeCheckedNodes.valueAt(TypeScript.syntaxID(ast)) && this.fileName === TypeScript.syntaxTree(ast).fileName();
        };

        PullTypeResolutionContext.prototype._pushAnyContextualType = function (type, provisional, isInferentiallyTyping, argContext) {
            this.contextStack.push(new PullContextualTypeContext(type, provisional, isInferentiallyTyping, argContext));
        };

        // Use this to push any kind of contextual type if it is NOT propagated inward from a parent
        // contextual type. This corresponds to the first series of bullets in Section 4.19 of the spec.
        PullTypeResolutionContext.prototype.pushNewContextualType = function (type) {
            this._pushAnyContextualType(type, this.inProvisionalResolution(), false, null);
        };

        // Use this when propagating a contextual type from a parent contextual type to a subexpression.
        // This corresponds to the second series of bullets in section 4.19 of the spec.
        PullTypeResolutionContext.prototype.propagateContextualType = function (type) {
            this._pushAnyContextualType(type, this.inProvisionalResolution(), this.isInferentiallyTyping(), this.getCurrentTypeArgumentInferenceContext());
        };

        // Use this if you are trying to infer type arguments.
        PullTypeResolutionContext.prototype.pushInferentialType = function (type, typeArgumentInferenceContext) {
            this._pushAnyContextualType(type, true, true, typeArgumentInferenceContext);
        };

        // Use this if you are trying to choose an overload and are trying a contextual type.
        PullTypeResolutionContext.prototype.pushProvisionalType = function (type) {
            this._pushAnyContextualType(type, true, false, null);
        };

        // Use this to pop any kind of contextual type
        PullTypeResolutionContext.prototype.popAnyContextualType = function () {
            var tc = this.contextStack.pop();

            tc.invalidateProvisionallyTypedSymbols();

            // If the context we just popped off had provisional errors, and we are *still* in a provisional context,
            // we need to not forget that we had provisional errors in a deeper context. We do this by setting the
            // hasProvisioanlErrors flag on the now top context on the stack.
            if (tc.hasProvisionalErrors && this.inProvisionalResolution()) {
                this.contextStack[this.contextStack.length - 1].hasProvisionalErrors = true;
            }

            return tc;
        };

        PullTypeResolutionContext.prototype.hasProvisionalErrors = function () {
            return this.contextStack.length ? this.contextStack[this.contextStack.length - 1].hasProvisionalErrors : false;
        };

        // Gets the current contextual or inferential type
        PullTypeResolutionContext.prototype.getContextualType = function () {
            var context = !this.contextStack.length ? null : this.contextStack[this.contextStack.length - 1];

            if (context) {
                var type = context.contextualType;

                if (!type) {
                    return null;
                }

                return type;
            }

            return null;
        };

        PullTypeResolutionContext.prototype.fixAllTypeParametersReferencedByType = function (type, resolver, argContext) {
            var argContext = this.getCurrentTypeArgumentInferenceContext();
            if (type.wrapsSomeTypeParameter(argContext.candidateCache)) {
                // Build up a type parameter argument map with which we will instantiate this type
                // after fixing type parameters
                var typeParameterArgumentMap = [];

                for (var n in argContext.candidateCache) {
                    var typeParameter = argContext.candidateCache[n] && argContext.candidateCache[n].typeParameter;
                    if (typeParameter) {
                        var dummyMap = [];
                        dummyMap[typeParameter.pullSymbolID] = typeParameter;
                        if (type.wrapsSomeTypeParameter(dummyMap)) {
                            argContext.fixTypeParameter(typeParameter);
                            TypeScript.Debug.assert(argContext.candidateCache[n]._inferredTypeAfterFixing);
                            typeParameterArgumentMap[typeParameter.pullSymbolID] = argContext.candidateCache[n]._inferredTypeAfterFixing;
                        }
                    }
                }

                return resolver.instantiateType(type, typeParameterArgumentMap);
            }

            return type;
        };

        // If we are not in inferential typing, this will return null
        PullTypeResolutionContext.prototype.getCurrentTypeArgumentInferenceContext = function () {
            return this.contextStack.length ? this.contextStack[this.contextStack.length - 1].typeArgumentInferenceContext : null;
        };

        PullTypeResolutionContext.prototype.isInferentiallyTyping = function () {
            return this.contextStack.length > 0 && this.contextStack[this.contextStack.length - 1].isInferentiallyTyping;
        };

        PullTypeResolutionContext.prototype.inProvisionalResolution = function () {
            return (!this.contextStack.length ? false : this.contextStack[this.contextStack.length - 1].provisional);
        };

        PullTypeResolutionContext.prototype.isInBaseTypeResolution = function () {
            return this.inBaseTypeResolution;
        };

        PullTypeResolutionContext.prototype.startBaseTypeResolution = function () {
            var wasInBaseTypeResoltion = this.inBaseTypeResolution;
            this.inBaseTypeResolution = true;
            return wasInBaseTypeResoltion;
        };

        PullTypeResolutionContext.prototype.doneBaseTypeResolution = function (wasInBaseTypeResolution) {
            this.inBaseTypeResolution = wasInBaseTypeResolution;
        };

        PullTypeResolutionContext.prototype.setTypeInContext = function (symbol, type) {
            // if type of symbol was already determined and it is error - do not replace it with something else
            // otherwise it might cause problems in cases like:
            // var bar: foo;
            // class bar {}
            // class foo {}
            // Symbol for variable bar will get created first, then after binding class constructor of class bar conflict will be detected and symbol.type will be set to error.
            // Later after binding type reference 'foo', symbol.type (that is now 'error') will be incorrectly replace with 'foo'.
            // Since this symbol shared between explicit variable declaration and implicit variable for class constructor
            // we now ended up in situation where class constructor for 'baz' is type reference to 'foo' which is wrong.
            if (symbol.type && symbol.type.isError() && !type.isError()) {
                return;
            }
            symbol.type = type;

            if (this.contextStack.length && this.inProvisionalResolution()) {
                this.contextStack[this.contextStack.length - 1].recordProvisionallyTypedSymbol(symbol);
            }
        };

        PullTypeResolutionContext.prototype.postDiagnostic = function (diagnostic) {
            if (diagnostic) {
                if (this.inProvisionalResolution()) {
                    (this.contextStack[this.contextStack.length - 1]).hasProvisionalErrors = true;
                } else if (this.inTypeCheck && this.resolver) {
                    this.resolver.semanticInfoChain.addDiagnostic(diagnostic);
                }
            }
        };

        PullTypeResolutionContext.prototype.typeCheck = function () {
            return this.inTypeCheck && !this.inProvisionalResolution();
        };

        PullTypeResolutionContext.prototype.setSymbolForAST = function (ast, symbol) {
            this.contextStack[this.contextStack.length - 1].setSymbolForAST(ast, symbol);
        };

        PullTypeResolutionContext.prototype.getSymbolForAST = function (ast) {
            for (var i = this.contextStack.length - 1; i >= 0; i--) {
                var typeContext = this.contextStack[i];
                if (!typeContext.provisional) {
                    break;
                }

                var symbol = typeContext.getSymbolForAST(ast);
                if (symbol) {
                    return symbol;
                }
            }

            return null;
        };

        PullTypeResolutionContext.prototype.startWalkingTypes = function (symbol1, symbol2) {
            if (!this.enclosingTypeWalker1) {
                this.enclosingTypeWalker1 = new TypeScript.PullTypeEnclosingTypeWalker(this.resolver.semanticInfoChain);
            }
            var stateWhenStartedWalkingTypes1 = this.enclosingTypeWalker1.startWalkingType(symbol1);
            if (!this.enclosingTypeWalker2) {
                this.enclosingTypeWalker2 = new TypeScript.PullTypeEnclosingTypeWalker(this.resolver.semanticInfoChain);
            }
            var stateWhenStartedWalkingTypes2 = this.enclosingTypeWalker2.startWalkingType(symbol2);
            return {
                stateWhenStartedWalkingTypes1: stateWhenStartedWalkingTypes1,
                stateWhenStartedWalkingTypes2: stateWhenStartedWalkingTypes2
            };
        };

        PullTypeResolutionContext.prototype.endWalkingTypes = function (statesWhenStartedWalkingTypes) {
            this.enclosingTypeWalker1.endWalkingType(statesWhenStartedWalkingTypes.stateWhenStartedWalkingTypes1);
            this.enclosingTypeWalker2.endWalkingType(statesWhenStartedWalkingTypes.stateWhenStartedWalkingTypes2);
        };

        PullTypeResolutionContext.prototype.setEnclosingTypeForSymbols = function (symbol1, symbol2) {
            if (!this.enclosingTypeWalker1) {
                this.enclosingTypeWalker1 = new TypeScript.PullTypeEnclosingTypeWalker(this.resolver.semanticInfoChain);
            }
            var enclosingTypeWalkerState1 = this.enclosingTypeWalker1.setEnclosingTypeForSymbol(symbol1);
            if (!this.enclosingTypeWalker2) {
                this.enclosingTypeWalker2 = new TypeScript.PullTypeEnclosingTypeWalker(this.resolver.semanticInfoChain);
            }
            var enclosingTypeWalkerState2 = this.enclosingTypeWalker2.setEnclosingTypeForSymbol(symbol2);
            return {
                enclosingTypeWalkerState1: enclosingTypeWalkerState1,
                enclosingTypeWalkerState2: enclosingTypeWalkerState2
            };
        };

        PullTypeResolutionContext.prototype.walkMemberTypes = function (memberName) {
            this.enclosingTypeWalker1.walkMemberType(memberName, this.resolver);
            this.enclosingTypeWalker2.walkMemberType(memberName, this.resolver);
        };

        PullTypeResolutionContext.prototype.postWalkMemberTypes = function () {
            this.enclosingTypeWalker1.postWalkMemberType();
            this.enclosingTypeWalker2.postWalkMemberType();
        };

        PullTypeResolutionContext.prototype.walkSignatures = function (kind, index, index2) {
            this.enclosingTypeWalker1.walkSignature(kind, index);
            this.enclosingTypeWalker2.walkSignature(kind, index2 == undefined ? index : index2);
        };

        PullTypeResolutionContext.prototype.postWalkSignatures = function () {
            this.enclosingTypeWalker1.postWalkSignature();
            this.enclosingTypeWalker2.postWalkSignature();
        };

        PullTypeResolutionContext.prototype.walkTypeParameterConstraints = function (index) {
            this.enclosingTypeWalker1.walkTypeParameterConstraint(index);
            this.enclosingTypeWalker2.walkTypeParameterConstraint(index);
        };

        PullTypeResolutionContext.prototype.postWalkTypeParameterConstraints = function () {
            this.enclosingTypeWalker1.postWalkTypeParameterConstraint();
            this.enclosingTypeWalker2.postWalkTypeParameterConstraint();
        };

        PullTypeResolutionContext.prototype.walkTypeArgument = function (index) {
            this.enclosingTypeWalker1.walkTypeArgument(index);
            this.enclosingTypeWalker2.walkTypeArgument(index);
        };

        PullTypeResolutionContext.prototype.postWalkTypeArgument = function () {
            this.enclosingTypeWalker1.postWalkTypeArgument();
            this.enclosingTypeWalker2.postWalkTypeArgument();
        };

        PullTypeResolutionContext.prototype.walkReturnTypes = function () {
            this.enclosingTypeWalker1.walkReturnType();
            this.enclosingTypeWalker2.walkReturnType();
        };

        PullTypeResolutionContext.prototype.postWalkReturnTypes = function () {
            this.enclosingTypeWalker1.postWalkReturnType();
            this.enclosingTypeWalker2.postWalkReturnType();
        };

        PullTypeResolutionContext.prototype.walkParameterTypes = function (iParam) {
            this.enclosingTypeWalker1.walkParameterType(iParam);
            this.enclosingTypeWalker2.walkParameterType(iParam);
        };

        PullTypeResolutionContext.prototype.postWalkParameterTypes = function () {
            this.enclosingTypeWalker1.postWalkParameterType();
            this.enclosingTypeWalker2.postWalkParameterType();
        };

        PullTypeResolutionContext.prototype.getBothKindOfIndexSignatures = function (includeAugmentedType1, includeAugmentedType2) {
            var indexSigs1 = this.enclosingTypeWalker1.getBothKindOfIndexSignatures(this.resolver, this, includeAugmentedType1);
            var indexSigs2 = this.enclosingTypeWalker2.getBothKindOfIndexSignatures(this.resolver, this, includeAugmentedType2);
            return { indexSigs1: indexSigs1, indexSigs2: indexSigs2 };
        };

        PullTypeResolutionContext.prototype.walkIndexSignatureReturnTypes = function (indexSigs, useStringIndexSignature1, useStringIndexSignature2, onlySignature) {
            this.enclosingTypeWalker1.walkIndexSignatureReturnType(indexSigs.indexSigs1, useStringIndexSignature1, onlySignature);
            this.enclosingTypeWalker2.walkIndexSignatureReturnType(indexSigs.indexSigs2, useStringIndexSignature2, onlySignature);
        };

        PullTypeResolutionContext.prototype.postWalkIndexSignatureReturnTypes = function (onlySignature) {
            this.enclosingTypeWalker1.postWalkIndexSignatureReturnType(onlySignature);
            this.enclosingTypeWalker2.postWalkIndexSignatureReturnType(onlySignature);
        };

        PullTypeResolutionContext.prototype.swapEnclosingTypeWalkers = function () {
            var tempEnclosingWalker1 = this.enclosingTypeWalker1;
            this.enclosingTypeWalker1 = this.enclosingTypeWalker2;
            this.enclosingTypeWalker2 = tempEnclosingWalker1;
        };

        PullTypeResolutionContext.prototype.oneOfClassificationsIsInfinitelyExpanding = function () {
            var generativeClassification1 = this.enclosingTypeWalker1.getGenerativeClassification();
            if (generativeClassification1 === 3 /* InfinitelyExpanding */) {
                return true;
            }
            var generativeClassification2 = this.enclosingTypeWalker2.getGenerativeClassification();
            if (generativeClassification2 === 3 /* InfinitelyExpanding */) {
                return true;
            }

            return false;
        };

        PullTypeResolutionContext.prototype.resetEnclosingTypeWalkerStates = function () {
            var enclosingTypeWalkerState1 = this.enclosingTypeWalker1 ? this.enclosingTypeWalker1.resetEnclosingTypeWalkerState() : null;
            var enclosingTypeWalkerState2 = this.enclosingTypeWalker2 ? this.enclosingTypeWalker2.resetEnclosingTypeWalkerState() : null;
            return {
                enclosingTypeWalkerState1: enclosingTypeWalkerState1,
                enclosingTypeWalkerState2: enclosingTypeWalkerState2
            };
        };

        PullTypeResolutionContext.prototype.setEnclosingTypeWalkerStates = function (enclosingTypeWalkerStates) {
            TypeScript.Debug.assert(this.enclosingTypeWalker1 || !enclosingTypeWalkerStates.enclosingTypeWalkerState1);
            if (this.enclosingTypeWalker1) {
                this.enclosingTypeWalker1.setEnclosingTypeWalkerState(enclosingTypeWalkerStates.enclosingTypeWalkerState1);
            }
            TypeScript.Debug.assert(this.enclosingTypeWalker2 || !enclosingTypeWalkerStates.enclosingTypeWalkerState2);
            if (this.enclosingTypeWalker2) {
                this.enclosingTypeWalker2.setEnclosingTypeWalkerState(enclosingTypeWalkerStates.enclosingTypeWalkerState2);
            }
        };
        return PullTypeResolutionContext;
    })();
    TypeScript.PullTypeResolutionContext = PullTypeResolutionContext;
})(TypeScript || (TypeScript = {}));
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    var OverloadApplicabilityStatus;
    (function (OverloadApplicabilityStatus) {
        OverloadApplicabilityStatus[OverloadApplicabilityStatus["NotAssignable"] = 0] = "NotAssignable";
        OverloadApplicabilityStatus[OverloadApplicabilityStatus["AssignableButWithProvisionalErrors"] = 1] = "AssignableButWithProvisionalErrors";
        OverloadApplicabilityStatus[OverloadApplicabilityStatus["AssignableWithNoProvisionalErrors"] = 2] = "AssignableWithNoProvisionalErrors";
        OverloadApplicabilityStatus[OverloadApplicabilityStatus["Subtype"] = 3] = "Subtype";
    })(OverloadApplicabilityStatus || (OverloadApplicabilityStatus = {}));

    var PullAdditionalCallResolutionData = (function () {
        function PullAdditionalCallResolutionData() {
            this.targetSymbol = null;
            this.resolvedSignatures = null;
            this.candidateSignature = null;
            this.actualParametersContextTypeSymbols = null;
            this.diagnosticsFromOverloadResolution = [];
        }
        return PullAdditionalCallResolutionData;
    })();
    TypeScript.PullAdditionalCallResolutionData = PullAdditionalCallResolutionData;

    var PullAdditionalObjectLiteralResolutionData = (function () {
        function PullAdditionalObjectLiteralResolutionData() {
            this.membersContextTypeSymbols = null;
        }
        return PullAdditionalObjectLiteralResolutionData;
    })();
    TypeScript.PullAdditionalObjectLiteralResolutionData = PullAdditionalObjectLiteralResolutionData;

    // A base origin is for inherited members. It points to which base the member was inherited from.
    var MemberWithBaseOrigin = (function () {
        function MemberWithBaseOrigin(memberSymbol, baseOrigin) {
            this.memberSymbol = memberSymbol;
            this.baseOrigin = baseOrigin;
        }
        return MemberWithBaseOrigin;
    })();

    var SignatureWithBaseOrigin = (function () {
        function SignatureWithBaseOrigin(signature, baseOrigin) {
            this.signature = signature;
            this.baseOrigin = baseOrigin;
        }
        return SignatureWithBaseOrigin;
    })();

    var InheritedIndexSignatureInfo = (function () {
        function InheritedIndexSignatureInfo() {
        }
        return InheritedIndexSignatureInfo;
    })();

    var CompilerReservedName;
    (function (CompilerReservedName) {
        CompilerReservedName[CompilerReservedName["_this"] = 1] = "_this";
        CompilerReservedName[CompilerReservedName["_super"] = 2] = "_super";
        CompilerReservedName[CompilerReservedName["arguments"] = 3] = "arguments";
        CompilerReservedName[CompilerReservedName["_i"] = 4] = "_i";
        CompilerReservedName[CompilerReservedName["require"] = 5] = "require";
        CompilerReservedName[CompilerReservedName["exports"] = 6] = "exports";
    })(CompilerReservedName || (CompilerReservedName = {}));

    function getCompilerReservedName(name) {
        var nameText = TypeScript.tokenValueText(name);
        return CompilerReservedName[nameText];
    }

    // The resolver associates types with a given AST
    var PullTypeResolver = (function () {
        function PullTypeResolver(compilationSettings, semanticInfoChain) {
            this.compilationSettings = compilationSettings;
            this.semanticInfoChain = semanticInfoChain;
            this._cachedArrayInterfaceType = null;
            this._cachedNumberInterfaceType = null;
            this._cachedStringInterfaceType = null;
            this._cachedBooleanInterfaceType = null;
            this._cachedObjectInterfaceType = null;
            this._cachedFunctionInterfaceType = null;
            this._cachedIArgumentsInterfaceType = null;
            this._cachedRegExpInterfaceType = null;
            this._cachedAnyTypeArgs = null;
            this.typeCheckCallBacks = [];
            this.postTypeCheckWorkitems = [];
            this._cachedFunctionArgumentsSymbol = null;
            this.assignableCache = TypeScript.BitMatrix.getBitMatrix(true);
            this.subtypeCache = TypeScript.BitMatrix.getBitMatrix(true);
            this.identicalCache = TypeScript.BitMatrix.getBitMatrix(true);
            this.inResolvingOtherDeclsWalker = new TypeScript.PullHelpers.OtherPullDeclsWalker();
        }
        PullTypeResolver.prototype.cachedArrayInterfaceType = function () {
            if (!this._cachedArrayInterfaceType) {
                this._cachedArrayInterfaceType = this.getSymbolFromDeclPath("Array", [], TypeScript.PullElementKind.Interface) || this.semanticInfoChain.emptyTypeSymbol;
            }

            if (!this._cachedArrayInterfaceType.isResolved) {
                this.resolveDeclaredSymbol(this._cachedArrayInterfaceType, new TypeScript.PullTypeResolutionContext(this));
            }

            return this._cachedArrayInterfaceType;
        };

        // Returns the named type for the global Array<T> symbol.  Note that this will be
        // uninstantiated (i.e. it will have type parameters, and not type arguments).
        PullTypeResolver.prototype.getArrayNamedType = function () {
            return this.cachedArrayInterfaceType();
        };

        PullTypeResolver.prototype.cachedNumberInterfaceType = function () {
            if (!this._cachedNumberInterfaceType) {
                this._cachedNumberInterfaceType = this.getSymbolFromDeclPath("Number", [], TypeScript.PullElementKind.Interface) || this.semanticInfoChain.emptyTypeSymbol;
            }

            if (this._cachedNumberInterfaceType && !this._cachedNumberInterfaceType.isResolved) {
                this.resolveDeclaredSymbol(this._cachedNumberInterfaceType, new TypeScript.PullTypeResolutionContext(this));
            }

            return this._cachedNumberInterfaceType;
        };

        PullTypeResolver.prototype.cachedStringInterfaceType = function () {
            if (!this._cachedStringInterfaceType) {
                this._cachedStringInterfaceType = this.getSymbolFromDeclPath("String", [], TypeScript.PullElementKind.Interface) || this.semanticInfoChain.emptyTypeSymbol;
            }

            if (this._cachedStringInterfaceType && !this._cachedStringInterfaceType.isResolved) {
                this.resolveDeclaredSymbol(this._cachedStringInterfaceType, new TypeScript.PullTypeResolutionContext(this));
            }

            return this._cachedStringInterfaceType;
        };

        PullTypeResolver.prototype.cachedBooleanInterfaceType = function () {
            if (!this._cachedBooleanInterfaceType) {
                this._cachedBooleanInterfaceType = this.getSymbolFromDeclPath("Boolean", [], TypeScript.PullElementKind.Interface) || this.semanticInfoChain.emptyTypeSymbol;
            }

            if (this._cachedBooleanInterfaceType && !this._cachedBooleanInterfaceType.isResolved) {
                this.resolveDeclaredSymbol(this._cachedBooleanInterfaceType, new TypeScript.PullTypeResolutionContext(this));
            }

            return this._cachedBooleanInterfaceType;
        };

        PullTypeResolver.prototype.cachedObjectInterfaceType = function () {
            if (!this._cachedObjectInterfaceType) {
                this._cachedObjectInterfaceType = this.getSymbolFromDeclPath("Object", [], TypeScript.PullElementKind.Interface) || this.semanticInfoChain.emptyTypeSymbol;
            }

            if (!this._cachedObjectInterfaceType) {
                this._cachedObjectInterfaceType = this.semanticInfoChain.anyTypeSymbol;
            }

            if (!this._cachedObjectInterfaceType.isResolved) {
                this.resolveDeclaredSymbol(this._cachedObjectInterfaceType, new TypeScript.PullTypeResolutionContext(this));
            }

            return this._cachedObjectInterfaceType;
        };

        PullTypeResolver.prototype.cachedFunctionInterfaceType = function () {
            if (!this._cachedFunctionInterfaceType) {
                this._cachedFunctionInterfaceType = this.getSymbolFromDeclPath("Function", [], TypeScript.PullElementKind.Interface) || this.semanticInfoChain.emptyTypeSymbol;
            }

            if (this._cachedFunctionInterfaceType && !this._cachedFunctionInterfaceType.isResolved) {
                this.resolveDeclaredSymbol(this._cachedFunctionInterfaceType, new TypeScript.PullTypeResolutionContext(this));
            }

            return this._cachedFunctionInterfaceType;
        };

        PullTypeResolver.prototype.cachedIArgumentsInterfaceType = function () {
            if (!this._cachedIArgumentsInterfaceType) {
                this._cachedIArgumentsInterfaceType = this.getSymbolFromDeclPath("IArguments", [], TypeScript.PullElementKind.Interface) || this.semanticInfoChain.emptyTypeSymbol;
            }

            if (this._cachedIArgumentsInterfaceType && !this._cachedIArgumentsInterfaceType.isResolved) {
                this.resolveDeclaredSymbol(this._cachedIArgumentsInterfaceType, new TypeScript.PullTypeResolutionContext(this));
            }

            return this._cachedIArgumentsInterfaceType;
        };

        PullTypeResolver.prototype.cachedRegExpInterfaceType = function () {
            if (!this._cachedRegExpInterfaceType) {
                this._cachedRegExpInterfaceType = this.getSymbolFromDeclPath("RegExp", [], TypeScript.PullElementKind.Interface) || this.semanticInfoChain.emptyTypeSymbol;
            }

            if (this._cachedRegExpInterfaceType && !this._cachedRegExpInterfaceType.isResolved) {
                this.resolveDeclaredSymbol(this._cachedRegExpInterfaceType, new TypeScript.PullTypeResolutionContext(this));
            }

            return this._cachedRegExpInterfaceType;
        };

        PullTypeResolver.prototype.cachedFunctionArgumentsSymbol = function () {
            if (!this._cachedFunctionArgumentsSymbol) {
                this._cachedFunctionArgumentsSymbol = new TypeScript.PullSymbol("arguments", TypeScript.PullElementKind.Variable, this.semanticInfoChain);
                this._cachedFunctionArgumentsSymbol.type = this.cachedIArgumentsInterfaceType() || this.semanticInfoChain.anyTypeSymbol;
                this._cachedFunctionArgumentsSymbol.setResolved();

                var functionArgumentsDecl = new TypeScript.PullSynthesizedDecl("arguments", "arguments", TypeScript.PullElementKind.Parameter, 0 /* None */, null);
                functionArgumentsDecl.setSymbol(this._cachedFunctionArgumentsSymbol, this.semanticInfoChain);
                this._cachedFunctionArgumentsSymbol.addDeclaration(functionArgumentsDecl);
            }

            return this._cachedFunctionArgumentsSymbol;
        };

        // Section 3.8.1: November 18, 2013
        // If T is the primitive type Number, Boolean, or String, the apparent type
        // of T is the augmented form(as defined below) of the global interface type
        // 'Number', 'Boolean', or 'String'.
        // If T is an enum type, the apparent type of T is the augmented form of the
        // global interface type 'Number'.
        // If T is an object type, the apparent type of T is the augmented form of T.
        // If T is a type parameter, the apparent type of T is the augmented form
        // of the base constraint(section 3.4.1) of T.
        // Otherwise, the apparent type of T is T itself.
        PullTypeResolver.prototype.getApparentType = function (type) {
            if (type.isTypeParameter()) {
                var baseConstraint = type.getBaseConstraint(this.semanticInfoChain);
                if (baseConstraint === this.semanticInfoChain.anyTypeSymbol) {
                    // This is not yet in the spec. If a type parameter's base constraint is any
                    // (implicitly or explicitly), its apparent type is {}.
                    return this.semanticInfoChain.emptyTypeSymbol;
                } else {
                    // Don't return. We need to feed the resulting type thru the rest of the method
                    type = baseConstraint;
                }
            }
            if (type.isPrimitive()) {
                if (type === this.semanticInfoChain.numberTypeSymbol) {
                    return this.cachedNumberInterfaceType();
                }
                if (type === this.semanticInfoChain.booleanTypeSymbol) {
                    return this.cachedBooleanInterfaceType();
                }
                if (type === this.semanticInfoChain.stringTypeSymbol) {
                    return this.cachedStringInterfaceType();
                }
                return type;
            }
            if (type.isEnum()) {
                return this.cachedNumberInterfaceType();
            }
            return type;
        };

        PullTypeResolver.prototype.setTypeChecked = function (ast, context) {
            context.setTypeChecked(ast);
        };

        PullTypeResolver.prototype.canTypeCheckAST = function (ast, context) {
            return context.canTypeCheckAST(ast);
        };

        PullTypeResolver.prototype.setSymbolForAST = function (ast, symbol, context) {
            if (context && context.inProvisionalResolution()) {
                // Cache provisionally
                context.setSymbolForAST(ast, symbol);
            } else {
                // Cache globally
                this.semanticInfoChain.setSymbolForAST(ast, symbol);
            }
        };

        PullTypeResolver.prototype.getSymbolForAST = function (ast, context) {
            // Check global cache
            var symbol = this.semanticInfoChain.getSymbolForAST(ast);

            if (!symbol) {
                // Check provisional cache
                if (context && context.inProvisionalResolution()) {
                    symbol = context.getSymbolForAST(ast);
                }
            }

            return symbol;
        };

        PullTypeResolver.prototype.getASTForDecl = function (decl) {
            return this.semanticInfoChain.getASTForDecl(decl);
        };

        PullTypeResolver.prototype.getNewErrorTypeSymbol = function (name) {
            if (typeof name === "undefined") { name = null; }
            return new TypeScript.PullErrorTypeSymbol(this.semanticInfoChain.anyTypeSymbol, name, this.semanticInfoChain);
        };

        PullTypeResolver.prototype.getEnclosingDecl = function (decl) {
            var declPath = decl.getParentPath();

            if (declPath.length > 1 && declPath[declPath.length - 1] === decl) {
                return declPath[declPath.length - 2];
            } else {
                return declPath[declPath.length - 1];
            }
        };

        PullTypeResolver.prototype.getExportedMemberSymbol = function (symbol, parent) {
            if (!(symbol.kind & (TypeScript.PullElementKind.Method | TypeScript.PullElementKind.Property))) {
                var isContainer = (parent.kind & (TypeScript.PullElementKind.Container | TypeScript.PullElementKind.DynamicModule)) !== 0;
                var containerType = !isContainer ? parent.getAssociatedContainerType() : parent;

                if (isContainer && containerType) {
                    if (symbol.anyDeclHasFlag(1 /* Exported */)) {
                        return symbol;
                    }

                    return null;
                }
            }

            return symbol;
        };

        // This is a modification of getMemberSymbol to fall back to Object or Function as necessary
        // November 18th, 2013, Section 3.8.1:
        // The augmented form of an object type T adds to T those members of the global interface type
        // 'Object' that aren?t hidden by members in T. Furthermore, if T has one or more call or
        // construct signatures, the augmented form of T adds to T the members of the global interface
        // type 'Function' that aren?t hidden by members in T.
        // Note: The most convenient way to do this is to have a method on PullTypeSymbol that
        // gives the apparent type. However, this would require synthesizing a new type because
        // almost every type in the system should inherit the properties from Object. It would essentially
        // double the number of type symbols, which would significantly increase memory usage.
        PullTypeResolver.prototype._getNamedPropertySymbolOfAugmentedType = function (symbolName, parent) {
            var memberSymbol = this.getNamedPropertySymbol(symbolName, TypeScript.PullElementKind.SomeValue, parent);
            if (memberSymbol) {
                return memberSymbol;
            }

            // Check if the parent has a call/construct signature, and if so, inherit from Function
            if (this.cachedFunctionInterfaceType() && parent.isFunctionType()) {
                memberSymbol = this.cachedFunctionInterfaceType().findMember(symbolName, true);
                if (memberSymbol) {
                    return memberSymbol;
                }
            }

            // Lastly, check the Object type
            if (this.cachedObjectInterfaceType()) {
                return this.cachedObjectInterfaceType().findMember(symbolName, true);
            }

            return null;
        };

        PullTypeResolver.prototype.getNamedPropertySymbol = function (symbolName, declSearchKind, parent) {
            var member = null;

            if (declSearchKind & TypeScript.PullElementKind.SomeValue) {
                member = parent.findMember(symbolName, true);
            } else if (declSearchKind & TypeScript.PullElementKind.SomeType) {
                member = parent.findNestedType(symbolName);
            } else if (declSearchKind & TypeScript.PullElementKind.SomeContainer) {
                member = parent.findNestedContainer(symbolName);
            }

            if (member) {
                return this.getExportedMemberSymbol(member, parent);
            }

            var containerType = parent.getAssociatedContainerType();

            if (containerType) {
                // If we were searching over the constructor type, we don't want to also search
                // over the class instance type (we only want to consider static fields)
                if (containerType.isClass()) {
                    return null;
                }

                parent = containerType;

                if (declSearchKind & TypeScript.PullElementKind.SomeValue) {
                    member = parent.findMember(symbolName, true);
                } else if (declSearchKind & TypeScript.PullElementKind.SomeType) {
                    member = parent.findNestedType(symbolName);
                } else if (declSearchKind & TypeScript.PullElementKind.SomeContainer) {
                    member = parent.findNestedContainer(symbolName);
                }

                if (member) {
                    return this.getExportedMemberSymbol(member, parent);
                }
            }

            if (parent.kind & TypeScript.PullElementKind.SomeContainer) {
                var typeDeclarations = parent.getDeclarations();
                var childDecls = null;

                for (var j = 0; j < typeDeclarations.length; j++) {
                    childDecls = typeDeclarations[j].searchChildDecls(symbolName, declSearchKind);

                    if (childDecls.length) {
                        member = childDecls[0].getSymbol(this.semanticInfoChain);

                        if (!member) {
                            member = childDecls[0].getSignatureSymbol(this.semanticInfoChain);
                        }
                        return this.getExportedMemberSymbol(member, parent);
                    }

                    // If we were looking  for some type or value, we need to look for alias so we can see if it has associated value or type symbol with it
                    if ((declSearchKind & TypeScript.PullElementKind.SomeType) !== 0 || (declSearchKind & TypeScript.PullElementKind.SomeValue) !== 0) {
                        childDecls = typeDeclarations[j].searchChildDecls(symbolName, TypeScript.PullElementKind.TypeAlias);
                        if (childDecls.length && childDecls[0].kind === TypeScript.PullElementKind.TypeAlias) {
                            var aliasSymbol = this.getExportedMemberSymbol(childDecls[0].getSymbol(this.semanticInfoChain), parent);
                            if (aliasSymbol) {
                                if (!aliasSymbol.isResolved) {
                                    this.resolveDeclaredSymbol(aliasSymbol);
                                }

                                if ((declSearchKind & TypeScript.PullElementKind.SomeType) !== 0) {
                                    // Some type
                                    var typeSymbol = aliasSymbol.getExportAssignedTypeSymbol();
                                    if (typeSymbol) {
                                        return typeSymbol;
                                    }
                                } else {
                                    // Some value
                                    var valueSymbol = aliasSymbol.getExportAssignedValueSymbol();
                                    if (valueSymbol) {
                                        aliasSymbol.setIsUsedAsValue();
                                        return valueSymbol;
                                    }
                                }

                                return aliasSymbol;
                            }
                        }
                    }
                }
            }
        };

        // search for an unqualified symbol name within a given decl path
        PullTypeResolver.prototype.getSymbolFromDeclPath = function (symbolName, declPath, declSearchKind) {
            var _this = this;
            var symbol = null;

            // search backwards through the decl list
            //  - if the decl in question is a function, search its members
            //  - if the decl in question is a module, search the decl then the symbol
            //  - Otherwise, search globally
            var decl = null;
            var childDecls;
            var declSymbol = null;
            var declMembers;
            var pathDeclKind;
            var valDecl = null;
            var kind;
            var instanceSymbol = null;
            var instanceType = null;
            var childSymbol = null;

            // if search kind allows searching for enum members - expand search space to enums
            var allowedContainerDeclKind = TypeScript.PullElementKind.Container | TypeScript.PullElementKind.DynamicModule;
            if (TypeScript.hasFlag(declSearchKind, TypeScript.PullElementKind.EnumMember)) {
                allowedContainerDeclKind |= TypeScript.PullElementKind.Enum;
            }

            var isAcceptableAlias = function (symbol) {
                if (symbol.isAlias()) {
                    _this.resolveDeclaredSymbol(symbol);
                    if (TypeScript.hasFlag(declSearchKind, TypeScript.PullElementKind.SomeContainer)) {
                        if (symbol.assignedContainer() || symbol.getExportAssignedContainerSymbol()) {
                            return true;
                        }
                    } else if (TypeScript.hasFlag(declSearchKind, TypeScript.PullElementKind.SomeType)) {
                        // check if alias points to dynamic module - it should not be returned if type is requested
                        var type = symbol.getExportAssignedTypeSymbol();
                        if (type && type.kind !== TypeScript.PullElementKind.DynamicModule) {
                            return true;
                        }

                        // check if alias points to dynamic module - if should not be returned if type is requested
                        var type = symbol.assignedType();
                        if (type && type.kind !== TypeScript.PullElementKind.DynamicModule) {
                            return true;
                        }
                    } else if (TypeScript.hasFlag(declSearchKind, TypeScript.PullElementKind.SomeValue & ~TypeScript.PullElementKind.EnumMember)) {
                        // if alias is dereferenced to unresolved module - be conservative and treat it as value
                        if (symbol.assignedType() && symbol.assignedType().isError()) {
                            return true;
                        } else if (symbol.assignedValue() || symbol.getExportAssignedValueSymbol()) {
                            return true;
                        } else {
                            // alias is dereferenced to container with existing instance side - return alias
                            var assignedType = symbol.assignedType();
                            if (assignedType && assignedType.isContainer() && assignedType.getInstanceType()) {
                                return true;
                            }

                            // Spec Nov 18:
                            // 11.2.3 Unlike a non-instantiated internal module (section 10.1),
                            // an external module containing only interface types and non-instantiated internal modules still has a module instance associated with it, albeit one with no members.
                            var decls = symbol.getDeclarations();
                            var ast = decls[0].ast();
                            return ast.moduleReference.kind() === 245 /* ExternalModuleReference */;
                        }
                    }
                }

                return false;
            };

            var tryFindAlias = function (decl) {
                var childDecls = decl.searchChildDecls(symbolName, TypeScript.PullElementKind.TypeAlias);

                if (childDecls.length) {
                    var sym = childDecls[0].getSymbol(_this.semanticInfoChain);
                    if (isAcceptableAlias(sym)) {
                        return sym;
                    }
                }
                return null;
            };

            for (var i = declPath.length - 1; i >= 0; i--) {
                decl = declPath[i];
                pathDeclKind = decl.kind;

                if (decl.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock) {
                    return this.semanticInfoChain.anyTypeSymbol;
                }

                // Specification May 7, 2014 - Section 2.4
                // Note that class and interface members are never directly in scope - they can only be accessed by
                // applying the dot ('.') operator to a class or interface instance. This even includes members of
                // the current instance in a constructor or member function, which are accessed by applying the dot operator to this.
                var inClassOrInterface = TypeScript.hasFlag(pathDeclKind, TypeScript.PullElementKind.Class | TypeScript.PullElementKind.Interface);
                if (inClassOrInterface && TypeScript.hasFlag(declSearchKind, TypeScript.PullElementKind.SomeValue)) {
                    continue;
                }

                if (pathDeclKind & allowedContainerDeclKind) {
                    // first check locally
                    childDecls = decl.searchChildDecls(symbolName, declSearchKind);

                    if (childDecls.length) {
                        return childDecls[0].getSymbol(this.semanticInfoChain);
                    }

                    var alias = tryFindAlias(decl);
                    if (alias) {
                        return alias;
                    }

                    if (declSearchKind & TypeScript.PullElementKind.SomeValue) {
                        // search "split" exported members
                        instanceSymbol = decl.getSymbol(this.semanticInfoChain).getInstanceSymbol();

                        if (instanceSymbol) {
                            instanceType = instanceSymbol.type;

                            childSymbol = this.getNamedPropertySymbol(symbolName, declSearchKind, instanceType);

                            // Make sure we are not picking up a static from a class (it is never in scope)
                            if (childSymbol && (childSymbol.kind & declSearchKind) && !childSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.Static)) {
                                return childSymbol;
                            }
                        }

                        valDecl = decl.getValueDecl();

                        if (valDecl) {
                            decl = valDecl;
                        }
                    }

                    // otherwise, check the members
                    declSymbol = decl.getSymbol(this.semanticInfoChain).type;

                    var childSymbol = this.getNamedPropertySymbol(symbolName, declSearchKind, declSymbol);

                    if (childSymbol && (childSymbol.kind & declSearchKind) && !childSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.Static)) {
                        return childSymbol;
                    }
                } else {
                    var candidateSymbol = null;

                    // If the decl is a function expression, we still want to check its children since it may be shadowed by one
                    // of its parameters
                    if (pathDeclKind === TypeScript.PullElementKind.FunctionExpression && symbolName === decl.getFunctionExpressionName()) {
                        candidateSymbol = decl.getSymbol(this.semanticInfoChain);
                    }

                    childDecls = decl.searchChildDecls(symbolName, declSearchKind);

                    if (childDecls.length) {
                        // if the enclosing decl is a function of some sort, we need to ensure that it's bound
                        // otherwise, the child decl may not be properly bound if it's a parameter (since they're
                        // bound when binding the function symbol)
                        if (decl.kind & TypeScript.PullElementKind.SomeFunction) {
                            decl.ensureSymbolIsBound(this.semanticInfoChain);
                        }
                        return childDecls[0].getSymbol(this.semanticInfoChain);
                    }

                    if (candidateSymbol) {
                        return candidateSymbol;
                    }

                    var alias = tryFindAlias(decl);
                    if (alias) {
                        return alias;
                    }
                }
            }

            // otherwise, search globally
            symbol = this.semanticInfoChain.findSymbol([symbolName], declSearchKind);
            if (symbol) {
                return symbol;
            }

            // if element was not found and we were not searching for aliases- try to find globally defined type alias
            if (!TypeScript.hasFlag(declSearchKind, TypeScript.PullElementKind.TypeAlias)) {
                symbol = this.semanticInfoChain.findSymbol([symbolName], TypeScript.PullElementKind.TypeAlias);
                if (symbol && isAcceptableAlias(symbol)) {
                    return symbol;
                }
            }

            return null;
        };

        PullTypeResolver.prototype.getVisibleDeclsFromDeclPath = function (declPath, declSearchKind) {
            var result = [];
            var decl = null;
            var childDecls;
            var pathDeclKind;

            for (var i = declPath.length - 1; i >= 0; i--) {
                decl = declPath[i];
                pathDeclKind = decl.kind;

                var declKind = decl.kind;

                // First add locals
                // Child decls of classes and interfaces are members, and should only be visible as members of 'this'
                if (declKind !== TypeScript.PullElementKind.Class && declKind !== TypeScript.PullElementKind.Interface) {
                    this.addFilteredDecls(decl.getChildDecls(), declSearchKind, result);
                }

                switch (declKind) {
                    case TypeScript.PullElementKind.Container:
                    case TypeScript.PullElementKind.DynamicModule:
                        // Add members from other instances
                        var otherDecls = this.semanticInfoChain.findDeclsFromPath(declPath.slice(0, i + 1), TypeScript.PullElementKind.SomeContainer);
                        for (var j = 0, m = otherDecls.length; j < m; j++) {
                            var otherDecl = otherDecls[j];
                            if (otherDecl === decl) {
                                continue;
                            }

                            var otherDeclChildren = otherDecl.getChildDecls();
                            for (var k = 0, s = otherDeclChildren.length; k < s; k++) {
                                var otherDeclChild = otherDeclChildren[k];
                                if ((otherDeclChild.flags & 1 /* Exported */) && (otherDeclChild.kind & declSearchKind)) {
                                    result.push(otherDeclChild);
                                }
                            }
                        }

                        break;

                    case TypeScript.PullElementKind.Class:
                    case TypeScript.PullElementKind.Interface:
                        // Add generic types prameters
                        var parameters = decl.getTypeParameters();
                        if (parameters && parameters.length) {
                            this.addFilteredDecls(parameters, declSearchKind, result);
                        }

                        break;

                    case TypeScript.PullElementKind.FunctionExpression:
                        var functionExpressionName = decl.getFunctionExpressionName();
                        if (functionExpressionName) {
                            result.push(decl);
                        }

                    case TypeScript.PullElementKind.Function:
                    case TypeScript.PullElementKind.ConstructorMethod:
                    case TypeScript.PullElementKind.Method:
                        // Add generic types prameters
                        var parameters = decl.getTypeParameters();
                        if (parameters && parameters.length) {
                            this.addFilteredDecls(parameters, declSearchKind, result);
                        }

                        break;
                }
            }

            // Get the global decls
            var topLevelDecls = this.semanticInfoChain.topLevelDecls();
            for (var i = 0, n = topLevelDecls.length; i < n; i++) {
                var topLevelDecl = topLevelDecls[i];
                if (declPath.length > 0 && topLevelDecl.fileName() === declPath[0].fileName()) {
                    continue;
                }

                if (!topLevelDecl.isExternalModule()) {
                    this.addFilteredDecls(topLevelDecl.getChildDecls(), declSearchKind, result);
                }
            }

            return result;
        };

        PullTypeResolver.prototype.addFilteredDecls = function (decls, declSearchKind, result) {
            if (decls.length) {
                for (var i = 0, n = decls.length; i < n; i++) {
                    var decl = decls[i];
                    if (decl.kind & declSearchKind) {
                        result.push(decl);
                    }
                }
            }
        };

        PullTypeResolver.prototype.getVisibleDecls = function (enclosingDecl) {
            var declPath = enclosingDecl.getParentPath();

            var declSearchKind = TypeScript.PullElementKind.SomeType | TypeScript.PullElementKind.SomeContainer | TypeScript.PullElementKind.SomeValue;

            return this.getVisibleDeclsFromDeclPath(declPath, declSearchKind);
        };

        PullTypeResolver.prototype.getVisibleContextSymbols = function (enclosingDecl, context) {
            var contextualTypeSymbol = context.getContextualType();
            if (!contextualTypeSymbol || this.isAnyOrEquivalent(contextualTypeSymbol)) {
                return null;
            }

            var declSearchKind = TypeScript.PullElementKind.SomeType | TypeScript.PullElementKind.SomeContainer | TypeScript.PullElementKind.SomeValue;
            var members = contextualTypeSymbol.getAllMembers(declSearchKind, 2 /* externallyVisible */);

            for (var i = 0; i < members.length; i++) {
                members[i].setUnresolved();
            }

            return members;
        };

        PullTypeResolver.prototype.getVisibleMembersFromExpression = function (expression, enclosingDecl, context) {
            var lhs = this.resolveAST(expression, false, context);

            if (isTypesOnlyLocation(expression) && (lhs.kind === TypeScript.PullElementKind.Class || lhs.kind === TypeScript.PullElementKind.Interface || lhs.kind === TypeScript.PullElementKind.Enum)) {
                // No more sub types in these types
                return null;
            }

            var lhsType = lhs.type;
            if (!lhsType) {
                return null;
            }

            this.resolveDeclaredSymbol(lhsType, context);

            if (lhsType.isContainer() && lhsType.isAlias()) {
                lhsType = lhsType.getExportAssignedTypeSymbol();
            }

            if (this.isAnyOrEquivalent(lhsType)) {
                return null;
            }

            // Figure out if privates are available under the current scope
            var memberVisibilty = 2 /* externallyVisible */;
            var containerSymbol = lhsType;
            if (containerSymbol.kind === TypeScript.PullElementKind.ConstructorType) {
                containerSymbol = containerSymbol.getConstructSignatures()[0].returnType;
            }

            if (containerSymbol && containerSymbol.isClass()) {
                var declPath = enclosingDecl.getParentPath();
                if (declPath && declPath.length) {
                    var declarations = containerSymbol.getDeclarations();
                    for (var i = 0, n = declarations.length; i < n; i++) {
                        var declaration = declarations[i];
                        if (TypeScript.ArrayUtilities.contains(declPath, declaration)) {
                            memberVisibilty = 1 /* internallyVisible */;
                            break;
                        }
                    }
                }
            }

            var declSearchKind = TypeScript.PullElementKind.SomeType | TypeScript.PullElementKind.SomeContainer | TypeScript.PullElementKind.SomeValue;

            var members = [];

            if (lhsType.isContainer()) {
                var exportedAssignedContainerSymbol = lhsType.getExportAssignedContainerSymbol();
                if (exportedAssignedContainerSymbol) {
                    lhsType = exportedAssignedContainerSymbol;
                }
            }

            lhsType = this.getApparentType(lhsType);

            if (!lhsType.isResolved) {
                var potentiallySpecializedType = this.resolveDeclaredSymbol(lhsType, context);

                if (potentiallySpecializedType !== lhsType) {
                    if (!lhs.isType()) {
                        context.setTypeInContext(lhs, potentiallySpecializedType);
                    }

                    lhsType = potentiallySpecializedType;
                }
            }

            members = lhsType.getAllMembers(declSearchKind, memberVisibilty);

            // In order to show all members in type or value positions, query the associated symbol for members
            // on modules.
            if (lhsType.isContainer()) {
                var associatedInstance = lhsType.getInstanceSymbol();
                if (associatedInstance) {
                    var instanceType = associatedInstance.type;
                    this.resolveDeclaredSymbol(instanceType, context);
                    var instanceMembers = instanceType.getAllMembers(declSearchKind, memberVisibilty);
                    members = members.concat(instanceMembers);
                }

                var exportedContainer = lhsType.getExportAssignedContainerSymbol();
                if (exportedContainer) {
                    var exportedContainerMembers = exportedContainer.getAllMembers(declSearchKind, memberVisibilty);
                    members = members.concat(exportedContainerMembers);
                }
            } else if (!lhsType.isConstructor() && !lhsType.isEnum()) {
                var associatedContainerSymbol = lhsType.getAssociatedContainerType();
                if (associatedContainerSymbol) {
                    var containerType = associatedContainerSymbol.type;
                    this.resolveDeclaredSymbol(containerType, context);
                    var containerMembers = containerType.getAllMembers(declSearchKind, memberVisibilty);
                    members = members.concat(containerMembers);
                }
            }

            // could be a function symbol
            if (lhsType.isFunctionType() && this.cachedFunctionInterfaceType()) {
                members = members.concat(this.cachedFunctionInterfaceType().getAllMembers(declSearchKind, 2 /* externallyVisible */));
            }

            return members;
        };

        PullTypeResolver.prototype.isAnyOrEquivalent = function (type) {
            return (type === this.semanticInfoChain.anyTypeSymbol) || type.isError();
        };

        PullTypeResolver.prototype.resolveExternalModuleReference = function (idText, currentFileName) {
            var originalIdText = idText;
            var symbol = null;

            if (TypeScript.isRelative(originalIdText)) {
                // Find the module relative to current file
                var path = TypeScript.getRootFilePath(TypeScript.switchToForwardSlashes(currentFileName));
                symbol = this.semanticInfoChain.findExternalModule(path + idText);
            } else {
                idText = originalIdText;

                // Search in global context if there exists ambient module
                symbol = this.semanticInfoChain.findAmbientExternalModuleInGlobalContext(TypeScript.quoteStr(originalIdText));

                if (!symbol) {
                    // REVIEW: Technically, we shouldn't have to normalize here - we should normalize in addUnit.
                    // Still, normalizing here alows any language services to be free of assumptions
                    var path = TypeScript.getRootFilePath(TypeScript.switchToForwardSlashes(currentFileName));

                    while (symbol === null && path != "") {
                        symbol = this.semanticInfoChain.findExternalModule(path + idText);
                        if (symbol === null) {
                            if (path === '/') {
                                path = '';
                            } else {
                                path = TypeScript.normalizePath(path + "..");
                                path = path && path != '/' ? path + '/' : path;
                            }
                        }
                    }
                }
            }

            return symbol;
        };

        // PULLTODO: VERY IMPORTANT
        // Right now, the assumption is that the declaration's parse tree is still in memory
        // we need to add a cache-in/cache-out mechanism so that we can break the dependency on in-memory ASTs
        PullTypeResolver.prototype.resolveDeclaredSymbol = function (symbol, context) {
            if (!symbol || symbol.isResolved || symbol.isTypeReference()) {
                return symbol;
            }

            if (!context) {
                context = new TypeScript.PullTypeResolutionContext(this);
            }

            return this.resolveDeclaredSymbolWorker(symbol, context);
        };

        PullTypeResolver.prototype.resolveDeclaredSymbolWorker = function (symbol, context) {
            if (!symbol || symbol.isResolved) {
                return symbol;
            }

            if (symbol.inResolution) {
                if (!symbol.type && !symbol.isType()) {
                    symbol.type = this.semanticInfoChain.anyTypeSymbol;
                }

                return symbol;
            }

            var decls = symbol.getDeclarations();

            for (var i = 0; i < decls.length; i++) {
                var decl = decls[i];

                var ast = this.semanticInfoChain.getASTForDecl(decl);

                // if it's an object literal member, just return the symbol and wait for
                // the object lit to be resolved
                if (!ast || (ast.kind() === 139 /* GetAccessor */ && ast.parent.parent.kind() === 215 /* ObjectLiteralExpression */) || (ast.kind() === 140 /* SetAccessor */ && ast.parent.parent.kind() === 215 /* ObjectLiteralExpression */)) {
                    // We'll return the cached results, and let the decl be corrected on the next invalidation
                    return symbol;
                }

                // There are a few places where an identifier may represent the declaration of
                // a symbol.  They include:
                // A catch variable.  i.e.:  catch (e) { ...
                if (ast.parent && ast.parent.kind() === 236 /* CatchClause */ && ast.parent.identifier === ast) {
                    return symbol;
                }

                // A simple arrow parameter.  i.e.:   a => ...
                if (ast.parent && ast.parent.kind() === 219 /* SimpleArrowFunctionExpression */ && ast.parent.parameter === ast) {
                    return symbol;
                }

                // One of the names in a module declaration.  i.e.:  module A.B.C { ...
                // If our decl points at a single name of a module, then just resolve that individual module.
                var enclosingModule = TypeScript.ASTHelpers.getModuleDeclarationFromNameAST(ast);
                var resolvedSymbol;
                if (enclosingModule) {
                    resolvedSymbol = this.resolveSingleModuleDeclaration(enclosingModule, ast, context);
                } else if (ast.kind() === 120 /* SourceUnit */ && decl.kind === TypeScript.PullElementKind.DynamicModule) {
                    // Otherwise, if we have a decl for the top level external module, then just resolve that
                    // specific module.
                    resolvedSymbol = this.resolveModuleSymbol(decl.getSymbol(this.semanticInfoChain), context, null, null, ast);
                } else {
                    // This assert is here to catch potential stack overflows. There have been infinite recursions resulting
                    // from one of these decls pointing to a name expression.
                    TypeScript.Debug.assert(ast.kind() !== 11 /* IdentifierName */ && ast.kind() !== 212 /* MemberAccessExpression */);
                    resolvedSymbol = this.resolveAST(ast, false, context);
                }

                // if the symbol is a parameter property referenced in an out-of-order fashion, it may not have been resolved
                // along with the original property, so we need to "fix" its type here
                if (decl.kind === TypeScript.PullElementKind.Parameter && !symbol.isResolved && !symbol.type && resolvedSymbol && symbol.anyDeclHasFlag(TypeScript.PullElementFlags.PropertyParameter | TypeScript.PullElementFlags.ConstructorParameter)) {
                    symbol.type = resolvedSymbol.type;
                    symbol.setResolved();
                }
            }

            if (!symbol.isResolved) {
                TypeScript.Debug.assert(!symbol.inResolution);

                // All declarations are resolved there is nothing to do any more
                symbol.setResolved();
            }

            return symbol;
        };

        PullTypeResolver.prototype.resolveOtherDecl = function (otherDecl, context) {
            var astForOtherDecl = this.getASTForDecl(otherDecl);
            var moduleDecl = TypeScript.ASTHelpers.getModuleDeclarationFromNameAST(astForOtherDecl);
            if (moduleDecl) {
                this.resolveSingleModuleDeclaration(moduleDecl, astForOtherDecl, context);
            } else {
                this.resolveAST(astForOtherDecl, false, context);
            }
        };

        PullTypeResolver.prototype.resolveOtherDeclarations = function (astName, context) {
            var _this = this;
            var resolvedDecl = this.semanticInfoChain.getDeclForAST(astName);
            var symbol = resolvedDecl.getSymbol(this.semanticInfoChain);

            var allDecls = symbol.getDeclarations();
            this.inResolvingOtherDeclsWalker.walkOtherPullDecls(resolvedDecl, symbol.getDeclarations(), function (otherDecl) {
                return _this.resolveOtherDecl(otherDecl, context);
            });
        };

        PullTypeResolver.prototype.resolveSourceUnit = function (sourceUnit, context) {
            // Ensure that any export assignments are resolved before we proceed.
            var enclosingDecl = this.getEnclosingDeclForAST(sourceUnit);
            var moduleSymbol = enclosingDecl.getSymbol(this.semanticInfoChain);
            this.ensureAllSymbolsAreBound(moduleSymbol);

            this.resolveFirstExportAssignmentStatement(sourceUnit.moduleElements, context);
            this.resolveAST(sourceUnit.moduleElements, false, context);

            if (this.canTypeCheckAST(sourceUnit, context)) {
                this.typeCheckSourceUnit(sourceUnit, context);
            }

            return moduleSymbol;
        };

        PullTypeResolver.prototype.typeCheckSourceUnit = function (sourceUnit, context) {
            var _this = this;
            this.setTypeChecked(sourceUnit, context);
            this.checkForDisallowedExports(sourceUnit.moduleElements);
            this.checkForMultipleExportAssignments(sourceUnit.moduleElements);
            this.checkFunctionOverloadChains(sourceUnit, sourceUnit.moduleElements);

            this.resolveAST(sourceUnit.moduleElements, false, context);

            this.typeCheckCallBacks.push(function (context) {
                return _this.verifyUniquenessOfImportNamesInSourceUnit(sourceUnit);
            });
        };

        PullTypeResolver.prototype.verifyUniquenessOfImportNamesInSourceUnit = function (sourceUnit) {
            var _this = this;
            var enclosingDecl = this.semanticInfoChain.getDeclForAST(sourceUnit);

            var doesImportNameExistInOtherFiles = function (name) {
                var importSymbol = _this.semanticInfoChain.findTopLevelSymbol(name, TypeScript.PullElementKind.TypeAlias, null);
                return importSymbol && importSymbol.isAlias();
            };

            this.checkUniquenessOfImportNames([enclosingDecl], doesImportNameExistInOtherFiles);
        };

        PullTypeResolver.prototype.resolveEnumDeclaration = function (ast, context) {
            var containerDecl = this.semanticInfoChain.getDeclForAST(ast);
            var containerSymbol = containerDecl.getSymbol(this.semanticInfoChain);

            if (containerSymbol.isResolved || containerSymbol.inResolution) {
                return containerSymbol;
            }

            containerSymbol.inResolution = true;

            var containerDecls = containerSymbol.getDeclarations();

            for (var i = 0; i < containerDecls.length; i++) {
                var childDecls = containerDecls[i].getChildDecls();

                for (var j = 0; j < childDecls.length; j++) {
                    childDecls[j].ensureSymbolIsBound(this.semanticInfoChain);
                }
            }

            containerSymbol.setResolved();

            this.resolveOtherDeclarations(ast, context);

            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckEnumDeclaration(ast, context);
            }

            return containerSymbol;
        };

        PullTypeResolver.prototype.typeCheckEnumDeclaration = function (ast, context) {
            var _this = this;
            this.setTypeChecked(ast, context);

            this.checkForReservedName(ast, ast.identifier, TypeScript.DiagnosticCode.Enum_name_cannot_be_0);

            this.resolveAST(ast.enumElements, false, context);
            var containerDecl = this.semanticInfoChain.getDeclForAST(ast);
            this.validateVariableDeclarationGroups(containerDecl, context);

            this.typeCheckCallBacks.push(function (context) {
                return _this.checkInitializersInEnumDeclarations(containerDecl, context);
            });

            if (!TypeScript.ASTHelpers.enumIsElided(ast)) {
                this.checkNameForCompilerGeneratedDeclarationCollision(ast, true, ast.identifier, context);
            }
        };

        PullTypeResolver.prototype.postTypeCheckEnumDeclaration = function (ast, context) {
            this.checkThisCaptureVariableCollides(ast, true, context);
        };

        PullTypeResolver.prototype.checkInitializersInEnumDeclarations = function (decl, context) {
            var symbol = decl.getSymbol(this.semanticInfoChain);

            // check should be executed just once so run it only for one decl
            var declarations = symbol.getDeclarations();
            if (decl !== declarations[0]) {
                return;
            }

            // SPEC: NOV 18
            // It isn?t possible for one enum declaration to continue the automatic numbering sequence of another,
            // and when an enum type has multiple declarations, only one declaration is permitted to omit a value for the first member.
            var seenEnumDeclWithNoFirstMember = false;
            for (var i = 0; i < declarations.length; ++i) {
                var currentDecl = declarations[i];

                var ast = currentDecl.ast();
                if (ast.enumElements.length === 0) {
                    continue;
                }

                var firstVariable = ast.enumElements[0];
                if (!firstVariable.equalsValueClause) {
                    if (!seenEnumDeclWithNoFirstMember) {
                        seenEnumDeclWithNoFirstMember = true;
                    } else {
                        this.semanticInfoChain.addDiagnosticFromAST(firstVariable, TypeScript.DiagnosticCode.In_enums_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_the_first_enum_element);
                    }
                }
            }
        };

        //
        // Resolve a module declaration
        //
        PullTypeResolver.prototype.resolveModuleDeclaration = function (ast, context) {
            var result;

            if (ast.stringLiteral) {
                result = this.resolveSingleModuleDeclaration(ast, ast.stringLiteral, context);
            } else {
                var moduleNames = TypeScript.ASTHelpers.getModuleNames(ast.name);
                for (var i = 0, n = moduleNames.length; i < n; i++) {
                    result = this.resolveSingleModuleDeclaration(ast, moduleNames[i], context);
                }
            }

            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckModuleDeclaration(ast, context);
            }

            return result;
        };

        PullTypeResolver.prototype.ensureAllSymbolsAreBound = function (containerSymbol) {
            if (containerSymbol) {
                var containerDecls = containerSymbol.getDeclarations();

                for (var i = 0; i < containerDecls.length; i++) {
                    var childDecls = containerDecls[i].getChildDecls();

                    for (var j = 0; j < childDecls.length; j++) {
                        childDecls[j].ensureSymbolIsBound(this.semanticInfoChain);
                    }
                }
            }
        };

        PullTypeResolver.prototype.resolveModuleSymbol = function (containerSymbol, context, moduleDeclAST, moduleDeclNameAST, sourceUnitAST) {
            if (containerSymbol.isResolved || containerSymbol.inResolution) {
                return containerSymbol;
            }

            containerSymbol.inResolution = true;
            this.ensureAllSymbolsAreBound(containerSymbol);

            var instanceSymbol = containerSymbol.getInstanceSymbol();

            // resolve the instance variable, if neccesary
            if (instanceSymbol) {
                this.resolveDeclaredSymbol(instanceSymbol, context);
            }

            var isLastName = TypeScript.ASTHelpers.isLastNameOfModule(moduleDeclAST, moduleDeclNameAST);
            if (isLastName) {
                this.resolveFirstExportAssignmentStatement(moduleDeclAST.moduleElements, context);
            } else if (sourceUnitAST) {
                this.resolveFirstExportAssignmentStatement(sourceUnitAST.moduleElements, context);
            }

            containerSymbol.setResolved();

            if (moduleDeclNameAST) {
                this.resolveOtherDeclarations(moduleDeclNameAST, context);
            }

            return containerSymbol;
        };

        PullTypeResolver.prototype.resolveFirstExportAssignmentStatement = function (moduleElements, context) {
            for (var i = 0, n = moduleElements.length; i < n; i++) {
                var moduleElement = moduleElements[i];
                if (moduleElement.kind() === 134 /* ExportAssignment */) {
                    this.resolveExportAssignmentStatement(moduleElement, context);
                    return;
                }
            }
        };

        PullTypeResolver.prototype.resolveSingleModuleDeclaration = function (ast, astName, context) {
            var containerDecl = this.semanticInfoChain.getDeclForAST(astName);
            var containerSymbol = containerDecl.getSymbol(this.semanticInfoChain);

            return this.resolveModuleSymbol(containerSymbol, context, ast, astName, null);
        };

        PullTypeResolver.prototype.typeCheckModuleDeclaration = function (ast, context) {
            this.checkForDisallowedExports(ast.moduleElements);
            this.checkForMultipleExportAssignments(ast.moduleElements);

            if (ast.stringLiteral) {
                this.typeCheckSingleModuleDeclaration(ast, ast.stringLiteral, context);
            } else {
                if (!TypeScript.SyntaxUtilities.containsToken(ast.modifiers, 63 /* DeclareKeyword */)) {
                    this.checkFunctionOverloadChains(ast, ast.moduleElements);
                }

                var moduleNames = TypeScript.ASTHelpers.getModuleNames(ast.name);
                for (var i = 0, n = moduleNames.length; i < n; i++) {
                    this.typeCheckSingleModuleDeclaration(ast, moduleNames[i], context);
                }
            }
        };

        PullTypeResolver.prototype.typeCheckSingleModuleDeclaration = function (ast, astName, context) {
            var _this = this;
            this.setTypeChecked(ast, context);

            if (TypeScript.ASTHelpers.isLastNameOfModule(ast, astName)) {
                this.resolveAST(ast.moduleElements, false, context);
            }

            var containerDecl = this.semanticInfoChain.getDeclForAST(astName);
            this.validateVariableDeclarationGroups(containerDecl, context);

            if (ast.stringLiteral) {
                if (TypeScript.isRelative(TypeScript.tokenValueText(ast.stringLiteral))) {
                    this.semanticInfoChain.addDiagnosticFromAST(ast.stringLiteral, TypeScript.DiagnosticCode.Ambient_external_module_declaration_cannot_specify_relative_module_name);
                }
            }

            if (!TypeScript.ASTHelpers.moduleIsElided(ast) && !ast.stringLiteral) {
                this.checkNameForCompilerGeneratedDeclarationCollision(astName, true, astName, context);
            }

            this.typeCheckCallBacks.push(function (context) {
                return _this.verifyUniquenessOfImportNamesInModule(containerDecl);
            });
        };

        PullTypeResolver.prototype.verifyUniquenessOfImportNamesInModule = function (decl) {
            var symbol = decl.getSymbol(this.semanticInfoChain);
            if (!symbol) {
                return;
            }

            var decls = symbol.getDeclarations();

            // this check should be performed once per module.
            // to guarantee this we'll perform check only for one declaration that form the module
            if (decls[0] !== decl) {
                return;
            }

            this.checkUniquenessOfImportNames(decls);
        };

        PullTypeResolver.prototype.checkUniquenessOfImportNames = function (decls, doesNameExistOutside) {
            var _this = this;
            var importDeclarationNames;

            for (var i = 0; i < decls.length; ++i) {
                var childDecls = decls[i].getChildDecls();
                for (var j = 0; j < childDecls.length; ++j) {
                    var childDecl = childDecls[j];
                    if (childDecl.kind === TypeScript.PullElementKind.TypeAlias) {
                        importDeclarationNames = importDeclarationNames || TypeScript.createIntrinsicsObject();
                        importDeclarationNames[childDecl.name] = true;
                    }
                }
            }

            if (!importDeclarationNames && !doesNameExistOutside) {
                return;
            }

            for (var i = 0; i < decls.length; ++i) {
                // Walk over all variable declaration groups located in 'decls[i]',
                // pick the first item from the group and test if it name conflicts with the name of any of import declaration.
                // Taking just first item is enough since all variables in group have the same name
                this.scanVariableDeclarationGroups(decls[i], function (firstDeclInGroup) {
                    // Make sure the variable declaration doesn't conflict with an import declaration.
                    var nameConflict = importDeclarationNames && importDeclarationNames[firstDeclInGroup.name];
                    if (!nameConflict) {
                        nameConflict = doesNameExistOutside && doesNameExistOutside(firstDeclInGroup.name);
                        if (nameConflict) {
                            // save result for name == 'firstDeclInGroup.name' so if we'll see it again the result will be picked from the cache instead of invoking 'doesNameExistOutside' callback.
                            importDeclarationNames = importDeclarationNames || TypeScript.createIntrinsicsObject();
                            importDeclarationNames[firstDeclInGroup.name] = true;
                        }
                    }

                    if (nameConflict) {
                        _this.semanticInfoChain.addDiagnosticFromAST(firstDeclInGroup.ast(), TypeScript.DiagnosticCode.Variable_declaration_cannot_have_the_same_name_as_an_import_declaration);
                    }
                });
            }
        };

        PullTypeResolver.prototype.scanVariableDeclarationGroups = function (enclosingDecl, firstDeclHandler, subsequentDeclHandler) {
            var declGroups = enclosingDecl.getVariableDeclGroups();

            for (var i = 0; i < declGroups.length; i++) {
                var firstSymbol = null;
                var enclosingDeclForFirstSymbol = null;

                if (enclosingDecl.kind === TypeScript.PullElementKind.Script && declGroups[i].length) {
                    var name = declGroups[i][0].name;
                    var candidateSymbol = this.semanticInfoChain.findTopLevelSymbol(name, TypeScript.PullElementKind.Variable, enclosingDecl);
                    if (candidateSymbol) {
                        if (!candidateSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.ImplicitVariable)) {
                            // in case if candidate is declared in lib.d.ts it might not be resolved in IDE scenarios (because of deferred resolution of lib.d.ts)
                            // however we cannot just ignore it since then behavior will be different from command line (where everything is resolved).
                            if (!candidateSymbol.isResolved) {
                                this.resolveDeclaredSymbol(candidateSymbol);
                            }
                            firstSymbol = candidateSymbol;
                        }
                    }
                }

                for (var j = 0; j < declGroups[i].length; j++) {
                    var decl = declGroups[i][j];

                    var name = decl.name;

                    var symbol = decl.getSymbol(this.semanticInfoChain);

                    if (j === 0) {
                        firstDeclHandler(decl);
                        if (!subsequentDeclHandler) {
                            break;
                        }

                        if (!firstSymbol || !firstSymbol.type) {
                            firstSymbol = symbol;
                            continue;
                        }
                    }

                    subsequentDeclHandler(decl, firstSymbol);
                }
            }
        };

        PullTypeResolver.prototype.postTypeCheckModuleDeclaration = function (ast, context) {
            this.checkThisCaptureVariableCollides(ast, true, context);
        };

        PullTypeResolver.prototype.isTypeRefWithoutTypeArgs = function (term) {
            if (term.kind() === 11 /* IdentifierName */) {
                return true;
            } else if (term.kind() === 121 /* QualifiedName */) {
                var binex = term;

                if (binex.right.kind() === 11 /* IdentifierName */) {
                    return true;
                }
            }

            return false;
        };

        PullTypeResolver.prototype.createInstantiatedType = function (type, typeArguments) {
            if (!type.isGeneric()) {
                return type;
            }

            // if the type had previously been instantiated, we want to re-instantiate the type arguments.  Otherwise,
            // we just use the type parameters.  E.g., for
            //      class Foo<T> {
            //          public <U>(p: Foo<U>): void
            //      }
            // For parameter 'p', we'd need to specialize from 'T' to 'U' to 'any', so we'd need to request p's type arguments
            // and not its type parameters
            var typeParameters = type.getTypeArgumentsOrTypeParameters();

            var typeParameterArgumentMap = [];

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameterArgumentMap[typeParameters[i].pullSymbolID] = typeArguments[i] || new TypeScript.PullErrorTypeSymbol(this.semanticInfoChain.anyTypeSymbol, typeParameters[i].name, this.semanticInfoChain);
            }

            return TypeScript.InstantiatedTypeReferenceSymbol.create(this, type, typeParameterArgumentMap);
        };

        //
        // Resolve a reference type (class or interface) type parameters, implements and extends clause, members, call, construct and index signatures
        //
        PullTypeResolver.prototype.resolveReferenceTypeDeclaration = function (classOrInterface, name, heritageClauses, context) {
            var _this = this;
            var typeDecl = this.semanticInfoChain.getDeclForAST(classOrInterface);
            var enclosingDecl = this.getEnclosingDecl(typeDecl);
            var typeDeclSymbol = typeDecl.getSymbol(this.semanticInfoChain);
            var typeDeclIsClass = classOrInterface.kind() === 131 /* ClassDeclaration */;
            var hasVisited = this.getSymbolForAST(classOrInterface, context) !== null;

            if ((typeDeclSymbol.isResolved && hasVisited) || (typeDeclSymbol.inResolution && !context.isInBaseTypeResolution())) {
                return typeDeclSymbol;
            }

            var wasResolving = typeDeclSymbol.inResolution;
            typeDeclSymbol.startResolving();

            // ensure that all members are bound
            var typeRefDecls = typeDeclSymbol.getDeclarations();

            for (var i = 0; i < typeRefDecls.length; i++) {
                var childDecls = typeRefDecls[i].getChildDecls();

                for (var j = 0; j < childDecls.length; j++) {
                    childDecls[j].ensureSymbolIsBound(this.semanticInfoChain);
                }
            }

            // Resolve Type Parameters
            if (!typeDeclSymbol.isResolved) {
                var typeDeclTypeParameters = typeDeclSymbol.getTypeParameters();
                for (var i = 0; i < typeDeclTypeParameters.length; i++) {
                    this.resolveDeclaredSymbol(typeDeclTypeParameters[i], context);
                }
            }

            var wasInBaseTypeResolution = context.startBaseTypeResolution();

            // if it's a "split" interface type, we'll need to consider constituent extends lists separately
            if (!typeDeclIsClass && !hasVisited) {
                typeDeclSymbol.resetKnownBaseTypeCount();
            }

            // Extends list
            var extendsClause = TypeScript.ASTHelpers.getExtendsHeritageClause(heritageClauses);
            if (extendsClause) {
                for (var i = typeDeclSymbol.getKnownBaseTypeCount(); i < extendsClause.typeNames.length; i = typeDeclSymbol.getKnownBaseTypeCount()) {
                    typeDeclSymbol.incrementKnownBaseCount();
                    var parentType = this.resolveTypeReference(extendsClause.typeNames[i], context);

                    if (typeDeclSymbol.isValidBaseKind(parentType, true)) {
                        this.setSymbolForAST(extendsClause.typeNames[i], parentType, null);

                        // Do not add parentType as a base if it already added, or if it will cause a cycle as it already inherits from typeDeclSymbol
                        if (!typeDeclSymbol.hasBase(parentType) && !parentType.hasBase(typeDeclSymbol)) {
                            typeDeclSymbol.addExtendedType(parentType);

                            var specializations = typeDeclSymbol.getKnownSpecializations();

                            for (var j = 0; j < specializations.length; j++) {
                                specializations[j].addExtendedType(parentType);
                            }
                        }
                    } else if (parentType && !this.getSymbolForAST(extendsClause.typeNames[i], context)) {
                        this.setSymbolForAST(extendsClause.typeNames[i], parentType, null);
                    }
                }
            }

            var implementsClause = TypeScript.ASTHelpers.getImplementsHeritageClause(heritageClauses);
            if (implementsClause && typeDeclIsClass) {
                var extendsCount = extendsClause ? extendsClause.typeNames.length : 0;
                for (var i = typeDeclSymbol.getKnownBaseTypeCount(); ((i - extendsCount) >= 0) && ((i - extendsCount) < implementsClause.typeNames.length); i = typeDeclSymbol.getKnownBaseTypeCount()) {
                    typeDeclSymbol.incrementKnownBaseCount();
                    var implementedTypeAST = implementsClause.typeNames[i - extendsCount];
                    var implementedType = this.resolveTypeReference(implementedTypeAST, context);

                    if (typeDeclSymbol.isValidBaseKind(implementedType, false)) {
                        this.setSymbolForAST(implementsClause.typeNames[i - extendsCount], implementedType, null);

                        // Do not add parentType as a base if it already added, or if it will cause a cycle as it already inherits from typeDeclSymbol
                        if (!typeDeclSymbol.hasBase(implementedType) && !implementedType.hasBase(typeDeclSymbol)) {
                            typeDeclSymbol.addImplementedType(implementedType);
                        }
                    } else if (implementedType && !this.getSymbolForAST(implementsClause.typeNames[i - extendsCount], context)) {
                        this.setSymbolForAST(implementsClause.typeNames[i - extendsCount], implementedType, null);
                    }
                }
            }

            context.doneBaseTypeResolution(wasInBaseTypeResolution);

            if (wasInBaseTypeResolution) {
                // Do not resolve members as yet
                typeDeclSymbol.inResolution = false;

                // Store off and resolve the reference type after we've finished checking the file
                // (This way, we'll still properly resolve the type even if its parent was already resolved during
                // base type resolution, making the type otherwise inaccessible).
                this.typeCheckCallBacks.push(function (context) {
                    if (classOrInterface.kind() === 131 /* ClassDeclaration */) {
                        _this.resolveClassDeclaration(classOrInterface, context);
                    } else {
                        _this.resolveInterfaceDeclaration(classOrInterface, context);
                    }
                });

                return typeDeclSymbol;
            }

            this.setSymbolForAST(name, typeDeclSymbol, context);
            this.setSymbolForAST(classOrInterface, typeDeclSymbol, context);

            typeDeclSymbol.setResolved();

            return typeDeclSymbol;
        };

        //
        // Resolve a class declaration
        //
        // A class's implements and extends lists are not pre-bound, so they must be bound here
        // Once bound, we can add the parent type's members to the class
        //
        PullTypeResolver.prototype.resolveClassDeclaration = function (classDeclAST, context) {
            var classDecl = this.semanticInfoChain.getDeclForAST(classDeclAST);
            var classDeclSymbol = classDecl.getSymbol(this.semanticInfoChain);

            if (!classDeclSymbol.isResolved) {
                this.resolveReferenceTypeDeclaration(classDeclAST, classDeclAST.identifier, classDeclAST.heritageClauses, context);

                var constructorMethod = classDeclSymbol.getConstructorMethod();
                var extendedTypes = classDeclSymbol.getExtendedTypes();
                var parentType = extendedTypes.length ? extendedTypes[0] : null;

                if (constructorMethod) {
                    // Need to ensure our constructor type can properly see our parent type's
                    // constructor type before going and resolving our members.
                    if (parentType) {
                        var parentConstructorSymbol = parentType.getConstructorMethod();

                        // this will only be null if we have upstream errors
                        if (parentConstructorSymbol) {
                            var parentConstructorTypeSymbol = parentConstructorSymbol.type;
                            var constructorTypeSymbol = constructorMethod.type;
                            if (!constructorTypeSymbol.hasBase(parentConstructorTypeSymbol)) {
                                constructorTypeSymbol.addExtendedType(parentConstructorTypeSymbol);
                            }
                        }
                    }

                    if (!classDeclSymbol.isResolved) {
                        return classDeclSymbol;
                    }
                }

                this.resolveOtherDeclarations(classDeclAST, context);
            }

            if (this.canTypeCheckAST(classDeclAST, context)) {
                this.typeCheckClassDeclaration(classDeclAST, context);
            }

            return classDeclSymbol;
        };

        PullTypeResolver.prototype.typeCheckTypeParametersOfTypeDeclaration = function (classOrInterface, context) {
            var _this = this;
            var typeParametersList = classOrInterface.kind() == 131 /* ClassDeclaration */ ? classOrInterface.typeParameterList : classOrInterface.typeParameterList;

            if (typeParametersList) {
                var typeDecl = this.semanticInfoChain.getDeclForAST(classOrInterface);
                var typeDeclSymbol = typeDecl.getSymbol(this.semanticInfoChain);

                for (var i = 0; i < typeParametersList.typeParameters.length; i++) {
                    // Resolve the type parameter
                    var typeParameterAST = typeParametersList.typeParameters[i];
                    this.resolveTypeParameterDeclaration(typeParameterAST, context);

                    var typeParameterDecl = this.semanticInfoChain.getDeclForAST(typeParameterAST);
                    var typeParameterSymbol = typeParameterDecl.getSymbol(this.semanticInfoChain);

                    this.checkSymbolPrivacy(typeDeclSymbol, typeParameterSymbol, function (symbol) {
                        return _this.typeParameterOfTypeDeclarationPrivacyErrorReporter(classOrInterface, typeParameterAST, typeParameterSymbol, symbol, context);
                    });
                }
            }
        };

        PullTypeResolver.prototype.typeCheckClassDeclaration = function (classDeclAST, context) {
            this.setTypeChecked(classDeclAST, context);

            this.checkForReservedName(classDeclAST, classDeclAST.identifier, TypeScript.DiagnosticCode.Class_name_cannot_be_0);
            this.checkClassOverloadChains(classDeclAST);

            var classDecl = this.semanticInfoChain.getDeclForAST(classDeclAST);
            var classDeclSymbol = classDecl.getSymbol(this.semanticInfoChain);

            // Add for post typeChecking if we want to verify name collision with _this
            this.checkNameForCompilerGeneratedDeclarationCollision(classDeclAST, true, classDeclAST.identifier, context);
            this.resolveAST(classDeclAST.classElements, false, context);

            this.typeCheckTypeParametersOfTypeDeclaration(classDeclAST, context);
            this.typeCheckBases(classDeclAST, classDeclAST.identifier, classDeclAST.heritageClauses, classDeclSymbol, this.getEnclosingDecl(classDecl), context);

            if (!classDeclSymbol.hasBaseTypeConflict()) {
                this.typeCheckMembersAgainstIndexer(classDeclSymbol, classDecl, context);
            }

            this.checkTypeForDuplicateIndexSignatures(classDeclSymbol);
        };

        PullTypeResolver.prototype.postTypeCheckClassDeclaration = function (classDeclAST, context) {
            this.checkThisCaptureVariableCollides(classDeclAST, true, context);
        };

        PullTypeResolver.prototype.resolveTypeSymbolSignatures = function (typeSymbol, context) {
            // Resolve call, construct and index signatures
            var callSignatures = typeSymbol.getCallSignatures();
            for (var i = 0; i < callSignatures.length; i++) {
                this.resolveDeclaredSymbol(callSignatures[i], context);
            }

            var constructSignatures = typeSymbol.getConstructSignatures();
            for (var i = 0; i < constructSignatures.length; i++) {
                this.resolveDeclaredSymbol(constructSignatures[i], context);
            }

            var indexSignatures = typeSymbol.getIndexSignatures();
            for (var i = 0; i < indexSignatures.length; i++) {
                this.resolveDeclaredSymbol(indexSignatures[i], context);
            }
        };

        PullTypeResolver.prototype.resolveInterfaceDeclaration = function (interfaceDeclAST, context) {
            this.resolveReferenceTypeDeclaration(interfaceDeclAST, interfaceDeclAST.identifier, interfaceDeclAST.heritageClauses, context);

            var interfaceDecl = this.semanticInfoChain.getDeclForAST(interfaceDeclAST);
            var interfaceDeclSymbol = interfaceDecl.getSymbol(this.semanticInfoChain);

            this.resolveTypeSymbolSignatures(interfaceDeclSymbol, context);

            if (interfaceDeclSymbol.isResolved) {
                this.resolveOtherDeclarations(interfaceDeclAST, context);

                if (this.canTypeCheckAST(interfaceDeclAST, context)) {
                    this.typeCheckInterfaceDeclaration(interfaceDeclAST, context);
                }
            }

            return interfaceDeclSymbol;
        };

        PullTypeResolver.prototype.typeCheckInterfaceDeclaration = function (interfaceDeclAST, context) {
            this.setTypeChecked(interfaceDeclAST, context);

            this.checkForReservedName(interfaceDeclAST, interfaceDeclAST.identifier, TypeScript.DiagnosticCode.Interface_name_cannot_be_0);

            var interfaceDecl = this.semanticInfoChain.getDeclForAST(interfaceDeclAST);
            var interfaceDeclSymbol = interfaceDecl.getSymbol(this.semanticInfoChain);

            this.resolveAST(interfaceDeclAST.body.typeMembers, false, context);

            this.typeCheckTypeParametersOfTypeDeclaration(interfaceDeclAST, context);
            this.typeCheckBases(interfaceDeclAST, interfaceDeclAST.identifier, interfaceDeclAST.heritageClauses, interfaceDeclSymbol, this.getEnclosingDecl(interfaceDecl), context);

            if (!interfaceDeclSymbol.hasBaseTypeConflict()) {
                this.typeCheckMembersAgainstIndexer(interfaceDeclSymbol, interfaceDecl, context);
            }

            // Only check for duplicate index signatures once per symbol
            // We check that this interface decl is the last one for this symbol. The reason we don't
            // use the first decl is because in case one decl is in lib.d.ts, the experience is
            // slightly better in the language service because of the order we tend to type check
            // the files in. Lib.d.ts is usually last in the language service, but it contains the
            // first decl. Therefore, picking the last decl will report the error sooner.
            var allInterfaceDecls = interfaceDeclSymbol.getDeclarations();
            if (interfaceDecl === allInterfaceDecls[allInterfaceDecls.length - 1]) {
                this.checkTypeForDuplicateIndexSignatures(interfaceDeclSymbol);
            }

            if (!this.checkInterfaceDeclForIdenticalTypeParameters(interfaceDeclAST, context)) {
                this.semanticInfoChain.addDiagnosticFromAST(interfaceDeclAST.identifier, TypeScript.DiagnosticCode.All_declarations_of_an_interface_must_have_identical_type_parameters);
            }
        };

        // Spec section 7.2:
        // When a generic interface has multiple declarations, all declarations must have identical type parameter lists,
        // i.e.identical type parameter names with identical constraints in identical order.
        PullTypeResolver.prototype.checkInterfaceDeclForIdenticalTypeParameters = function (interfaceDeclAST, context) {
            var interfaceDecl = this.semanticInfoChain.getDeclForAST(interfaceDeclAST);
            var interfaceDeclSymbol = interfaceDecl.getSymbol(this.semanticInfoChain);

            // Only generic symbols need the type parameter verification
            if (!interfaceDeclSymbol.isGeneric()) {
                return true;
            }

            // Verify against the first interface declaration only
            var firstInterfaceDecl = interfaceDeclSymbol.getDeclarations()[0];
            if (firstInterfaceDecl == interfaceDecl) {
                return true;
            }

            var typeParameters = interfaceDecl.getTypeParameters();
            var firstInterfaceDeclTypeParameters = firstInterfaceDecl.getTypeParameters();

            // Type parameter length should match
            if (typeParameters.length != firstInterfaceDeclTypeParameters.length) {
                return false;
            }

            for (var i = 0; i < typeParameters.length; i++) {
                var typeParameter = typeParameters[i];
                var firstInterfaceDeclTypeParameter = firstInterfaceDeclTypeParameters[i];

                // Type parameter names should be identical
                if (typeParameter.name != firstInterfaceDeclTypeParameter.name) {
                    return false;
                }

                var typeParameterSymbol = typeParameter.getSymbol(this.semanticInfoChain);
                var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameter);
                var firstInterfaceDeclTypeParameterAST = this.semanticInfoChain.getASTForDecl(firstInterfaceDeclTypeParameter);

                // Constraint should be present or absent in both the decls
                if (!!typeParameterAST.constraint != !!firstInterfaceDeclTypeParameterAST.constraint) {
                    return false;
                }

                // If the constraint is present, it should be identical
                if (typeParameterAST.constraint) {
                    var typeParameterConstraint = this.resolveAST(typeParameterAST.constraint, false, context);
                    if (!this.typesAreIdenticalWithNewEnclosingTypes(typeParameterConstraint, typeParameterSymbol.getConstraint(), context)) {
                        return false;
                    }
                }
            }

            return true;
        };

        // November 18, 2013: Section 3.7.4:
        // An object type can contain at most one string index signature and one numeric index signature.
        PullTypeResolver.prototype.checkTypeForDuplicateIndexSignatures = function (enclosingTypeSymbol) {
            var indexSignatures = enclosingTypeSymbol.getOwnIndexSignatures();
            var firstStringIndexer = null;
            var firstNumberIndexer = null;
            for (var i = 0; i < indexSignatures.length; i++) {
                var currentIndexer = indexSignatures[i];
                if (currentIndexer.parameters.length > 0) {
                    var currentParameterType = currentIndexer.parameters[0].type;
                    TypeScript.Debug.assert(currentParameterType);
                    if (currentParameterType === this.semanticInfoChain.stringTypeSymbol) {
                        if (firstStringIndexer) {
                            this.semanticInfoChain.addDiagnosticFromAST(currentIndexer.getDeclarations()[0].ast(), TypeScript.DiagnosticCode.Duplicate_string_index_signature, null);
                            return;
                        } else {
                            firstStringIndexer = currentIndexer;
                        }
                    } else if (currentParameterType === this.semanticInfoChain.numberTypeSymbol) {
                        if (firstNumberIndexer) {
                            this.semanticInfoChain.addDiagnosticFromAST(currentIndexer.getDeclarations()[0].ast(), TypeScript.DiagnosticCode.Duplicate_number_index_signature, null);
                            return;
                        } else {
                            firstNumberIndexer = currentIndexer;
                        }
                    }
                }
            }
        };

        PullTypeResolver.prototype.filterSymbol = function (symbol, kind, enclosingDecl, context) {
            if (symbol) {
                if (symbol.kind & kind) {
                    return symbol;
                }

                if (symbol.isAlias()) {
                    this.resolveDeclaredSymbol(symbol, context);

                    var alias = symbol;
                    if (kind & TypeScript.PullElementKind.SomeContainer) {
                        return alias.getExportAssignedContainerSymbol();
                    } else if (kind & TypeScript.PullElementKind.SomeType) {
                        return alias.getExportAssignedTypeSymbol();
                    } else if (kind & TypeScript.PullElementKind.SomeValue) {
                        return alias.getExportAssignedValueSymbol();
                    }
                }
            }
            return null;
        };

        PullTypeResolver.prototype.getMemberSymbolOfKind = function (symbolName, kind, pullTypeSymbol, enclosingDecl, context) {
            var memberSymbol = this.getNamedPropertySymbol(symbolName, kind, pullTypeSymbol);

            // Verify that the symbol is actually of the given kind
            return {
                symbol: this.filterSymbol(memberSymbol, kind, enclosingDecl, context),
                aliasSymbol: memberSymbol && memberSymbol.isAlias() ? memberSymbol : null
            };
        };

        PullTypeResolver.prototype.resolveIdentifierOfInternalModuleReference = function (importDecl, identifier, moduleSymbol, enclosingDecl, context) {
            var rhsName = TypeScript.tokenValueText(identifier);
            if (rhsName.length === 0) {
                return null;
            }

            var moduleTypeSymbol = moduleSymbol.type;
            var memberSymbol = this.getMemberSymbolOfKind(rhsName, TypeScript.PullElementKind.SomeContainer, moduleTypeSymbol, enclosingDecl, context);
            var containerSymbol = memberSymbol.symbol;
            var valueSymbol = null;
            var typeSymbol = null;
            var aliasSymbol = null;

            var acceptableAlias = true;

            if (containerSymbol) {
                acceptableAlias = (containerSymbol.kind & TypeScript.PullElementKind.AcceptableAlias) !== 0;
                aliasSymbol = memberSymbol.aliasSymbol;
            }

            if (!acceptableAlias && containerSymbol && containerSymbol.kind === TypeScript.PullElementKind.TypeAlias) {
                this.resolveDeclaredSymbol(containerSymbol, context);
                var aliasedAssignedValue = containerSymbol.getExportAssignedValueSymbol();
                var aliasedAssignedType = containerSymbol.getExportAssignedTypeSymbol();
                var aliasedAssignedContainer = containerSymbol.getExportAssignedContainerSymbol();

                if (aliasedAssignedValue || aliasedAssignedType || aliasedAssignedContainer) {
                    aliasSymbol = containerSymbol;
                    valueSymbol = aliasedAssignedValue;
                    typeSymbol = aliasedAssignedType;
                    containerSymbol = aliasedAssignedContainer;
                    acceptableAlias = true;
                }
            }

            // check for valid export assignment type (variable, function, class, interface, enum, internal module)
            if (!acceptableAlias) {
                this.semanticInfoChain.addDiagnosticFromAST(identifier, TypeScript.DiagnosticCode.Import_declaration_referencing_identifier_from_internal_module_can_only_be_made_with_variables_functions_classes_interfaces_enums_and_internal_modules);
                return null;
            }

            // if we haven't already gotten a value or type from the alias, look for them now
            if (!valueSymbol) {
                if (moduleTypeSymbol.getInstanceSymbol()) {
                    memberSymbol = this.getMemberSymbolOfKind(rhsName, TypeScript.PullElementKind.SomeValue, moduleTypeSymbol.getInstanceSymbol().type, enclosingDecl, context);
                    valueSymbol = memberSymbol.symbol;
                    if (valueSymbol && memberSymbol.aliasSymbol) {
                        aliasSymbol = memberSymbol.aliasSymbol;
                    }
                }
            }

            if (!typeSymbol) {
                memberSymbol = this.getMemberSymbolOfKind(rhsName, TypeScript.PullElementKind.SomeType, moduleTypeSymbol, enclosingDecl, context);
                typeSymbol = memberSymbol.symbol;
                if (typeSymbol && memberSymbol.aliasSymbol) {
                    aliasSymbol = memberSymbol.aliasSymbol;
                }
            }

            if (!valueSymbol && !typeSymbol && !containerSymbol) {
                this.semanticInfoChain.addDiagnosticFromAST(identifier, TypeScript.DiagnosticCode.Module_0_has_no_exported_member_1, [moduleSymbol.toString(), rhsName]);
                return null;
            }

            if (!typeSymbol && containerSymbol) {
                typeSymbol = containerSymbol;
            }

            return {
                valueSymbol: valueSymbol,
                typeSymbol: typeSymbol,
                containerSymbol: containerSymbol,
                aliasSymbol: aliasSymbol
            };
        };

        PullTypeResolver.prototype.resolveModuleReference = function (importDecl, moduleNameExpr, enclosingDecl, context, declPath) {
            TypeScript.Debug.assert(moduleNameExpr.kind() === 121 /* QualifiedName */ || moduleNameExpr.kind() === 11 /* IdentifierName */ || moduleNameExpr.kind() === 14 /* StringLiteral */, "resolving module reference should always be either name or member reference");

            var moduleSymbol = null;
            var moduleName;

            if (moduleNameExpr.kind() === 121 /* QualifiedName */) {
                var dottedNameAST = moduleNameExpr;

                var moduleContainer = this.resolveModuleReference(importDecl, dottedNameAST.left, enclosingDecl, context, declPath);
                if (moduleContainer) {
                    moduleName = TypeScript.tokenValueText(dottedNameAST.right);

                    // We dont care about setting alias symbol here, because it has to be exported member which would make the import statement to emit anyways
                    moduleSymbol = this.getMemberSymbolOfKind(moduleName, TypeScript.PullElementKind.Container, moduleContainer.type, enclosingDecl, context).symbol;
                    if (!moduleSymbol) {
                        this.semanticInfoChain.addDiagnosticFromAST(dottedNameAST.right, TypeScript.DiagnosticCode.Could_not_find_module_0_in_module_1, [moduleName, moduleContainer.toString()]);
                    }
                }
            } else {
                var valueText = moduleNameExpr.kind() === 11 /* IdentifierName */ ? TypeScript.tokenValueText(moduleNameExpr) : TypeScript.tokenValueText(moduleNameExpr);
                var text = moduleNameExpr.kind() === 11 /* IdentifierName */ ? moduleNameExpr.text() : moduleNameExpr.text();

                if (text.length > 0) {
                    var resolvedModuleNameSymbol = this.getSymbolFromDeclPath(valueText, declPath, TypeScript.PullElementKind.Container);
                    moduleSymbol = this.filterSymbol(resolvedModuleNameSymbol, TypeScript.PullElementKind.Container, enclosingDecl, context);
                    if (moduleSymbol) {
                        // Import declaration isn't contextual so set the symbol and diagnostic message irrespective of the context
                        this.semanticInfoChain.setSymbolForAST(moduleNameExpr, moduleSymbol);
                        if (resolvedModuleNameSymbol.isAlias()) {
                            this.semanticInfoChain.setAliasSymbolForAST(moduleNameExpr, resolvedModuleNameSymbol);
                            var importDeclSymbol = importDecl.getSymbol(this.semanticInfoChain);
                            importDeclSymbol.addLinkedAliasSymbol(resolvedModuleNameSymbol);
                        }
                    } else {
                        this.semanticInfoChain.addDiagnosticFromAST(moduleNameExpr, TypeScript.DiagnosticCode.Unable_to_resolve_module_reference_0, [valueText]);
                    }
                }
            }

            return moduleSymbol;
        };

        PullTypeResolver.prototype.resolveInternalModuleReference = function (importStatementAST, context) {
            // ModuleName or ModuleName.Identifier or ModuleName.ModuleName....Identifier
            var importDecl = this.semanticInfoChain.getDeclForAST(importStatementAST);
            var enclosingDecl = this.getEnclosingDecl(importDecl);

            var moduleReference = importStatementAST.moduleReference;

            var aliasExpr = moduleReference.kind() === 245 /* ExternalModuleReference */ ? moduleReference.stringLiteral : moduleReference.moduleName;

            var declPath = enclosingDecl.getParentPath();
            var aliasedType = null;
            var importDeclSymbol = importDecl.getSymbol(this.semanticInfoChain);

            if (aliasExpr.kind() === 11 /* IdentifierName */ || aliasExpr.kind() === 14 /* StringLiteral */) {
                var moduleSymbol = this.resolveModuleReference(importDecl, aliasExpr, enclosingDecl, context, declPath);
                if (moduleSymbol) {
                    aliasedType = moduleSymbol.type;
                    this.semanticInfoChain.setAliasSymbolForAST(moduleReference, this.semanticInfoChain.getAliasSymbolForAST(aliasExpr));
                    if (aliasedType.anyDeclHasFlag(TypeScript.PullElementFlags.InitializedModule)) {
                        var moduleName = aliasExpr.kind() === 11 /* IdentifierName */ ? TypeScript.tokenValueText(aliasExpr) : TypeScript.tokenValueText(aliasExpr);
                        var valueSymbol = this.getSymbolFromDeclPath(moduleName, declPath, TypeScript.PullElementKind.SomeValue);
                        var instanceSymbol = aliasedType.getInstanceSymbol();

                        // If there is module and it is instantiated, value symbol needs to refer to the module instance symbol
                        if (valueSymbol && (instanceSymbol != valueSymbol || valueSymbol.type === aliasedType)) {
                            var text = aliasExpr.text();
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(aliasExpr, TypeScript.DiagnosticCode.Internal_module_reference_0_in_import_declaration_does_not_reference_module_instance_for_1, [text, moduleSymbol.type.toString(enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null)]));
                        } else {
                            // Set value symbol, type and container setting will be taken care of later using aliasedType
                            importDeclSymbol.setAssignedValueSymbol(valueSymbol);
                        }
                    }
                } else {
                    aliasedType = this.getNewErrorTypeSymbol();
                }
            } else if (aliasExpr.kind() === 121 /* QualifiedName */) {
                var dottedNameAST = aliasExpr;
                var moduleSymbol = this.resolveModuleReference(importDecl, dottedNameAST.left, enclosingDecl, context, declPath);
                if (moduleSymbol) {
                    var identifierResolution = this.resolveIdentifierOfInternalModuleReference(importDecl, dottedNameAST.right, moduleSymbol, enclosingDecl, context);
                    if (identifierResolution) {
                        importDeclSymbol.setAssignedValueSymbol(identifierResolution.valueSymbol);
                        importDeclSymbol.setAssignedTypeSymbol(identifierResolution.typeSymbol);
                        importDeclSymbol.setAssignedContainerSymbol(identifierResolution.containerSymbol);
                        this.semanticInfoChain.setAliasSymbolForAST(moduleReference, identifierResolution.aliasSymbol);
                        return null;
                    }
                }
            }

            if (!aliasedType) {
                // unresolved alias - set error as assigned type
                importDeclSymbol.setAssignedTypeSymbol(this.getNewErrorTypeSymbol());
            }

            return aliasedType;
        };

        PullTypeResolver.prototype.resolveImportDeclaration = function (importStatementAST, context) {
            // internal or external? (Does it matter?)
            var importDecl = this.semanticInfoChain.getDeclForAST(importStatementAST);
            var enclosingDecl = this.getEnclosingDecl(importDecl);
            var importDeclSymbol = importDecl.getSymbol(this.semanticInfoChain);

            var aliasedType = null;

            if (importDeclSymbol.isResolved) {
                return importDeclSymbol;
            }

            importDeclSymbol.startResolving();

            // the alias name may be a string literal, in which case we'll need to convert it to a type
            // reference
            if (importStatementAST.moduleReference.kind() === 245 /* ExternalModuleReference */) {
                // dynamic module name (string literal)
                var modPath = TypeScript.tokenValueText(importStatementAST.moduleReference.stringLiteral);
                var declPath = enclosingDecl.getParentPath();

                aliasedType = this.resolveExternalModuleReference(modPath, importDecl.fileName());

                if (!aliasedType) {
                    var path = importStatementAST.moduleReference.stringLiteral.text();
                    this.semanticInfoChain.addDiagnosticFromAST(importStatementAST, TypeScript.DiagnosticCode.Cannot_find_external_module_0, [path]);
                    aliasedType = this.getNewErrorTypeSymbol();
                }
            } else {
                aliasedType = this.resolveInternalModuleReference(importStatementAST, context);
            }

            if (aliasedType) {
                if (!aliasedType.isContainer()) {
                    this.semanticInfoChain.addDiagnosticFromAST(importStatementAST, TypeScript.DiagnosticCode.Module_cannot_be_aliased_to_a_non_module_type);
                    if (!aliasedType.isError()) {
                        aliasedType = this.getNewErrorTypeSymbol();
                    }
                }

                if (aliasedType.isContainer()) {
                    importDeclSymbol.setAssignedContainerSymbol(aliasedType);
                }
                importDeclSymbol.setAssignedTypeSymbol(aliasedType);

                // Import declaration isn't contextual so set the symbol and diagnostic message irrespective of the context
                this.setSymbolForAST(importStatementAST.moduleReference, aliasedType, null);
            }

            importDeclSymbol.setResolved();

            this.resolveDeclaredSymbol(importDeclSymbol.assignedValue(), context);
            this.resolveDeclaredSymbol(importDeclSymbol.assignedType(), context);
            this.resolveDeclaredSymbol(importDeclSymbol.assignedContainer(), context);

            // these checks should be made after 'resolveDeclaredSymbol' calls.since 'resolveDeclaredSymbol' can set 'assignedValue' to aliasedType
            if (aliasedType && importDeclSymbol.anyDeclHasFlag(1 /* Exported */)) {
                importDeclSymbol.setIsUsedInExportedAlias();

                if (aliasedType.isContainer() && aliasedType.getExportAssignedValueSymbol()) {
                    importDeclSymbol.setIsUsedAsValue();
                }
            }

            if (this.canTypeCheckAST(importStatementAST, context)) {
                this.typeCheckImportDeclaration(importStatementAST, context);
            }

            return importDeclSymbol;
        };

        PullTypeResolver.prototype.typeCheckImportDeclaration = function (importStatementAST, context) {
            var _this = this;
            this.setTypeChecked(importStatementAST, context);

            var importDecl = this.semanticInfoChain.getDeclForAST(importStatementAST);
            var enclosingDecl = this.getEnclosingDecl(importDecl);
            var importDeclSymbol = importDecl.getSymbol(this.semanticInfoChain);

            if (importStatementAST.moduleReference.kind() === 245 /* ExternalModuleReference */) {
                if (this.compilationSettings.noResolve()) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(importStatementAST, TypeScript.DiagnosticCode.Import_declaration_cannot_refer_to_external_module_reference_when_noResolve_option_is_set, null));
                }

                var modPath = TypeScript.tokenValueText(importStatementAST.moduleReference.stringLiteral);
                if (enclosingDecl.kind === TypeScript.PullElementKind.DynamicModule) {
                    var ast = TypeScript.ASTHelpers.getEnclosingModuleDeclaration(this.getASTForDecl(enclosingDecl));
                    if (ast && ast.kind() === 130 /* ModuleDeclaration */) {
                        if (TypeScript.isRelative(modPath)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(importStatementAST, TypeScript.DiagnosticCode.Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name));
                        }
                    }
                }
            }

            var checkPrivacy;
            if (importStatementAST.moduleReference.kind() === 245 /* ExternalModuleReference */) {
                var containerSymbol = importDeclSymbol.getExportAssignedContainerSymbol();
                var container = containerSymbol ? containerSymbol.getContainer() : null;
                if (container && container.kind === TypeScript.PullElementKind.DynamicModule) {
                    checkPrivacy = true;
                }
            } else {
                checkPrivacy = true;
            }

            if (checkPrivacy) {
                // Check if import satisfies type privacy
                var typeSymbol = importDeclSymbol.getExportAssignedTypeSymbol();
                var containerSymbol = importDeclSymbol.getExportAssignedContainerSymbol();
                var valueSymbol = importDeclSymbol.getExportAssignedValueSymbol();

                this.checkSymbolPrivacy(importDeclSymbol, containerSymbol, function (symbol) {
                    var messageCode = TypeScript.DiagnosticCode.Exported_import_declaration_0_is_assigned_container_that_is_or_is_using_inaccessible_module_1;
                    var messageArguments = [importDeclSymbol.getScopedName(enclosingDecl ? enclosingDecl.getSymbol(_this.semanticInfoChain) : null), symbol.getScopedName(enclosingDecl ? enclosingDecl.getSymbol(_this.semanticInfoChain) : null, false, false, true)];
                    context.postDiagnostic(_this.semanticInfoChain.diagnosticFromAST(importStatementAST, messageCode, messageArguments));
                });

                if (typeSymbol !== containerSymbol) {
                    this.checkSymbolPrivacy(importDeclSymbol, typeSymbol, function (symbol) {
                        var messageCode = symbol.isContainer() && !symbol.isEnum() ? TypeScript.DiagnosticCode.Exported_import_declaration_0_is_assigned_type_that_is_using_inaccessible_module_1 : TypeScript.DiagnosticCode.Exported_import_declaration_0_is_assigned_type_that_has_or_is_using_private_type_1;

                        var messageArguments = [importDeclSymbol.getScopedName(enclosingDecl ? enclosingDecl.getSymbol(_this.semanticInfoChain) : null), symbol.getScopedName(enclosingDecl ? enclosingDecl.getSymbol(_this.semanticInfoChain) : null, false, false, true)];
                        context.postDiagnostic(_this.semanticInfoChain.diagnosticFromAST(importStatementAST, messageCode, messageArguments));
                    });
                }

                if (valueSymbol) {
                    this.checkSymbolPrivacy(importDeclSymbol, valueSymbol.type, function (symbol) {
                        var messageCode = symbol.isContainer() && !symbol.isEnum() ? TypeScript.DiagnosticCode.Exported_import_declaration_0_is_assigned_value_with_type_that_is_using_inaccessible_module_1 : TypeScript.DiagnosticCode.Exported_import_declaration_0_is_assigned_value_with_type_that_has_or_is_using_private_type_1;
                        var messageArguments = [importDeclSymbol.getScopedName(enclosingDecl ? enclosingDecl.getSymbol(_this.semanticInfoChain) : null), symbol.getScopedName(enclosingDecl ? enclosingDecl.getSymbol(_this.semanticInfoChain) : null, false, false, true)];
                        context.postDiagnostic(_this.semanticInfoChain.diagnosticFromAST(importStatementAST, messageCode, messageArguments));
                    });
                }
            }

            // Check if there's a name collision with the import's name.  Note: checkNameFor...
            // will do the check in a post typeCheck callback.  This is critical for import
            // statements as we need to know how the import is actually used in order for us to
            // know if there will be a collision or not.  For example, if the import is never used
            // as a value, and is only used as a type, then no collision will occur.
            this.checkNameForCompilerGeneratedDeclarationCollision(importStatementAST, true, importStatementAST.identifier, context);
        };

        PullTypeResolver.prototype.postTypeCheckImportDeclaration = function (importStatementAST, context) {
            var importDecl = this.semanticInfoChain.getDeclForAST(importStatementAST);
            var importSymbol = importDecl.getSymbol(this.semanticInfoChain);

            var isUsedAsValue = importSymbol.isUsedAsValue();
            var hasAssignedValue = importStatementAST.moduleReference.kind() !== 245 /* ExternalModuleReference */ && importSymbol.getExportAssignedValueSymbol() !== null;

            if (isUsedAsValue || hasAssignedValue) {
                this.checkThisCaptureVariableCollides(importStatementAST, true, context);
            }
        };

        PullTypeResolver.prototype.resolveExportAssignmentStatement = function (exportAssignmentAST, context) {
            var id = TypeScript.tokenValueText(exportAssignmentAST.identifier);
            if (id.length === 0) {
                // No point trying to resolve an export assignment without an actual identifier.
                return this.semanticInfoChain.anyTypeSymbol;
            }

            // get the identifier text
            var valueSymbol = null;
            var typeSymbol = null;
            var containerSymbol = null;

            var enclosingDecl = this.getEnclosingDeclForAST(exportAssignmentAST);
            var parentSymbol = enclosingDecl.getSymbol(this.semanticInfoChain);

            if (!parentSymbol.isType() && parentSymbol.isContainer()) {
                // Error
                // Export assignments may only be used at the top-level of external modules
                this.semanticInfoChain.addDiagnosticFromAST(exportAssignmentAST, TypeScript.DiagnosticCode.Export_assignments_may_only_be_used_at_the_top_level_of_external_modules);
                return this.semanticInfoChain.anyTypeSymbol;
            }

            // The Identifier of an export assignment must name a variable, function, class, interface,
            // enum, or internal module declared at the top level in the external module.
            // So look for the id only from this dynamic module
            var declPath = enclosingDecl !== null ? [enclosingDecl] : [];

            containerSymbol = this.getSymbolFromDeclPath(id, declPath, TypeScript.PullElementKind.SomeContainer);

            var acceptableAlias = true;

            if (containerSymbol) {
                acceptableAlias = (containerSymbol.kind & TypeScript.PullElementKind.AcceptableAlias) !== 0;
            }

            if (!acceptableAlias && containerSymbol && containerSymbol.kind === TypeScript.PullElementKind.TypeAlias) {
                this.resolveDeclaredSymbol(containerSymbol, context);

                var aliasSymbol = containerSymbol;
                var aliasedAssignedValue = aliasSymbol.getExportAssignedValueSymbol();
                var aliasedAssignedType = aliasSymbol.getExportAssignedTypeSymbol();
                var aliasedAssignedContainer = aliasSymbol.getExportAssignedContainerSymbol();

                if (aliasedAssignedValue || aliasedAssignedType || aliasedAssignedContainer) {
                    valueSymbol = aliasedAssignedValue;
                    typeSymbol = aliasedAssignedType;
                    containerSymbol = aliasedAssignedContainer;
                    aliasSymbol.setTypeUsedExternally();
                    if (valueSymbol) {
                        aliasSymbol.setIsUsedAsValue();
                    }
                    acceptableAlias = true;
                }
            }

            // check for valid export assignment type (variable, function, class, interface, enum, internal module)
            if (!acceptableAlias) {
                // Error
                // Export assignments may only be made with variables, functions, classes, interfaces, enums and internal modules
                this.semanticInfoChain.addDiagnosticFromAST(exportAssignmentAST, TypeScript.DiagnosticCode.Export_assignments_may_only_be_made_with_variables_functions_classes_interfaces_enums_and_internal_modules);
                return this.semanticInfoChain.voidTypeSymbol;
            }

            // if we haven't already gotten a value or type from the alias, look for them now
            if (!valueSymbol) {
                valueSymbol = this.getSymbolFromDeclPath(id, declPath, TypeScript.PullElementKind.SomeValue);
            }
            if (!typeSymbol) {
                typeSymbol = this.getSymbolFromDeclPath(id, declPath, TypeScript.PullElementKind.SomeType);
            }

            if (!valueSymbol && !typeSymbol && !containerSymbol) {
                // Error
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(exportAssignmentAST, TypeScript.DiagnosticCode.Cannot_find_name_0, [id]));
                return this.semanticInfoChain.voidTypeSymbol;
            }

            if (valueSymbol) {
                parentSymbol.setExportAssignedValueSymbol(valueSymbol);
            }
            if (typeSymbol) {
                parentSymbol.setExportAssignedTypeSymbol(typeSymbol);
            }
            if (containerSymbol) {
                parentSymbol.setExportAssignedContainerSymbol(containerSymbol);
            }

            this.resolveDeclaredSymbol(valueSymbol, context);
            this.resolveDeclaredSymbol(typeSymbol, context);
            this.resolveDeclaredSymbol(containerSymbol, context);

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveAnyFunctionTypeSignature = function (funcDeclAST, typeParameters, parameterList, returnTypeAnnotation, context) {
            var functionDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
            TypeScript.Debug.assert(functionDecl);

            var funcDeclSymbol = functionDecl.getSymbol(this.semanticInfoChain);

            var signature = funcDeclSymbol.kind === TypeScript.PullElementKind.ConstructorType ? funcDeclSymbol.getConstructSignatures()[0] : funcDeclSymbol.getCallSignatures()[0];

            // resolve the return type annotation
            if (returnTypeAnnotation) {
                signature.returnType = this.resolveTypeReference(returnTypeAnnotation, context);
            }

            if (typeParameters) {
                for (var i = 0; i < typeParameters.typeParameters.length; i++) {
                    this.resolveTypeParameterDeclaration(typeParameters.typeParameters[i], context);
                }
            }

            // link parameters and resolve their annotations
            if (parameterList) {
                for (var i = 0; i < parameterList.parameters.length; i++) {
                    this.resolveFunctionTypeSignatureParameter(parameterList.parameters[i], signature, functionDecl, context);
                }
            }

            funcDeclSymbol.setResolved();

            if (this.canTypeCheckAST(funcDeclAST, context)) {
                this.setTypeChecked(funcDeclAST, context);
                this.typeCheckFunctionOverloads(funcDeclAST, context);
            }

            return funcDeclSymbol;
        };

        PullTypeResolver.prototype.resolveFunctionTypeSignatureParameter = function (argDeclAST, signature, enclosingDecl, context) {
            var paramDecl = this.semanticInfoChain.getDeclForAST(argDeclAST);
            var paramSymbol = paramDecl.getSymbol(this.semanticInfoChain);

            if (argDeclAST.typeAnnotation) {
                var typeRef = this.resolveTypeReference(argDeclAST.typeAnnotation.type, context);

                if (paramSymbol.isVarArg && !typeRef.isArrayNamedTypeReference()) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.A_rest_parameter_must_be_of_an_array_type));
                    typeRef = this.getNewErrorTypeSymbol();
                }

                context.setTypeInContext(paramSymbol, typeRef);
            } else {
                if (paramSymbol.isVarArg) {
                    if (this.cachedArrayInterfaceType()) {
                        context.setTypeInContext(paramSymbol, this.createInstantiatedType(this.cachedArrayInterfaceType(), [this.semanticInfoChain.anyTypeSymbol]));
                    } else {
                        context.setTypeInContext(paramSymbol, this.semanticInfoChain.anyTypeSymbol);
                    }
                } else {
                    context.setTypeInContext(paramSymbol, this.semanticInfoChain.anyTypeSymbol);
                }

                // if the noImplicitAny flag is set to be true, report an error
                if (this.compilationSettings.noImplicitAny()) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.Parameter_0_of_function_type_implicitly_has_an_any_type, [argDeclAST.identifier.text()]));
                }
            }

            if (TypeScript.hasFlag(paramDecl.flags, TypeScript.PullElementFlags.Optional) && argDeclAST.equalsValueClause && isTypesOnlyLocation(argDeclAST)) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation));
            }

            this.typeCheckParameterModifiers(argDeclAST, context);

            paramSymbol.setResolved();
        };

        PullTypeResolver.prototype.resolveFunctionExpressionParameter = function (argDeclAST, contextParam, enclosingDecl, context) {
            var paramDecl = this.semanticInfoChain.getDeclForAST(argDeclAST);
            var paramSymbol = paramDecl.getSymbol(this.semanticInfoChain);
            var contextualType = contextParam && contextParam.type;
            var isImplicitAny = false;

            if (argDeclAST.typeAnnotation) {
                var typeRef = this.resolveTypeReference(argDeclAST.typeAnnotation.type, context);

                if (paramSymbol.isVarArg && !typeRef.isArrayNamedTypeReference()) {
                    var diagnostic = context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.A_rest_parameter_must_be_of_an_array_type));
                    typeRef = this.getNewErrorTypeSymbol();
                }

                // The contextual type now gets overriden by the type annotation
                contextualType = typeRef || contextualType;
            }
            if (contextualType) {
                // November 18, 2013, Section 4.12.2:
                // When a function expression is inferentially typed (section 4.9.3) and a type assigned
                // to a parameter in that expression references type parameters for which inferences are
                // being made, the corresponding inferred type arguments to become fixed and no further
                // candidate inferences are made for them.
                if (context.isInferentiallyTyping()) {
                    contextualType = context.fixAllTypeParametersReferencedByType(contextualType, this);
                }
                context.setTypeInContext(paramSymbol, contextualType);
            } else if (paramSymbol.isVarArg) {
                if (this.cachedArrayInterfaceType()) {
                    context.setTypeInContext(paramSymbol, this.createInstantiatedType(this.cachedArrayInterfaceType(), [this.semanticInfoChain.anyTypeSymbol]));
                } else {
                    context.setTypeInContext(paramSymbol, this.semanticInfoChain.anyTypeSymbol);
                }
                isImplicitAny = true;
            }

            // Resolve the function expression parameter init only if we have contexual type to evaluate the expression in or we are in typeCheck
            var canTypeCheckAST = this.canTypeCheckAST(argDeclAST, context);
            if (argDeclAST.equalsValueClause && (canTypeCheckAST || !contextualType)) {
                if (contextualType) {
                    context.propagateContextualType(contextualType);
                }

                var initExprSymbol = this.resolveAST(argDeclAST.equalsValueClause, contextualType !== null, context);

                if (contextualType) {
                    context.popAnyContextualType();
                }

                if (!initExprSymbol || !initExprSymbol.type) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.Unable_to_resolve_type_of_0, [argDeclAST.identifier.text()]));

                    if (!contextualType) {
                        context.setTypeInContext(paramSymbol, this.getNewErrorTypeSymbol(paramSymbol.name));
                    }
                } else {
                    var initTypeSymbol = this.getInstanceTypeForAssignment(argDeclAST, initExprSymbol.type, context);
                    if (!contextualType) {
                        // Set the type to the inferred initializer type
                        context.setTypeInContext(paramSymbol, initTypeSymbol.widenedType(this, argDeclAST.equalsValueClause, context));
                        isImplicitAny = initTypeSymbol !== paramSymbol.type;
                    } else {
                        var comparisonInfo = new TypeComparisonInfo();

                        var isAssignable = this.sourceIsAssignableToTarget(initTypeSymbol, contextualType, argDeclAST, context, comparisonInfo);

                        if (!isAssignable) {
                            var enclosingSymbol = this.getEnclosingSymbolForAST(argDeclAST);
                            if (comparisonInfo.message) {
                                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1_NL_2, [initTypeSymbol.toString(enclosingSymbol), contextualType.toString(enclosingSymbol), comparisonInfo.message]));
                            } else {
                                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1, [initTypeSymbol.toString(enclosingSymbol), contextualType.toString(enclosingSymbol)]));
                            }
                        }
                    }
                }
            }

            // If we do not have any type for it, set it to any
            if (!contextualType && !paramSymbol.isVarArg && !initTypeSymbol) {
                context.setTypeInContext(paramSymbol, this.semanticInfoChain.anyTypeSymbol);
                isImplicitAny = true;
            }

            // if the noImplicitAny flag is set to be true, report an error
            if (isImplicitAny && this.compilationSettings.noImplicitAny()) {
                // there is a name for function expression then use the function expression name otherwise use "lambda"
                var functionExpressionName = paramDecl.getParentDecl().getFunctionExpressionName();
                if (functionExpressionName) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.Parameter_0_of_1_implicitly_has_an_any_type, [argDeclAST.identifier.text(), functionExpressionName]));
                } else {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(argDeclAST, TypeScript.DiagnosticCode.Parameter_0_of_lambda_function_implicitly_has_an_any_type, [argDeclAST.identifier.text()]));
                }
            }

            if (canTypeCheckAST) {
                this.checkNameForCompilerGeneratedDeclarationCollision(argDeclAST, true, argDeclAST.identifier, context);
                this.typeCheckParameterModifiers(argDeclAST, context);
            }

            paramSymbol.setResolved();
        };

        PullTypeResolver.prototype.checkNameForCompilerGeneratedDeclarationCollision = function (astWithName, isDeclaration, name, context) {
            var compilerReservedName = getCompilerReservedName(name);
            switch (compilerReservedName) {
                case 1 /* _this */:
                    this.postTypeCheckWorkitems.push(astWithName);
                    return;

                case 2 /* _super */:
                    this.checkSuperCaptureVariableCollides(astWithName, isDeclaration, context);
                    return;

                case 3 /* arguments */:
                    this.checkArgumentsCollides(astWithName, context);
                    return;

                case 4 /* _i */:
                    this.checkIndexOfRestArgumentInitializationCollides(astWithName, isDeclaration, context);
                    return;

                case 5 /* require */:
                case 6 /* exports */:
                    if (isDeclaration) {
                        this.checkExternalModuleRequireExportsCollides(astWithName, name, context);
                    }
                    return;
            }
        };

        PullTypeResolver.prototype.hasRestParameterCodeGen = function (someFunctionDecl) {
            var enclosingAST = this.getASTForDecl(someFunctionDecl);
            var nodeType = enclosingAST.kind();

            // If the method/function/constructor is non ambient, with code block and has rest parameter it would have the rest parameter code gen
            if (nodeType === 129 /* FunctionDeclaration */) {
                var functionDeclaration = enclosingAST;
                return !TypeScript.hasFlag(someFunctionDecl.kind === TypeScript.PullElementKind.Method ? someFunctionDecl.getParentDecl().flags : someFunctionDecl.flags, TypeScript.PullElementFlags.Ambient) && functionDeclaration.block && TypeScript.lastParameterIsRest(functionDeclaration.callSignature.parameterList.parameters);
            } else if (nodeType === 135 /* MemberFunctionDeclaration */) {
                var memberFunction = enclosingAST;
                return !TypeScript.hasFlag(someFunctionDecl.kind === TypeScript.PullElementKind.Method ? someFunctionDecl.getParentDecl().flags : someFunctionDecl.flags, TypeScript.PullElementFlags.Ambient) && memberFunction.block && TypeScript.lastParameterIsRest(memberFunction.callSignature.parameterList.parameters);
            } else if (nodeType === 137 /* ConstructorDeclaration */) {
                var constructorDeclaration = enclosingAST;
                return !TypeScript.hasFlag(someFunctionDecl.getParentDecl().flags, TypeScript.PullElementFlags.Ambient) && constructorDeclaration.block && TypeScript.lastParameterIsRest(constructorDeclaration.callSignature.parameterList.parameters);
            } else if (nodeType === 218 /* ParenthesizedArrowFunctionExpression */) {
                var arrowFunctionExpression = enclosingAST;
                return TypeScript.lastParameterIsRest(arrowFunctionExpression.callSignature.parameterList.parameters);
            } else if (nodeType === 222 /* FunctionExpression */) {
                var functionExpression = enclosingAST;
                return TypeScript.lastParameterIsRest(functionExpression.callSignature.parameterList.parameters);
            }

            return false;
        };

        PullTypeResolver.prototype.checkArgumentsCollides = function (ast, context) {
            if (ast.kind() === 242 /* Parameter */) {
                var enclosingDecl = this.getEnclosingDeclForAST(ast);
                if (TypeScript.hasFlag(enclosingDecl.kind, TypeScript.PullElementKind.SomeFunction)) {
                    if (this.hasRestParameterCodeGen(enclosingDecl)) {
                        // It is error to use the arguments as variable name or parameter name in function with rest parameters
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters));
                    }
                }
            }
        };

        PullTypeResolver.prototype.checkIndexOfRestArgumentInitializationCollides = function (ast, isDeclaration, context) {
            if (!isDeclaration || ast.kind() === 242 /* Parameter */) {
                var enclosingDecl = this.getEnclosingDeclForAST(ast);
                var declPath = isDeclaration ? [enclosingDecl] : (enclosingDecl ? enclosingDecl.getParentPath() : []);
                var resolvedSymbol = null;
                var resolvedSymbolContainer;
                for (var i = declPath.length - 1; i >= 0; i--) {
                    var decl = declPath[i];
                    if (!isDeclaration) {
                        // Get the symbol this ast would be resolved to
                        if (!resolvedSymbol) {
                            resolvedSymbol = this.resolveNameExpression(ast, context);
                            if (resolvedSymbol.isError()) {
                                return;
                            }

                            resolvedSymbolContainer = resolvedSymbol.getContainer();
                        }

                        // If the resolved symbol was declared in this decl, then it would always resolve to this symbol
                        // so stop looking in the decls as it is valid usage of _i
                        if (resolvedSymbolContainer && TypeScript.ArrayUtilities.contains(resolvedSymbolContainer.getDeclarations(), decl)) {
                            break;
                        }
                    }

                    if (TypeScript.hasFlag(decl.kind, TypeScript.PullElementKind.SomeFunction)) {
                        if (this.hasRestParameterCodeGen(decl)) {
                            // It is error to use the _i varible name
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, isDeclaration ? TypeScript.DiagnosticCode.Duplicate_identifier_i_Compiler_uses_i_to_initialize_rest_parameter : TypeScript.DiagnosticCode.Expression_resolves_to_variable_declaration_i_that_compiler_uses_to_initialize_rest_parameter));
                        }
                    }
                }
            }
        };

        PullTypeResolver.prototype.checkExternalModuleRequireExportsCollides = function (ast, name, context) {
            var enclosingDecl = this.getEnclosingDeclForAST(ast);

            var enclosingModule = TypeScript.ASTHelpers.getModuleDeclarationFromNameAST(name);
            if (enclosingModule) {
                // If we're actually the name of a module, then we want the enclosing decl for the
                // module that we're in.
                enclosingDecl = this.getEnclosingDeclForAST(enclosingModule);
            }

            // If the declaration is in external module
            if (enclosingDecl && enclosingDecl.kind === TypeScript.PullElementKind.DynamicModule) {
                var decl = this.semanticInfoChain.getDeclForAST(ast);

                // This is not ambient declaration, then there would be code gen
                if (!TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Ambient)) {
                    // It is error to use 'require' or 'exports' as name for the declaration
                    var nameText = TypeScript.tokenValueText(name);
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, [nameText, nameText]));
                }
            }
        };

        PullTypeResolver.prototype.resolveObjectTypeTypeReference = function (objectType, context) {
            var interfaceDecl = this.semanticInfoChain.getDeclForAST(objectType);
            TypeScript.Debug.assert(interfaceDecl);

            var interfaceSymbol = interfaceDecl.getSymbol(this.semanticInfoChain);
            TypeScript.Debug.assert(interfaceSymbol);

            if (objectType.typeMembers) {
                var memberDecl = null;
                var memberSymbol = null;
                var memberType = null;
                var typeMembers = objectType.typeMembers;

                for (var i = 0; i < typeMembers.length; i++) {
                    memberDecl = this.semanticInfoChain.getDeclForAST(typeMembers[i]);
                    memberSymbol = (memberDecl.kind & TypeScript.PullElementKind.SomeSignature) ? memberDecl.getSignatureSymbol(this.semanticInfoChain) : memberDecl.getSymbol(this.semanticInfoChain);

                    this.resolveAST(typeMembers[i], false, context);

                    memberType = memberSymbol.type;

                    if ((memberType && memberType.isGeneric()) || (memberSymbol.isSignature() && memberSymbol.isGeneric())) {
                        interfaceSymbol.setHasGenericMember();
                    }
                }
            }

            interfaceSymbol.setResolved();

            if (this.canTypeCheckAST(objectType, context)) {
                this.typeCheckObjectTypeTypeReference(objectType, context);
            }

            return interfaceSymbol;
        };

        PullTypeResolver.prototype.typeCheckObjectTypeTypeReference = function (objectType, context) {
            this.setTypeChecked(objectType, context);
            var objectTypeDecl = this.semanticInfoChain.getDeclForAST(objectType);
            var objectTypeSymbol = objectTypeDecl.getSymbol(this.semanticInfoChain);

            this.typeCheckMembersAgainstIndexer(objectTypeSymbol, objectTypeDecl, context);
            this.checkTypeForDuplicateIndexSignatures(objectTypeSymbol);
        };

        PullTypeResolver.prototype.resolveTypeAnnotation = function (typeAnnotation, context) {
            return this.resolveTypeReference(typeAnnotation.type, context);
        };

        PullTypeResolver.prototype.resolveTypeReference = function (typeRef, context) {
            if (typeRef === null) {
                return null;
            }

            TypeScript.Debug.assert(typeRef.kind() !== 244 /* TypeAnnotation */);

            var aliasType = null;
            var type = this.computeTypeReferenceSymbol(typeRef, context);

            if (type.kind === TypeScript.PullElementKind.Container) {
                var container = type;
                var instanceSymbol = container.getInstanceSymbol();

                // check if it is actually merged with class
                if (instanceSymbol && (instanceSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.ClassConstructorVariable) || instanceSymbol.kind === TypeScript.PullElementKind.ConstructorMethod)) {
                    type = instanceSymbol.type.getAssociatedContainerType();
                }
            }

            // Unwrap an alias type to its true type.
            if (type && type.isAlias()) {
                aliasType = type;
                type = aliasType.getExportAssignedTypeSymbol();
            }

            if (type && !type.isGeneric()) {
                if (aliasType) {
                    this.semanticInfoChain.setAliasSymbolForAST(typeRef, aliasType);
                }
            }

            if (type && !type.isError()) {
                if ((type.kind & TypeScript.PullElementKind.SomeType) === 0) {
                    // Provide some helper messages for common cases.
                    if (type.kind & TypeScript.PullElementKind.SomeContainer) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(typeRef, TypeScript.DiagnosticCode.Type_reference_cannot_refer_to_container_0, [aliasType ? aliasType.toString() : type.toString()]));
                    } else {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(typeRef, TypeScript.DiagnosticCode.Type_reference_must_refer_to_type));
                    }
                }
            }

            if (this.canTypeCheckAST(typeRef, context)) {
                this.setTypeChecked(typeRef, context);
            }

            return type;
        };

        PullTypeResolver.prototype.getArrayType = function (elementType) {
            var arraySymbol = elementType.getArrayType();

            // ...But in case we haven't...
            if (!arraySymbol) {
                arraySymbol = this.createInstantiatedType(this.cachedArrayInterfaceType(), [elementType]);

                if (!arraySymbol) {
                    arraySymbol = this.semanticInfoChain.anyTypeSymbol;
                }

                elementType.setArrayType(arraySymbol);
            }

            return arraySymbol;
        };

        PullTypeResolver.prototype.computeTypeReferenceSymbol = function (term, context) {
            switch (term.kind()) {
                case 60 /* AnyKeyword */: return this.semanticInfoChain.anyTypeSymbol;
                case 61 /* BooleanKeyword */: return this.semanticInfoChain.booleanTypeSymbol;
                case 67 /* NumberKeyword */: return this.semanticInfoChain.numberTypeSymbol;
                case 69 /* StringKeyword */: return this.semanticInfoChain.stringTypeSymbol;
                case 41 /* VoidKeyword */: return this.semanticInfoChain.voidTypeSymbol;
            }

            var typeDeclSymbol = null;

            // a name
            if (term.kind() === 11 /* IdentifierName */) {
                typeDeclSymbol = this.resolveTypeNameExpression(term, context);
            } else if (term.kind() === 123 /* FunctionType */) {
                var functionType = term;
                typeDeclSymbol = this.resolveAnyFunctionTypeSignature(functionType, functionType.typeParameterList, functionType.parameterList, functionType.type, context);
            } else if (term.kind() === 125 /* ConstructorType */) {
                var constructorType = term;
                typeDeclSymbol = this.resolveAnyFunctionTypeSignature(constructorType, constructorType.typeParameterList, constructorType.parameterList, constructorType.type, context);
            } else if (term.kind() === 122 /* ObjectType */) {
                typeDeclSymbol = this.resolveObjectTypeTypeReference(term, context);
            } else if (term.kind() === 126 /* GenericType */) {
                typeDeclSymbol = this.resolveGenericTypeReference(term, context);
            } else if (term.kind() === 121 /* QualifiedName */) {
                // find the decl
                typeDeclSymbol = this.resolveQualifiedName(term, context);
            } else if (term.kind() === 14 /* StringLiteral */) {
                var stringConstantAST = term;
                var enclosingDecl = this.getEnclosingDeclForAST(term);
                typeDeclSymbol = new TypeScript.PullStringConstantTypeSymbol(stringConstantAST.text(), this.semanticInfoChain);
                var decl = new TypeScript.PullSynthesizedDecl(stringConstantAST.text(), stringConstantAST.text(), typeDeclSymbol.kind, null, enclosingDecl);
                typeDeclSymbol.addDeclaration(decl);
            } else if (term.kind() === 127 /* TypeQuery */) {
                var typeQuery = term;

                // TODO: This is a workaround if we encounter a TypeReference ISyntaxElement node. Remove it when we remove the ISyntaxElement.
                var typeQueryTerm = typeQuery.name;

                //if (typeQueryTerm.kind === SyntaxKind.TypeRef) {
                //    typeQueryTerm = (<TypeReference>typeQueryTerm).term;
                //}
                var valueSymbol = this.resolveAST(typeQueryTerm, false, context);

                if (valueSymbol && valueSymbol.isAlias()) {
                    if (valueSymbol.assignedValue()) {
                        valueSymbol = valueSymbol.assignedValue();
                    } else {
                        var containerSymbol = valueSymbol.getExportAssignedContainerSymbol();
                        valueSymbol = (containerSymbol && containerSymbol.isContainer() && !containerSymbol.isEnum()) ? containerSymbol.getInstanceSymbol() : null;
                    }
                }

                // Get the type of the symbol
                if (valueSymbol) {
                    typeDeclSymbol = valueSymbol.type.widenedType(this, typeQueryTerm, context);
                } else {
                    typeDeclSymbol = this.getNewErrorTypeSymbol();
                }
            } else if (term.kind() === 124 /* ArrayType */) {
                var arrayType = term;
                var underlying = this.resolveTypeReference(arrayType.type, context);
                typeDeclSymbol = this.getArrayType(underlying);
            } else {
                throw TypeScript.Errors.invalidOperation("unknown type");
            }

            if (!typeDeclSymbol) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(term, TypeScript.DiagnosticCode.Unable_to_resolve_type));
                return this.getNewErrorTypeSymbol();
            }

            if (typeDeclSymbol.isError()) {
                return typeDeclSymbol;
            }

            if (this.genericTypeIsUsedWithoutRequiredTypeArguments(typeDeclSymbol, term, context)) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(term, TypeScript.DiagnosticCode.Generic_type_0_requires_1_type_argument_s, [typeDeclSymbol.toString(), typeDeclSymbol.getTypeParameters().length]));
                typeDeclSymbol = this.instantiateTypeToAny(typeDeclSymbol, context);
            }

            return typeDeclSymbol;
        };

        PullTypeResolver.prototype.genericTypeIsUsedWithoutRequiredTypeArguments = function (typeSymbol, term, context) {
            if (!typeSymbol) {
                return false;
            }

            if (typeSymbol.isAlias()) {
                return this.genericTypeIsUsedWithoutRequiredTypeArguments(typeSymbol.getExportAssignedTypeSymbol(), term, context);
            }

            return typeSymbol.isNamedTypeSymbol() && typeSymbol.isGeneric() && !typeSymbol.isTypeParameter() && (typeSymbol.isResolved || typeSymbol.inResolution) && !typeSymbol.getIsSpecialized() && typeSymbol.getTypeParameters().length && typeSymbol.getTypeArguments() === null && this.isTypeRefWithoutTypeArgs(term);
        };

        PullTypeResolver.prototype.resolveMemberVariableDeclaration = function (varDecl, context) {
            return this.resolveVariableDeclaratorOrParameterOrEnumElement(varDecl, varDecl.modifiers, varDecl.variableDeclarator.propertyName, TypeScript.ASTHelpers.getType(varDecl.variableDeclarator), varDecl.variableDeclarator.equalsValueClause, context);
        };

        PullTypeResolver.prototype.resolvePropertySignature = function (varDecl, context) {
            return this.resolveVariableDeclaratorOrParameterOrEnumElement(varDecl, TypeScript.Syntax.emptyList(), varDecl.propertyName, TypeScript.ASTHelpers.getType(varDecl), null, context);
        };

        PullTypeResolver.prototype.resolveVariableDeclarator = function (varDecl, context) {
            return this.resolveVariableDeclaratorOrParameterOrEnumElement(varDecl, TypeScript.ASTHelpers.getVariableDeclaratorModifiers(varDecl), varDecl.propertyName, TypeScript.ASTHelpers.getType(varDecl), varDecl.equalsValueClause, context);
        };

        PullTypeResolver.prototype.resolveParameterList = function (list, context) {
            return this.resolveSeparatedList(list.parameters, context);
        };

        PullTypeResolver.prototype.resolveParameter = function (parameter, context) {
            return this.resolveVariableDeclaratorOrParameterOrEnumElement(parameter, parameter.modifiers, parameter.identifier, TypeScript.ASTHelpers.getType(parameter), parameter.equalsValueClause, context);
        };

        PullTypeResolver.prototype.getEnumTypeSymbol = function (enumElement, context) {
            var enumDeclaration = enumElement.parent.parent;
            var decl = this.semanticInfoChain.getDeclForAST(enumDeclaration);
            var symbol = decl.getSymbol(this.semanticInfoChain);
            this.resolveDeclaredSymbol(symbol, context);

            return symbol;
        };

        PullTypeResolver.prototype.resolveEnumElement = function (enumElement, context) {
            return this.resolveVariableDeclaratorOrParameterOrEnumElement(enumElement, TypeScript.Syntax.emptyList(), enumElement.propertyName, null, enumElement.equalsValueClause, context);
        };

        PullTypeResolver.prototype.typeCheckEnumElement = function (enumElement, context) {
            this.typeCheckVariableDeclaratorOrParameterOrEnumElement(enumElement, TypeScript.Syntax.emptyList(), enumElement.propertyName, null, enumElement.equalsValueClause, context);
        };

        PullTypeResolver.prototype.resolveEqualsValueClause = function (clause, isContextuallyTyped, context) {
            if (this.canTypeCheckAST(clause, context)) {
                this.setTypeChecked(clause, context);
            }

            return this.resolveAST(clause.value, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.resolveVariableDeclaratorOrParameterOrEnumElement = function (varDeclOrParameter, modifiers, name, typeExpr, init, context) {
            var hasTypeExpr = typeExpr !== null || varDeclOrParameter.kind() === 243 /* EnumElement */;
            var enclosingDecl = this.getEnclosingDeclForAST(varDeclOrParameter);
            var decl = this.semanticInfoChain.getDeclForAST(varDeclOrParameter);

            // if the enclosing decl is a lambda, we may not have bound the parent symbol
            if (enclosingDecl && decl.kind === TypeScript.PullElementKind.Parameter) {
                enclosingDecl.ensureSymbolIsBound(this.semanticInfoChain);
            }

            var declSymbol = decl.getSymbol(this.semanticInfoChain);
            var declParameterSymbol = decl.getValueDecl() ? decl.getValueDecl().getSymbol(this.semanticInfoChain) : null;

            if (declSymbol.isResolved) {
                var declType = declSymbol.type;
                var valDecl = decl.getValueDecl();

                if (valDecl) {
                    var valSymbol = valDecl.getSymbol(this.semanticInfoChain);

                    if (valSymbol && !valSymbol.isResolved) {
                        valSymbol.type = declType;
                        valSymbol.setResolved();
                    }
                }
            } else {
                if (declSymbol.inResolution) {
                    // PULLTODO: Error or warning?
                    declSymbol.type = this.semanticInfoChain.anyTypeSymbol;
                    declSymbol.setResolved();
                    return declSymbol;
                }

                if (!declSymbol.type || !declSymbol.type.isError()) {
                    declSymbol.startResolving();

                    // Does this have a type expression? If so, that's the type
                    var typeExprSymbol = this.resolveAndTypeCheckVariableDeclarationTypeExpr(varDeclOrParameter, name, typeExpr, context);

                    // If we're not type checking, and have a type expression, don't bother looking at the initializer expression
                    if (!hasTypeExpr) {
                        this.resolveAndTypeCheckVariableDeclaratorOrParameterInitExpr(varDeclOrParameter, name, typeExpr, init, context, typeExprSymbol);
                    }

                    // if we're lacking both a type annotation and an initialization expression, the type is 'any'
                    if (!(hasTypeExpr || init)) {
                        var defaultType = this.semanticInfoChain.anyTypeSymbol;

                        if (declSymbol.isVarArg && this.cachedArrayInterfaceType()) {
                            defaultType = this.createInstantiatedType(this.cachedArrayInterfaceType(), [defaultType]);
                        }

                        context.setTypeInContext(declSymbol, defaultType);

                        if (declParameterSymbol) {
                            declParameterSymbol.type = defaultType;
                        }
                    }
                    declSymbol.setResolved();

                    if (declParameterSymbol) {
                        declParameterSymbol.setResolved();
                    }
                }
            }

            if (this.canTypeCheckAST(varDeclOrParameter, context)) {
                this.typeCheckVariableDeclaratorOrParameterOrEnumElement(varDeclOrParameter, modifiers, name, typeExpr, init, context);
            }

            return declSymbol;
        };

        PullTypeResolver.prototype.resolveAndTypeCheckVariableDeclarationTypeExpr = function (varDeclOrParameter, name, typeExpr, context) {
            var enclosingDecl = this.getEnclosingDeclForAST(varDeclOrParameter);
            var decl = this.semanticInfoChain.getDeclForAST(varDeclOrParameter);
            var declSymbol = decl.getSymbol(this.semanticInfoChain);
            var declParameterSymbol = decl.getValueDecl() ? decl.getValueDecl().getSymbol(this.semanticInfoChain) : null;

            if (varDeclOrParameter.kind() === 243 /* EnumElement */) {
                var result = this.getEnumTypeSymbol(varDeclOrParameter, context);
                declSymbol.type = result;
                return result;
            }

            if (!typeExpr) {
                return null;
            }

            var wrapperDecl = this.getEnclosingDecl(decl);
            wrapperDecl = wrapperDecl || enclosingDecl;

            var typeExprSymbol = this.resolveTypeReference(typeExpr, context);

            if (!typeExprSymbol) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Unable_to_resolve_type_of_0, [name.text()]));
                declSymbol.type = this.getNewErrorTypeSymbol();

                if (declParameterSymbol) {
                    context.setTypeInContext(declParameterSymbol, this.semanticInfoChain.anyTypeSymbol);
                }
            } else if (typeExprSymbol.isError()) {
                context.setTypeInContext(declSymbol, typeExprSymbol);
                if (declParameterSymbol) {
                    context.setTypeInContext(declParameterSymbol, typeExprSymbol);
                }
            } else {
                if (typeExprSymbol === this.semanticInfoChain.anyTypeSymbol) {
                    decl.setFlag(TypeScript.PullElementFlags.IsAnnotatedWithAny);
                }

                // PULLREVIEW: If the type annotation is a container type, use the module instance type
                if (typeExprSymbol.isContainer()) {
                    var exportedTypeSymbol = typeExprSymbol.getExportAssignedTypeSymbol();

                    if (exportedTypeSymbol) {
                        typeExprSymbol = exportedTypeSymbol;
                    } else {
                        typeExprSymbol = typeExprSymbol.type;

                        if (typeExprSymbol.isAlias()) {
                            typeExprSymbol = typeExprSymbol.getExportAssignedTypeSymbol();
                        }

                        if (typeExprSymbol && typeExprSymbol.isContainer() && !typeExprSymbol.isEnum()) {
                            // aliased type could still be 'any' as the result of an error
                            var instanceSymbol = typeExprSymbol.getInstanceSymbol();

                            if (!instanceSymbol || !TypeScript.PullHelpers.symbolIsEnum(instanceSymbol)) {
                                typeExprSymbol = this.getNewErrorTypeSymbol();
                            } else {
                                typeExprSymbol = instanceSymbol.type;
                            }
                        }
                    }
                } else if (declSymbol.isVarArg && !(typeExprSymbol.isArrayNamedTypeReference() || typeExprSymbol === this.cachedArrayInterfaceType())) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.A_rest_parameter_must_be_of_an_array_type));
                    typeExprSymbol = this.getNewErrorTypeSymbol();
                }

                context.setTypeInContext(declSymbol, typeExprSymbol);

                if (declParameterSymbol) {
                    declParameterSymbol.type = typeExprSymbol;
                }

                // We associate the value with the function type here because we couldn't do so at biding
                // but need this information to get correct doc comments
                if (typeExprSymbol.kind === TypeScript.PullElementKind.FunctionType && !typeExprSymbol.getFunctionSymbol()) {
                    typeExprSymbol.setFunctionSymbol(declSymbol);
                }
            }

            return typeExprSymbol;
        };

        PullTypeResolver.prototype.resolveAndTypeCheckVariableDeclaratorOrParameterInitExpr = function (varDeclOrParameter, name, typeExpr, init, context, typeExprSymbol) {
            if (!init) {
                return null;
            }

            var hasTypeExpr = typeExpr !== null || varDeclOrParameter.kind() === 243 /* EnumElement */;
            if (typeExprSymbol) {
                context.pushNewContextualType(typeExprSymbol);
            }

            var enclosingDecl = this.getEnclosingDeclForAST(varDeclOrParameter);
            var decl = this.semanticInfoChain.getDeclForAST(varDeclOrParameter);
            var declSymbol = decl.getSymbol(this.semanticInfoChain);
            var declParameterSymbol = decl.getValueDecl() ? decl.getValueDecl().getSymbol(this.semanticInfoChain) : null;

            var wrapperDecl = this.getEnclosingDecl(decl);
            wrapperDecl = wrapperDecl || enclosingDecl;

            var initExprSymbol = this.resolveAST(init, typeExprSymbol !== null, context);

            if (typeExprSymbol) {
                context.popAnyContextualType();
            }

            if (!initExprSymbol) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Unable_to_resolve_type_of_0, [name.text()]));

                if (!hasTypeExpr) {
                    context.setTypeInContext(declSymbol, this.getNewErrorTypeSymbol());

                    if (declParameterSymbol) {
                        context.setTypeInContext(declParameterSymbol, this.semanticInfoChain.anyTypeSymbol);
                    }
                }
            } else {
                var initTypeSymbol = initExprSymbol.type;

                // Don't reset the type if we already have one from the type expression
                if (!hasTypeExpr) {
                    var widenedInitTypeSymbol = initTypeSymbol.widenedType(this, init.value, context);
                    context.setTypeInContext(declSymbol, widenedInitTypeSymbol);

                    if (declParameterSymbol) {
                        context.setTypeInContext(declParameterSymbol, widenedInitTypeSymbol);
                    }

                    // if the noImplicitAny flag is set to be true, report an error
                    if (this.compilationSettings.noImplicitAny()) {
                        // initializer is resolved to any type from widening variable declaration (i.e var x = null)
                        if ((widenedInitTypeSymbol !== initTypeSymbol) && (widenedInitTypeSymbol === this.semanticInfoChain.anyTypeSymbol)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Variable_0_implicitly_has_an_any_type, [name.text()]));
                        }
                    }

                    return widenedInitTypeSymbol;
                }
            }

            return initTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckPropertySignature = function (varDecl, context) {
            this.typeCheckVariableDeclaratorOrParameterOrEnumElement(varDecl, TypeScript.Syntax.emptyList(), varDecl.propertyName, TypeScript.ASTHelpers.getType(varDecl), null, context);
        };

        PullTypeResolver.prototype.typeCheckMemberVariableDeclaration = function (varDecl, context) {
            this.typeCheckVariableDeclaratorOrParameterOrEnumElement(varDecl, varDecl.modifiers, varDecl.variableDeclarator.propertyName, TypeScript.ASTHelpers.getType(varDecl), varDecl.variableDeclarator.equalsValueClause, context);
        };

        PullTypeResolver.prototype.typeCheckVariableDeclarator = function (varDecl, context) {
            this.typeCheckVariableDeclaratorOrParameterOrEnumElement(varDecl, TypeScript.ASTHelpers.getVariableDeclaratorModifiers(varDecl), varDecl.propertyName, TypeScript.ASTHelpers.getType(varDecl), varDecl.equalsValueClause, context);
        };

        PullTypeResolver.prototype.getContainingConstructorDeclaration = function (parameter) {
            var current = parameter;
            while (current.kind() !== 137 /* ConstructorDeclaration */) {
                current = current.parent;
            }

            return current;
        };

        PullTypeResolver.prototype.typeCheckParameter = function (parameter, context) {
            this.typeCheckVariableDeclaratorOrParameterOrEnumElement(parameter, parameter.modifiers, parameter.identifier, TypeScript.ASTHelpers.getType(parameter), parameter.equalsValueClause, context);
        };

        PullTypeResolver.prototype.typeCheckParameterModifiers = function (parameter, context) {
            if (parameter.modifiers.length) {
                var parameterDecl = this.semanticInfoChain.getDeclForAST(parameter);
                var isConstructorParam = TypeScript.hasFlag(parameterDecl.flags, TypeScript.PullElementFlags.ConstructorParameter);

                var inAmbientDeclaration = TypeScript.hasFlag(parameterDecl.getParentDecl().flags, TypeScript.PullElementFlags.Ambient);

                if (!inAmbientDeclaration && isConstructorParam) {
                    var constructorDeclaration = this.getContainingConstructorDeclaration(parameter);
                    if (!constructorDeclaration.block) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(parameter.modifiers[0], TypeScript.DiagnosticCode.A_parameter_property_is_only_allowed_in_a_constructor_implementation));
                    }
                } else {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(parameter.modifiers[0], TypeScript.DiagnosticCode.A_parameter_property_is_only_allowed_in_a_constructor_implementation));
                }
            }
        };

        PullTypeResolver.prototype.typeCheckVariableDeclaratorOrParameterOrEnumElement = function (varDeclOrParameter, modifiers, name, typeExpr, init, context) {
            var _this = this;
            this.setTypeChecked(varDeclOrParameter, context);

            if (varDeclOrParameter.kind() === 242 /* Parameter */) {
                this.typeCheckParameterModifiers(varDeclOrParameter, context);
            }

            var hasTypeExpr = typeExpr !== null || varDeclOrParameter.kind() === 243 /* EnumElement */;
            var enclosingDecl = this.getEnclosingDeclForAST(varDeclOrParameter);
            var decl = this.semanticInfoChain.getDeclForAST(varDeclOrParameter);
            var declSymbol = decl.getSymbol(this.semanticInfoChain);

            var typeExprSymbol = this.resolveAndTypeCheckVariableDeclarationTypeExpr(varDeclOrParameter, name, typeExpr, context);

            // Report errors on init Expr only if typeExpr is present because we wouldnt have resolved the initExpr when just resolving
            var initTypeSymbol = this.resolveAndTypeCheckVariableDeclaratorOrParameterInitExpr(varDeclOrParameter, name, typeExpr, init, context, typeExprSymbol);

            // If we're type checking, test the initializer and type annotation for assignment compatibility
            if (hasTypeExpr || init) {
                if (typeExprSymbol && typeExprSymbol.isAlias()) {
                    typeExprSymbol = typeExprSymbol.getExportAssignedTypeSymbol();
                }

                if (typeExprSymbol && typeExprSymbol.kind === TypeScript.PullElementKind.DynamicModule) {
                    var exportedTypeSymbol = typeExprSymbol.getExportAssignedTypeSymbol();

                    if (exportedTypeSymbol) {
                        typeExprSymbol = exportedTypeSymbol;
                    } else {
                        var instanceTypeSymbol = typeExprSymbol.getInstanceType();

                        if (!instanceTypeSymbol) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Tried_to_set_variable_type_to_uninitialized_module_type_0, [typeExprSymbol.toString()]));
                            typeExprSymbol = null;
                        } else {
                            typeExprSymbol = instanceTypeSymbol;
                        }
                    }
                }

                initTypeSymbol = this.getInstanceTypeForAssignment(varDeclOrParameter, initTypeSymbol, context);

                if (initTypeSymbol && typeExprSymbol) {
                    var comparisonInfo = new TypeComparisonInfo();

                    var isAssignable = this.sourceIsAssignableToTarget(initTypeSymbol, typeExprSymbol, varDeclOrParameter, context, comparisonInfo);

                    if (!isAssignable) {
                        var enclosingSymbol = this.getEnclosingSymbolForAST(varDeclOrParameter);
                        if (comparisonInfo.message) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1_NL_2, [initTypeSymbol.toString(enclosingSymbol), typeExprSymbol.toString(enclosingSymbol), comparisonInfo.message]));
                        } else {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1, [initTypeSymbol.toString(enclosingSymbol), typeExprSymbol.toString(enclosingSymbol)]));
                        }
                    }
                }
            } else if (varDeclOrParameter.kind() !== 243 /* EnumElement */ && this.compilationSettings.noImplicitAny() && !this.isForInVariableDeclarator(varDeclOrParameter)) {
                // if we're lacking both a type annotation and an initialization expression, the type is 'any'
                // if the noImplicitAny flag is set to be true, report an error
                // Do not report an error if the variable declaration is declared in ForIn statement
                var wrapperDecl = this.getEnclosingDecl(decl);
                wrapperDecl = wrapperDecl || enclosingDecl;

                // error should be reported if
                // - container decl is not ambient
                // OR
                // - container decl is ambient and self decl is not private (is provided)
                var needReportError = function (containerDecl, selfDecl) {
                    if (!TypeScript.hasFlag(containerDecl.flags, TypeScript.PullElementFlags.Ambient)) {
                        return true;
                    }

                    return selfDecl && !TypeScript.hasFlag(selfDecl.flags, TypeScript.PullElementFlags.Private);
                };

                // check what enclosingDecl the varDecl is in and report an appropriate error message
                // varDecl is a function/constructor/constructor-signature parameter
                if ((wrapperDecl.kind === TypeScript.PullElementKind.Function || wrapperDecl.kind === TypeScript.PullElementKind.ConstructorMethod || wrapperDecl.kind === TypeScript.PullElementKind.ConstructSignature)) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Parameter_0_of_1_implicitly_has_an_any_type, [name.text(), enclosingDecl.name]));
                } else if (wrapperDecl.kind === TypeScript.PullElementKind.Method) {
                    // check if the parent of wrapperDecl is ambient class declaration
                    var parentDecl = wrapperDecl.getParentDecl();

                    // parentDecl is not an ambient declaration; so report an error
                    // OR
                    //parentDecl is an ambient declaration, but the wrapperDecl(method) is a not private; so report an error
                    if (needReportError(parentDecl, wrapperDecl)) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Parameter_0_of_1_implicitly_has_an_any_type, [name.text(), enclosingDecl.name]));
                    }
                } else if (decl.kind === TypeScript.PullElementKind.Property && !declSymbol.getContainer().isNamedTypeSymbol()) {
                    if (needReportError(wrapperDecl, decl)) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Member_0_of_object_type_implicitly_has_an_any_type, [name.text()]));
                    }
                } else if (wrapperDecl.kind !== TypeScript.PullElementKind.CatchBlock) {
                    // varDecl is not declared in ambient declaration; so report an error
                    // OR
                    // varDecl is declared in ambient declaration but it is not private; so report an error
                    if (needReportError(wrapperDecl) || !TypeScript.hasModifier(modifiers, TypeScript.PullElementFlags.Private)) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.Variable_0_implicitly_has_an_any_type, [name.text()]));
                    }
                }
            }

            if (init && varDeclOrParameter.kind() === 242 /* Parameter */) {
                var containerSignature = enclosingDecl.getSignatureSymbol(this.semanticInfoChain);
                if (containerSignature && !containerSignature.isDefinition()) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(varDeclOrParameter, TypeScript.DiagnosticCode.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation));
                }
            }
            if (declSymbol.kind !== TypeScript.PullElementKind.Parameter && (declSymbol.kind !== TypeScript.PullElementKind.Property || declSymbol.getContainer().isNamedTypeSymbol())) {
                this.checkSymbolPrivacy(declSymbol, declSymbol.type, function (symbol) {
                    return _this.variablePrivacyErrorReporter(varDeclOrParameter, declSymbol, symbol, context);
                });
            }

            if ((declSymbol.kind !== TypeScript.PullElementKind.Property && declSymbol.kind !== TypeScript.PullElementKind.EnumMember) || declSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.PropertyParameter)) {
                // Non property variable with _this name, we need to verify if this would be ok
                this.checkNameForCompilerGeneratedDeclarationCollision(varDeclOrParameter, true, name, context);
            }
        };

        PullTypeResolver.prototype.isForInVariableDeclarator = function (ast) {
            return ast.kind() === 225 /* VariableDeclarator */ && ast.parent && ast.parent.parent && ast.parent.parent.parent && ast.parent.kind() === 2 /* SeparatedList */ && ast.parent.parent.kind() === 224 /* VariableDeclaration */ && ast.parent.parent.parent.kind() === 155 /* ForInStatement */ && ast.parent.parent.parent.variableDeclaration === ast.parent.parent;
        };

        PullTypeResolver.prototype.checkSuperCaptureVariableCollides = function (superAST, isDeclaration, context) {
            var enclosingDecl = this.getEnclosingDeclForAST(superAST);

            var classSymbol = this.getContextualClassSymbolForEnclosingDecl(superAST, enclosingDecl);

            if (classSymbol && !classSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.Ambient)) {
                if (superAST.kind() === 242 /* Parameter */) {
                    var enclosingAST = this.getASTForDecl(enclosingDecl);
                    if (enclosingAST.kind() !== 218 /* ParenthesizedArrowFunctionExpression */ && enclosingAST.kind() !== 219 /* SimpleArrowFunctionExpression */) {
                        var block = enclosingDecl.kind === TypeScript.PullElementKind.Method ? enclosingAST.block : enclosingAST.block;
                        if (!block) {
                            return;
                        }
                    }
                }

                this.resolveDeclaredSymbol(classSymbol, context);

                var parents = classSymbol.getExtendedTypes();
                if (parents.length) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(superAST, isDeclaration ? TypeScript.DiagnosticCode.Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference : TypeScript.DiagnosticCode.Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference));
                }
            }
        };

        PullTypeResolver.prototype.checkThisCaptureVariableCollides = function (_thisAST, isDeclaration, context) {
            if (isDeclaration) {
                var decl = this.semanticInfoChain.getDeclForAST(_thisAST);
                if (TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Ambient)) {
                    return;
                }
            }

            // Verify if this variable name conflicts with the _this that would be emitted to capture this in any of the enclosing context
            var enclosingDecl = this.getEnclosingDeclForAST(_thisAST);

            var enclosingModule = TypeScript.ASTHelpers.getModuleDeclarationFromNameAST(_thisAST);
            if (enclosingModule) {
                // If we're actually the name of a module, then we want the enclosing decl for the
                // module that we're in.
                enclosingDecl = this.getEnclosingDeclForAST(enclosingModule);
            }

            var declPath = enclosingDecl.getParentPath();

            for (var i = declPath.length - 1; i >= 0; i--) {
                var decl = declPath[i];
                var declKind = decl.kind;
                if (declKind === TypeScript.PullElementKind.FunctionExpression && TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.ArrowFunction)) {
                    continue;
                }

                if (declKind === TypeScript.PullElementKind.Function || declKind === TypeScript.PullElementKind.Method || declKind === TypeScript.PullElementKind.ConstructorMethod || declKind === TypeScript.PullElementKind.GetAccessor || declKind === TypeScript.PullElementKind.SetAccessor || declKind === TypeScript.PullElementKind.FunctionExpression || declKind === TypeScript.PullElementKind.Class || declKind === TypeScript.PullElementKind.Container || declKind === TypeScript.PullElementKind.DynamicModule || declKind === TypeScript.PullElementKind.Script) {
                    if (TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.MustCaptureThis)) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(_thisAST, isDeclaration ? TypeScript.DiagnosticCode.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference : TypeScript.DiagnosticCode.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference));
                    }
                    break;
                }
            }
        };

        PullTypeResolver.prototype.postTypeCheckVariableDeclaratorOrParameter = function (varDeclOrParameter, context) {
            this.checkThisCaptureVariableCollides(varDeclOrParameter, true, context);
        };

        PullTypeResolver.prototype.resolveTypeParameterDeclaration = function (typeParameterAST, context) {
            var typeParameterDecl = this.semanticInfoChain.getDeclForAST(typeParameterAST);
            var typeParameterSymbol = typeParameterDecl.getSymbol(this.semanticInfoChain);

            // Always resolve the first type parameter declaration to make sure we have the constraint set from the first decl
            this.resolveFirstTypeParameterDeclaration(typeParameterSymbol, context);

            if (typeParameterSymbol.isResolved && this.canTypeCheckAST(typeParameterAST, context)) {
                this.typeCheckTypeParameterDeclaration(typeParameterAST, context);
            }

            return typeParameterSymbol;
        };

        PullTypeResolver.prototype.resolveFirstTypeParameterDeclaration = function (typeParameterSymbol, context) {
            var typeParameterDecl = typeParameterSymbol.getDeclarations()[0];
            var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameterDecl);

            // REVIEW: We shouldn't bail if we're specializing
            if (typeParameterSymbol.isResolved || typeParameterSymbol.inResolution) {
                return;
            }

            typeParameterSymbol.startResolving();

            if (typeParameterAST.constraint) {
                var constraintTypeSymbol = this.resolveTypeReference(typeParameterAST.constraint.type, context);

                if (constraintTypeSymbol) {
                    typeParameterSymbol.setConstraint(constraintTypeSymbol);
                }
            }

            typeParameterSymbol.setResolved();
        };

        PullTypeResolver.prototype.typeCheckTypeParameterDeclaration = function (typeParameterAST, context) {
            this.setTypeChecked(typeParameterAST, context);

            var constraint = this.resolveAST(typeParameterAST.constraint, false, context);

            if (constraint) {
                // Get all type parameters and create a map that has entries at pullSymbolID for each of the type parameter
                // The value doesnt matter, the entry needs to be present for the wrapsSomeTypeParameter to be able to give the correct answer
                var typeParametersAST = typeParameterAST.parent;
                var typeParameters = [];
                for (var i = 0; i < typeParametersAST.length; i++) {
                    var currentTypeParameterAST = typeParametersAST[i];
                    var currentTypeParameterDecl = this.semanticInfoChain.getDeclForAST(currentTypeParameterAST);
                    var currentTypeParameter = this.semanticInfoChain.getSymbolForDecl(currentTypeParameterDecl);
                    typeParameters[currentTypeParameter.pullSymbolID] = currentTypeParameter;
                }

                // If constraint wraps any of the type parameter from the type parameters list report error
                if (constraint.wrapsSomeTypeParameter(typeParameters)) {
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list);
                }
            }
        };

        PullTypeResolver.prototype.resolveConstraint = function (constraint, context) {
            if (this.canTypeCheckAST(constraint, context)) {
                this.setTypeChecked(constraint, context);
            }

            return this.resolveTypeReference(constraint.type, context);
        };

        PullTypeResolver.prototype.resolveFunctionBodyReturnTypes = function (funcDeclAST, block, bodyExpression, signature, useContextualType, enclosingDecl, context) {
            var _this = this;
            var returnStatementsExpressions = [];

            var enclosingDeclStack = [enclosingDecl];

            var preFindReturnExpressionTypes = function (ast, walker) {
                var go = true;

                switch (ast.kind()) {
                    case 150 /* ReturnStatement */:
                        var returnStatement = ast;
                        enclosingDecl.setFlag(TypeScript.PullElementFlags.HasReturnStatement);
                        returnStatementsExpressions.push({ expression: returnStatement.expression, enclosingDecl: enclosingDeclStack[enclosingDeclStack.length - 1] });
                        go = false;
                        break;

                    case 236 /* CatchClause */:
                    case 163 /* WithStatement */:
                        enclosingDeclStack[enclosingDeclStack.length] = _this.semanticInfoChain.getDeclForAST(ast);
                        break;

                    default:
                        // don't recurse into a function\object literal decl - we don't want to confuse a nested
                        // return type with the top-level function's return type
                        go = !TypeScript.SyntaxUtilities.isAnyFunctionExpressionOrDeclaration(ast);
                        break;
                }

                walker.options.goChildren = go;

                return ast;
            };

            var postFindReturnExpressionEnclosingDecls = function (ast, walker) {
                switch (ast.kind()) {
                    case 236 /* CatchClause */:
                    case 163 /* WithStatement */:
                        enclosingDeclStack.length--;
                        break;
                    default:
                        break;
                }

                walker.options.goChildren = true;

                return ast;
            };

            if (block) {
                TypeScript.getAstWalkerFactory().walk(block, preFindReturnExpressionTypes, postFindReturnExpressionEnclosingDecls);
            } else {
                returnStatementsExpressions.push({ expression: bodyExpression, enclosingDecl: enclosingDecl });
                enclosingDecl.setFlag(TypeScript.PullElementFlags.HasReturnStatement);
            }

            if (!returnStatementsExpressions.length) {
                signature.returnType = this.semanticInfoChain.voidTypeSymbol;
            } else {
                var returnExpressionSymbols = [];
                var returnExpressions = [];

                for (var i = 0; i < returnStatementsExpressions.length; i++) {
                    var returnExpression = returnStatementsExpressions[i].expression;
                    if (returnExpression) {
                        var returnType = this.resolveAST(returnExpression, useContextualType, context).type;

                        if (returnType.isError()) {
                            signature.returnType = returnType;
                            return;
                        } else {
                            if (returnExpression.parent.kind() === 150 /* ReturnStatement */) {
                                this.setSymbolForAST(returnExpression.parent, returnType, context);
                            }
                        }

                        returnExpressionSymbols.push(returnType);
                        returnExpressions.push(returnExpression);
                    }
                }

                if (!returnExpressionSymbols.length) {
                    signature.returnType = this.semanticInfoChain.voidTypeSymbol;
                } else {
                    // combine return expression types for best common type
                    var collection = {
                        getLength: function () {
                            return returnExpressionSymbols.length;
                        },
                        getTypeAtIndex: function (index) {
                            return returnExpressionSymbols[index].type;
                        }
                    };

                    var bestCommonReturnType = this.findBestCommonType(null, collection, context);
                    var returnType = bestCommonReturnType;
                    var returnExpression = returnExpressions[returnExpressionSymbols.indexOf(returnType)];

                    var functionDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
                    var functionSymbol = functionDecl.getSymbol(this.semanticInfoChain);

                    if (returnType) {
                        var previousReturnType = returnType;
                        var newReturnType = returnType.widenedType(this, returnExpression, context);
                        signature.returnType = newReturnType;

                        if (!TypeScript.ArrayUtilities.contains(returnExpressionSymbols, bestCommonReturnType)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.No_best_common_type_exists_among_return_expressions));
                        }

                        // if noImplicitAny flag is set to be true and return statements are not cast expressions, report an error
                        if (this.compilationSettings.noImplicitAny()) {
                            // if the returnType got widen to Any
                            if (previousReturnType !== newReturnType && newReturnType === this.semanticInfoChain.anyTypeSymbol) {
                                var functionName = enclosingDecl.name;
                                if (functionName === "") {
                                    functionName = enclosingDecl.getFunctionExpressionName();
                                }

                                if (functionName != "") {
                                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode._0_which_lacks_return_type_annotation_implicitly_has_an_any_return_type, [functionName]));
                                } else {
                                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_any_return_type));
                                }
                            }
                        }
                    }

                    // If the accessor is referenced via a recursive chain, we may not have set the accessor's type just yet and we'll
                    // need to do so before setting the 'isGeneric' flag
                    if (!functionSymbol.type && functionSymbol.isAccessor()) {
                        functionSymbol.type = signature.returnType;
                    }
                }
            }
        };

        PullTypeResolver.prototype.typeCheckConstructorDeclaration = function (funcDeclAST, context) {
            var _this = this;
            this.setTypeChecked(funcDeclAST, context);

            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            for (var i = 0; i < funcDeclAST.callSignature.parameterList.parameters.length; i++) {
                this.resolveAST(funcDeclAST.callSignature.parameterList.parameters[i], false, context);
            }

            this.resolveAST(funcDeclAST.block, false, context);

            if (funcDecl.getSignatureSymbol(this.semanticInfoChain) && funcDecl.getSignatureSymbol(this.semanticInfoChain).isDefinition() && this.enclosingClassIsDerived(funcDecl.getParentDecl())) {
                // Constructors for derived classes must contain a call to the class's 'super' constructor
                if (!this.constructorHasSuperCall(funcDeclAST)) {
                    var syntaxTree = TypeScript.syntaxTree(funcDeclAST);
                    context.postDiagnostic(new TypeScript.Diagnostic(syntaxTree.fileName(), syntaxTree.lineMap(), TypeScript.start(funcDeclAST.constructorKeyword), TypeScript.width(funcDeclAST.constructorKeyword), TypeScript.DiagnosticCode.Constructors_for_derived_classes_must_contain_a_super_call));
                } else if (this.superCallMustBeFirstStatementInConstructor(funcDecl)) {
                    var firstStatement = this.getFirstStatementOfBlockOrNull(funcDeclAST.block);
                    if (!firstStatement || !this.isSuperInvocationExpressionStatement(firstStatement)) {
                        var syntaxTree = TypeScript.syntaxTree(funcDeclAST);
                        context.postDiagnostic(new TypeScript.Diagnostic(syntaxTree.fileName(), syntaxTree.lineMap(), TypeScript.start(funcDeclAST.constructorKeyword), TypeScript.width(funcDeclAST.constructorKeyword), TypeScript.DiagnosticCode.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties));
                    }
                }
            }

            this.validateVariableDeclarationGroups(funcDecl, context);

            this.checkFunctionTypePrivacy(funcDeclAST, false, null, funcDeclAST.callSignature.parameterList.parameters, null, funcDeclAST.block, context);

            this.typeCheckCallBacks.push(function (context) {
                // Function or constructor
                _this.typeCheckFunctionOverloads(funcDeclAST, context);
            });
        };

        PullTypeResolver.prototype.constructorHasSuperCall = function (constructorDecl) {
            var _this = this;
            // October 1, 2013
            // Constructors of classes with no extends clause may not contain super calls, whereas
            // constructors of derived classes must contain at least one super call somewhere in
            // their function body. Super calls are not permitted outside constructors or in local
            // functions inside constructors.
            if (constructorDecl.block) {
                var foundSuperCall = false;
                var pre = function (ast, walker) {
                    // do not dive in functions - super calls inside them are illegal and should not be considered valid search results
                    if (TypeScript.SyntaxUtilities.isAnyFunctionExpressionOrDeclaration(ast)) {
                        walker.options.goChildren = false;
                        return;
                    }

                    // If we hit a super invocation, then we're done.  Stop everything we're doing.
                    // Note 1: there is no restriction on there being multiple super calls.
                    // Note 2: The restriction about super calls not being permitted in a local
                    // function is checked in typeCheckSuperExpression
                    if (_this.isSuperInvocationExpression(ast)) {
                        foundSuperCall = true;
                        walker.options.stopWalking = true;
                    }
                };

                TypeScript.getAstWalkerFactory().walk(constructorDecl.block, pre);
                return foundSuperCall;
            }

            return false;
        };

        PullTypeResolver.prototype.typeCheckFunctionExpression = function (funcDecl, isContextuallyTyped, context) {
            this.typeCheckAnyFunctionExpression(funcDecl, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList.parameters, funcDecl.callSignature.typeAnnotation, funcDecl.block, null, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.typeCheckCallSignature = function (funcDecl, context) {
            this.typeCheckAnyFunctionDeclaration(funcDecl, false, null, funcDecl.typeParameterList, funcDecl.parameterList, TypeScript.ASTHelpers.getType(funcDecl), null, context);
        };

        PullTypeResolver.prototype.typeCheckConstructSignature = function (funcDecl, context) {
            this.typeCheckAnyFunctionDeclaration(funcDecl, false, null, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList, TypeScript.ASTHelpers.getType(funcDecl), null, context);
        };

        PullTypeResolver.prototype.typeCheckMethodSignature = function (funcDecl, context) {
            this.typeCheckAnyFunctionDeclaration(funcDecl, false, funcDecl.propertyName, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList, TypeScript.ASTHelpers.getType(funcDecl), null, context);
        };

        PullTypeResolver.prototype.typeCheckMemberFunctionDeclaration = function (funcDecl, context) {
            this.typeCheckAnyFunctionDeclaration(funcDecl, TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Static), funcDecl.propertyName, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList, TypeScript.ASTHelpers.getType(funcDecl), funcDecl.block, context);
        };

        PullTypeResolver.prototype.containsSingleThrowStatement = function (block) {
            return block !== null && block.statements.length === 1 && block.statements[0].kind() === 157 /* ThrowStatement */;
        };

        PullTypeResolver.prototype.typeCheckAnyFunctionDeclaration = function (funcDeclAST, isStatic, name, typeParameters, parameters, returnTypeAnnotation, block, context) {
            var _this = this;
            this.setTypeChecked(funcDeclAST, context);

            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            if (typeParameters) {
                for (var i = 0; i < typeParameters.typeParameters.length; i++) {
                    this.resolveTypeParameterDeclaration(typeParameters.typeParameters[i], context);
                }
            }

            // resolve parameter type annotations as necessary
            this.resolveAST(parameters, false, context);

            this.resolveAST(block, false, context);
            var enclosingDecl = this.getEnclosingDecl(funcDecl);

            this.resolveReturnTypeAnnotationOfFunctionDeclaration(funcDeclAST, returnTypeAnnotation, context);
            this.validateVariableDeclarationGroups(funcDecl, context);

            this.checkFunctionTypePrivacy(funcDeclAST, isStatic, typeParameters, parameters.parameters, returnTypeAnnotation, block, context);

            this.checkThatNonVoidFunctionHasReturnExpressionOrThrowStatement(funcDecl, returnTypeAnnotation, funcDecl.getSignatureSymbol(this.semanticInfoChain).returnType, block, context);

            if (funcDecl.kind === TypeScript.PullElementKind.Function) {
                this.checkNameForCompilerGeneratedDeclarationCollision(funcDeclAST, true, name, context);
            }

            // Check for implicit any return types on signatures.
            // In cases where a function has a body, the return type can be inferred from the body.
            // In such cases, we do not consider an inferred any type to be implicit.
            if (this.compilationSettings.noImplicitAny() && block === null && returnTypeAnnotation === null) {
                this.checkAndReportImplicitAnyOnFunctionSignature(funcDeclAST, name, context);
            }

            this.typeCheckCallBacks.push(function (context) {
                // Function or constructor
                _this.typeCheckFunctionOverloads(funcDeclAST, context);
            });
        };

        // Given that we have no type annotation nor body, raise an error if we find it appropriate to do so.
        PullTypeResolver.prototype.checkAndReportImplicitAnyOnFunctionSignature = function (funcDeclAST, funcDeclASTName, context) {
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            // Don't report an error to the user if the field is a private ambient member.
            // Private fields don't actually need their types exposed, and in generated
            // .d.ts files, they are given no type annotations.
            if (this.isPrivateWithinAmbientDeclaration(funcDecl)) {
                return;
            }

            if (funcDecl.kind === TypeScript.PullElementKind.ConstructSignature) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Constructor_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type));
            } else if (funcDeclASTName !== null) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode._0_which_lacks_return_type_annotation_implicitly_has_an_any_return_type, [funcDeclASTName.text()]));
            } else {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Lambda_Function_which_lacks_return_type_annotation_implicitly_has_an_any_return_type));
            }
        };

        PullTypeResolver.prototype.isPrivateWithinAmbientDeclaration = function (funcDecl) {
            if (TypeScript.hasFlag(funcDecl.flags, TypeScript.PullElementFlags.Private)) {
                var parentDecl = funcDecl.getParentDecl();

                if (parentDecl !== null) {
                    return TypeScript.hasFlag(parentDecl.flags, TypeScript.PullElementFlags.Ambient);
                }
            }

            return false;
        };

        PullTypeResolver.prototype.checkThatNonVoidFunctionHasReturnExpressionOrThrowStatement = function (functionDecl, returnTypeAnnotation, returnTypeSymbol, block, context) {
            var hasReturn = TypeScript.hasFlag(functionDecl.flags, TypeScript.PullElementFlags.HasReturnStatement);

            // November 18, 2013
            // An explicitly typed function returning a non-void type must have at least one return
            // statement somewhere in its body. An exception to this rule is if the function
            // implementation consists of a single 'throw' statement.
            if (block !== null && returnTypeAnnotation !== null && !hasReturn) {
                var isVoidOrAny = this.isAnyOrEquivalent(returnTypeSymbol) || returnTypeSymbol === this.semanticInfoChain.voidTypeSymbol;

                if (!isVoidOrAny && !this.containsSingleThrowStatement(block)) {
                    var funcName = functionDecl.getDisplayName() || TypeScript.getLocalizedText(TypeScript.DiagnosticCode.expression, null);

                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(returnTypeAnnotation, TypeScript.DiagnosticCode.Function_declared_a_non_void_return_type_but_has_no_return_expression));
                }
            }
        };

        PullTypeResolver.prototype.typeCheckIndexSignature = function (funcDeclAST, context) {
            var _this = this;
            this.setTypeChecked(funcDeclAST, context);

            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            // resolve parameter type annotations as necessary
            this.resolveAST(funcDeclAST.parameters, false, context);

            var enclosingDecl = this.getEnclosingDecl(funcDecl);

            this.resolveReturnTypeAnnotationOfFunctionDeclaration(funcDeclAST, TypeScript.ASTHelpers.getType(funcDeclAST), context);
            this.validateVariableDeclarationGroups(funcDecl, context);

            this.checkFunctionTypePrivacy(funcDeclAST, false, null, funcDeclAST.parameters, TypeScript.ASTHelpers.getType(funcDeclAST), null, context);

            var signature = funcDecl.getSignatureSymbol(this.semanticInfoChain);

            this.typeCheckCallBacks.push(function (context) {
                var parentSymbol = funcDecl.getSignatureSymbol(_this.semanticInfoChain).getContainer();
                var allIndexSignatures = _this.getBothKindsOfIndexSignaturesExcludingAugmentedType(parentSymbol, context);
                var stringIndexSignature = allIndexSignatures.stringSignature;
                var numberIndexSignature = allIndexSignatures.numericSignature;
                var isNumericIndexer = numberIndexSignature === signature;

                // Section 3.7.4 (November 18, 2013):
                // Specifically, in a type with a string index signature of type T, all properties and numeric index signatures must
                // have types that are subtypes of T.
                // Check that the number signature is assignable to the string index signature. To ensure that we only check this once,
                // we make sure that if the two signatures share a container, we only check this when type checking the number signature.
                if (numberIndexSignature && stringIndexSignature && (isNumericIndexer || stringIndexSignature.getDeclarations()[0].getParentDecl() !== numberIndexSignature.getDeclarations()[0].getParentDecl())) {
                    var comparisonInfo = new TypeComparisonInfo();

                    if (!_this.sourceIsAssignableToTarget(numberIndexSignature.returnType, stringIndexSignature.returnType, funcDeclAST, context, comparisonInfo)) {
                        var enclosingSymbol = _this.getEnclosingSymbolForAST(funcDeclAST);
                        if (comparisonInfo.message) {
                            context.postDiagnostic(_this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Numeric_indexer_type_0_must_be_assignable_to_string_indexer_type_1_NL_2, [numberIndexSignature.returnType.toString(enclosingSymbol), stringIndexSignature.returnType.toString(enclosingSymbol), comparisonInfo.message]));
                        } else {
                            context.postDiagnostic(_this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Numeric_indexer_type_0_must_be_assignable_to_string_indexer_type_1, [numberIndexSignature.returnType.toString(enclosingSymbol), stringIndexSignature.returnType.toString(enclosingSymbol)]));
                        }
                    }
                }

                // Check that property names comply with indexer constraints (either string or numeric)
                var allMembers = parentSymbol.type.getAllMembers(TypeScript.PullElementKind.All, 0 /* all */);
                for (var i = 0; i < allMembers.length; i++) {
                    var member = allMembers[i];
                    var name = member.name;
                    if (name || (member.kind === TypeScript.PullElementKind.Property && name === "")) {
                        if (!allMembers[i].isResolved) {
                            _this.resolveDeclaredSymbol(allMembers[i], context);
                        }

                        // Skip members in the same container, they will be checked during their member type check
                        if (parentSymbol !== allMembers[i].getContainer()) {
                            // Check if the member name kind (number or string), matches the index signature kind. If it does give an error.
                            // If it doesn't we only want to give an error if this is a string signature, and we don't have a numeric signature
                            var isMemberNumeric = TypeScript.PullHelpers.isNameNumeric(name);
                            var indexerKindMatchesMemberNameKind = isNumericIndexer === isMemberNumeric;
                            var onlyStringIndexerIsPresent = !numberIndexSignature;

                            if (indexerKindMatchesMemberNameKind || onlyStringIndexerIsPresent) {
                                var comparisonInfo = new TypeComparisonInfo();
                                if (!_this.sourceIsAssignableToTarget(allMembers[i].type, signature.returnType, funcDeclAST, context, comparisonInfo, false)) {
                                    _this.reportErrorThatMemberIsNotSubtypeOfIndexer(allMembers[i], signature, funcDeclAST, context, comparisonInfo);
                                }
                            }
                        }
                    }
                }
            });
        };

        PullTypeResolver.prototype.postTypeCheckFunctionDeclaration = function (funcDeclAST, context) {
            this.checkThisCaptureVariableCollides(funcDeclAST, true, context);
        };

        PullTypeResolver.prototype.resolveReturnTypeAnnotationOfFunctionDeclaration = function (funcDeclAST, returnTypeAnnotation, context) {
            var returnTypeSymbol = null;

            // resolve the return type annotation
            if (returnTypeAnnotation) {
                var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

                // use the funcDecl for the enclosing decl, since we want to pick up any type parameters
                // on the function when resolving the return type
                returnTypeSymbol = this.resolveTypeReference(returnTypeAnnotation, context);

                if (!returnTypeSymbol) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(returnTypeAnnotation, TypeScript.DiagnosticCode.Cannot_resolve_return_type_reference));
                } else {
                    var isConstructor = funcDeclAST.kind() === 137 /* ConstructorDeclaration */ || funcDeclAST.kind() === 143 /* ConstructSignature */;
                    if (isConstructor && returnTypeSymbol === this.semanticInfoChain.voidTypeSymbol) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Constructors_cannot_have_a_return_type_of_void));
                    }
                }
            }

            return returnTypeSymbol;
        };

        PullTypeResolver.prototype.resolveMemberFunctionDeclaration = function (funcDecl, context) {
            return this.resolveFunctionDeclaration(funcDecl, TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Static), funcDecl.propertyName, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList, TypeScript.ASTHelpers.getType(funcDecl), funcDecl.block, context);
        };

        PullTypeResolver.prototype.resolveCallSignature = function (funcDecl, context) {
            return this.resolveFunctionDeclaration(funcDecl, false, null, funcDecl.typeParameterList, funcDecl.parameterList, TypeScript.ASTHelpers.getType(funcDecl), null, context);
        };

        PullTypeResolver.prototype.resolveConstructSignature = function (funcDecl, context) {
            return this.resolveFunctionDeclaration(funcDecl, false, null, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList, TypeScript.ASTHelpers.getType(funcDecl), null, context);
        };

        PullTypeResolver.prototype.resolveMethodSignature = function (funcDecl, context) {
            return this.resolveFunctionDeclaration(funcDecl, false, funcDecl.propertyName, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList, TypeScript.ASTHelpers.getType(funcDecl), null, context);
        };

        PullTypeResolver.prototype.resolveAnyFunctionDeclaration = function (funcDecl, context) {
            return this.resolveFunctionDeclaration(funcDecl, TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Static), funcDecl.identifier, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList, TypeScript.ASTHelpers.getType(funcDecl), funcDecl.block, context);
        };

        PullTypeResolver.prototype.resolveFunctionExpression = function (funcDecl, isContextuallyTyped, context) {
            return this.resolveAnyFunctionExpression(funcDecl, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList.parameters, TypeScript.ASTHelpers.getType(funcDecl), funcDecl.block, null, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.resolveSimpleArrowFunctionExpression = function (funcDecl, isContextuallyTyped, context) {
            return this.resolveAnyFunctionExpression(funcDecl, null, [funcDecl.parameter], null, funcDecl.block, funcDecl.expression, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.resolveParenthesizedArrowFunctionExpression = function (funcDecl, isContextuallyTyped, context) {
            return this.resolveAnyFunctionExpression(funcDecl, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList.parameters, TypeScript.ASTHelpers.getType(funcDecl), funcDecl.block, funcDecl.expression, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.getEnclosingClassDeclaration = function (ast) {
            while (ast) {
                if (ast.kind() === 131 /* ClassDeclaration */) {
                    return ast;
                }

                ast = ast.parent;
            }

            return null;
        };

        PullTypeResolver.prototype.resolveConstructorDeclaration = function (funcDeclAST, context) {
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            var funcSymbol = funcDecl.getSymbol(this.semanticInfoChain);

            var signature = funcDecl.getSignatureSymbol(this.semanticInfoChain);

            var hadError = false;

            if (signature) {
                if (signature.isResolved) {
                    if (this.canTypeCheckAST(funcDeclAST, context)) {
                        this.typeCheckConstructorDeclaration(funcDeclAST, context);
                    }
                    return funcSymbol;
                }

                if (!signature.inResolution) {
                    var classAST = this.getEnclosingClassDeclaration(funcDeclAST);

                    if (classAST) {
                        var classDecl = this.semanticInfoChain.getDeclForAST(classAST);
                        var classSymbol = classDecl.getSymbol(this.semanticInfoChain);

                        if (!classSymbol.isResolved && !classSymbol.inResolution) {
                            this.resolveDeclaredSymbol(classSymbol, context);
                        }
                    }
                }

                // Save this in case we had set the function type to any because of a recursive reference.
                var functionTypeSymbol = funcSymbol && funcSymbol.type;

                if (signature.inResolution) {
                    signature.returnType = this.semanticInfoChain.anyTypeSymbol;

                    if (funcSymbol) {
                        funcSymbol.setUnresolved();
                        if (funcSymbol.type === this.semanticInfoChain.anyTypeSymbol) {
                            funcSymbol.type = functionTypeSymbol;
                        }
                    }
                    signature.setResolved();
                    return funcSymbol;
                }

                if (funcSymbol) {
                    funcSymbol.startResolving();
                }
                signature.startResolving();

                // resolve parameter type annotations as necessary
                var prevInTypeCheck = context.inTypeCheck;

                // TODO: why are we getting ourselves out of typecheck here?
                context.inTypeCheck = false;

                for (var i = 0; i < funcDeclAST.callSignature.parameterList.parameters.length; i++) {
                    // TODO: why are we calling resolveParameter instead of resolveAST.
                    this.resolveParameter(funcDeclAST.callSignature.parameterList.parameters[i], context);
                }

                context.inTypeCheck = prevInTypeCheck;

                if (signature.isGeneric()) {
                    // PULLREVIEW: This is split into a spearate if statement to make debugging slightly easier...
                    if (funcSymbol) {
                        funcSymbol.type.setHasGenericSignature();
                    }
                }

                if (!hadError) {
                    if (funcSymbol) {
                        funcSymbol.setUnresolved();
                        if (funcSymbol.type === this.semanticInfoChain.anyTypeSymbol) {
                            funcSymbol.type = functionTypeSymbol;
                        }
                    }
                    signature.setResolved();
                }
            }

            if (funcSymbol) {
                this.resolveOtherDeclarations(funcDeclAST, context);
            }

            if (this.canTypeCheckAST(funcDeclAST, context)) {
                this.typeCheckConstructorDeclaration(funcDeclAST, context);
            }

            return funcSymbol;
        };

        PullTypeResolver.prototype.resolveIndexMemberDeclaration = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);
            }

            return this.resolveIndexSignature(ast.indexSignature, context);
        };

        PullTypeResolver.prototype.resolveIndexSignature = function (funcDeclAST, context) {
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            var funcSymbol = funcDecl.getSymbol(this.semanticInfoChain);

            var signature = funcDecl.getSignatureSymbol(this.semanticInfoChain);

            var hadError = false;

            if (signature) {
                if (signature.isResolved) {
                    if (this.canTypeCheckAST(funcDeclAST, context)) {
                        this.typeCheckIndexSignature(funcDeclAST, context);
                    }
                    return funcSymbol;
                }

                // Save this in case we had set the function type to any because of a recursive reference.
                var functionTypeSymbol = funcSymbol && funcSymbol.type;

                if (signature.inResolution) {
                    // try to set the return type, even though we may be lacking in some information
                    if (funcDeclAST.typeAnnotation) {
                        var returnTypeSymbol = this.resolveTypeReference(funcDeclAST.typeAnnotation.type, context);
                        if (!returnTypeSymbol) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(TypeScript.ASTHelpers.getType(funcDeclAST), TypeScript.DiagnosticCode.Cannot_resolve_return_type_reference));
                            signature.returnType = this.getNewErrorTypeSymbol();
                            hadError = true;
                        } else {
                            signature.returnType = returnTypeSymbol;
                        }
                    } else {
                        signature.returnType = this.semanticInfoChain.anyTypeSymbol;
                    }

                    if (funcSymbol) {
                        funcSymbol.setUnresolved();
                        if (funcSymbol.type === this.semanticInfoChain.anyTypeSymbol) {
                            funcSymbol.type = functionTypeSymbol;
                        }
                    }
                    signature.setResolved();
                    return funcSymbol;
                }

                if (funcSymbol) {
                    funcSymbol.startResolving();
                }
                signature.startResolving();

                // resolve parameter type annotations as necessary
                if (funcDeclAST.parameters.length === 1) {
                    var prevInTypeCheck = context.inTypeCheck;

                    // TODO: why are we setting inTypeCheck false here?
                    context.inTypeCheck = false;
                    this.resolveParameter(funcDeclAST.parameters[0], context);
                    context.inTypeCheck = prevInTypeCheck;
                }

                // resolve the return type annotation
                if (funcDeclAST.typeAnnotation) {
                    returnTypeSymbol = this.resolveReturnTypeAnnotationOfFunctionDeclaration(funcDeclAST, TypeScript.ASTHelpers.getType(funcDeclAST), context);

                    if (!returnTypeSymbol) {
                        signature.returnType = this.getNewErrorTypeSymbol();
                        hadError = true;
                    } else {
                        signature.returnType = returnTypeSymbol;
                    }
                } else {
                    signature.returnType = this.semanticInfoChain.anyTypeSymbol;
                }

                if (!hadError) {
                    if (funcSymbol) {
                        funcSymbol.setUnresolved();
                        if (funcSymbol.type === this.semanticInfoChain.anyTypeSymbol) {
                            funcSymbol.type = functionTypeSymbol;
                        }
                    }
                    signature.setResolved();
                }
            }

            if (funcSymbol) {
                this.resolveOtherDeclarations(funcDeclAST, context);
            }

            if (this.canTypeCheckAST(funcDeclAST, context)) {
                this.typeCheckIndexSignature(funcDeclAST, context);
            }

            return funcSymbol;
        };

        PullTypeResolver.prototype.resolveFunctionDeclaration = function (funcDeclAST, isStatic, name, typeParameters, parameterList, returnTypeAnnotation, block, context) {
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            var funcSymbol = funcDecl.getSymbol(this.semanticInfoChain);

            var signature = funcDecl.getSignatureSymbol(this.semanticInfoChain);

            var hadError = false;

            var isConstructor = funcDeclAST.kind() === 143 /* ConstructSignature */;

            if (signature) {
                if (signature.isResolved) {
                    if (this.canTypeCheckAST(funcDeclAST, context)) {
                        this.typeCheckAnyFunctionDeclaration(funcDeclAST, isStatic, name, typeParameters, parameterList, returnTypeAnnotation, block, context);
                    }
                    return funcSymbol;
                }

                if (isConstructor && !signature.inResolution) {
                    var classAST = this.getEnclosingClassDeclaration(funcDeclAST);

                    if (classAST) {
                        var classDecl = this.semanticInfoChain.getDeclForAST(classAST);
                        var classSymbol = classDecl.getSymbol(this.semanticInfoChain);

                        if (!classSymbol.isResolved && !classSymbol.inResolution) {
                            this.resolveDeclaredSymbol(classSymbol, context);
                        }
                    }
                }

                // Save this in case we had set the function type to any because of a recursive reference.
                var functionTypeSymbol = funcSymbol && funcSymbol.type;

                if (signature.inResolution) {
                    // try to set the return type, even though we may be lacking in some information
                    if (returnTypeAnnotation) {
                        var returnTypeSymbol = this.resolveTypeReference(returnTypeAnnotation, context);
                        if (!returnTypeSymbol) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(returnTypeAnnotation, TypeScript.DiagnosticCode.Cannot_resolve_return_type_reference));
                            signature.returnType = this.getNewErrorTypeSymbol();
                            hadError = true;
                        } else {
                            signature.returnType = returnTypeSymbol;

                            if (isConstructor && returnTypeSymbol === this.semanticInfoChain.voidTypeSymbol) {
                                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Constructors_cannot_have_a_return_type_of_void));
                            }
                        }
                    } else {
                        signature.returnType = this.semanticInfoChain.anyTypeSymbol;
                    }

                    if (funcSymbol) {
                        funcSymbol.setUnresolved();
                        if (funcSymbol.type === this.semanticInfoChain.anyTypeSymbol) {
                            funcSymbol.type = functionTypeSymbol;
                        }
                    }
                    signature.setResolved();
                    return funcSymbol;
                }

                if (funcSymbol) {
                    funcSymbol.startResolving();
                }
                signature.startResolving();

                if (typeParameters) {
                    for (var i = 0; i < typeParameters.typeParameters.length; i++) {
                        this.resolveTypeParameterDeclaration(typeParameters.typeParameters[i], context);
                    }
                }

                // resolve parameter type annotations as necessary
                if (parameterList) {
                    var prevInTypeCheck = context.inTypeCheck;

                    // TODO: why are we setting inTypeCheck false here?
                    context.inTypeCheck = false;

                    for (var i = 0; i < parameterList.parameters.length; i++) {
                        // TODO: why are are calling resolveParameter directly here?
                        this.resolveParameter(parameterList.parameters[i], context);
                    }

                    context.inTypeCheck = prevInTypeCheck;
                }

                // resolve the return type annotation
                if (returnTypeAnnotation) {
                    returnTypeSymbol = this.resolveReturnTypeAnnotationOfFunctionDeclaration(funcDeclAST, returnTypeAnnotation, context);

                    if (!returnTypeSymbol) {
                        signature.returnType = this.getNewErrorTypeSymbol();
                        hadError = true;
                    } else {
                        signature.returnType = returnTypeSymbol;
                    }
                } else if (funcDecl.kind !== TypeScript.PullElementKind.ConstructSignature) {
                    if (TypeScript.hasFlag(funcDecl.flags, TypeScript.PullElementFlags.Signature)) {
                        signature.returnType = this.semanticInfoChain.anyTypeSymbol;
                    } else {
                        this.resolveFunctionBodyReturnTypes(funcDeclAST, block, null, signature, false, funcDecl, context);
                    }
                } else {
                    signature.returnType = this.semanticInfoChain.anyTypeSymbol;
                }

                if (!hadError) {
                    if (funcSymbol) {
                        funcSymbol.setUnresolved();
                        if (funcSymbol.type === this.semanticInfoChain.anyTypeSymbol) {
                            funcSymbol.type = functionTypeSymbol;
                        }
                    }
                    signature.setResolved();
                }
            }

            if (funcSymbol) {
                this.resolveOtherDeclarations(funcDeclAST, context);
            }

            if (this.canTypeCheckAST(funcDeclAST, context)) {
                this.typeCheckAnyFunctionDeclaration(funcDeclAST, isStatic, name, typeParameters, parameterList, returnTypeAnnotation, block, context);
            }

            return funcSymbol;
        };

        PullTypeResolver.prototype.resolveGetterReturnTypeAnnotation = function (getterFunctionDeclarationAst, enclosingDecl, context) {
            if (getterFunctionDeclarationAst && getterFunctionDeclarationAst.callSignature.typeAnnotation) {
                return this.resolveTypeReference(TypeScript.ASTHelpers.getType(getterFunctionDeclarationAst), context);
            }

            return null;
        };

        PullTypeResolver.prototype.resolveSetterArgumentTypeAnnotation = function (setterFunctionDeclarationAst, enclosingDecl, context) {
            if (setterFunctionDeclarationAst && setterFunctionDeclarationAst.callSignature.parameterList && setterFunctionDeclarationAst.callSignature.parameterList.parameters.length > 0) {
                var parameter = setterFunctionDeclarationAst.callSignature.parameterList.parameters[0];
                return this.resolveTypeReference(TypeScript.ASTHelpers.getType(parameter), context);
            }

            return null;
        };

        PullTypeResolver.prototype.resolveAccessorDeclaration = function (funcDeclAst, context) {
            var functionDeclaration = this.semanticInfoChain.getDeclForAST(funcDeclAst);
            var accessorSymbol = functionDeclaration.getSymbol(this.semanticInfoChain);

            if (accessorSymbol.inResolution) {
                // TODO: Review, should an error be raised?
                accessorSymbol.type = this.semanticInfoChain.anyTypeSymbol;
                accessorSymbol.setResolved();

                return accessorSymbol;
            }

            if (accessorSymbol.isResolved) {
                if (!accessorSymbol.type) {
                    accessorSymbol.type = this.semanticInfoChain.anyTypeSymbol;
                }
            } else {
                var getterSymbol = accessorSymbol.getGetter();
                var getterFunctionDeclarationAst = getterSymbol ? getterSymbol.getDeclarations()[0].ast() : null;
                var hasGetter = getterSymbol !== null;

                var setterSymbol = accessorSymbol.getSetter();
                var setterFunctionDeclarationAst = setterSymbol ? setterSymbol.getDeclarations()[0].ast() : null;
                var hasSetter = setterSymbol !== null;

                var getterAnnotatedType = this.resolveGetterReturnTypeAnnotation(getterFunctionDeclarationAst, functionDeclaration, context);
                var getterHasTypeAnnotation = getterAnnotatedType !== null;

                var setterAnnotatedType = this.resolveSetterArgumentTypeAnnotation(setterFunctionDeclarationAst, functionDeclaration, context);
                var setterHasTypeAnnotation = setterAnnotatedType !== null;

                accessorSymbol.startResolving();

                // resolve accessors - resolution order doesn't matter
                if (hasGetter) {
                    getterSymbol = this.resolveGetAccessorDeclaration(getterFunctionDeclarationAst, getterFunctionDeclarationAst.callSignature.parameterList, TypeScript.ASTHelpers.getType(getterFunctionDeclarationAst), getterFunctionDeclarationAst.block, setterAnnotatedType, context);
                }

                if (hasSetter) {
                    setterSymbol = this.resolveSetAccessorDeclaration(setterFunctionDeclarationAst, setterFunctionDeclarationAst.callSignature.parameterList, context);
                }

                // enforce spec resolution rules
                if (hasGetter && hasSetter) {
                    var setterSig = setterSymbol.type.getCallSignatures()[0];
                    var setterParameters = setterSig.parameters;
                    var setterHasParameters = setterParameters.length > 0;
                    var getterSig = getterSymbol.type.getCallSignatures()[0];

                    var setterSuppliedTypeSymbol = setterHasParameters ? setterParameters[0].type : null;
                    var getterSuppliedTypeSymbol = getterSig.returnType;

                    // SPEC: October 1, 2013 section 4.5 -
                    // ? If only one accessor includes a type annotation, the other behaves as if it had the same type annotation.
                    // -- In this case setter has annotation and getter does not.
                    if (setterHasTypeAnnotation && !getterHasTypeAnnotation) {
                        getterSuppliedTypeSymbol = setterSuppliedTypeSymbol;
                        getterSig.returnType = setterSuppliedTypeSymbol;
                    } else if ((getterHasTypeAnnotation && !setterHasTypeAnnotation) || (!getterHasTypeAnnotation && !setterHasTypeAnnotation)) {
                        setterSuppliedTypeSymbol = getterSuppliedTypeSymbol;

                        if (setterHasParameters) {
                            setterParameters[0].type = getterSuppliedTypeSymbol;
                        }
                    }

                    // SPEC: October 1, 2013 section 4.5 -
                    // ? If both accessors include type annotations, the specified types must be identical.
                    if (!this.typesAreIdentical(setterSuppliedTypeSymbol, getterSuppliedTypeSymbol, context)) {
                        accessorSymbol.type = this.getNewErrorTypeSymbol();
                    } else {
                        accessorSymbol.type = getterSuppliedTypeSymbol;
                    }
                } else if (hasSetter) {
                    // only has setter
                    var setterSig = setterSymbol.type.getCallSignatures()[0];
                    var setterParameters = setterSig.parameters;
                    var setterHasParameters = setterParameters.length > 0;

                    accessorSymbol.type = setterHasParameters ? setterParameters[0].type : this.semanticInfoChain.anyTypeSymbol;
                } else {
                    // only has getter
                    var getterSig = getterSymbol.type.getCallSignatures()[0];
                    accessorSymbol.type = getterSig.returnType;
                }

                accessorSymbol.setResolved();
            }

            // type check if possible
            if (this.canTypeCheckAST(funcDeclAst, context)) {
                this.typeCheckAccessorDeclaration(funcDeclAst, context);
            }

            return accessorSymbol;
        };

        PullTypeResolver.prototype.typeCheckAccessorDeclaration = function (funcDeclAst, context) {
            this.setTypeChecked(funcDeclAst, context);
            var functionDeclaration = this.semanticInfoChain.getDeclForAST(funcDeclAst);
            var accessorSymbol = functionDeclaration.getSymbol(this.semanticInfoChain);
            var getterSymbol = accessorSymbol.getGetter();
            var setterSymbol = accessorSymbol.getSetter();

            var isGetter = funcDeclAst.kind() === 139 /* GetAccessor */;
            if (isGetter) {
                var getterFunctionDeclarationAst = funcDeclAst;
                context.pushNewContextualType(getterSymbol.type);
                this.typeCheckGetAccessorDeclaration(getterFunctionDeclarationAst, context);
                context.popAnyContextualType();
            } else {
                var setterFunctionDeclarationAst = funcDeclAst;
                this.typeCheckSetAccessorDeclaration(setterFunctionDeclarationAst, context);
            }
        };

        PullTypeResolver.prototype.resolveGetAccessorDeclaration = function (funcDeclAST, parameters, returnTypeAnnotation, block, setterAnnotatedType, context) {
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
            var accessorSymbol = funcDecl.getSymbol(this.semanticInfoChain);

            var getterSymbol = accessorSymbol.getGetter();
            var getterTypeSymbol = getterSymbol.type;

            var signature = getterTypeSymbol.getCallSignatures()[0];

            var hadError = false;

            if (signature) {
                if (signature.isResolved) {
                    return getterSymbol;
                }

                if (signature.inResolution) {
                    // PULLTODO: Error or warning?
                    signature.returnType = this.semanticInfoChain.anyTypeSymbol;
                    signature.setResolved();

                    return getterSymbol;
                }

                signature.startResolving();

                // resolve the return type annotation
                if (returnTypeAnnotation) {
                    var returnTypeSymbol = this.resolveReturnTypeAnnotationOfFunctionDeclaration(funcDeclAST, returnTypeAnnotation, context);

                    if (!returnTypeSymbol) {
                        signature.returnType = this.getNewErrorTypeSymbol();

                        hadError = true;
                    } else {
                        signature.returnType = returnTypeSymbol;
                    }
                } else {
                    // SPEC: October 1, 2013 section 4.5 -
                    // ? If only one accessor includes a type annotation, the other behaves as if it had the same type annotation.
                    // -- Use setterAnnotatedType if available
                    // ? If neither accessor includes a type annotation, the inferred return type of the get accessor becomes the parameter type of the set accessor.
                    if (!setterAnnotatedType) {
                        this.resolveFunctionBodyReturnTypes(funcDeclAST, block, null, signature, false, funcDecl, context);
                    } else {
                        signature.returnType = setterAnnotatedType;
                    }
                }

                if (!hadError) {
                    signature.setResolved();
                }
            }

            return getterSymbol;
        };

        PullTypeResolver.prototype.checkIfGetterAndSetterTypeMatch = function (funcDeclAST, context) {
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
            var accessorSymbol = funcDecl.getSymbol(this.semanticInfoChain);
            var getter = accessorSymbol.getGetter();
            var setter = accessorSymbol.getSetter();

            if (getter && setter) {
                var getterAST = getter.getDeclarations()[0].ast();
                var setterAST = setter.getDeclarations()[0].ast();

                // There exists:
                //     return type annotaion for the getter &&
                //     parameter type annotation for the setter
                if (getterAST.callSignature.typeAnnotation && PullTypeResolver.hasSetAccessorParameterTypeAnnotation(setterAST)) {
                    var setterSig = setter.type.getCallSignatures()[0];
                    var setterParameters = setterSig.parameters;

                    var getter = accessorSymbol.getGetter();
                    var getterSig = getter.type.getCallSignatures()[0];

                    var setterSuppliedTypeSymbol = setterParameters[0].type;
                    var getterSuppliedTypeSymbol = getterSig.returnType;

                    // Report errors if type do not match
                    if (!this.typesAreIdentical(setterSuppliedTypeSymbol, getterSuppliedTypeSymbol, context)) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.get_and_set_accessor_must_have_the_same_type));
                    }
                }
            }
        };

        PullTypeResolver.prototype.typeCheckGetAccessorDeclaration = function (funcDeclAST, context) {
            // Accessors are handled only by resolve/typeCheckAccessorDeclaration,
            // hence the resolve/typeCheckGetAccessorDeclaration is helper and need not set setTypeChecked flag
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
            var accessorSymbol = funcDecl.getSymbol(this.semanticInfoChain);

            this.resolveReturnTypeAnnotationOfFunctionDeclaration(funcDeclAST, TypeScript.ASTHelpers.getType(funcDeclAST), context);

            this.resolveAST(funcDeclAST.block, false, context);

            this.validateVariableDeclarationGroups(funcDecl, context);

            var enclosingDecl = this.getEnclosingDecl(funcDecl);

            var hasReturn = (funcDecl.flags & (TypeScript.PullElementFlags.Signature | TypeScript.PullElementFlags.HasReturnStatement)) !== 0;
            var funcNameAST = funcDeclAST.propertyName;

            // If there is no return statement report error:
            //      signature is doesnt have the return statement flag &&
            //      accessor body has atleast one statement and it isnt throw statement
            if (!hasReturn && !this.containsSingleThrowStatement(funcDeclAST.block)) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcNameAST, TypeScript.DiagnosticCode.Getters_must_return_a_value));
            }

            // Setter with return value is checked in typeCheckReturnExpression
            var setter = accessorSymbol.getSetter();
            if (setter) {
                var setterDecl = setter.getDeclarations()[0];
                var setterIsPrivate = TypeScript.hasFlag(setterDecl.flags, TypeScript.PullElementFlags.Private);
                var getterIsPrivate = TypeScript.hasModifier(funcDeclAST.modifiers, TypeScript.PullElementFlags.Private);

                if (getterIsPrivate !== setterIsPrivate) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcNameAST, TypeScript.DiagnosticCode.Getter_and_setter_accessors_do_not_agree_in_visibility));
                }

                this.checkIfGetterAndSetterTypeMatch(funcDeclAST, context);
            }

            this.checkFunctionTypePrivacy(funcDeclAST, TypeScript.hasModifier(funcDeclAST.modifiers, TypeScript.PullElementFlags.Static), null, funcDeclAST.callSignature.parameterList.parameters, TypeScript.ASTHelpers.getType(funcDeclAST), funcDeclAST.block, context);
        };

        PullTypeResolver.hasSetAccessorParameterTypeAnnotation = function (setAccessor) {
            return setAccessor.callSignature.parameterList && setAccessor.callSignature.parameterList.parameters.length > 0 && setAccessor.callSignature.parameterList.parameters[0].typeAnnotation !== null;
        };

        PullTypeResolver.prototype.resolveSetAccessorDeclaration = function (funcDeclAST, parameterList, context) {
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
            var accessorSymbol = funcDecl.getSymbol(this.semanticInfoChain);

            var setterSymbol = accessorSymbol.getSetter();
            var setterTypeSymbol = setterSymbol.type;

            var signature = funcDecl.getSignatureSymbol(this.semanticInfoChain);

            var hadError = false;

            if (signature) {
                if (signature.isResolved) {
                    return setterSymbol;
                }

                if (signature.inResolution) {
                    // PULLTODO: Error or warning?
                    signature.returnType = this.semanticInfoChain.voidTypeSymbol;
                    signature.setResolved();
                    return setterSymbol;
                }

                signature.startResolving();

                // resolve parameter type annotations as necessary
                if (parameterList) {
                    for (var i = 0; i < parameterList.parameters.length; i++) {
                        this.resolveParameter(parameterList.parameters[i], context);
                    }
                }

                // SPEC: October 1, 2013 section 4.5 -
                // ? A set accessor declaration is processed in the same manner as an ordinary function declaration
                //      with a single parameter and a Void return type.
                signature.returnType = this.semanticInfoChain.voidTypeSymbol;

                if (!hadError) {
                    signature.setResolved();
                }
            }

            return setterSymbol;
        };

        PullTypeResolver.prototype.typeCheckSetAccessorDeclaration = function (funcDeclAST, context) {
            // Accessors are handled only by resolve/typeCheckAccessorDeclaration,
            // hence the resolve/typeCheckSetAccessorDeclaration is helper and need not set setTypeChecked flag
            var funcDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
            var accessorSymbol = funcDecl.getSymbol(this.semanticInfoChain);

            if (funcDeclAST.callSignature.parameterList) {
                for (var i = 0; i < funcDeclAST.callSignature.parameterList.parameters.length; i++) {
                    this.resolveParameter(funcDeclAST.callSignature.parameterList.parameters[i], context);
                }
            }

            this.resolveAST(funcDeclAST.block, false, context);

            this.validateVariableDeclarationGroups(funcDecl, context);

            var hasReturn = (funcDecl.flags & (TypeScript.PullElementFlags.Signature | TypeScript.PullElementFlags.HasReturnStatement)) !== 0;

            var getter = accessorSymbol.getGetter();

            var funcNameAST = funcDeclAST.propertyName;

            // Setter with return value is checked in typeCheckReturnExpression
            if (getter) {
                var getterDecl = getter.getDeclarations()[0];
                var getterIsPrivate = TypeScript.hasFlag(getterDecl.flags, TypeScript.PullElementFlags.Private);
                var setterIsPrivate = TypeScript.hasModifier(funcDeclAST.modifiers, TypeScript.PullElementFlags.Private);

                if (getterIsPrivate !== setterIsPrivate) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcNameAST, TypeScript.DiagnosticCode.Getter_and_setter_accessors_do_not_agree_in_visibility));
                }

                this.checkIfGetterAndSetterTypeMatch(funcDeclAST, context);
            } else {
                // There is no getter specified
                // Only report noImplicitAny error message on setter if there is no getter
                // if the noImplicitAny flag is set to be true, report an error
                if (this.compilationSettings.noImplicitAny()) {
                    // if setter has an any type, it must be implicit any
                    var setterFunctionDeclarationAst = funcDeclAST;

                    if (!PullTypeResolver.hasSetAccessorParameterTypeAnnotation(setterFunctionDeclarationAst) && accessorSymbol.type === this.semanticInfoChain.anyTypeSymbol) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode._0_which_lacks_get_accessor_and_parameter_type_annotation_on_set_accessor_implicitly_has_an_any_type, [setterFunctionDeclarationAst.propertyName.text()]));
                    }
                }
            }

            this.checkFunctionTypePrivacy(funcDeclAST, TypeScript.hasModifier(funcDeclAST.modifiers, TypeScript.PullElementFlags.Static), null, funcDeclAST.callSignature.parameterList.parameters, null, funcDeclAST.block, context);
        };

        PullTypeResolver.prototype.resolveList = function (list, context) {
            if (this.canTypeCheckAST(list, context)) {
                this.setTypeChecked(list, context);

                for (var i = 0, n = list.length; i < n; i++) {
                    this.resolveAST(list[i], false, context);
                }
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveSeparatedList = function (list, context) {
            if (this.canTypeCheckAST(list, context)) {
                this.setTypeChecked(list, context);

                for (var i = 0, n = list.length; i < n; i++) {
                    this.resolveAST(list[i], false, context);
                }
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveVoidExpression = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);

                this.resolveAST(ast.expression, false, context);
            }

            // September 17, 2013: The void operator takes an operand of any type and produces the
            // value undefined.The type of the result is the Undefined type(3.2.6).
            return this.semanticInfoChain.undefinedTypeSymbol;
        };

        PullTypeResolver.prototype.resolveLogicalOperation = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckLogicalOperation(ast, context);
            }

            // September 17, 2013: The result is always of the Boolean primitive type.
            return this.semanticInfoChain.booleanTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckLogicalOperation = function (binex, context) {
            this.setTypeChecked(binex, context);

            var leftType = this.resolveAST(binex.left, false, context).type;
            var rightType = this.resolveAST(binex.right, false, context).type;

            // September 17, 2013:
            // The <, >, <=, >=, ==, !=, ===, and !== operators
            // These operators require one operand type to be identical to or a subtype of the
            // other operand type.
            var comparisonInfo = new TypeComparisonInfo();
            if (!this.sourceIsAssignableToTarget(leftType, rightType, binex, context, comparisonInfo) && !this.sourceIsAssignableToTarget(rightType, leftType, binex, context, comparisonInfo)) {
                var enclosingSymbol = this.getEnclosingSymbolForAST(binex);
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binex, TypeScript.DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2, [
                    TypeScript.SyntaxFacts.getText(TypeScript.SyntaxFacts.getOperatorTokenFromBinaryExpression(binex.kind())),
                    leftType.toString(enclosingSymbol), rightType.toString(enclosingSymbol)]));
            }
        };

        PullTypeResolver.prototype.resolveLogicalNotExpression = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);

                this.resolveAST(ast.operand, false, context);
            }

            // September 17, 2013: The ! operator permits its operand to be of any type and
            // produces a result of the Boolean primitive type.
            return this.semanticInfoChain.booleanTypeSymbol;
        };

        PullTypeResolver.prototype.resolveUnaryArithmeticOperation = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckUnaryArithmeticOperation(ast, context);
            }

            // September 17, 2013:
            // The ++ and-- operators ... produce a result of the Number primitive type.
            // The +, ?, and ~ operators ... produce a result of the Number primitive type.
            return this.semanticInfoChain.numberTypeSymbol;
        };

        PullTypeResolver.prototype.resolvePostfixUnaryExpression = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckPostfixUnaryExpression(ast, context);
            }

            // September 17, 2013:
            // The ++ and-- operators ... produce a result of the Number primitive type.
            // The +, ?, and ~ operators ... produce a result of the Number primitive type.
            return this.semanticInfoChain.numberTypeSymbol;
        };

        PullTypeResolver.prototype.isAnyOrNumberOrEnum = function (type) {
            return this.isAnyOrEquivalent(type) || type === this.semanticInfoChain.numberTypeSymbol || TypeScript.PullHelpers.symbolIsEnum(type);
        };

        PullTypeResolver.prototype.typeCheckUnaryArithmeticOperation = function (unaryExpression, context) {
            this.setTypeChecked(unaryExpression, context);

            var nodeType = unaryExpression.kind();
            var expression = this.resolveAST(unaryExpression.operand, false, context);

            // September 17, 2013: The +, ?, and ~ operators
            // These operators permit their operand to be of any type and produce a result of the
            // Number primitive type.
            if (nodeType === 164 /* PlusExpression */ || nodeType == 165 /* NegateExpression */ || nodeType == 166 /* BitwiseNotExpression */) {
                return;
            }

            TypeScript.Debug.assert(nodeType === 168 /* PreIncrementExpression */ || nodeType === 169 /* PreDecrementExpression */);

            // September 17, 2013: 4.14.1	The ++ and -- operators
            // These operators, in prefix or postfix form, require their operand to be of type Any,
            // the Number primitive type, or an enum type, and classified as a reference(section 4.1).
            var operandType = expression.type;
            if (!this.isAnyOrNumberOrEnum(operandType)) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(unaryExpression.operand, TypeScript.DiagnosticCode.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type));
            }

            // September 17, ... and classified as a reference(section 4.1).
            if (!this.isReference(unaryExpression.operand, expression)) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(unaryExpression.operand, TypeScript.DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer));
            }
        };

        PullTypeResolver.prototype.typeCheckPostfixUnaryExpression = function (unaryExpression, context) {
            this.setTypeChecked(unaryExpression, context);

            var nodeType = unaryExpression.kind();
            var expression = this.resolveAST(unaryExpression.operand, false, context);

            TypeScript.Debug.assert(nodeType === 210 /* PostIncrementExpression */ || nodeType === 211 /* PostDecrementExpression */);

            // September 17, 2013: 4.14.1	The ++ and -- operators
            // These operators, in prefix or postfix form, require their operand to be of type Any,
            // the Number primitive type, or an enum type, and classified as a reference(section 4.1).
            var operandType = expression.type;
            if (!this.isAnyOrNumberOrEnum(operandType)) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(unaryExpression.operand, TypeScript.DiagnosticCode.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type));
            }

            // September 17, ... and classified as a reference(section 4.1).
            if (!this.isReference(unaryExpression.operand, expression)) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(unaryExpression.operand, TypeScript.DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer));
            }
        };

        PullTypeResolver.prototype.resolveBinaryArithmeticExpression = function (binaryExpression, context) {
            if (this.canTypeCheckAST(binaryExpression, context)) {
                this.typeCheckBinaryArithmeticExpression(binaryExpression, context);
            }

            // September 17, 2013: The result is always of the Number primitive type.
            return this.semanticInfoChain.numberTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckBinaryArithmeticExpression = function (binaryExpression, context) {
            this.setTypeChecked(binaryExpression, context);

            var lhsSymbol = this.resolveAST(binaryExpression.left, false, context);

            var lhsType = lhsSymbol.type;
            var rhsType = this.resolveAST(binaryExpression.right, false, context).type;

            // September 17, 2013:
            // If one operand is the null or undefined value, it is treated as having the
            // type of the other operand.
            if (lhsType === this.semanticInfoChain.nullTypeSymbol || lhsType === this.semanticInfoChain.undefinedTypeSymbol) {
                lhsType = rhsType;
            }

            if (rhsType === this.semanticInfoChain.nullTypeSymbol || rhsType === this.semanticInfoChain.undefinedTypeSymbol) {
                rhsType = lhsType;
            }

            // September 17, 2013:
            // 4.15.1	The *, /, %, ?, <<, >>, >>>, &, ^, and | operators
            // These operators require their operands to be of type Any, the Number primitive type,
            // or an enum type
            var lhsIsFit = this.isAnyOrNumberOrEnum(lhsType);
            var rhsIsFit = this.isAnyOrNumberOrEnum(rhsType);

            if (!rhsIsFit) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.right, TypeScript.DiagnosticCode.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type));
            }

            if (!lhsIsFit) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.left, TypeScript.DiagnosticCode.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type));
            }

            if (lhsIsFit && rhsIsFit) {
                switch (binaryExpression.kind()) {
                    case 183 /* LeftShiftAssignmentExpression */:
                    case 184 /* SignedRightShiftAssignmentExpression */:
                    case 185 /* UnsignedRightShiftAssignmentExpression */:
                    case 176 /* SubtractAssignmentExpression */:
                    case 177 /* MultiplyAssignmentExpression */:
                    case 178 /* DivideAssignmentExpression */:
                    case 179 /* ModuloAssignmentExpression */:
                    case 182 /* OrAssignmentExpression */:
                    case 180 /* AndAssignmentExpression */:
                    case 181 /* ExclusiveOrAssignmentExpression */:
                        // Check if LHS is a valid target
                        if (!this.isReference(binaryExpression.left, lhsSymbol)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.left, TypeScript.DiagnosticCode.Invalid_left_hand_side_of_assignment_expression));
                        }

                        this.checkAssignability(binaryExpression.left, rhsType, lhsType, context);
                }
            }
        };

        PullTypeResolver.prototype.resolveTypeOfExpression = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);

                this.resolveAST(ast.expression, false, context);
            }

            // September 17, 2013: The typeof operator takes an operand of any type and produces
            // a value of the String primitive type
            return this.semanticInfoChain.stringTypeSymbol;
        };

        PullTypeResolver.prototype.resolveThrowStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);

                this.resolveAST(ast.expression, false, context);
            }

            // All statements have the 'void' type.
            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveDeleteExpression = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);
                this.resolveAST(ast.expression, false, context);
            }

            // September 17, 2013: The delete operator takes an operand of any type and produces a
            // result of the Boolean primitive type.
            return this.semanticInfoChain.booleanTypeSymbol;
        };

        PullTypeResolver.prototype.resolveInstanceOfExpression = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckInstanceOfExpression(ast, context);
            }

            // September 17, 2013: The result is always of the Boolean primitive type.
            return this.semanticInfoChain.booleanTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckInstanceOfExpression = function (binaryExpression, context) {
            this.setTypeChecked(binaryExpression, context);

            // Section 4.15.4:
            // September 17, 2013: The instanceof operator requires the left operand to be of type
            // Any, an object type, or a type parameter type, and the right operand to be of type
            // Any or a subtype of the ?Function? interface type.
            // We are using assignability instead of subtype here, which will be reflected in the
            // new spec.
            var lhsType = this.resolveAST(binaryExpression.left, false, context).type;
            var rhsType = this.resolveAST(binaryExpression.right, false, context).type;

            var enclosingSymbol = this.getEnclosingSymbolForAST(binaryExpression);
            var isValidLHS = this.isAnyOrEquivalent(lhsType) || lhsType.isObject() || lhsType.isTypeParameter();
            var isValidRHS = this.isAnyOrEquivalent(rhsType) || this.typeIsAssignableToFunction(rhsType, binaryExpression, context);

            if (!isValidLHS) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.left, TypeScript.DiagnosticCode.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter));
            }

            if (!isValidRHS) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.right, TypeScript.DiagnosticCode.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type));
            }
        };

        PullTypeResolver.prototype.resolveCommaExpression = function (commaExpression, context) {
            if (this.canTypeCheckAST(commaExpression, context)) {
                this.setTypeChecked(commaExpression, context);

                this.resolveAST(commaExpression.left, false, context);
            }

            // September 17, 2013: The comma operator permits the operands to be of any type and
            // produces a result that is of the same type as the second operand.
            return this.resolveAST(commaExpression.right, false, context).type;
        };

        PullTypeResolver.prototype.resolveInExpression = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckInExpression(ast, context);
            }

            // October 11, 2013:
            // The in operator requires the left operand to be of type Any, the String primitive
            // type, or the Number primitive type, and the right operand to be of type Any, an
            // object type, or a type parameter type.
            //
            // The result is always of the Boolean primitive type.
            return this.semanticInfoChain.booleanTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckInExpression = function (binaryExpression, context) {
            this.setTypeChecked(binaryExpression, context);

            // October 11, 2013:
            // The in operator requires the left operand to be of type Any, the String primitive
            // type, or the Number primitive type, and the right operand to be of type Any, an
            // object type, or a type parameter type.
            var lhsType = this.resolveAST(binaryExpression.left, false, context).type;
            var rhsType = this.resolveAST(binaryExpression.right, false, context).type;

            var isValidLHS = this.isAnyOrEquivalent(lhsType.type) || lhsType.type === this.semanticInfoChain.stringTypeSymbol || lhsType.type === this.semanticInfoChain.numberTypeSymbol;

            var isValidRHS = this.isAnyOrEquivalent(rhsType) || rhsType.isObject() || rhsType.isTypeParameter();

            if (!isValidLHS) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.left, TypeScript.DiagnosticCode.The_left_hand_side_of_an_in_expression_must_be_of_types_any_string_or_number));
            }

            if (!isValidRHS) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.right, TypeScript.DiagnosticCode.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter));
            }
        };

        PullTypeResolver.prototype.resolveForStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);

                this.resolveAST(ast.variableDeclaration, false, context);
                this.resolveAST(ast.initializer, false, context);
                this.resolveAST(ast.condition, false, context);
                this.resolveAST(ast.incrementor, false, context);
                this.resolveAST(ast.statement, false, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveForInStatement = function (forInStatement, context) {
            if (this.canTypeCheckAST(forInStatement, context)) {
                this.typeCheckForInStatement(forInStatement, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckForInStatement = function (forInStatement, context) {
            this.setTypeChecked(forInStatement, context);

            if (forInStatement.variableDeclaration) {
                var declaration = forInStatement.variableDeclaration;

                // The parser will already have reported an error if 0 or more than 1 variable
                // declarators are provided.
                if (declaration.variableDeclarators.length === 1) {
                    var varDecl = declaration.variableDeclarators[0];

                    if (varDecl.typeAnnotation) {
                        // November 18, 2013
                        // VarDecl must be a variable declaration without a type annotation.
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(declaration, TypeScript.DiagnosticCode.Variable_declarations_of_a_for_statement_cannot_use_a_type_annotation));
                    }
                }
            } else {
                // November 18, 2013
                // In a ?for-in? statement of the form
                // for (Var in Expr) Statement
                // Var must be an expression classified as a reference of type Any or the String primitive type
                var varSym = this.resolveAST(forInStatement.left, false, context);
                var isStringOrNumber = varSym.type === this.semanticInfoChain.stringTypeSymbol || this.isAnyOrEquivalent(varSym.type);

                if (!isStringOrNumber) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(forInStatement.left, TypeScript.DiagnosticCode.Variable_declarations_of_a_for_statement_must_be_of_types_string_or_any));
                }
            }

            // November 18, 2013
            // In a ?for-in? statement of the form
            // for (Var in Expr) Statement [or of the form]
            // for (var VarDecl in Expr) Statement
            // ... Expr must be an expression of type Any, an object type, or a type parameter type.
            var rhsType = this.resolveAST(forInStatement.expression, false, context).type;
            var isValidRHS = rhsType && (this.isAnyOrEquivalent(rhsType) || rhsType.isObject() || rhsType.isTypeParameter());

            if (!isValidRHS) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(forInStatement.expression, TypeScript.DiagnosticCode.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter));
            }

            this.resolveAST(forInStatement.statement, false, context);
        };

        PullTypeResolver.prototype.resolveWhileStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckWhileStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckWhileStatement = function (ast, context) {
            this.setTypeChecked(ast, context);

            this.resolveAST(ast.condition, false, context);
            this.resolveAST(ast.statement, false, context);
        };

        PullTypeResolver.prototype.resolveDoStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckDoStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckDoStatement = function (ast, context) {
            this.setTypeChecked(ast, context);

            this.resolveAST(ast.condition, false, context);
            this.resolveAST(ast.statement, false, context);
        };

        PullTypeResolver.prototype.resolveIfStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckIfStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckIfStatement = function (ast, context) {
            this.setTypeChecked(ast, context);

            this.resolveAST(ast.condition, false, context);
            this.resolveAST(ast.statement, false, context);
            this.resolveAST(ast.elseClause, false, context);
        };

        PullTypeResolver.prototype.resolveElseClause = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckElseClause(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckElseClause = function (ast, context) {
            this.setTypeChecked(ast, context);

            this.resolveAST(ast.statement, false, context);
        };

        PullTypeResolver.prototype.resolveBlock = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);

                this.checkFunctionOverloadChains(ast, ast.statements);
                this.resolveAST(ast.statements, false, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveVariableStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);
                this.resolveAST(ast.variableDeclaration, false, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveVariableDeclarationList = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);
                this.resolveAST(ast.variableDeclarators, false, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveWithStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckWithStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckWithStatement = function (ast, context) {
            this.setTypeChecked(ast, context);
            var withStatement = ast;
            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(withStatement.condition, TypeScript.DiagnosticCode.All_symbols_within_a_with_block_will_be_resolved_to_any));
        };

        PullTypeResolver.prototype.resolveTryStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckTryStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckTryStatement = function (ast, context) {
            this.setTypeChecked(ast, context);
            var tryStatement = ast;

            this.resolveAST(tryStatement.block, false, context);
            this.resolveAST(tryStatement.catchClause, false, context);
            this.resolveAST(tryStatement.finallyClause, false, context);
        };

        PullTypeResolver.prototype.resolveCatchClause = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckCatchClause(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckCatchClause = function (ast, context) {
            this.setTypeChecked(ast, context);
            this.resolveAST(ast.block, false, context);

            var catchDecl = this.semanticInfoChain.getDeclForAST(ast);
            this.validateVariableDeclarationGroups(catchDecl, context);
        };

        PullTypeResolver.prototype.resolveFinallyClause = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckFinallyClause(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckFinallyClause = function (ast, context) {
            this.setTypeChecked(ast, context);
            this.resolveAST(ast.block, false, context);
        };

        PullTypeResolver.prototype.getEnclosingFunctionDeclaration = function (ast) {
            var enclosingDecl = this.getEnclosingDeclForAST(ast);

            while (enclosingDecl) {
                if (enclosingDecl.kind & TypeScript.PullElementKind.SomeFunction) {
                    return enclosingDecl;
                }

                enclosingDecl = enclosingDecl.getParentDecl();
            }

            return null;
        };

        PullTypeResolver.prototype.resolveReturnExpression = function (expression, enclosingFunction, context) {
            if (enclosingFunction) {
                enclosingFunction.setFlag(TypeScript.PullElementFlags.HasReturnStatement);
            }

            // push contextual type
            var isContextuallyTyped = false;

            if (enclosingFunction) {
                var enclosingDeclAST = this.getASTForDecl(enclosingFunction);
                var typeAnnotation = TypeScript.ASTHelpers.getType(enclosingDeclAST);
                if (typeAnnotation) {
                    // The containing function has a type annotation, propagate it as the contextual type
                    var returnTypeAnnotationSymbol = this.resolveTypeReference(typeAnnotation, context);
                    if (returnTypeAnnotationSymbol) {
                        isContextuallyTyped = true;
                        context.pushNewContextualType(returnTypeAnnotationSymbol);
                    }
                } else {
                    // No type annotation, check if there is a contextual type enforced on the function, and propagate that
                    var currentContextualType = context.getContextualType();
                    if (currentContextualType && currentContextualType.isFunction()) {
                        var contextualSignatures = currentContextualType.kind == TypeScript.PullElementKind.ConstructorType ? currentContextualType.getConstructSignatures() : currentContextualType.getCallSignatures();
                        var currentContextualTypeSignatureSymbol = contextualSignatures[0];

                        var currentContextualTypeReturnTypeSymbol = currentContextualTypeSignatureSymbol.returnType;
                        if (currentContextualTypeReturnTypeSymbol) {
                            isContextuallyTyped = true;
                            context.propagateContextualType(currentContextualTypeReturnTypeSymbol);
                        }
                    }
                }
            }

            var result = this.resolveAST(expression, isContextuallyTyped, context).type;
            if (isContextuallyTyped) {
                context.popAnyContextualType();
            }

            return result;
        };

        PullTypeResolver.prototype.typeCheckReturnExpression = function (expression, expressionType, enclosingFunction, context) {
            // Return type of constructor signature must be assignable to the instance type of the class.
            if (enclosingFunction && enclosingFunction.kind === TypeScript.PullElementKind.ConstructorMethod) {
                var classDecl = enclosingFunction.getParentDecl();
                if (classDecl) {
                    var classSymbol = classDecl.getSymbol(this.semanticInfoChain);
                    this.resolveDeclaredSymbol(classSymbol, context);

                    var comparisonInfo = new TypeComparisonInfo();
                    var isAssignable = this.sourceIsAssignableToTarget(expressionType, classSymbol.type, expression, context, comparisonInfo);
                    if (!isAssignable) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(expression, TypeScript.DiagnosticCode.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class));
                    }
                }
            }

            if (enclosingFunction && enclosingFunction.kind === TypeScript.PullElementKind.SetAccessor) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(expression, TypeScript.DiagnosticCode.Setters_cannot_return_a_value));
            }

            if (enclosingFunction) {
                var enclosingDeclAST = this.getASTForDecl(enclosingFunction);
                var typeAnnotation = TypeScript.ASTHelpers.getType(enclosingDeclAST);
                if (typeAnnotation || enclosingFunction.kind === TypeScript.PullElementKind.GetAccessor) {
                    var signatureSymbol = enclosingFunction.getSignatureSymbol(this.semanticInfoChain);
                    var sigReturnType = signatureSymbol.returnType;

                    if (expressionType && sigReturnType) {
                        var comparisonInfo = new TypeComparisonInfo();
                        var upperBound = null;

                        this.resolveDeclaredSymbol(expressionType, context);
                        this.resolveDeclaredSymbol(sigReturnType, context);

                        var isAssignable = this.sourceIsAssignableToTarget(expressionType, sigReturnType, expression, context, comparisonInfo);

                        if (!isAssignable) {
                            var enclosingSymbol = this.getEnclosingSymbolForAST(expression);
                            if (comparisonInfo.message) {
                                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(expression, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1_NL_2, [expressionType.toString(enclosingSymbol), sigReturnType.toString(enclosingSymbol), comparisonInfo.message]));
                            } else {
                                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(expression, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1, [expressionType.toString(enclosingSymbol), sigReturnType.toString(enclosingSymbol)]));
                            }
                        }
                    }
                }
            }
        };

        PullTypeResolver.prototype.resolveReturnStatement = function (returnAST, context) {
            var enclosingFunction = this.getEnclosingFunctionDeclaration(returnAST);
            if (enclosingFunction) {
                enclosingFunction.setFlag(TypeScript.PullElementFlags.HasReturnStatement);
            }

            var returnType = this.getSymbolForAST(returnAST, context);
            var canTypeCheckAST = this.canTypeCheckAST(returnAST, context);
            if (!returnType || canTypeCheckAST) {
                var returnExpr = returnAST.expression;

                var resolvedReturnType = returnExpr === null ? this.semanticInfoChain.voidTypeSymbol : this.resolveReturnExpression(returnExpr, enclosingFunction, context);

                if (!returnType) {
                    returnType = resolvedReturnType;
                    this.setSymbolForAST(returnAST, resolvedReturnType, context);
                }

                if (returnExpr && canTypeCheckAST) {
                    this.setTypeChecked(returnExpr, context);
                    this.typeCheckReturnExpression(returnExpr, resolvedReturnType, enclosingFunction, context);
                }
            }

            return returnType;
        };

        PullTypeResolver.prototype.resolveSwitchStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckSwitchStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckSwitchStatement = function (ast, context) {
            this.setTypeChecked(ast, context);

            var expressionType = this.resolveAST(ast.expression, false, context).type;

            for (var i = 0, n = ast.switchClauses.length; i < n; i++) {
                var switchClause = ast.switchClauses[i];
                if (switchClause.kind() === 233 /* CaseSwitchClause */) {
                    var caseSwitchClause = switchClause;

                    var caseClauseExpressionType = this.resolveAST(caseSwitchClause.expression, false, context).type;
                    this.resolveAST(caseSwitchClause.statements, false, context);

                    var comparisonInfo = new TypeComparisonInfo();
                    if (!this.sourceIsAssignableToTarget(expressionType, caseClauseExpressionType, caseSwitchClause.expression, context, comparisonInfo) && !this.sourceIsAssignableToTarget(caseClauseExpressionType, expressionType, caseSwitchClause.expression, context, comparisonInfo)) {
                        var enclosingSymbol = this.getEnclosingSymbolForAST(caseSwitchClause.expression);
                        if (comparisonInfo.message) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(caseSwitchClause.expression, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1_NL_2, [caseClauseExpressionType.toString(enclosingSymbol), expressionType.toString(enclosingSymbol), comparisonInfo.message]));
                        } else {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(caseSwitchClause.expression, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1, [caseClauseExpressionType.toString(enclosingSymbol), expressionType.toString(enclosingSymbol)]));
                        }
                    }
                } else {
                    var defaultSwitchClause = switchClause;
                    this.resolveAST(defaultSwitchClause.statements, false, context);
                }
            }
        };

        PullTypeResolver.prototype.resolveLabeledStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckLabeledStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckLabeledStatement = function (ast, context) {
            this.setTypeChecked(ast, context);

            this.resolveAST(ast.statement, false, context);
        };

        PullTypeResolver.prototype.resolveContinueStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckContinueStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckContinueStatement = function (ast, context) {
            this.setTypeChecked(ast, context);
        };

        PullTypeResolver.prototype.resolveBreakStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckBreakStatement(ast, context);
            }

            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.typeCheckBreakStatement = function (ast, context) {
            this.setTypeChecked(ast, context);
        };

        // Expression resolution
        PullTypeResolver.prototype.resolveAST = function (ast, isContextuallyTyped, context) {
            if (!ast) {
                return null;
            }

            if (TypeScript.isShared(ast)) {
                return null;
            }

            var symbol = this.getSymbolForAST(ast, context);
            if (symbol && symbol.isResolved) {
                this.typeCheckAST(ast, isContextuallyTyped, context);
                return symbol;
            }

            // We also have to check isTypesOnlyLocation because an identifier representing a type reference
            // is considered an expression at the AST level, yet we only want to resolve it as an expression
            // if it is in an expression position.
            if (TypeScript.isNode(ast) || TypeScript.isToken(ast)) {
                if (TypeScript.SyntaxUtilities.isExpression(ast) && !isTypesOnlyLocation(ast)) {
                    return this.resolveExpressionAST(ast, isContextuallyTyped, context);
                }
            }

            var nodeType = ast.kind();

            switch (nodeType) {
                case 124 /* ArrayType */:
                case 126 /* GenericType */:
                case 122 /* ObjectType */:
                case 127 /* TypeQuery */:
                case 125 /* ConstructorType */:
                case 123 /* FunctionType */:
                    return this.resolveTypeReference(ast, context);

                case 1 /* List */:
                    return this.resolveList(ast, context);

                case 2 /* SeparatedList */:
                    return this.resolveSeparatedList(ast, context);

                case 120 /* SourceUnit */:
                    return this.resolveSourceUnit(ast, context);

                case 132 /* EnumDeclaration */:
                    return this.resolveEnumDeclaration(ast, context);

                case 130 /* ModuleDeclaration */:
                    return this.resolveModuleDeclaration(ast, context);

                case 128 /* InterfaceDeclaration */:
                    return this.resolveInterfaceDeclaration(ast, context);

                case 131 /* ClassDeclaration */:
                    return this.resolveClassDeclaration(ast, context);

                case 224 /* VariableDeclaration */:
                    return this.resolveVariableDeclarationList(ast, context);

                case 136 /* MemberVariableDeclaration */:
                    return this.resolveMemberVariableDeclaration(ast, context);

                case 225 /* VariableDeclarator */:
                    return this.resolveVariableDeclarator(ast, context);

                case 141 /* PropertySignature */:
                    return this.resolvePropertySignature(ast, context);

                case 227 /* ParameterList */:
                    return this.resolveParameterList(ast, context);

                case 242 /* Parameter */:
                    return this.resolveParameter(ast, context);

                case 243 /* EnumElement */:
                    return this.resolveEnumElement(ast, context);

                case 232 /* EqualsValueClause */:
                    return this.resolveEqualsValueClause(ast, isContextuallyTyped, context);

                case 238 /* TypeParameter */:
                    return this.resolveTypeParameterDeclaration(ast, context);

                case 239 /* Constraint */:
                    return this.resolveConstraint(ast, context);

                case 133 /* ImportDeclaration */:
                    return this.resolveImportDeclaration(ast, context);

                case 240 /* SimplePropertyAssignment */:
                    return this.resolveSimplePropertyAssignment(ast, isContextuallyTyped, context);

                case 241 /* FunctionPropertyAssignment */:
                    return this.resolveFunctionPropertyAssignment(ast, isContextuallyTyped, context);

                case 11 /* IdentifierName */:
                    TypeScript.Debug.assert(isTypesOnlyLocation(ast));
                    return this.resolveTypeNameExpression(ast, context);

                case 121 /* QualifiedName */:
                    return this.resolveQualifiedName(ast, context);

                case 137 /* ConstructorDeclaration */:
                    return this.resolveConstructorDeclaration(ast, context);

                case 139 /* GetAccessor */:
                case 140 /* SetAccessor */:
                    return this.resolveAccessorDeclaration(ast, context);

                case 138 /* IndexMemberDeclaration */:
                    return this.resolveIndexMemberDeclaration(ast, context);

                case 144 /* IndexSignature */:
                    return this.resolveIndexSignature(ast, context);

                case 135 /* MemberFunctionDeclaration */:
                    return this.resolveMemberFunctionDeclaration(ast, context);

                case 142 /* CallSignature */:
                    return this.resolveCallSignature(ast, context);

                case 143 /* ConstructSignature */:
                    return this.resolveConstructSignature(ast, context);

                case 145 /* MethodSignature */:
                    return this.resolveMethodSignature(ast, context);

                case 129 /* FunctionDeclaration */:
                    return this.resolveAnyFunctionDeclaration(ast, context);

                case 244 /* TypeAnnotation */:
                    return this.resolveTypeAnnotation(ast, context);

                case 134 /* ExportAssignment */:
                    return this.resolveExportAssignmentStatement(ast, context);

                case 157 /* ThrowStatement */:
                    return this.resolveThrowStatement(ast, context);

                case 149 /* ExpressionStatement */:
                    return this.resolveExpressionStatement(ast, context);

                case 154 /* ForStatement */:
                    return this.resolveForStatement(ast, context);

                case 155 /* ForInStatement */:
                    return this.resolveForInStatement(ast, context);

                case 158 /* WhileStatement */:
                    return this.resolveWhileStatement(ast, context);

                case 161 /* DoStatement */:
                    return this.resolveDoStatement(ast, context);

                case 147 /* IfStatement */:
                    return this.resolveIfStatement(ast, context);

                case 235 /* ElseClause */:
                    return this.resolveElseClause(ast, context);

                case 146 /* Block */:
                    return this.resolveBlock(ast, context);

                case 148 /* VariableStatement */:
                    return this.resolveVariableStatement(ast, context);

                case 163 /* WithStatement */:
                    return this.resolveWithStatement(ast, context);

                case 159 /* TryStatement */:
                    return this.resolveTryStatement(ast, context);

                case 236 /* CatchClause */:
                    return this.resolveCatchClause(ast, context);

                case 237 /* FinallyClause */:
                    return this.resolveFinallyClause(ast, context);

                case 150 /* ReturnStatement */:
                    return this.resolveReturnStatement(ast, context);

                case 151 /* SwitchStatement */:
                    return this.resolveSwitchStatement(ast, context);

                case 153 /* ContinueStatement */:
                    return this.resolveContinueStatement(ast, context);

                case 152 /* BreakStatement */:
                    return this.resolveBreakStatement(ast, context);

                case 160 /* LabeledStatement */:
                    return this.resolveLabeledStatement(ast, context);
            }

            return this.semanticInfoChain.anyTypeSymbol;
        };

        PullTypeResolver.prototype.resolveExpressionAST = function (ast, isContextuallyOrInferentiallyTyped, context) {
            var expressionSymbol = this.resolveExpressionWorker(ast, isContextuallyOrInferentiallyTyped, context);

            // November 18, 2013, Section 4.12.2:
            // If e is an expression of a function type that contains exactly one generic call signature
            // and no other members, and T is a function type with exactly one non-generic call signature
            // and no other members, then any inferences made for type parameters referenced by the
            // parameters of T's call signature are fixed and, if e's call signature can successfully be
            // instantiated in the context of T's call signature(section 3.8.5), e's type is changed to
            // a function type with that instantiated signature.
            if (isContextuallyOrInferentiallyTyped && context.isInferentiallyTyping()) {
                return this.alterPotentialGenericFunctionTypeToInstantiatedFunctionTypeForTypeArgumentInference(expressionSymbol, context);
            } else {
                return expressionSymbol;
            }
        };

        PullTypeResolver.prototype.resolveExpressionWorker = function (ast, isContextuallyTyped, context) {
            switch (ast.kind()) {
                case 215 /* ObjectLiteralExpression */:
                    return this.resolveObjectLiteralExpression(ast, isContextuallyTyped, context);

                case 11 /* IdentifierName */:
                    // We already know we are in an expression, so there is no need
                    // to decide between resolveNameExpression and resolveTypeNameExpression
                    return this.resolveNameExpression(ast, context);

                case 212 /* MemberAccessExpression */:
                    return this.resolveMemberAccessExpression(ast, context);

                case 222 /* FunctionExpression */:
                    return this.resolveFunctionExpression(ast, isContextuallyTyped, context);

                case 219 /* SimpleArrowFunctionExpression */:
                    return this.resolveSimpleArrowFunctionExpression(ast, isContextuallyTyped, context);

                case 218 /* ParenthesizedArrowFunctionExpression */:
                    return this.resolveParenthesizedArrowFunctionExpression(ast, isContextuallyTyped, context);

                case 214 /* ArrayLiteralExpression */:
                    return this.resolveArrayLiteralExpression(ast, isContextuallyTyped, context);

                case 35 /* ThisKeyword */:
                    return this.resolveThisExpression(ast, context);

                case 50 /* SuperKeyword */:
                    return this.resolveSuperExpression(ast, context);

                case 213 /* InvocationExpression */:
                    return this.resolveInvocationExpression(ast, context);

                case 216 /* ObjectCreationExpression */:
                    return this.resolveObjectCreationExpression(ast, context);

                case 220 /* CastExpression */:
                    return this.resolveCastExpression(ast, context);

                case 13 /* NumericLiteral */:
                    return this.semanticInfoChain.numberTypeSymbol;

                case 14 /* StringLiteral */:
                    return this.semanticInfoChain.stringTypeSymbol;

                case 32 /* NullKeyword */:
                    return this.semanticInfoChain.nullTypeSymbol;

                case 37 /* TrueKeyword */:
                case 24 /* FalseKeyword */:
                    return this.semanticInfoChain.booleanTypeSymbol;

                case 172 /* VoidExpression */:
                    return this.resolveVoidExpression(ast, context);

                case 174 /* AssignmentExpression */:
                    return this.resolveAssignmentExpression(ast, context);

                case 167 /* LogicalNotExpression */:
                    return this.resolveLogicalNotExpression(ast, context);

                case 193 /* NotEqualsWithTypeConversionExpression */:
                case 192 /* EqualsWithTypeConversionExpression */:
                case 194 /* EqualsExpression */:
                case 195 /* NotEqualsExpression */:
                case 196 /* LessThanExpression */:
                case 198 /* LessThanOrEqualExpression */:
                case 199 /* GreaterThanOrEqualExpression */:
                case 197 /* GreaterThanExpression */:
                    return this.resolveLogicalOperation(ast, context);

                case 208 /* AddExpression */:
                case 175 /* AddAssignmentExpression */:
                    return this.resolveBinaryAdditionOperation(ast, context);

                case 164 /* PlusExpression */:
                case 165 /* NegateExpression */:
                case 166 /* BitwiseNotExpression */:
                case 168 /* PreIncrementExpression */:
                case 169 /* PreDecrementExpression */:
                    return this.resolveUnaryArithmeticOperation(ast, context);

                case 210 /* PostIncrementExpression */:
                case 211 /* PostDecrementExpression */:
                    return this.resolvePostfixUnaryExpression(ast, context);

                case 209 /* SubtractExpression */:
                case 205 /* MultiplyExpression */:
                case 206 /* DivideExpression */:
                case 207 /* ModuloExpression */:
                case 189 /* BitwiseOrExpression */:
                case 191 /* BitwiseAndExpression */:
                case 202 /* LeftShiftExpression */:
                case 203 /* SignedRightShiftExpression */:
                case 204 /* UnsignedRightShiftExpression */:
                case 190 /* BitwiseExclusiveOrExpression */:
                case 181 /* ExclusiveOrAssignmentExpression */:
                case 183 /* LeftShiftAssignmentExpression */:
                case 184 /* SignedRightShiftAssignmentExpression */:
                case 185 /* UnsignedRightShiftAssignmentExpression */:
                case 176 /* SubtractAssignmentExpression */:
                case 177 /* MultiplyAssignmentExpression */:
                case 178 /* DivideAssignmentExpression */:
                case 179 /* ModuloAssignmentExpression */:
                case 182 /* OrAssignmentExpression */:
                case 180 /* AndAssignmentExpression */:
                    return this.resolveBinaryArithmeticExpression(ast, context);

                case 221 /* ElementAccessExpression */:
                    return this.resolveElementAccessExpression(ast, context);

                case 187 /* LogicalOrExpression */:
                    return this.resolveLogicalOrExpression(ast, isContextuallyTyped, context);

                case 188 /* LogicalAndExpression */:
                    return this.resolveLogicalAndExpression(ast, context);

                case 171 /* TypeOfExpression */:
                    return this.resolveTypeOfExpression(ast, context);

                case 170 /* DeleteExpression */:
                    return this.resolveDeleteExpression(ast, context);

                case 186 /* ConditionalExpression */:
                    return this.resolveConditionalExpression(ast, isContextuallyTyped, context);

                case 12 /* RegularExpressionLiteral */:
                    return this.resolveRegularExpressionLiteral();

                case 217 /* ParenthesizedExpression */:
                    return this.resolveParenthesizedExpression(ast, context);

                case 200 /* InstanceOfExpression */:
                    return this.resolveInstanceOfExpression(ast, context);

                case 173 /* CommaExpression */:
                    return this.resolveCommaExpression(ast, context);

                case 201 /* InExpression */:
                    return this.resolveInExpression(ast, context);

                case 223 /* OmittedExpression */:
                    return this.semanticInfoChain.undefinedTypeSymbol;
            }

            TypeScript.Debug.fail("resolveExpressionASTWorker: Missing expression kind: " + TypeScript.SyntaxKind[ast.kind()]);
        };

        PullTypeResolver.prototype.typeCheckAST = function (ast, isContextuallyTyped, context) {
            if (!this.canTypeCheckAST(ast, context)) {
                return;
            }

            var nodeType = ast.kind();
            switch (nodeType) {
                case 120 /* SourceUnit */:
                    this.typeCheckSourceUnit(ast, context);
                    return;

                case 132 /* EnumDeclaration */:
                    this.typeCheckEnumDeclaration(ast, context);
                    return;

                case 130 /* ModuleDeclaration */:
                    this.typeCheckModuleDeclaration(ast, context);
                    return;

                case 128 /* InterfaceDeclaration */:
                    this.typeCheckInterfaceDeclaration(ast, context);
                    return;

                case 131 /* ClassDeclaration */:
                    this.typeCheckClassDeclaration(ast, context);
                    return;

                case 243 /* EnumElement */:
                    this.typeCheckEnumElement(ast, context);
                    return;

                case 136 /* MemberVariableDeclaration */:
                    this.typeCheckMemberVariableDeclaration(ast, context);
                    return;

                case 225 /* VariableDeclarator */:
                    this.typeCheckVariableDeclarator(ast, context);
                    return;

                case 141 /* PropertySignature */:
                    this.typeCheckPropertySignature(ast, context);
                    return;

                case 242 /* Parameter */:
                    this.typeCheckParameter(ast, context);
                    return;

                case 133 /* ImportDeclaration */:
                    this.typeCheckImportDeclaration(ast, context);
                    return;

                case 215 /* ObjectLiteralExpression */:
                    this.resolveObjectLiteralExpression(ast, isContextuallyTyped, context);
                    return;

                case 241 /* FunctionPropertyAssignment */:
                    this.typeCheckFunctionPropertyAssignment(ast, isContextuallyTyped, context);
                    return;

                case 11 /* IdentifierName */:
                    if (isTypesOnlyLocation(ast)) {
                        this.resolveTypeNameExpression(ast, context);
                    } else {
                        this.resolveNameExpression(ast, context);
                    }
                    return;

                case 212 /* MemberAccessExpression */:
                    this.resolveMemberAccessExpression(ast, context);
                    return;

                case 121 /* QualifiedName */:
                    this.resolveQualifiedName(ast, context);
                    return;

                case 222 /* FunctionExpression */:
                    this.typeCheckFunctionExpression(ast, isContextuallyTyped, context);
                    return;

                case 137 /* ConstructorDeclaration */:
                    this.typeCheckConstructorDeclaration(ast, context);
                    return;

                case 139 /* GetAccessor */:
                case 140 /* SetAccessor */:
                    this.typeCheckAccessorDeclaration(ast, context);
                    return;

                case 135 /* MemberFunctionDeclaration */:
                    this.typeCheckMemberFunctionDeclaration(ast, context);
                    return;

                case 145 /* MethodSignature */:
                    this.typeCheckMethodSignature(ast, context);
                    return;

                case 144 /* IndexSignature */:
                    this.typeCheckIndexSignature(ast, context);
                    break;

                case 142 /* CallSignature */:
                    this.typeCheckCallSignature(ast, context);
                    return;

                case 143 /* ConstructSignature */:
                    this.typeCheckConstructSignature(ast, context);
                    return;

                case 129 /* FunctionDeclaration */: {
                    var funcDecl = ast;
                    this.typeCheckAnyFunctionDeclaration(funcDecl, TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Static), funcDecl.identifier, funcDecl.callSignature.typeParameterList, funcDecl.callSignature.parameterList, TypeScript.ASTHelpers.getType(funcDecl), funcDecl.block, context);
                    return;
                }

                case 219 /* SimpleArrowFunctionExpression */:
                    this.typeCheckSimpleArrowFunctionExpression(ast, isContextuallyTyped, context);
                    return;

                case 218 /* ParenthesizedArrowFunctionExpression */:
                    this.typeCheckParenthesizedArrowFunctionExpression(ast, isContextuallyTyped, context);
                    return;

                case 214 /* ArrayLiteralExpression */:
                    this.resolveArrayLiteralExpression(ast, isContextuallyTyped, context);
                    return;

                case 213 /* InvocationExpression */:
                    this.typeCheckInvocationExpression(ast, context);
                    return;

                case 216 /* ObjectCreationExpression */:
                    this.typeCheckObjectCreationExpression(ast, context);
                    return;

                case 150 /* ReturnStatement */:
                    // Since we want to resolve the return expression to traverse parents, resolve will take care of typeChecking
                    this.resolveReturnStatement(ast, context);
                    return;

                default:
                    TypeScript.Debug.assert(false, "Failure nodeType: " + TypeScript.SyntaxKind[ast.kind()] + ". Implement typeCheck when symbol is set for the ast as part of resolution.");
            }
        };

        PullTypeResolver.prototype.processPostTypeCheckWorkItems = function (context) {
            while (this.postTypeCheckWorkitems.length) {
                var ast = this.postTypeCheckWorkitems.pop();
                this.postTypeCheck(ast, context);
            }
        };

        PullTypeResolver.prototype.postTypeCheck = function (ast, context) {
            var nodeType = ast.kind();

            switch (nodeType) {
                case 242 /* Parameter */:
                case 225 /* VariableDeclarator */:
                    this.postTypeCheckVariableDeclaratorOrParameter(ast, context);
                    return;

                case 131 /* ClassDeclaration */:
                    this.postTypeCheckClassDeclaration(ast, context);
                    return;

                case 129 /* FunctionDeclaration */:
                    this.postTypeCheckFunctionDeclaration(ast, context);
                    return;

                case 130 /* ModuleDeclaration */:
                    this.postTypeCheckModuleDeclaration(ast, context);
                    return;

                case 132 /* EnumDeclaration */:
                    this.postTypeCheckEnumDeclaration(ast, context);
                    return;

                case 133 /* ImportDeclaration */:
                    this.postTypeCheckImportDeclaration(ast, context);
                    return;

                case 11 /* IdentifierName */:
                    this.postTypeCheckNameExpression(ast, context);
                    return;

                default:
                    TypeScript.Debug.assert(false, "Implement postTypeCheck clause to handle the postTypeCheck work, nodeType: " + TypeScript.SyntaxKind[ast.kind()]);
            }
        };

        PullTypeResolver.prototype.resolveRegularExpressionLiteral = function () {
            if (this.cachedRegExpInterfaceType()) {
                return this.cachedRegExpInterfaceType();
            } else {
                return this.semanticInfoChain.anyTypeSymbol;
            }
        };

        PullTypeResolver.prototype.postTypeCheckNameExpression = function (nameAST, context) {
            this.checkThisCaptureVariableCollides(nameAST, false, context);
        };

        PullTypeResolver.prototype.typeCheckNameExpression = function (nameAST, context) {
            this.setTypeChecked(nameAST, context);
            this.checkNameForCompilerGeneratedDeclarationCollision(nameAST, false, nameAST, context);
        };

        PullTypeResolver.prototype.resolveNameExpression = function (nameAST, context) {
            var nameSymbol = this.getSymbolForAST(nameAST, context);
            var foundCached = nameSymbol !== null;

            if (!foundCached || this.canTypeCheckAST(nameAST, context)) {
                if (this.canTypeCheckAST(nameAST, context)) {
                    this.typeCheckNameExpression(nameAST, context);
                }
                nameSymbol = this.computeNameExpression(nameAST, context);
            }

            this.resolveDeclaredSymbol(nameSymbol, context);

            // We don't want to capture an intermediate 'any' from a recursive resolution
            if (nameSymbol && (nameSymbol.type !== this.semanticInfoChain.anyTypeSymbol || nameSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.IsAnnotatedWithAny | 1 /* Exported */))) {
                this.setSymbolForAST(nameAST, nameSymbol, context);
            }

            return nameSymbol;
        };

        PullTypeResolver.prototype.isInEnumDecl = function (decl) {
            if (decl.kind & TypeScript.PullElementKind.Enum) {
                return true;
            }

            var declPath = decl.getParentPath();

            // enum cannot contain these kinds of declarations, if one is met - exit with false
            var disallowedKinds = TypeScript.PullElementKind.SomeContainer | TypeScript.PullElementKind.SomeType;
            for (var i = declPath.length - 1; i >= 0; i--) {
                var decl = declPath[i];

                if (decl.kind & TypeScript.PullElementKind.Enum) {
                    return true;
                }

                if (decl.kind & disallowedKinds) {
                    return false;
                }
            }
            return false;
        };

        PullTypeResolver.prototype.getSomeInnermostFunctionScopeDecl = function (declPath) {
            for (var i = declPath.length - 1; i >= 0; i--) {
                var decl = declPath[i];
                if (decl.kind & TypeScript.PullElementKind.SomeFunction) {
                    return decl;
                }
            }

            return null;
        };

        PullTypeResolver.prototype.isFromFunctionScope = function (nameSymbol, functionScopeDecl) {
            var _this = this;
            // If there exists any declaration that is from same functionScopeDecl, nameSymbol is from functionScope
            return TypeScript.ArrayUtilities.any(nameSymbol.getDeclarations(), function (nameSymbolDecl) {
                return _this.getSomeInnermostFunctionScopeDecl(nameSymbolDecl.getParentPath()) === functionScopeDecl;
            });
        };

        PullTypeResolver.prototype.findConstructorDeclOfEnclosingType = function (decl) {
            var current = decl;
            while (current) {
                if (TypeScript.hasFlag(current.kind, TypeScript.PullElementKind.Property)) {
                    var parentDecl = current.getParentDecl();
                    if (TypeScript.hasFlag(parentDecl.kind, TypeScript.PullElementKind.Class)) {
                        return TypeScript.ArrayUtilities.lastOrDefault(parentDecl.getChildDecls(), function (decl) {
                            return TypeScript.hasFlag(decl.kind, TypeScript.PullElementKind.ConstructorMethod);
                        });
                    }
                }

                if (TypeScript.hasFlag(current.kind, TypeScript.PullElementKind.SomeContainer)) {
                    return null;
                }

                current = current.getParentDecl();
            }
            return null;
        };

        PullTypeResolver.prototype.checkNameAsPartOfInitializerExpressionForInstanceMemberVariable = function (nameAST, nameSymbol, context) {
            var id = TypeScript.tokenValueText(nameAST);
            if (id.length === 0) {
                return false;
            }

            // SPEC: Nov 18, 2013
            // Initializer expressions for instance member variables are evaluated in the scope of the class constructor body
            // but are not permitted to reference parameters or local variables of the constructor.
            // This effectively means that entities from outer scopes by the same name as a constructor parameter or local variable are inaccessible
            // in initializer expressions for instance member variables.
            var memberVariableDeclarationAST = TypeScript.ASTHelpers.getEnclosingMemberDeclaration(nameAST);
            if (memberVariableDeclarationAST && memberVariableDeclarationAST.kind() === 136 /* MemberVariableDeclaration */) {
                var memberVariableDecl = this.semanticInfoChain.getDeclForAST(memberVariableDeclarationAST);
                if (!TypeScript.hasFlag(memberVariableDecl.flags, TypeScript.PullElementFlags.Static)) {
                    var constructorDecl = this.findConstructorDeclOfEnclosingType(memberVariableDecl);

                    if (constructorDecl) {
                        var childDecls = constructorDecl.searchChildDecls(id, TypeScript.PullElementKind.SomeValue);
                        if (childDecls.length) {
                            // Check if symbol is from scope that is outer to constructor's outer scope
                            if (TypeScript.PullHelpers.isSymbolDeclaredInScopeChain(nameSymbol, constructorDecl.getSymbol(this.semanticInfoChain).getContainer())) {
                                var memberVariableSymbol = memberVariableDecl.getSymbol(this.semanticInfoChain);

                                // Currently name was resolved to something from outerscope of the class
                                // But constructor contains same parameter name, and hence this member initializer
                                // when moved into constructor function in generated js would resolve to the constructor
                                // parameter but thats not what user intended. Report error
                                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(nameAST, TypeScript.DiagnosticCode.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, [memberVariableSymbol.getScopedName(constructorDecl.getSymbol(this.semanticInfoChain)), nameAST.text()]));
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        };

        PullTypeResolver.prototype.computeNameExpression = function (nameAST, context) {
            var id = TypeScript.tokenValueText(nameAST);
            if (id.length === 0) {
                return this.semanticInfoChain.anyTypeSymbol;
            }

            var nameSymbol = null;
            var enclosingDecl = this.getEnclosingDeclForAST(nameAST);

            // if enclosing decl is property check if it has valueDecl that corresponds to parameter
            if (TypeScript.hasFlag(enclosingDecl.flags, TypeScript.PullElementFlags.PropertyParameter)) {
                var valueDecl = enclosingDecl.getValueDecl();
                if (valueDecl && TypeScript.hasFlag(valueDecl.kind, TypeScript.PullElementKind.Parameter)) {
                    enclosingDecl = valueDecl;
                }
            }

            // First check if this is the name child of a declaration. If it is, no need to search for a name in scope since this is not a reference.
            var isDeclarationASTOrDeclarationNameAST = TypeScript.ASTHelpers.isDeclarationASTOrDeclarationNameAST(nameAST);
            if (isDeclarationASTOrDeclarationNameAST) {
                nameSymbol = this.semanticInfoChain.getDeclForAST(nameAST.parent).getSymbol(this.semanticInfoChain);
            }

            var declPath = enclosingDecl.getParentPath();

            if (!nameSymbol) {
                var searchKind = TypeScript.PullElementKind.SomeValue;

                // disallow accessing enum members with no qualification except the case when enclosing decl is enum
                if (!this.isInEnumDecl(enclosingDecl)) {
                    searchKind = searchKind & ~(TypeScript.PullElementKind.EnumMember);
                }

                var nameSymbol = this.getSymbolFromDeclPath(id, declPath, searchKind);
            }

            // arguments is resolved to local variable in the function or the arguments list that runtime passes and never to any other symbol
            if (id === "arguments") {
                var functionScopeDecl = this.getSomeInnermostFunctionScopeDecl(declPath);
                if (functionScopeDecl) {
                    // if there wasnt nameSymbol Or the nameSymbol isnt from the functionScope we are looking in
                    // resolve this to arguments of type IArguments
                    if (!nameSymbol || !this.isFromFunctionScope(nameSymbol, functionScopeDecl)) {
                        nameSymbol = this.cachedFunctionArgumentsSymbol();
                        this.resolveDeclaredSymbol(this.cachedIArgumentsInterfaceType(), context);
                    }
                }
            }

            var aliasSymbol = null;
            if (nameSymbol && nameSymbol.isAlias() && !isDeclarationASTOrDeclarationNameAST) {
                aliasSymbol = nameSymbol;
                if (!this.inTypeQuery(nameAST)) {
                    aliasSymbol.setIsUsedAsValue();
                }

                this.resolveDeclaredSymbol(nameSymbol, context);

                this.resolveDeclaredSymbol(aliasSymbol.assignedValue(), context);
                this.resolveDeclaredSymbol(aliasSymbol.assignedContainer(), context);

                nameSymbol = aliasSymbol.getExportAssignedValueSymbol();
                if (!nameSymbol) {
                    aliasSymbol = null;
                }
            }

            if (!nameSymbol) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(nameAST, TypeScript.DiagnosticCode.Cannot_find_name_0, [nameAST.text()]));
                return this.getNewErrorTypeSymbol(id);
            } else if (this.checkNameAsPartOfInitializerExpressionForInstanceMemberVariable(nameAST, nameSymbol, context)) {
                return this.getNewErrorTypeSymbol(id);
            }

            // October 11, 2013:
            // Initializer expressions are evaluated in the scope of the function body but are not
            // permitted to reference local variables and are only permitted to access parameters
            // that are declared to the left of the parameter they initialize.
            // If we've referenced a parameter of a function, make sure that we're either inside
            // the function, or if we're in a parameter initializer, that the parameter
            // initializer is to the left of this reference.
            var nameDeclaration = nameSymbol.getDeclarations()[0];
            var nameParentDecl = nameDeclaration.getParentDecl();
            if (nameParentDecl && (nameParentDecl.kind & TypeScript.PullElementKind.SomeFunction) && (nameParentDecl.flags & TypeScript.PullElementFlags.HasDefaultArgs)) {
                // Get the ISyntaxElement and look it up in the parameter index context to find which parameter we are in
                var enclosingFunctionAST = this.semanticInfoChain.getASTForDecl(nameParentDecl);
                var currentParameterIndex = this.getCurrentParameterIndexForFunction(nameAST, enclosingFunctionAST);

                var parameterList = TypeScript.ASTHelpers.getParameterList(enclosingFunctionAST);

                // Short circuit if we are located in the function body, since all child decls of the function are accessible there
                if (currentParameterIndex >= 0) {
                    // Search the enclosing function AST for a parameter with the right name, but stop once we hit our current context
                    var matchingParameter;
                    if (parameterList) {
                        for (var i = 0; i <= currentParameterIndex; i++) {
                            var candidateParameter = parameterList.parameters[i];
                            if (candidateParameter && TypeScript.tokenValueText(candidateParameter.identifier) === id) {
                                matchingParameter = candidateParameter;
                                break;
                            }
                        }
                    }

                    if (!matchingParameter) {
                        // We didn't find a matching parameter to the left, so error
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(nameAST, TypeScript.DiagnosticCode.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, [parameterList.parameters[currentParameterIndex].identifier.text(), nameAST.text()]));
                        return this.getNewErrorTypeSymbol(id);
                    } else if (matchingParameter === TypeScript.ASTHelpers.getEnclosingParameterForInitializer(nameAST)) {
                        // we've found matching parameter but it references itself from the initializer
                        // per spec Nov 18:
                        // Initializer expressions ..and are only permitted to access parameters that are declared to the left of the parameter they initialize
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(nameAST, TypeScript.DiagnosticCode.Parameter_0_cannot_be_referenced_in_its_initializer, [parameterList.parameters[currentParameterIndex].identifier.text()]));
                        return this.getNewErrorTypeSymbol(id);
                    }
                }
            }

            if (aliasSymbol) {
                this.semanticInfoChain.setAliasSymbolForAST(nameAST, aliasSymbol);
            }

            return nameSymbol;
        };

        // Returns the parameter index in the specified function declaration where ast is contained
        // within.  Returns -1 if ast is not contained within a parameter initializer in the
        // provided function declaration.
        PullTypeResolver.prototype.getCurrentParameterIndexForFunction = function (parameter, funcDecl) {
            var parameterList = TypeScript.ASTHelpers.getParameterList(funcDecl);
            if (parameterList) {
                while (parameter && parameter.parent) {
                    if (parameter.parent.parent === parameterList) {
                        // We were contained in the parameter list.  Return which parameter index
                        // we were at.
                        return TypeScript.Syntax.nonSeparatorIndexOf(parameterList.parameters, parameter);
                    }

                    parameter = parameter.parent;
                }
            }

            // ast was not found within the parameter list of this function.
            return -1;
        };

        PullTypeResolver.prototype.resolveMemberAccessExpression = function (dottedNameAST, context) {
            return this.resolveDottedNameExpression(dottedNameAST, dottedNameAST.expression, dottedNameAST.name, context);
        };

        PullTypeResolver.prototype.resolveDottedNameExpression = function (dottedNameAST, expression, name, context) {
            var symbol = this.getSymbolForAST(dottedNameAST, context);
            var foundCached = symbol !== null;

            if (!foundCached || this.canTypeCheckAST(dottedNameAST, context)) {
                var canTypeCheckDottedNameAST = this.canTypeCheckAST(dottedNameAST, context);
                if (canTypeCheckDottedNameAST) {
                    this.setTypeChecked(dottedNameAST, context);
                }

                symbol = this.computeDottedNameExpression(expression, name, context, canTypeCheckDottedNameAST);
            }

            this.resolveDeclaredSymbol(symbol, context);

            if (symbol && (symbol.type !== this.semanticInfoChain.anyTypeSymbol || symbol.anyDeclHasFlag(TypeScript.PullElementFlags.IsAnnotatedWithAny | 1 /* Exported */))) {
                this.setSymbolForAST(dottedNameAST, symbol, context);
                this.setSymbolForAST(name, symbol, context);
            }

            return symbol;
        };

        PullTypeResolver.prototype.computeDottedNameExpression = function (expression, name, context, checkSuperPrivateAndStaticAccess) {
            var rhsName = TypeScript.tokenValueText(name);
            if (rhsName.length === 0) {
                return this.semanticInfoChain.anyTypeSymbol;
            }

            // assemble the dotted name path
            var lhs = this.resolveAST(expression, false, context);
            return this.computeDottedNameExpressionFromLHS(lhs, expression, name, context, checkSuperPrivateAndStaticAccess);
        };

        PullTypeResolver.prototype.computeDottedNameExpressionFromLHS = function (lhs, expression, name, context, checkSuperPrivateAndStaticAccess) {
            // This can be case if incomplete qualified name
            var rhsName = TypeScript.tokenValueText(name);
            if (rhsName.length === 0) {
                return this.semanticInfoChain.anyTypeSymbol;
            }

            var lhsType = lhs.type;

            if (lhs.isAlias()) {
                var lhsAlias = lhs;
                if (!this.inTypeQuery(expression)) {
                    lhsAlias.setIsUsedAsValue();
                }
                lhsType = lhsAlias.getExportAssignedTypeSymbol();
            }

            // this can happen if a var is set to a type alias and the var is used in a dotted name.
            // i.e.
            //    import myAlias = require('someModule');
            //    var myAliasVar = myAlias
            //    myAliasVar.someModulesMember();
            // without this we would not be able to resolve someModules Members
            if (lhsType.isAlias()) {
                lhsType = lhsType.getExportAssignedTypeSymbol();
            }

            if (!lhsType) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(name, TypeScript.DiagnosticCode.Could_not_find_enclosing_symbol_for_dotted_name_0, [name.text()]));
                return this.getNewErrorTypeSymbol();
            }

            if (!lhsType.isResolved) {
                var potentiallySpecializedType = this.resolveDeclaredSymbol(lhsType, context);

                if (potentiallySpecializedType !== lhsType) {
                    if (!lhs.isType()) {
                        context.setTypeInContext(lhs, potentiallySpecializedType);
                    }

                    lhsType = potentiallySpecializedType;
                }
            }

            if (lhsType.isContainer() && !lhsType.isAlias() && !lhsType.isEnum()) {
                // we're searching in the value space, so we should try to use the
                // instance value type
                var instanceSymbol = lhsType.getInstanceSymbol();

                if (instanceSymbol) {
                    lhsType = instanceSymbol.type;
                }
            }

            var originalLhsTypeForErrorReporting = lhsType;

            lhsType = this.getApparentType(lhsType).widenedType(this, expression, context);

            if (this.isAnyOrEquivalent(lhsType)) {
                return lhsType;
            }

            // November 18, 2013, Section 4.10:
            // If Name denotes a property member in the apparent type of ObjExpr, the property access
            // is of the type of that property.
            // Note that here we are assuming the apparent type is already accounted for up to
            // augmentation. So we just check the augmented type.
            var nameSymbol = this._getNamedPropertySymbolOfAugmentedType(rhsName, lhsType);

            if (!nameSymbol) {
                // could be a function symbol
                if (lhsType.kind === TypeScript.PullElementKind.DynamicModule) {
                    var container = lhsType;
                    var associatedInstance = container.getInstanceSymbol();

                    if (associatedInstance) {
                        var instanceType = associatedInstance.type;

                        nameSymbol = this.getNamedPropertySymbol(rhsName, TypeScript.PullElementKind.SomeValue, instanceType);
                    }
                } else {
                    var associatedType = lhsType.getAssociatedContainerType();

                    if (associatedType && !associatedType.isClass()) {
                        nameSymbol = this.getNamedPropertySymbol(rhsName, TypeScript.PullElementKind.SomeValue, associatedType);
                    }
                }

                if (!nameSymbol) {
                    var enclosingDecl = this.getEnclosingDeclForAST(expression);
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(name, TypeScript.DiagnosticCode.Property_0_does_not_exist_on_value_of_type_1, [name.text(), originalLhsTypeForErrorReporting.toString(enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null)]));
                    return this.getNewErrorTypeSymbol(rhsName);
                }
            }

            if (checkSuperPrivateAndStaticAccess) {
                this.checkForSuperMemberAccess(expression, name, nameSymbol, context) || this.checkForPrivateMemberAccess(name, lhsType, nameSymbol, context);
            }

            return nameSymbol;
        };

        PullTypeResolver.prototype.resolveTypeNameExpression = function (nameAST, context) {
            var typeNameSymbol = this.getSymbolForAST(nameAST, context);

            // TODO(cyrusn): We really shouldn't be checking "isType" here.  However, we currently
            // have a bug where some part of the system calls resolveNameExpression on this node
            // and we cache the wrong thing.  We need to add appropriate checks to ensure that
            // resolveNameExpression is never called on a node that we should be calling
            // resolveTypeNameExpression (and vice versa).
            if (!typeNameSymbol || !typeNameSymbol.isType() || this.canTypeCheckAST(nameAST, context)) {
                if (this.canTypeCheckAST(nameAST, context)) {
                    this.setTypeChecked(nameAST, context);
                }
                typeNameSymbol = this.computeTypeNameExpression(nameAST, context);
                this.setSymbolForAST(nameAST, typeNameSymbol, context);
            }

            this.resolveDeclaredSymbol(typeNameSymbol, context);

            return typeNameSymbol;
        };

        PullTypeResolver.prototype.computeTypeNameExpression = function (nameAST, context) {
            var id = TypeScript.tokenValueText(nameAST);
            if (id.length === 0) {
                return this.semanticInfoChain.anyTypeSymbol;
            }

            var enclosingDecl = this.getEnclosingDeclForAST(nameAST);

            var declPath = enclosingDecl.getParentPath();

            // If we're resolving a dotted type name, every dotted name but the last will be a container type, so we'll search those
            // first if need be, and then fall back to type names.  Otherwise, look for a type first, since we are probably looking for
            // a type reference (the exception being an alias or export assignment)
            var onLeftOfDot = this.isLeftSideOfQualifiedName(nameAST);

            var kindToCheckFirst = onLeftOfDot ? TypeScript.PullElementKind.SomeContainer : TypeScript.PullElementKind.SomeType;
            var kindToCheckSecond = onLeftOfDot ? TypeScript.PullElementKind.SomeType : TypeScript.PullElementKind.SomeContainer;

            var typeNameSymbol = this.getSymbolFromDeclPath(id, declPath, kindToCheckFirst);

            if (!typeNameSymbol) {
                typeNameSymbol = this.getSymbolFromDeclPath(id, declPath, kindToCheckSecond);
            }

            if (!typeNameSymbol) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(nameAST, TypeScript.DiagnosticCode.Cannot_find_name_0, [nameAST.text()]));
                return this.getNewErrorTypeSymbol(id);
            }

            var typeNameSymbolAlias = null;
            if (typeNameSymbol.isAlias()) {
                typeNameSymbolAlias = typeNameSymbol;
                this.resolveDeclaredSymbol(typeNameSymbol, context);

                var aliasedType = typeNameSymbolAlias.getExportAssignedTypeSymbol();

                this.resolveDeclaredSymbol(aliasedType, context);
            }

            if (typeNameSymbol.isTypeParameter()) {
                if (TypeScript.PullHelpers.isInStaticMemberContext(nameAST, this.semanticInfoChain)) {
                    var parentDecl = typeNameSymbol.getDeclarations()[0].getParentDecl();

                    if (parentDecl.kind === TypeScript.PullElementKind.Class) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(nameAST, TypeScript.DiagnosticCode.Static_members_cannot_reference_class_type_parameters));
                        return this.getNewErrorTypeSymbol();
                    }
                }
            }

            if (!typeNameSymbol.isGeneric() && (typeNameSymbol.isClass() || typeNameSymbol.isInterface())) {
                typeNameSymbol = TypeScript.TypeReferenceSymbol.createTypeReference(typeNameSymbol);
            }

            return typeNameSymbol;
        };

        PullTypeResolver.prototype.isLeftSideOfQualifiedName = function (ast) {
            return ast && ast.parent && ast.parent.kind() === 121 /* QualifiedName */ && ast.parent.left === ast;
        };

        PullTypeResolver.prototype.resolveGenericTypeReference = function (genericTypeAST, context) {
            var _this = this;
            var genericTypeSymbol = this.resolveAST(genericTypeAST.name, false, context).type;

            if (genericTypeSymbol.isError()) {
                return genericTypeSymbol;
            }

            if (!genericTypeSymbol.inResolution && !genericTypeSymbol.isResolved) {
                this.resolveDeclaredSymbol(genericTypeSymbol, context);
            }

            if (genericTypeSymbol.isAlias()) {
                if (this.inClassExtendsHeritageClause(genericTypeAST) && !this.inTypeArgumentList(genericTypeAST)) {
                    genericTypeSymbol.setIsUsedAsValue();
                }
                genericTypeSymbol = genericTypeSymbol.getExportAssignedTypeSymbol();
            }

            var typeParameters = genericTypeSymbol.getTypeParameters();
            if (typeParameters.length === 0) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(genericTypeAST, TypeScript.DiagnosticCode.Type_0_is_not_generic, [genericTypeSymbol.toString()]));
                return this.getNewErrorTypeSymbol();
            }

            // specialize the type arguments
            var typeArgs = [];

            if (genericTypeAST.typeArgumentList && genericTypeAST.typeArgumentList.typeArguments.length) {
                for (var i = 0; i < genericTypeAST.typeArgumentList.typeArguments.length; i++) {
                    typeArgs[i] = this.resolveTypeReference(genericTypeAST.typeArgumentList.typeArguments[i], context);

                    if (typeArgs[i].isError()) {
                        typeArgs[i] = this.semanticInfoChain.anyTypeSymbol;
                    }
                }
            }

            if (typeArgs.length && typeArgs.length !== typeParameters.length) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(genericTypeAST, TypeScript.DiagnosticCode.Generic_type_0_requires_1_type_argument_s, [genericTypeSymbol.toString(), genericTypeSymbol.getTypeParameters().length]));
                return this.getNewErrorTypeSymbol();
            }

            // if the generic type symbol is not resolved, we need to ensure that all of its members are bound before specializing
            if (!genericTypeSymbol.isResolved) {
                var typeDecls = genericTypeSymbol.getDeclarations();
                var childDecls = null;

                for (var i = 0; i < typeDecls.length; i++) {
                    childDecls = typeDecls[i].getChildDecls();

                    for (var j = 0; j < childDecls.length; j++) {
                        childDecls[j].ensureSymbolIsBound(this.semanticInfoChain);
                    }
                }
            }

            var specializedSymbol = this.createInstantiatedType(genericTypeSymbol, typeArgs);

            // check constraints, if appropriate
            var upperBound = null;

            // Get the instantiated versions of the type parameters (in case their constraints were generic)
            typeParameters = specializedSymbol.getTypeParameters();

            var typeConstraintSubstitutionMap = [];

            var instantiatedSubstitutionMap = specializedSymbol.getTypeParameterSubstitutionMap();

            for (var i = 0; i < typeParameters.length; i++) {
                typeConstraintSubstitutionMap[typeParameters[i].pullSymbolID] = typeParameters[i];
            }

            for (var id in instantiatedSubstitutionMap) {
                typeConstraintSubstitutionMap[id] = instantiatedSubstitutionMap[id];
            }

            for (var iArg = 0; (iArg < typeArgs.length) && (iArg < typeParameters.length); iArg++) {
                var typeArg = typeArgs[iArg];
                var typeParameter = typeParameters[iArg];
                var typeConstraint = typeParameter.getConstraint();

                typeConstraintSubstitutionMap[typeParameter.pullSymbolID] = typeArg;

                // test specialization type for assignment compatibility with the constraint
                if (typeConstraint) {
                    if (typeConstraint.isTypeParameter()) {
                        for (var j = 0; j < typeParameters.length && j < typeArgs.length; j++) {
                            if (typeParameters[j] === typeConstraint) {
                                typeConstraint = typeArgs[j];
                            }
                        }
                    } else if (typeConstraint.isGeneric()) {
                        typeConstraint = this.instantiateType(typeConstraint, typeConstraintSubstitutionMap);
                    }

                    if (typeArg.isTypeParameter()) {
                        upperBound = typeArg.getConstraint();

                        if (upperBound) {
                            typeArg = upperBound;
                        }
                    }

                    // handle cases where the type argument is a wrapped name type, that's being recursively resolved
                    if (typeArg.inResolution || (typeArg.isTypeReference() && typeArg.referencedTypeSymbol.inResolution)) {
                        return specializedSymbol;
                    }

                    if (context.canTypeCheckAST(genericTypeAST)) {
                        this.typeCheckCallBacks.push(function (context) {
                            // Section 3.4.2 (November 18, 2013):
                            // A type argument satisfies a type parameter constraint if the type argument is assignable
                            // to(section 3.8.4) the constraint type once type arguments are substituted for type parameters.
                            if (!_this.sourceIsAssignableToTarget(typeArg, typeConstraint, genericTypeAST, context)) {
                                var enclosingSymbol = _this.getEnclosingSymbolForAST(genericTypeAST);
                                context.postDiagnostic(_this.semanticInfoChain.diagnosticFromAST(genericTypeAST, TypeScript.DiagnosticCode.Type_0_does_not_satisfy_the_constraint_1, [typeArg.toString(enclosingSymbol, true), typeConstraint.toString(enclosingSymbol, true)]));
                            }
                        });
                    }
                }
            }

            return specializedSymbol;
        };

        PullTypeResolver.prototype.resolveQualifiedName = function (dottedNameAST, context) {
            if (this.inTypeQuery(dottedNameAST)) {
                // If we're in a type query, then treat the qualified name as a normal dotted
                // name expression.
                return this.resolveDottedNameExpression(dottedNameAST, dottedNameAST.left, dottedNameAST.right, context).type;
            }

            var symbol = this.getSymbolForAST(dottedNameAST, context);
            if (!symbol || this.canTypeCheckAST(dottedNameAST, context)) {
                var canTypeCheck = this.canTypeCheckAST(dottedNameAST, context);
                if (canTypeCheck) {
                    this.setTypeChecked(dottedNameAST, context);
                }

                symbol = this.computeQualifiedName(dottedNameAST, context);
                this.setSymbolForAST(dottedNameAST, symbol, context);
            }

            this.resolveDeclaredSymbol(symbol, context);

            return symbol;
        };

        PullTypeResolver.prototype.isLastNameOfQualifiedModuleNameModuleReference = function (ast) {
            // SPEC: November 18, 2013 section 10.3 -
            // Don't walk up any other qualified names because the spec says only the last entity name can be a non-module
            // i.e. Only Module.Module.Module.var and not Module.Type.var or Module.var.member
            return ast.kind() === 11 /* IdentifierName */ && ast.parent && ast.parent.kind() === 121 /* QualifiedName */ && ast.parent.right === ast && ast.parent.parent && ast.parent.parent.kind() === 246 /* ModuleNameModuleReference */;
        };

        PullTypeResolver.prototype.computeQualifiedName = function (dottedNameAST, context) {
            var rhsName = TypeScript.tokenValueText(dottedNameAST.right);
            if (rhsName.length === 0) {
                return this.semanticInfoChain.anyTypeSymbol;
            }

            // assemble the dotted name path
            var enclosingDecl = this.getEnclosingDeclForAST(dottedNameAST);
            var lhs = this.resolveAST(dottedNameAST.left, false, context);

            var lhsType = lhs.isAlias() ? lhs.getExportAssignedContainerSymbol() : lhs.type;

            if (this.inClassExtendsHeritageClause(dottedNameAST) && !this.inTypeArgumentList(dottedNameAST)) {
                if (lhs.isAlias()) {
                    lhs.setIsUsedAsValue();
                }
            }

            if (!lhsType) {
                return this.getNewErrorTypeSymbol();
            }

            if (this.isAnyOrEquivalent(lhsType)) {
                return lhsType;
            }

            // now for the name...
            var onLeftOfDot = this.isLeftSideOfQualifiedName(dottedNameAST);
            var isNameOfModule = dottedNameAST.parent.kind() === 130 /* ModuleDeclaration */ && dottedNameAST.parent.name === dottedNameAST;

            var memberKind = (onLeftOfDot || isNameOfModule) ? TypeScript.PullElementKind.SomeContainer : TypeScript.PullElementKind.SomeType;

            var childTypeSymbol = this.getNamedPropertySymbol(rhsName, memberKind, lhsType);

            // SPEC: November 18, 2013 section 10.3 -
            //  - An EntityName consisting of more than one identifier is resolved as
            //     a ModuleName followed by an identifier that names one or more exported entities in the given module.
            //     The resulting local alias has all the meanings and classifications of the referenced entity or entities.
            //     (As many as three distinct meanings are possible for an entity name ? namespace, type, and member.)
            if (!childTypeSymbol && !isNameOfModule && this.isLastNameOfQualifiedModuleNameModuleReference(dottedNameAST.right)) {
                childTypeSymbol = this.getNamedPropertySymbol(rhsName, TypeScript.PullElementKind.SomeValue, lhsType);
            }

            // if the lhs exports a container type, but not a type, we should check the container type
            if (!childTypeSymbol && lhsType.isContainer()) {
                var exportedContainer = lhsType.getExportAssignedContainerSymbol();

                if (exportedContainer) {
                    childTypeSymbol = this.getNamedPropertySymbol(rhsName, memberKind, exportedContainer);
                }
            }

            // If the name is expressed as a dotted name within the parent type,
            // then it will be considered a contained member, so back up to the nearest
            // enclosing symbol and look there
            if (!childTypeSymbol && enclosingDecl) {
                var parentDecl = enclosingDecl;

                while (parentDecl) {
                    if (parentDecl.kind & TypeScript.PullElementKind.SomeContainer) {
                        break;
                    }

                    parentDecl = parentDecl.getParentDecl();
                }

                if (parentDecl) {
                    var enclosingSymbolType = parentDecl.getSymbol(this.semanticInfoChain).type;

                    if (enclosingSymbolType === lhsType) {
                        childTypeSymbol = this.getNamedPropertySymbol(rhsName, memberKind, lhsType); //lhsType.findContainedMember(rhsName);
                    }
                }
            }

            if (!childTypeSymbol) {
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(dottedNameAST.right, TypeScript.DiagnosticCode.Property_0_does_not_exist_on_value_of_type_1, [dottedNameAST.right.text(), lhsType.toString(enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null)]));
                return this.getNewErrorTypeSymbol(rhsName);
            }

            return childTypeSymbol;
        };

        PullTypeResolver.prototype.shouldContextuallyTypeAnyFunctionExpression = function (functionExpressionAST, typeParameters, parameters, returnTypeAnnotation, context) {
            // September 21, 2013: If e is a FunctionExpression or ArrowFunctionExpression with no type parameters and no parameter
            // or return type annotations, and T is a function type with exactly one non - generic call signature, then any
            // inferences made for type parameters referenced by the parameters of T?s call signature are fixed(section 4.12.2)
            // and e is processed with the contextual type T, as described in section 4.9.3.
            // No type parameters
            if (typeParameters && typeParameters.typeParameters.length > 0) {
                return false;
            }

            // No return type annotation
            if (returnTypeAnnotation) {
                return false;
            }

            // No parameter type annotations
            if (parameters) {
                for (var i = 0, n = parameters.length; i < n; i++) {
                    if (parameters[i].typeAnnotation) {
                        return false;
                    }
                }
            }

            var contextualFunctionTypeSymbol = context.getContextualType();

            // Exactly one non-generic call signature (note that this means it must have exactly one call signature,
            // AND that call signature must be non-generic)
            if (contextualFunctionTypeSymbol) {
                this.resolveDeclaredSymbol(contextualFunctionTypeSymbol, context);
                var callSignatures = contextualFunctionTypeSymbol.getCallSignatures();
                var exactlyOneCallSignature = callSignatures && callSignatures.length === 1;
                if (!exactlyOneCallSignature) {
                    return false;
                }

                var callSignatureIsGeneric = callSignatures[0].getTypeParameters().length > 0;
                return !callSignatureIsGeneric;
            }

            return false;
        };

        PullTypeResolver.prototype.resolveAnyFunctionExpression = function (funcDeclAST, typeParameters, parameters, returnTypeAnnotation, block, bodyExpression, isContextuallyTyped, context) {
            var funcDeclSymbol = null;
            var functionDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
            TypeScript.Debug.assert(functionDecl);

            if (functionDecl && functionDecl.hasSymbol(this.semanticInfoChain)) {
                funcDeclSymbol = functionDecl.getSymbol(this.semanticInfoChain);
                if (funcDeclSymbol.isResolved || funcDeclSymbol.inResolution) {
                    return funcDeclSymbol;
                }
            }

            funcDeclSymbol = functionDecl.getSymbol(this.semanticInfoChain);
            TypeScript.Debug.assert(funcDeclSymbol);

            var funcDeclType = funcDeclSymbol.type;
            var signature = funcDeclType.getCallSignatures()[0];
            funcDeclSymbol.startResolving();

            if (typeParameters) {
                for (var i = 0; i < typeParameters.typeParameters.length; i++) {
                    this.resolveTypeParameterDeclaration(typeParameters.typeParameters[i], context);
                }
            }

            var assigningFunctionSignature = null;
            if (isContextuallyTyped && this.shouldContextuallyTypeAnyFunctionExpression(funcDeclAST, typeParameters, parameters, returnTypeAnnotation, context)) {
                assigningFunctionSignature = context.getContextualType().getCallSignatures()[0];
            }

            // link parameters and resolve their annotations
            this.resolveAnyFunctionExpressionParameters(funcDeclAST, typeParameters, parameters, returnTypeAnnotation, isContextuallyTyped, context);

            // resolve the return type annotation
            if (returnTypeAnnotation) {
                signature.returnType = this.resolveTypeReference(returnTypeAnnotation, context);
            } else {
                if (assigningFunctionSignature) {
                    var returnType = assigningFunctionSignature.returnType;

                    if (returnType) {
                        context.propagateContextualType(returnType);
                        this.resolveFunctionBodyReturnTypes(funcDeclAST, block, bodyExpression, signature, true, functionDecl, context);
                        context.popAnyContextualType();
                    } else {
                        signature.returnType = this.semanticInfoChain.anyTypeSymbol;

                        // if noimplictiany flag is set to be true, report an error
                        if (this.compilationSettings.noImplicitAny()) {
                            var functionExpressionName = functionDecl.getFunctionExpressionName();

                            // If there is a function name for the funciton expression, report an error with that name
                            if (functionExpressionName != "") {
                                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode._0_which_lacks_return_type_annotation_implicitly_has_an_any_return_type, [functionExpressionName]));
                            } else {
                                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_any_return_type));
                            }
                        }
                    }
                } else {
                    this.resolveFunctionBodyReturnTypes(funcDeclAST, block, bodyExpression, signature, false, functionDecl, context);
                }
            }

            // reset the type to the one we already had,
            // this makes sure if we had short - circuited the type of this symbol to any, we would get back to the function type
            context.setTypeInContext(funcDeclSymbol, funcDeclType);
            funcDeclSymbol.setResolved();

            if (this.canTypeCheckAST(funcDeclAST, context)) {
                this.typeCheckAnyFunctionExpression(funcDeclAST, typeParameters, parameters, returnTypeAnnotation, block, bodyExpression, isContextuallyTyped, context);
            }

            return funcDeclSymbol;
        };

        PullTypeResolver.prototype.resolveAnyFunctionExpressionParameters = function (funcDeclAST, typeParameters, parameters, returnTypeAnnotation, isContextuallyTyped, context) {
            if (!parameters) {
                return;
            }

            var functionDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            var contextParams = [];

            var assigningFunctionSignature = null;
            if (isContextuallyTyped && this.shouldContextuallyTypeAnyFunctionExpression(funcDeclAST, typeParameters, parameters, returnTypeAnnotation, context)) {
                assigningFunctionSignature = context.getContextualType().getCallSignatures()[0];
            }

            if (assigningFunctionSignature) {
                contextParams = assigningFunctionSignature.parameters;
            }

            // Push the function onto the parameter index stack
            var contextualParametersCount = contextParams.length;
            for (var i = 0, n = parameters.length; i < n; i++) {
                // Function has a variable argument list, and this paramter is the last
                var actualParameterIsVarArgParameter = (i === (n - 1)) && TypeScript.lastParameterIsRest(parameters);
                var correspondingContextualParameter = null;
                var contextualParameterType = null;

                // Find the matching contextual paramter
                if (i < contextualParametersCount) {
                    correspondingContextualParameter = contextParams[i];
                } else if (contextualParametersCount && contextParams[contextualParametersCount - 1].isVarArg) {
                    correspondingContextualParameter = contextParams[contextualParametersCount - 1];
                }

                // Find the contextual type from the paramter
                if (correspondingContextualParameter) {
                    if (correspondingContextualParameter.isVarArg === actualParameterIsVarArgParameter) {
                        contextualParameterType = correspondingContextualParameter.type;
                    } else if (correspondingContextualParameter.isVarArg) {
                        contextualParameterType = correspondingContextualParameter.type.getElementType();
                    }
                }

                // use the function decl as the enclosing decl, so as to properly resolve type parameters
                this.resolveFunctionExpressionParameter(parameters[i], contextualParameterType, functionDecl, context);
            }
        };

        PullTypeResolver.prototype.typeCheckSimpleArrowFunctionExpression = function (arrowFunction, isContextuallyTyped, context) {
            return this.typeCheckAnyFunctionExpression(arrowFunction, null, [arrowFunction.parameter], null, arrowFunction.block, arrowFunction.expression, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.typeCheckParenthesizedArrowFunctionExpression = function (arrowFunction, isContextuallyTyped, context) {
            return this.typeCheckAnyFunctionExpression(arrowFunction, arrowFunction.callSignature.typeParameterList, arrowFunction.callSignature.parameterList.parameters, TypeScript.ASTHelpers.getType(arrowFunction), arrowFunction.block, arrowFunction.expression, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.typeCheckAnyFunctionExpression = function (funcDeclAST, typeParameters, parameters, returnTypeAnnotation, block, bodyExpression, isContextuallyTyped, context) {
            var _this = this;
            this.setTypeChecked(funcDeclAST, context);

            var functionDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);

            var funcDeclSymbol = functionDecl.getSymbol(this.semanticInfoChain);
            var funcDeclType = funcDeclSymbol.type;
            var signature = funcDeclType.getCallSignatures()[0];
            var returnTypeSymbol = signature.returnType;

            if (typeParameters) {
                for (var i = 0; i < typeParameters.typeParameters.length; i++) {
                    this.resolveTypeParameterDeclaration(typeParameters.typeParameters[i], context);
                }
            }

            this.resolveAnyFunctionExpressionParameters(funcDeclAST, typeParameters, parameters, returnTypeAnnotation, isContextuallyTyped, context);

            // Make sure there is no contextual type on the stack when resolving the block
            context.pushNewContextualType(null);
            if (block) {
                this.resolveAST(block, false, context);
            } else {
                var bodyExpressionType = this.resolveReturnExpression(bodyExpression, functionDecl, context);
                this.typeCheckReturnExpression(bodyExpression, bodyExpressionType, functionDecl, context);
            }

            context.popAnyContextualType();

            this.checkThatNonVoidFunctionHasReturnExpressionOrThrowStatement(functionDecl, returnTypeAnnotation, returnTypeSymbol, block, context);

            this.validateVariableDeclarationGroups(functionDecl, context);

            this.typeCheckCallBacks.push(function (context) {
                _this.typeCheckFunctionOverloads(funcDeclAST, context);
            });
        };

        PullTypeResolver.prototype.resolveThisExpression = function (thisExpression, context) {
            var enclosingDecl = this.getEnclosingDeclForAST(thisExpression);
            var thisTypeSymbol = this.getContextualClassSymbolForEnclosingDecl(thisExpression, enclosingDecl) || this.semanticInfoChain.anyTypeSymbol;

            if (this.canTypeCheckAST(thisExpression, context)) {
                this.typeCheckThisExpression(thisExpression, context, enclosingDecl);
            }

            return thisTypeSymbol;
        };

        PullTypeResolver.prototype.inTypeArgumentList = function (ast) {
            var previous = null;
            var current = ast;

            while (current) {
                switch (current.kind()) {
                    case 126 /* GenericType */:
                        var genericType = current;
                        if (genericType.typeArgumentList === previous) {
                            return true;
                        }
                        break;

                    case 226 /* ArgumentList */:
                        var argumentList = current;
                        return argumentList.typeArgumentList === previous;
                }

                previous = current;
                current = current.parent;
            }

            return false;
        };

        PullTypeResolver.prototype.inClassExtendsHeritageClause = function (ast) {
            while (ast) {
                switch (ast.kind()) {
                    case 230 /* ExtendsHeritageClause */:
                        var heritageClause = ast;

                        // Heritage clause is parented by the heritage clause list.  Which is
                        // parented by either a class or an interface.  So check the grandparent.
                        return heritageClause.parent.parent.kind() === 131 /* ClassDeclaration */;

                    case 137 /* ConstructorDeclaration */:
                    case 131 /* ClassDeclaration */:
                    case 130 /* ModuleDeclaration */:
                        return false;
                }

                ast = ast.parent;
            }

            return false;
        };

        PullTypeResolver.prototype.inTypeQuery = function (ast) {
            while (ast) {
                switch (ast.kind()) {
                    case 127 /* TypeQuery */:
                        return true;
                    case 129 /* FunctionDeclaration */:
                    case 213 /* InvocationExpression */:
                    case 137 /* ConstructorDeclaration */:
                    case 131 /* ClassDeclaration */:
                    case 130 /* ModuleDeclaration */:
                        return false;
                }

                ast = ast.parent;
            }

            return false;
        };

        PullTypeResolver.prototype.inArgumentListOfSuperInvocation = function (ast) {
            var previous = null;
            var current = ast;
            while (current) {
                switch (current.kind()) {
                    case 213 /* InvocationExpression */:
                        var invocationExpression = current;
                        if (previous === invocationExpression.argumentList && invocationExpression.expression.kind() === 50 /* SuperKeyword */) {
                            return true;
                        }
                        break;

                    case 137 /* ConstructorDeclaration */:
                    case 131 /* ClassDeclaration */:
                    case 130 /* ModuleDeclaration */:
                        return false;
                }

                previous = current;
                current = current.parent;
            }

            return false;
        };

        PullTypeResolver.prototype.inConstructorParameterList = function (ast) {
            var previous = null;
            var current = ast;
            while (current) {
                switch (current.kind()) {
                    case 142 /* CallSignature */:
                        var callSignature = current;
                        if (previous === callSignature.parameterList && callSignature.parent.kind() === 137 /* ConstructorDeclaration */) {
                            return true;
                        }

                    case 131 /* ClassDeclaration */:
                    case 130 /* ModuleDeclaration */:
                        return false;
                }

                previous = current;
                current = current.parent;
            }

            return false;
        };
        PullTypeResolver.prototype.isFunctionAccessorOrNonArrowFunctionExpression = function (decl) {
            if (decl.kind === TypeScript.PullElementKind.GetAccessor || decl.kind === TypeScript.PullElementKind.SetAccessor) {
                return true;
            }

            return this.isFunctionOrNonArrowFunctionExpression(decl);
        };

        PullTypeResolver.prototype.isFunctionOrNonArrowFunctionExpression = function (decl) {
            if (decl.kind === TypeScript.PullElementKind.Function) {
                return true;
            } else if (decl.kind === TypeScript.PullElementKind.FunctionExpression && !TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.ArrowFunction)) {
                return true;
            }

            return false;
        };

        PullTypeResolver.prototype.typeCheckThisExpression = function (thisExpression, context, enclosingDecl) {
            this.checkForThisCaptureInArrowFunction(thisExpression);

            if (this.inConstructorParameterList(thisExpression)) {
                // October 11, 2013
                // Similar to functions, only the constructor implementation (and not
                // constructor overloads) can specify default value expressions for optional
                // parameters.It is a compile - time error for such default value expressions
                //  to reference this.
                //
                // Note: this applies for constructor parameters and constructor parameter
                // properties.
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(thisExpression, TypeScript.DiagnosticCode.this_cannot_be_referenced_in_constructor_arguments));
                return;
            }

            for (var currentDecl = enclosingDecl; currentDecl !== null; currentDecl = currentDecl.getParentDecl()) {
                if (this.isFunctionAccessorOrNonArrowFunctionExpression(currentDecl)) {
                    // 'this' is always ok in a function.  It just has the 'any' type.
                    return;
                } else if (currentDecl.kind === TypeScript.PullElementKind.Container || currentDecl.kind === TypeScript.PullElementKind.DynamicModule) {
                    if (currentDecl.getParentDecl() === null) {
                        // Legal in the global module.
                        return;
                    } else {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(thisExpression, TypeScript.DiagnosticCode.this_cannot_be_referenced_in_a_module_body));
                        return;
                    }
                } else if (currentDecl.kind === TypeScript.PullElementKind.Enum) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(thisExpression, TypeScript.DiagnosticCode.this_cannot_be_referenced_in_current_location));
                    return;
                } else if (currentDecl.kind === TypeScript.PullElementKind.ConstructorMethod) {
                    // October 11, 2013
                    // The first statement in the body of a constructor must be a super call if
                    // both of the following are true:
                    //      The containing class is a derived class.
                    //      The constructor declares parameter properties or the containing class
                    //      declares instance member variables with initializers.
                    // In such a required super call, it is a compile - time error for argument
                    // expressions to reference this.
                    if (this.inArgumentListOfSuperInvocation(thisExpression) && this.superCallMustBeFirstStatementInConstructor(currentDecl)) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(thisExpression, TypeScript.DiagnosticCode.this_cannot_be_referenced_in_current_location));
                    }

                    // Otherwise, it's ok to access 'this' in a constructor.
                    return;
                } else if (currentDecl.kind === TypeScript.PullElementKind.Class) {
                    if (this.inStaticMemberVariableDeclaration(thisExpression)) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(thisExpression, TypeScript.DiagnosticCode.this_cannot_be_referenced_in_a_static_property_initializer));
                    }

                    // Legal use of 'this'.
                    return;
                }
            }
        };

        PullTypeResolver.prototype.getContextualClassSymbolForEnclosingDecl = function (ast, enclosingDecl) {
            var declPath = enclosingDecl.getParentPath();

            // work back up the decl path, until you can find a class
            if (declPath.length) {
                var isStaticContext = false;

                for (var i = declPath.length - 1; i >= 0; i--) {
                    var decl = declPath[i];
                    var declKind = decl.kind;
                    var declFlags = decl.flags;

                    if (declFlags & TypeScript.PullElementFlags.Static) {
                        isStaticContext = true;
                    } else if (declKind === TypeScript.PullElementKind.FunctionExpression && !TypeScript.hasFlag(declFlags, TypeScript.PullElementFlags.ArrowFunction)) {
                        return null;
                    } else if (declKind === TypeScript.PullElementKind.Function) {
                        return null;
                    } else if (declKind === TypeScript.PullElementKind.Class) {
                        if (this.inStaticMemberVariableDeclaration(ast)) {
                            return this.getNewErrorTypeSymbol();
                        } else {
                            var classSymbol = decl.getSymbol(this.semanticInfoChain);
                            if (isStaticContext) {
                                var constructorSymbol = classSymbol.getConstructorMethod();
                                return constructorSymbol.type;
                            } else {
                                return classSymbol;
                            }
                        }
                    }
                }
            }

            return null;
        };

        PullTypeResolver.prototype.inStaticMemberVariableDeclaration = function (ast) {
            while (ast) {
                if (ast.kind() === 136 /* MemberVariableDeclaration */ && TypeScript.hasModifier(ast.modifiers, TypeScript.PullElementFlags.Static)) {
                    return true;
                }

                ast = ast.parent;
            }

            return false;
        };

        PullTypeResolver.prototype.resolveSuperExpression = function (ast, context) {
            var enclosingDecl = this.getEnclosingDeclForAST(ast);
            var superType = this.semanticInfoChain.anyTypeSymbol;

            var classSymbol = this.getContextualClassSymbolForEnclosingDecl(ast, enclosingDecl);

            if (classSymbol) {
                this.resolveDeclaredSymbol(classSymbol, context);

                var parents = classSymbol.getExtendedTypes();

                if (parents.length) {
                    superType = parents[0];
                }
            }

            if (this.canTypeCheckAST(ast, context)) {
                this.typeCheckSuperExpression(ast, context, enclosingDecl);
            }

            return superType;
        };

        PullTypeResolver.prototype.typeCheckSuperExpression = function (ast, context, enclosingDecl) {
            this.setTypeChecked(ast, context);

            this.checkForThisCaptureInArrowFunction(ast);

            var isSuperCall = ast.parent.kind() === 213 /* InvocationExpression */;
            var isSuperPropertyAccess = ast.parent.kind() === 212 /* MemberAccessExpression */;
            TypeScript.Debug.assert(isSuperCall || isSuperPropertyAccess);

            if (isSuperPropertyAccess) {
                for (var currentDecl = enclosingDecl; currentDecl !== null; currentDecl = currentDecl.getParentDecl()) {
                    if (this.isFunctionOrNonArrowFunctionExpression(currentDecl)) {
                        break;
                    } else if (currentDecl.kind === TypeScript.PullElementKind.Class) {
                        // We're in some class member.  That's good.
                        if (!this.enclosingClassIsDerived(currentDecl)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.super_can_only_be_referenced_in_a_derived_class));
                            return;
                        } else if (this.inConstructorParameterList(ast)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.super_cannot_be_referenced_in_constructor_arguments));
                            return;
                        } else if (this.inStaticMemberVariableDeclaration(ast)) {
                            break;
                        }

                        // We've checked the bad cases, at this point we're good.
                        return;
                    }
                }
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class));
                return;
            } else {
                for (var currentDecl = enclosingDecl; currentDecl !== null; currentDecl = currentDecl.getParentDecl()) {
                    if (currentDecl.kind === TypeScript.PullElementKind.ConstructorMethod) {
                        // We were in a constructor.  That's good.
                        var classDecl = currentDecl.getParentDecl();

                        if (!this.enclosingClassIsDerived(classDecl)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.super_can_only_be_referenced_in_a_derived_class));
                            return;
                        } else if (this.inConstructorParameterList(ast)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.super_cannot_be_referenced_in_constructor_arguments));
                            return;
                        }

                        // Nothing wrong with how we were referenced.  Note: the check if we're the
                        // first statement in the constructor happens in typeCheckConstructorDeclaration.
                        return;
                    } else if (TypeScript.SyntaxUtilities.isAnyFunctionExpressionOrDeclaration(currentDecl.ast())) {
                        break;
                    }
                }

                // SPEC NOV 18: Super calls are not permitted outside constructors or in local functions inside constructors.
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors));
            }
        };

        PullTypeResolver.prototype.resolveSimplePropertyAssignment = function (propertyAssignment, isContextuallyTyped, context) {
            return this.resolveAST(propertyAssignment.expression, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.resolveFunctionPropertyAssignment = function (funcProp, isContextuallyTyped, context) {
            return this.resolveAnyFunctionExpression(funcProp, funcProp.callSignature.typeParameterList, funcProp.callSignature.parameterList.parameters, TypeScript.ASTHelpers.getType(funcProp), funcProp.block, null, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.typeCheckFunctionPropertyAssignment = function (funcProp, isContextuallyTyped, context) {
            this.typeCheckAnyFunctionExpression(funcProp, funcProp.callSignature.typeParameterList, funcProp.callSignature.parameterList.parameters, TypeScript.ASTHelpers.getType(funcProp), funcProp.block, null, isContextuallyTyped, context);
        };

        PullTypeResolver.prototype.resolveObjectLiteralExpression = function (expressionAST, isContextuallyTyped, context, additionalResults) {
            var symbol = this.getSymbolForAST(expressionAST, context);
            var hasResolvedSymbol = symbol && symbol.isResolved;

            if (!hasResolvedSymbol || additionalResults || this.canTypeCheckAST(expressionAST, context)) {
                if (this.canTypeCheckAST(expressionAST, context)) {
                    this.setTypeChecked(expressionAST, context);
                }
                symbol = this.computeObjectLiteralExpression(expressionAST, isContextuallyTyped, context, additionalResults);
                this.setSymbolForAST(expressionAST, symbol, context);
            }

            return symbol;
        };

        PullTypeResolver.prototype.bindObjectLiteralMembers = function (objectLiteralDeclaration, objectLiteralTypeSymbol, objectLiteralMembers, isUsingExistingSymbol, pullTypeContext) {
            var boundMemberSymbols = [];
            var memberSymbol;
            for (var i = 0, len = objectLiteralMembers.length; i < len; i++) {
                var propertyAssignment = objectLiteralMembers[i];

                var id = this.getPropertyAssignmentName(propertyAssignment);
                var assignmentText = getPropertyAssignmentNameTextFromIdentifier(id);

                var isAccessor = propertyAssignment.kind() === 139 /* GetAccessor */ || propertyAssignment.kind() === 140 /* SetAccessor */;
                var decl = this.semanticInfoChain.getDeclForAST(propertyAssignment);
                TypeScript.Debug.assert(decl);

                if (propertyAssignment.kind() === 240 /* SimplePropertyAssignment */) {
                    if (!isUsingExistingSymbol) {
                        memberSymbol = new TypeScript.PullSymbol(assignmentText.memberName, TypeScript.PullElementKind.Property, this.semanticInfoChain);
                        memberSymbol.addDeclaration(decl);
                        decl.setSymbol(memberSymbol, this.semanticInfoChain);
                    } else {
                        memberSymbol = decl.getSymbol(this.semanticInfoChain);
                    }
                } else if (propertyAssignment.kind() === 241 /* FunctionPropertyAssignment */) {
                    memberSymbol = decl.getSymbol(this.semanticInfoChain);
                } else {
                    TypeScript.Debug.assert(isAccessor);
                    memberSymbol = decl.getSymbol(this.semanticInfoChain);
                }

                if (!isUsingExistingSymbol && !isAccessor) {
                    // Make sure this was not defined before
                    var existingMember = objectLiteralTypeSymbol.findMember(memberSymbol.name, true);
                    if (existingMember) {
                        pullTypeContext.postDiagnostic(this.semanticInfoChain.duplicateIdentifierDiagnosticFromAST(propertyAssignment, assignmentText.actualText));
                    }

                    objectLiteralTypeSymbol.addMember(memberSymbol);
                }

                boundMemberSymbols.push(memberSymbol);
            }

            return boundMemberSymbols;
        };

        PullTypeResolver.prototype.resolveObjectLiteralMembers = function (objectLiteralDeclaration, objectLiteralTypeSymbol, objectLiteralContextualType, objectLiteralMembers, stringIndexerSignature, numericIndexerSignature, allMemberTypes, allNumericMemberTypes, boundMemberSymbols, isUsingExistingSymbol, pullTypeContext, additionalResults) {
            for (var i = 0, len = objectLiteralMembers.length; i < len; i++) {
                var propertyAssignment = objectLiteralMembers[i];

                var acceptedContextualType = false;
                var assigningSymbol = null;

                var id = this.getPropertyAssignmentName(propertyAssignment);
                var memberSymbol = boundMemberSymbols[i];
                var contextualMemberType = null;

                if (objectLiteralContextualType) {
                    assigningSymbol = this.getNamedPropertySymbol(memberSymbol.name, TypeScript.PullElementKind.SomeValue, objectLiteralContextualType);

                    // Consider index signatures as potential contextual types
                    if (!assigningSymbol) {
                        if (numericIndexerSignature && TypeScript.PullHelpers.isNameNumeric(memberSymbol.name)) {
                            assigningSymbol = numericIndexerSignature;
                        } else if (stringIndexerSignature) {
                            assigningSymbol = stringIndexerSignature;
                        }
                    }

                    if (assigningSymbol) {
                        this.resolveDeclaredSymbol(assigningSymbol, pullTypeContext);

                        contextualMemberType = assigningSymbol.kind === TypeScript.PullElementKind.IndexSignature ? assigningSymbol.returnType : assigningSymbol.type;
                        pullTypeContext.propagateContextualType(contextualMemberType);

                        acceptedContextualType = true;

                        if (additionalResults) {
                            additionalResults.membersContextTypeSymbols[i] = contextualMemberType;
                        }
                    }
                }

                var memberSymbolType = this.resolveAST(propertyAssignment, contextualMemberType !== null, pullTypeContext).type;

                if (memberSymbolType) {
                    if (memberSymbolType.isGeneric()) {
                        objectLiteralTypeSymbol.setHasGenericMember();
                    }

                    // Add the member to the appropriate member type lists to compute the type of the synthesized index signatures
                    if (stringIndexerSignature) {
                        allMemberTypes.push(memberSymbolType);
                    }
                    if (numericIndexerSignature && TypeScript.PullHelpers.isNameNumeric(memberSymbol.name)) {
                        allNumericMemberTypes.push(memberSymbolType);
                    }
                }

                if (acceptedContextualType) {
                    pullTypeContext.popAnyContextualType();
                }

                var isAccessor = propertyAssignment.kind() === 140 /* SetAccessor */ || propertyAssignment.kind() === 139 /* GetAccessor */;
                if (!memberSymbol.isResolved) {
                    if (isAccessor) {
                        this.setSymbolForAST(id, memberSymbolType, pullTypeContext);
                    } else {
                        pullTypeContext.setTypeInContext(memberSymbol, memberSymbolType);
                        memberSymbol.setResolved();

                        this.setSymbolForAST(id, memberSymbol, pullTypeContext);
                    }
                }
            }
        };

        // if there's no type annotation on the assigning ISyntaxElement, we need to create a type from each binary expression
        // in the object literal
        PullTypeResolver.prototype.computeObjectLiteralExpression = function (objectLitAST, isContextuallyTyped, context, additionalResults) {
            // PULLTODO: Create a decl for the object literal
            // walk the members of the object literal,
            // create fields for each based on the value assigned in
            var objectLitDecl = this.semanticInfoChain.getDeclForAST(objectLitAST);
            TypeScript.Debug.assert(objectLitDecl);

            var typeSymbol = this.getSymbolForAST(objectLitAST, context);
            var isUsingExistingSymbol = !!typeSymbol;

            if (!typeSymbol) {
                // TODO: why don't se just use the normal symbol binder for this?
                typeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.ObjectLiteral, this.semanticInfoChain);
                typeSymbol.addDeclaration(objectLitDecl);
                this.setSymbolForAST(objectLitAST, typeSymbol, context);
                objectLitDecl.setSymbol(typeSymbol, this.semanticInfoChain);
            }

            var propertyAssignments = objectLitAST.propertyAssignments;
            var contextualType = null;

            if (isContextuallyTyped) {
                contextualType = context.getContextualType();
                this.resolveDeclaredSymbol(contextualType, context);
            }

            var stringIndexerSignature = null;
            var numericIndexerSignature = null;
            var allMemberTypes = null;
            var allNumericMemberTypes = null;

            // Get the index signatures for contextual typing
            if (contextualType) {
                var indexSignatures = this.getBothKindsOfIndexSignaturesExcludingAugmentedType(contextualType, context);

                stringIndexerSignature = indexSignatures.stringSignature;
                numericIndexerSignature = indexSignatures.numericSignature;

                // Start collecting the types of all the members so we can stamp the object
                // literal with the proper index signatures
                if (stringIndexerSignature) {
                    allMemberTypes = [];
                }

                if (numericIndexerSignature) {
                    allNumericMemberTypes = [];
                }
            }

            if (propertyAssignments) {
                if (additionalResults) {
                    additionalResults.membersContextTypeSymbols = [];
                }

                // first bind decls and symbols
                var boundMemberSymbols = this.bindObjectLiteralMembers(objectLitDecl, typeSymbol, propertyAssignments, isUsingExistingSymbol, context);

                // now perform member symbol resolution
                this.resolveObjectLiteralMembers(objectLitDecl, typeSymbol, contextualType, propertyAssignments, stringIndexerSignature, numericIndexerSignature, allMemberTypes, allNumericMemberTypes, boundMemberSymbols, isUsingExistingSymbol, context, additionalResults);

                if (!isUsingExistingSymbol) {
                    this.stampObjectLiteralWithIndexSignature(typeSymbol, allMemberTypes, stringIndexerSignature, context);
                    this.stampObjectLiteralWithIndexSignature(typeSymbol, allNumericMemberTypes, numericIndexerSignature, context);
                }
            }

            typeSymbol.setResolved();
            return typeSymbol;
        };

        PullTypeResolver.prototype.getPropertyAssignmentName = function (propertyAssignment) {
            if (propertyAssignment.kind() === 240 /* SimplePropertyAssignment */) {
                return propertyAssignment.propertyName;
            } else if (propertyAssignment.kind() === 241 /* FunctionPropertyAssignment */) {
                return propertyAssignment.propertyName;
            } else if (propertyAssignment.kind() === 139 /* GetAccessor */) {
                return propertyAssignment.propertyName;
            } else if (propertyAssignment.kind() === 140 /* SetAccessor */) {
                return propertyAssignment.propertyName;
            } else {
                TypeScript.Debug.assert(false);
            }
        };

        PullTypeResolver.prototype.stampObjectLiteralWithIndexSignature = function (objectLiteralSymbol, indexerTypeCandidates, contextualIndexSignature, context) {
            if (contextualIndexSignature) {
                var typeCollection = {
                    getLength: function () {
                        return indexerTypeCandidates.length;
                    },
                    getTypeAtIndex: function (index) {
                        return indexerTypeCandidates[index];
                    }
                };
                var decl = objectLiteralSymbol.getDeclarations()[0];
                var indexerReturnType = this.findBestCommonType(contextualIndexSignature.returnType, typeCollection, context).widenedType(this, null, context);
                if (indexerReturnType === contextualIndexSignature.returnType) {
                    objectLiteralSymbol.addIndexSignature(contextualIndexSignature);
                } else {
                    // Create an index signature
                    this.semanticInfoChain.addSyntheticIndexSignature(decl, objectLiteralSymbol, this.getASTForDecl(decl), contextualIndexSignature.parameters[0].name, contextualIndexSignature.parameters[0].type, indexerReturnType);
                }
            }
        };

        PullTypeResolver.prototype.resolveArrayLiteralExpression = function (arrayLit, isContextuallyTyped, context) {
            var symbol = this.getSymbolForAST(arrayLit, context);
            if (!symbol || this.canTypeCheckAST(arrayLit, context)) {
                if (this.canTypeCheckAST(arrayLit, context)) {
                    this.setTypeChecked(arrayLit, context);
                }
                symbol = this.computeArrayLiteralExpressionSymbol(arrayLit, isContextuallyTyped, context);
                this.setSymbolForAST(arrayLit, symbol, context);
            }

            return symbol;
        };

        PullTypeResolver.prototype.computeArrayLiteralExpressionSymbol = function (arrayLit, isContextuallyTyped, context) {
            var elements = arrayLit.expressions;
            var elementTypes = [];
            var contextualElementType = null;

            // if the target type is an array type, extract the element type
            if (isContextuallyTyped) {
                var contextualType = context.getContextualType();

                this.resolveDeclaredSymbol(contextualType, context);

                if (contextualType) {
                    // Get the number indexer if it exists
                    var indexSignatures = this.getBothKindsOfIndexSignaturesExcludingAugmentedType(contextualType, context);
                    if (indexSignatures.numericSignature) {
                        contextualElementType = indexSignatures.numericSignature.returnType;
                    }
                }
            }

            // Resolve element types
            if (elements) {
                if (contextualElementType) {
                    context.propagateContextualType(contextualElementType);
                }

                for (var i = 0, n = elements.length; i < n; i++) {
                    elementTypes.push(this.resolveAST(elements[i], contextualElementType !== null, context).type);
                }

                if (contextualElementType) {
                    context.popAnyContextualType();
                }
            }

            var elementTypesCollection = {
                getLength: function () {
                    return elements.length;
                },
                getTypeAtIndex: function (index) {
                    return elementTypes[index];
                }
            };

            // April 2014, Section 4.6:
            //      In the absence of a contextual type, the type of an array literal is C[], where C is the
            //      Undefined type(section 3.2.6) if the array literal is empty, or the best common type of
            //      the element expressions if the array literal is not empty.
            //      When an array literal is contextually typed(section 4.19) by an object type containing a
            //      numeric index signature of type T, each element expression is contextually typed by T and
            //      the type of the array literal is the best common type of T and the types of the element
            //      expressions.
            //
            // While the spec does not say it, an inferential type causes an empty array literal to have
            // the undefined[] type. In other words, the first clause from the excerpt above applies even
            // though there is a "contextual type" present. This is the intention, even though the spec
            // seems to imply the contrary.
            contextualElementType = context.isInferentiallyTyping() ? null : contextualElementType;

            var elementType = contextualElementType === null && elements.length === 0 ? this.semanticInfoChain.undefinedTypeSymbol : this.findBestCommonType(contextualElementType, elementTypesCollection, context);

            return this.getArrayType(elementType);
        };

        PullTypeResolver.prototype.resolveElementAccessExpression = function (callEx, context) {
            var symbolAndDiagnostic = this.computeElementAccessExpressionSymbolAndDiagnostic(callEx, context);

            if (this.canTypeCheckAST(callEx, context)) {
                this.typeCheckElementAccessExpression(callEx, context, symbolAndDiagnostic);
            }

            return symbolAndDiagnostic.symbol;
        };

        PullTypeResolver.prototype.typeCheckElementAccessExpression = function (callEx, context, symbolAndDiagnostic) {
            this.setTypeChecked(callEx, context);
            context.postDiagnostic(symbolAndDiagnostic.diagnostic);
        };

        PullTypeResolver.prototype.computeElementAccessExpressionSymbolAndDiagnostic = function (callEx, context) {
            // resolve the target
            var targetSymbol = this.resolveAST(callEx.expression, false, context);
            var indexType = this.resolveAST(callEx.argumentExpression, false, context).type;

            var targetTypeSymbol = targetSymbol.type;

            targetTypeSymbol = this.getApparentType(targetTypeSymbol);

            if (this.isAnyOrEquivalent(targetTypeSymbol)) {
                return { symbol: targetTypeSymbol };
            }

            var elementType = targetTypeSymbol.getElementType();

            var isNumberIndex = indexType === this.semanticInfoChain.numberTypeSymbol || TypeScript.PullHelpers.symbolIsEnum(indexType);

            if (elementType && isNumberIndex) {
                return { symbol: elementType };
            }

            // if the index expression is a string literal or a numberic literal and the object expression has
            // a property with that name,  the property access is the type of that property
            if (callEx.argumentExpression.kind() === 14 /* StringLiteral */ || callEx.argumentExpression.kind() === 13 /* NumericLiteral */) {
                var memberName = callEx.argumentExpression.kind() === 14 /* StringLiteral */ ? TypeScript.stripStartAndEndQuotes(callEx.argumentExpression.text()) : TypeScript.tokenValueText(callEx.argumentExpression);

                // November 18, 2013, Section 4.10:
                // If IndexExpr is a string literal or a numeric literal and ObjExpr's apparent type
                // has a property with the name given by that literal(converted to its string representation
                // in the case of a numeric literal), the property access is of the type of that property.
                // Note that here we are assuming the apparent type is already accounted for up to
                // augmentation. So we just check the augmented type.
                var member = this._getNamedPropertySymbolOfAugmentedType(memberName, targetTypeSymbol);

                if (member) {
                    this.resolveDeclaredSymbol(member, context);

                    return { symbol: member.type };
                }
            }

            var signatures = this.getBothKindsOfIndexSignaturesIncludingAugmentedType(targetTypeSymbol, context);

            var stringSignature = signatures.stringSignature;
            var numberSignature = signatures.numericSignature;

            // otherwise, if the object expression has a numeric index signature and the index expression is
            // of type Any, the Number primitive type or an enum type, the property access is of the type of that index
            // signature
            if (numberSignature && (isNumberIndex || indexType === this.semanticInfoChain.anyTypeSymbol)) {
                return { symbol: numberSignature.returnType || this.semanticInfoChain.anyTypeSymbol };
            } else if (stringSignature && (isNumberIndex || indexType === this.semanticInfoChain.anyTypeSymbol || indexType === this.semanticInfoChain.stringTypeSymbol)) {
                return { symbol: stringSignature.returnType || this.semanticInfoChain.anyTypeSymbol };
            } else if (isNumberIndex || indexType === this.semanticInfoChain.anyTypeSymbol || indexType === this.semanticInfoChain.stringTypeSymbol) {
                if (this.compilationSettings.noImplicitAny()) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(callEx.argumentExpression, TypeScript.DiagnosticCode.Index_signature_of_object_type_implicitly_has_an_any_type));
                }
                return { symbol: this.semanticInfoChain.anyTypeSymbol };
            } else {
                return {
                    symbol: this.getNewErrorTypeSymbol(),
                    diagnostic: this.semanticInfoChain.diagnosticFromAST(callEx, TypeScript.DiagnosticCode.An_index_expression_argument_must_be_string_number_or_any)
                };
            }
        };

        PullTypeResolver.prototype.getBothKindsOfIndexSignaturesIncludingAugmentedType = function (enclosingType, context) {
            return this._getBothKindsOfIndexSignatures(enclosingType, context, true);
        };

        PullTypeResolver.prototype.getBothKindsOfIndexSignaturesExcludingAugmentedType = function (enclosingType, context) {
            return this._getBothKindsOfIndexSignatures(enclosingType, context, false);
        };

        PullTypeResolver.prototype._getBothKindsOfIndexSignatures = function (enclosingType, context, includeAugmentedType) {
            var signatures = includeAugmentedType ? enclosingType.getIndexSignaturesOfAugmentedType(this, this.cachedFunctionInterfaceType(), this.cachedObjectInterfaceType()) : enclosingType.getIndexSignatures();

            var stringSignature = null;
            var numberSignature = null;
            var signature = null;
            var paramSymbols;
            var paramType;

            for (var i = 0; i < signatures.length; i++) {
                if (stringSignature && numberSignature) {
                    break;
                }

                signature = signatures[i];
                if (!signature.isResolved) {
                    this.resolveDeclaredSymbol(signature, context);
                }

                paramSymbols = signature.parameters;

                if (paramSymbols.length) {
                    paramType = paramSymbols[0].type;

                    if (!stringSignature && paramType === this.semanticInfoChain.stringTypeSymbol) {
                        stringSignature = signature;
                        continue;
                    } else if (!numberSignature && paramType === this.semanticInfoChain.numberTypeSymbol) {
                        numberSignature = signature;
                        continue;
                    }
                }
            }

            return {
                numericSignature: numberSignature,
                stringSignature: stringSignature
            };
        };

        // This method can be called to get unhidden (not shadowed by a signature in derived class)
        // signatures from a set of base class signatures. Can be used for signatures of any kind.
        // October 16, 2013: Section 7.1:
        // A call signature declaration hides a base type call signature that is identical when
        // return types are ignored.
        // A construct signature declaration hides a base type construct signature that is
        // identical when return types are ignored.
        // A string index signature declaration hides a base type string index signature.
        // A numeric index signature declaration hides a base type numeric index signature.
        PullTypeResolver.prototype._addUnhiddenSignaturesFromBaseType = function (derivedTypeSignatures, baseTypeSignatures, signaturesBeingAggregated) {
            var _this = this;
            // If there are no derived type signatures, none of the base signatures will be hidden.
            if (!derivedTypeSignatures) {
                signaturesBeingAggregated.push.apply(signaturesBeingAggregated, baseTypeSignatures);
                return;
            }

            var context = new TypeScript.PullTypeResolutionContext(this);
            for (var i = 0; i < baseTypeSignatures.length; i++) {
                var baseSignature = baseTypeSignatures[i];

                // If it is different from every signature in the derived type (modulo
                // return types, add it to the list)
                var signatureIsHidden = TypeScript.ArrayUtilities.any(derivedTypeSignatures, function (sig) {
                    return _this.signaturesAreIdenticalWithNewEnclosingTypes(baseSignature, sig, context, false);
                });

                if (!signatureIsHidden) {
                    signaturesBeingAggregated.push(baseSignature);
                }
            }
        };

        PullTypeResolver.prototype.resolveBinaryAdditionOperation = function (binaryExpression, context) {
            var lhsExpression = this.resolveAST(binaryExpression.left, false, context);
            var lhsType = lhsExpression.type;
            var rhsType = this.resolveAST(binaryExpression.right, false, context).type;

            // November 18, 2013
            // 4.15.2 The + operator
            // The binary + operator requires both operands to be of the Number primitive type or an enum type, or at least one of the operands to be of type Any or the String primitive type.
            // Operands of an enum type are treated as having the primitive type Number.
            // If one operand is the null or undefined value, it is treated as having the type of the other operand.
            if (TypeScript.PullHelpers.symbolIsEnum(lhsType)) {
                lhsType = this.semanticInfoChain.numberTypeSymbol;
            }

            if (TypeScript.PullHelpers.symbolIsEnum(rhsType)) {
                rhsType = this.semanticInfoChain.numberTypeSymbol;
            }

            var isLhsTypeNullOrUndefined = lhsType === this.semanticInfoChain.nullTypeSymbol || lhsType === this.semanticInfoChain.undefinedTypeSymbol;
            var isRhsTypeNullOrUndefined = rhsType === this.semanticInfoChain.nullTypeSymbol || rhsType === this.semanticInfoChain.undefinedTypeSymbol;

            if (isLhsTypeNullOrUndefined) {
                if (isRhsTypeNullOrUndefined) {
                    lhsType = rhsType = this.semanticInfoChain.anyTypeSymbol;
                } else {
                    lhsType = rhsType;
                }
            } else if (isRhsTypeNullOrUndefined) {
                rhsType = lhsType;
            }

            var exprType = null;

            if (lhsType === this.semanticInfoChain.stringTypeSymbol || rhsType === this.semanticInfoChain.stringTypeSymbol) {
                exprType = this.semanticInfoChain.stringTypeSymbol;
            } else if (this.isAnyOrEquivalent(lhsType) || this.isAnyOrEquivalent(rhsType)) {
                exprType = this.semanticInfoChain.anyTypeSymbol;
            } else if (rhsType === this.semanticInfoChain.numberTypeSymbol && lhsType === this.semanticInfoChain.numberTypeSymbol) {
                exprType = this.semanticInfoChain.numberTypeSymbol;
            }

            if (this.canTypeCheckAST(binaryExpression, context)) {
                this.setTypeChecked(binaryExpression, context);

                if (exprType) {
                    if (binaryExpression.kind() === 175 /* AddAssignmentExpression */) {
                        // Check if LHS is a valid target
                        if (!this.isReference(binaryExpression.left, lhsExpression)) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.left, TypeScript.DiagnosticCode.Invalid_left_hand_side_of_assignment_expression));
                        }

                        this.checkAssignability(binaryExpression.left, exprType, lhsType, context);
                    }
                } else {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.left, TypeScript.DiagnosticCode.Invalid_expression_types_not_known_to_support_the_addition_operator));
                }
            }

            if (!exprType) {
                exprType = this.semanticInfoChain.anyTypeSymbol;
            }

            return exprType;
        };

        PullTypeResolver.prototype.bestCommonTypeOfTwoTypesWithOrWithoutContextualType = function (contextualType, type1, type2, context) {
            return this.findBestCommonType(contextualType, {
                getLength: function () {
                    return 2;
                },
                getTypeAtIndex: function (index) {
                    switch (index) {
                        case 0: return type1;
                        case 1: return type2;
                    }
                }
            }, context);
        };

        PullTypeResolver.prototype.resolveLogicalOrExpression = function (binex, isContextuallyTyped, context) {
            // October 11, 2013:
            // The || operator permits the operands to be of any type.
            if (this.canTypeCheckAST(binex, context)) {
                // So there's no type checking we actually have to do.
                this.setTypeChecked(binex, context);
            }

            if (isContextuallyTyped) {
                // If the || expression is contextually typed(section 4.19), the operands are
                // contextually typed by the same type and the result is of the best common type
                // (section 3.10) of the contextual type and the two operand types.
                var contextualType = context.getContextualType();
                var leftType = this.resolveAST(binex.left, isContextuallyTyped, context).type;
                var rightType = this.resolveAST(binex.right, isContextuallyTyped, context).type;

                return this.bestCommonTypeOfTwoTypesWithOrWithoutContextualType(contextualType, leftType, rightType, context);
            } else {
                // If the || expression is not contextually typed, the right operand is contextually
                // typed by the type of the left operand and the result is of the best common type of
                // the two operand types.
                var leftType = this.resolveAST(binex.left, false, context).type;

                context.pushNewContextualType(leftType);
                var rightType = this.resolveAST(binex.right, true, context).type;
                context.popAnyContextualType();

                return this.bestCommonTypeOfTwoTypesWithOrWithoutContextualType(null, leftType, rightType, context);
            }
        };

        PullTypeResolver.prototype.resolveLogicalAndExpression = function (binex, context) {
            if (this.canTypeCheckAST(binex, context)) {
                this.setTypeChecked(binex, context);

                this.resolveAST(binex.left, false, context);
            }

            // September 17, 2013: The && operator permits the operands to be of any type and
            // produces a result of the same type as the second operand.
            return this.resolveAST(binex.right, false, context).type;
        };

        PullTypeResolver.prototype.computeTypeOfConditionalExpression = function (leftType, rightType, isContextuallyTyped, context) {
            // October 11, 2013
            // If the conditional expression is contextually typed (section 4.19), Expr1 and Expr2
            // are contextually typed by the same type and the result is of the best common type
            // (section 3.10) of the contextual type and the types of Expr1 and Expr2.
            // If the conditional expression is not contextually typed, the result is of the
            // best common type of the types of Expr1 and Expr2.
            var contextualType = isContextuallyTyped ? context.getContextualType() : null;
            return this.bestCommonTypeOfTwoTypesWithOrWithoutContextualType(contextualType, leftType, rightType, context);
        };

        PullTypeResolver.prototype.resolveConditionalExpression = function (trinex, isContextuallyTyped, context) {
            // October 11, 2013
            // If the conditional expression is contextually typed (section 4.19), Expr1 and Expr2
            // are contextually typed by the same type and the result is of the best common type
            // (section 3.10) of the contextual type and the types of Expr1 and Expr2.  An error
            // occurs if the best common type is not identical to at least one of the three
            // candidate types.
            var leftType = this.resolveAST(trinex.whenTrue, isContextuallyTyped, context).type;
            var rightType = this.resolveAST(trinex.whenFalse, isContextuallyTyped, context).type;

            var expressionType = this.computeTypeOfConditionalExpression(leftType, rightType, isContextuallyTyped, context);

            var conditionalTypesAreValid = this.conditionExpressionTypesAreValid(leftType, rightType, expressionType, isContextuallyTyped, context);

            if (this.canTypeCheckAST(trinex, context)) {
                this.setTypeChecked(trinex, context);
                this.resolveAST(trinex.condition, false, context);

                if (!this.conditionExpressionTypesAreValid(leftType, rightType, expressionType, isContextuallyTyped, context)) {
                    if (isContextuallyTyped) {
                        var contextualType = context.getContextualType();
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(trinex, TypeScript.DiagnosticCode.No_best_common_type_exists_between_0_1_and_2, [contextualType.toString(), leftType.toString(), rightType.toString()]));
                    } else {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(trinex, TypeScript.DiagnosticCode.No_best_common_type_exists_between_0_and_1, [leftType.toString(), rightType.toString()]));
                    }
                }
            }

            // If the conditional is not valid, then return an error symbol.  That way we won't
            // report further errors higher up the stack.
            if (!conditionalTypesAreValid) {
                return this.getNewErrorTypeSymbol();
            }

            return expressionType;
        };

        PullTypeResolver.prototype.conditionExpressionTypesAreValid = function (leftType, rightType, expressionType, isContextuallyTyped, context) {
            if (isContextuallyTyped) {
                var contextualType = context.getContextualType();
                if (this.typesAreIdentical(expressionType, leftType, context) || this.typesAreIdentical(expressionType, rightType, context) || this.typesAreIdentical(expressionType, contextualType, context)) {
                    return true;
                }
            } else {
                if (this.typesAreIdentical(expressionType, leftType, context) || this.typesAreIdentical(expressionType, rightType, context)) {
                    return true;
                }
            }

            return false;
        };

        PullTypeResolver.prototype.resolveParenthesizedExpression = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);
            }

            // September 17, 2013: A parenthesized expression (Expression) has the same type and
            // classification as the Expression itself
            return this.resolveAST(ast.expression, false, context);
        };

        PullTypeResolver.prototype.resolveExpressionStatement = function (ast, context) {
            if (this.canTypeCheckAST(ast, context)) {
                this.setTypeChecked(ast, context);

                this.resolveAST(ast.expression, false, context);
            }

            // All statements have the 'void' type.
            return this.semanticInfoChain.voidTypeSymbol;
        };

        PullTypeResolver.prototype.resolveInvocationExpression = function (callEx, context, additionalResults) {
            var symbol = this.getSymbolForAST(callEx, context);

            if (!symbol || !symbol.isResolved) {
                if (!additionalResults) {
                    additionalResults = new PullAdditionalCallResolutionData();
                }
                symbol = this.computeInvocationExpressionSymbol(callEx, context, additionalResults);
                if (this.canTypeCheckAST(callEx, context)) {
                    this.setTypeChecked(callEx, context);
                }
                if (symbol !== this.semanticInfoChain.anyTypeSymbol) {
                    this.setSymbolForAST(callEx, symbol, context);
                }
                this.semanticInfoChain.setCallResolutionDataForAST(callEx, additionalResults);
            } else {
                if (this.canTypeCheckAST(callEx, context)) {
                    this.typeCheckInvocationExpression(callEx, context);
                }

                var callResolutionData = this.semanticInfoChain.getCallResolutionDataForAST(callEx);
                if (additionalResults && (callResolutionData !== additionalResults)) {
                    additionalResults.actualParametersContextTypeSymbols = callResolutionData.actualParametersContextTypeSymbols;
                    additionalResults.candidateSignature = callResolutionData.candidateSignature;
                    additionalResults.resolvedSignatures = callResolutionData.resolvedSignatures;
                    additionalResults.targetSymbol = callResolutionData.targetSymbol;
                }
            }

            return symbol;
        };

        PullTypeResolver.prototype.typeCheckInvocationExpression = function (callEx, context) {
            this.setTypeChecked(callEx, context);
            var targetSymbol = this.resolveAST(callEx.expression, false, context);

            if (callEx.argumentList.arguments) {
                var callResolutionData = this.semanticInfoChain.getCallResolutionDataForAST(callEx);

                var len = callEx.argumentList.arguments.length;
                for (var i = 0; i < len; i++) {
                    // Ensure call resolution data contains additional information.
                    // Actual parameters context type symbols will be undefined if the call target resolves to any or error types.
                    var contextualType = callResolutionData.actualParametersContextTypeSymbols ? callResolutionData.actualParametersContextTypeSymbols[i] : null;
                    if (contextualType) {
                        context.pushNewContextualType(contextualType);
                    }

                    this.resolveAST(callEx.argumentList.arguments[i], contextualType !== null, context);

                    if (contextualType) {
                        context.popAnyContextualType();
                        contextualType = null;
                    }
                }
            }

            for (var i = 0; i < callResolutionData.diagnosticsFromOverloadResolution.length; i++) {
                context.postDiagnostic(callResolutionData.diagnosticsFromOverloadResolution[i]);
            }
        };

        PullTypeResolver.prototype.computeInvocationExpressionSymbol = function (callEx, context, additionalResults) {
            // resolve the target
            var targetSymbol = this.resolveAST(callEx.expression, false, context);
            var targetAST = this.getCallTargetErrorSpanAST(callEx);

            var targetTypeSymbol = targetSymbol.type;
            if (this.isAnyOrEquivalent(targetTypeSymbol)) {
                // Note: targetType is either any or an error.
                // resolve any arguments.
                this.resolveAST(callEx.argumentList.arguments, false, context);

                if (callEx.argumentList.typeArgumentList && callEx.argumentList.typeArgumentList.typeArguments.length) {
                    // Can't invoke 'any' generically.
                    if (targetTypeSymbol === this.semanticInfoChain.anyTypeSymbol) {
                        this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Untyped_function_calls_may_not_accept_type_arguments), additionalResults, context);
                        return this.getNewErrorTypeSymbol();
                    }
                    // Note: if we get here, targetType is an error type.  In that case we don't
                    // want to report *another* error since the user will have already gotten
                    // the first error about the target not resolving properly.
                }

                return this.semanticInfoChain.anyTypeSymbol;
            }

            var isSuperCall = false;

            if (callEx.expression.kind() === 50 /* SuperKeyword */) {
                isSuperCall = true;

                if (targetTypeSymbol.isClass()) {
                    targetSymbol = targetTypeSymbol.getConstructorMethod();
                    this.resolveDeclaredSymbol(targetSymbol, context);
                    targetTypeSymbol = targetSymbol.type;
                } else {
                    this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Calls_to_super_are_only_valid_inside_a_class), additionalResults, context);
                    this.resolveAST(callEx.argumentList.arguments, false, context);

                    // POST diagnostics
                    return this.getNewErrorTypeSymbol();
                }
            }

            var signatures = isSuperCall ? targetTypeSymbol.getConstructSignatures() : targetTypeSymbol.getCallSignatures();

            if (!signatures.length && (targetTypeSymbol.kind === TypeScript.PullElementKind.ConstructorType)) {
                this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, [targetTypeSymbol.toString()]), additionalResults, context);
            }

            var explicitTypeArgs = null;
            var couldNotFindGenericOverload = false;
            var couldNotAssignToConstraint;
            var constraintDiagnostic = null;
            var typeArgumentCountDiagnostic = null;
            var diagnostics = [];

            // resolve the type arguments, specializing if necessary
            if (callEx.argumentList.typeArgumentList) {
                // specialize the type arguments
                explicitTypeArgs = [];

                if (callEx.argumentList.typeArgumentList && callEx.argumentList.typeArgumentList.typeArguments.length) {
                    for (var i = 0; i < callEx.argumentList.typeArgumentList.typeArguments.length; i++) {
                        explicitTypeArgs[i] = this.resolveTypeReference(callEx.argumentList.typeArgumentList.typeArguments[i], context);
                    }
                }
            }

            var triedToInferTypeArgs = false;

            // next, walk the available signatures
            // if any are generic, and we don't have type arguments, try to infer
            // otherwise, try to specialize to the type arguments above
            var resolvedSignatures = [];
            var inferredOrExplicitTypeArgs;
            var specializedSignature;
            var typeParameters;
            var typeConstraint = null;
            var beforeResolutionSignatures = signatures;
            var targetTypeReplacementMap = targetTypeSymbol.getTypeParameterSubstitutionMap();

            for (var i = 0; i < signatures.length; i++) {
                typeParameters = signatures[i].getTypeParameters();
                couldNotAssignToConstraint = false;

                if (signatures[i].isGeneric() && typeParameters.length) {
                    // If it is a constructor call, the type arguments are that of the return Type that is the super type
                    if (isSuperCall && targetTypeSymbol.isGeneric() && !callEx.argumentList.typeArgumentList) {
                        explicitTypeArgs = signatures[i].returnType.getTypeArguments();
                    }

                    if (explicitTypeArgs) {
                        // October 16, 2013: Section 4.12.2
                        // A generic signature is a candidate in a function call with type arguments
                        // arguments when:
                        // The signature has the same number of type parameters as were supplied in
                        // the type argument list
                        // ...
                        if (explicitTypeArgs.length === typeParameters.length) {
                            inferredOrExplicitTypeArgs = explicitTypeArgs;
                        } else {
                            typeArgumentCountDiagnostic = typeArgumentCountDiagnostic || this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Signature_expected_0_type_arguments_got_1_instead, [typeParameters.length, explicitTypeArgs.length]);
                            continue;
                        }
                    } else {
                        TypeScript.Debug.assert(callEx.argumentList);
                        var typeArgumentInferenceContext = new TypeScript.InvocationTypeArgumentInferenceContext(this, context, signatures[i], callEx.argumentList);
                        inferredOrExplicitTypeArgs = this.inferArgumentTypesForSignature(typeArgumentInferenceContext, new TypeComparisonInfo(), context);
                        triedToInferTypeArgs = true;
                    }

                    // if we could infer Args, or we have type arguments, then attempt to specialize the signature
                    TypeScript.Debug.assert(inferredOrExplicitTypeArgs && inferredOrExplicitTypeArgs.length == typeParameters.length);

                    // When specializing the constraints, seed the replacement map with any substitutions already specified by
                    // the target function's type
                    var mutableTypeReplacementMap = new TypeScript.PullInstantiationHelpers.MutableTypeParameterSubstitutionMap(targetTypeReplacementMap ? targetTypeReplacementMap : []);
                    TypeScript.PullInstantiationHelpers.updateMutableTypeParameterSubstitutionMap(typeParameters, inferredOrExplicitTypeArgs, mutableTypeReplacementMap);
                    var typeReplacementMap = mutableTypeReplacementMap.typeParameterSubstitutionMap;

                    if (explicitTypeArgs) {
                        for (var j = 0; j < typeParameters.length; j++) {
                            typeConstraint = typeParameters[j].getConstraint();

                            // test specialization type for assignment compatibility with the constraint
                            if (typeConstraint) {
                                if (typeConstraint.isGeneric()) {
                                    typeConstraint = this.instantiateType(typeConstraint, typeReplacementMap);
                                }

                                // Section 3.4.2 (November 18, 2013):
                                // A type argument satisfies a type parameter constraint if the type argument is assignable
                                // to(section 3.8.4) the constraint type once type arguments are substituted for type parameters.
                                if (!this.sourceIsAssignableToTarget(inferredOrExplicitTypeArgs[j], typeConstraint, targetAST, context, null, true)) {
                                    var enclosingSymbol = this.getEnclosingSymbolForAST(targetAST);
                                    constraintDiagnostic = this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Type_0_does_not_satisfy_the_constraint_1, [inferredOrExplicitTypeArgs[j].toString(enclosingSymbol, true), typeConstraint.toString(enclosingSymbol, true)]);
                                    couldNotAssignToConstraint = true;
                                }

                                if (couldNotAssignToConstraint) {
                                    break;
                                }
                            }
                        }
                    }

                    if (couldNotAssignToConstraint) {
                        continue;
                    }

                    specializedSignature = this.instantiateSignature(signatures[i], typeReplacementMap);

                    if (specializedSignature) {
                        resolvedSignatures[resolvedSignatures.length] = specializedSignature;
                    }
                } else {
                    if (!(callEx.argumentList.typeArgumentList && callEx.argumentList.typeArgumentList.typeArguments.length)) {
                        resolvedSignatures[resolvedSignatures.length] = signatures[i];
                    }
                }
            }

            if (signatures.length && !resolvedSignatures.length) {
                couldNotFindGenericOverload = true;
            }

            signatures = resolvedSignatures;

            var errorCondition = null;
            if (!signatures.length) {
                additionalResults.targetSymbol = targetSymbol;
                additionalResults.resolvedSignatures = beforeResolutionSignatures;
                additionalResults.candidateSignature = beforeResolutionSignatures && beforeResolutionSignatures.length ? beforeResolutionSignatures[0] : null;

                additionalResults.actualParametersContextTypeSymbols = actualParametersContextTypeSymbols;

                this.resolveAST(callEx.argumentList.arguments, false, context);

                // if there are no call signatures, but the target is assignable to 'Function', return 'any'
                if (!couldNotFindGenericOverload) {
                    // if there are no call signatures, but the target is assignable to 'Function', return 'any'
                    if (this.cachedFunctionInterfaceType() && this.sourceIsAssignableToTarget(targetTypeSymbol, this.cachedFunctionInterfaceType(), targetAST, context)) {
                        if (callEx.argumentList.typeArgumentList) {
                            this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Non_generic_functions_may_not_accept_type_arguments), additionalResults, context);
                        }
                        return this.semanticInfoChain.anyTypeSymbol;
                    }

                    this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(callEx, TypeScript.DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature), additionalResults, context);
                } else if (constraintDiagnostic) {
                    this.postOverloadResolutionDiagnostics(constraintDiagnostic, additionalResults, context);
                } else if (typeArgumentCountDiagnostic) {
                    this.postOverloadResolutionDiagnostics(typeArgumentCountDiagnostic, additionalResults, context);
                } else {
                    this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(callEx, TypeScript.DiagnosticCode.Could_not_select_overload_for_call_expression), additionalResults, context);
                }

                return this.getNewErrorTypeSymbol();
            }

            var signature = this.resolveOverloads(callEx, signatures, callEx.argumentList.typeArgumentList !== null, context, diagnostics);
            var useBeforeResolutionSignatures = signature == null;

            if (!signature) {
                for (var i = 0; i < diagnostics.length; i++) {
                    this.postOverloadResolutionDiagnostics(diagnostics[i], additionalResults, context);
                }

                this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Could_not_select_overload_for_call_expression), additionalResults, context);

                // Remember the error state
                // POST diagnostics
                errorCondition = this.getNewErrorTypeSymbol();

                if (!signatures.length) {
                    return errorCondition;
                }

                // Attempt to recover from the error condition
                // First, pick the first signature as the candidate signature
                signature = signatures[0];
            }

            var rootSignature = signature.getRootSymbol();
            if (!rootSignature.isGeneric() && callEx.argumentList.typeArgumentList) {
                this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Non_generic_functions_may_not_accept_type_arguments), additionalResults, context);
            } else if (rootSignature.isGeneric() && callEx.argumentList.typeArgumentList && rootSignature.getTypeParameters() && (callEx.argumentList.typeArgumentList.typeArguments.length !== rootSignature.getTypeParameters().length)) {
                this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Signature_expected_0_type_arguments_got_1_instead, [rootSignature.getTypeParameters().length, callEx.argumentList.typeArgumentList.typeArguments.length]), additionalResults, context);
            }

            var returnType = isSuperCall ? this.semanticInfoChain.voidTypeSymbol : signature.returnType;

            // contextually type arguments
            var actualParametersContextTypeSymbols = [];
            if (callEx.argumentList.arguments) {
                var len = callEx.argumentList.arguments.length;
                var params = signature.parameters;
                var contextualType = null;
                var signatureDecl = signature.getDeclarations()[0];

                for (var i = 0; i < len; i++) {
                    // account for varargs
                    if (params.length) {
                        if (i < params.length - 1 || (i < params.length && !signature.hasVarArgs)) {
                            this.resolveDeclaredSymbol(params[i], context);
                            contextualType = params[i].type;
                        } else if (signature.hasVarArgs) {
                            contextualType = params[params.length - 1].type;
                            if (contextualType.isArrayNamedTypeReference()) {
                                contextualType = contextualType.getElementType();
                            }
                        }
                    }

                    if (contextualType) {
                        context.pushNewContextualType(contextualType);
                        actualParametersContextTypeSymbols[i] = contextualType;
                    }

                    this.resolveAST(callEx.argumentList.arguments[i], contextualType !== null, context);

                    if (contextualType) {
                        context.popAnyContextualType();
                        contextualType = null;
                    }
                }
            }

            // Store any additional resolution results if needed before we return
            additionalResults.targetSymbol = targetSymbol;
            if (useBeforeResolutionSignatures && beforeResolutionSignatures) {
                additionalResults.resolvedSignatures = beforeResolutionSignatures;
                additionalResults.candidateSignature = beforeResolutionSignatures[0];
            } else {
                additionalResults.resolvedSignatures = signatures;
                additionalResults.candidateSignature = signature;
            }
            additionalResults.actualParametersContextTypeSymbols = actualParametersContextTypeSymbols;

            if (errorCondition) {
                return errorCondition;
            }

            if (!returnType) {
                returnType = this.semanticInfoChain.anyTypeSymbol;
            }

            return returnType;
        };

        PullTypeResolver.prototype.resolveObjectCreationExpression = function (callEx, context, additionalResults) {
            var symbol = this.getSymbolForAST(callEx, context);

            if (!symbol || !symbol.isResolved) {
                if (!additionalResults) {
                    additionalResults = new PullAdditionalCallResolutionData();
                }
                symbol = this.computeObjectCreationExpressionSymbol(callEx, context, additionalResults);
                if (this.canTypeCheckAST(callEx, context)) {
                    this.setTypeChecked(callEx, context);
                }
                this.setSymbolForAST(callEx, symbol, context);
                this.semanticInfoChain.setCallResolutionDataForAST(callEx, additionalResults);
            } else {
                if (this.canTypeCheckAST(callEx, context)) {
                    this.typeCheckObjectCreationExpression(callEx, context);
                }

                var callResolutionData = this.semanticInfoChain.getCallResolutionDataForAST(callEx);
                if (additionalResults && (callResolutionData !== additionalResults)) {
                    additionalResults.actualParametersContextTypeSymbols = callResolutionData.actualParametersContextTypeSymbols;
                    additionalResults.candidateSignature = callResolutionData.candidateSignature;
                    additionalResults.resolvedSignatures = callResolutionData.resolvedSignatures;
                    additionalResults.targetSymbol = callResolutionData.targetSymbol;
                }
            }

            return symbol;
        };

        PullTypeResolver.prototype.typeCheckObjectCreationExpression = function (callEx, context) {
            this.setTypeChecked(callEx, context);
            this.resolveAST(callEx.expression, false, context);
            var callResolutionData = this.semanticInfoChain.getCallResolutionDataForAST(callEx);
            if (callEx.argumentList) {
                var callResolutionData = this.semanticInfoChain.getCallResolutionDataForAST(callEx);
                var len = callEx.argumentList.arguments.length;

                for (var i = 0; i < len; i++) {
                    // Ensure call resolution data contains additional information.
                    // Actual parameters context type symbols will be undefined if the call target resolves to any or error types.
                    var contextualType = callResolutionData.actualParametersContextTypeSymbols ? callResolutionData.actualParametersContextTypeSymbols[i] : null;
                    if (contextualType) {
                        context.pushNewContextualType(contextualType);
                    }

                    this.resolveAST(callEx.argumentList.arguments[i], contextualType !== null, context);

                    if (contextualType) {
                        context.popAnyContextualType();
                        contextualType = null;
                    }
                }
            }

            for (var i = 0; i < callResolutionData.diagnosticsFromOverloadResolution.length; i++) {
                context.postDiagnostic(callResolutionData.diagnosticsFromOverloadResolution[i]);
            }
        };

        PullTypeResolver.prototype.postOverloadResolutionDiagnostics = function (diagnostic, additionalResults, context) {
            if (!context.inProvisionalResolution()) {
                additionalResults.diagnosticsFromOverloadResolution.push(diagnostic);
            }
            context.postDiagnostic(diagnostic);
        };

        PullTypeResolver.prototype.computeObjectCreationExpressionSymbol = function (callEx, context, additionalResults) {
            var _this = this;
            var returnType = null;

            // resolve the target
            var targetSymbol = this.resolveAST(callEx.expression, false, context);
            var targetTypeSymbol = targetSymbol.isType() ? targetSymbol : targetSymbol.type;

            var targetAST = this.getCallTargetErrorSpanAST(callEx);

            var constructSignatures = targetTypeSymbol.getConstructSignatures();

            var explicitTypeArgs = null;
            var usedCallSignaturesInstead = false;
            var couldNotAssignToConstraint;
            var constraintDiagnostic = null;
            var typeArgumentCountDiagnostic = null;
            var diagnostics = [];

            if (this.isAnyOrEquivalent(targetTypeSymbol)) {
                // resolve any arguments
                if (callEx.argumentList) {
                    this.resolveAST(callEx.argumentList.arguments, false, context);
                }

                return targetTypeSymbol;
            }

            if (!constructSignatures.length) {
                constructSignatures = targetTypeSymbol.getCallSignatures();
                usedCallSignaturesInstead = true;

                // if noImplicitAny flag is set to be true, report an error
                if (this.compilationSettings.noImplicitAny()) {
                    this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(callEx, TypeScript.DiagnosticCode.new_expression_which_lacks_a_constructor_signature_implicitly_has_an_any_type), additionalResults, context);
                }
            }

            if (constructSignatures.length) {
                // resolve the type arguments, specializing if necessary
                if (callEx.argumentList && callEx.argumentList.typeArgumentList) {
                    // specialize the type arguments
                    explicitTypeArgs = [];

                    if (callEx.argumentList.typeArgumentList && callEx.argumentList.typeArgumentList.typeArguments.length) {
                        for (var i = 0; i < callEx.argumentList.typeArgumentList.typeArguments.length; i++) {
                            explicitTypeArgs[i] = this.resolveTypeReference(callEx.argumentList.typeArgumentList.typeArguments[i], context);
                        }
                    }
                }

                // next, walk the available signatures
                // if any are generic, and we don't have type arguments, try to infer
                // otherwise, try to specialize to the type arguments above
                if (targetTypeSymbol.isGeneric()) {
                    var resolvedSignatures = [];
                    var inferredOrExplicitTypeArgs;
                    var specializedSignature;
                    var typeParameters;
                    var typeConstraint = null;
                    var triedToInferTypeArgs;
                    var targetTypeReplacementMap = targetTypeSymbol.getTypeParameterSubstitutionMap();

                    for (var i = 0; i < constructSignatures.length; i++) {
                        couldNotAssignToConstraint = false;

                        if (constructSignatures[i].isGeneric()) {
                            typeParameters = constructSignatures[i].getTypeParameters();

                            if (explicitTypeArgs) {
                                // October 16, 2013: Section 4.12.2
                                // A generic signature is a candidate in a function call with type arguments
                                // arguments when:
                                // The signature has the same number of type parameters as were supplied in
                                // the type argument list
                                // ...
                                if (explicitTypeArgs.length === typeParameters.length) {
                                    inferredOrExplicitTypeArgs = explicitTypeArgs;
                                } else {
                                    typeArgumentCountDiagnostic = typeArgumentCountDiagnostic || this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Signature_expected_0_type_arguments_got_1_instead, [typeParameters.length, explicitTypeArgs.length]);
                                    continue;
                                }
                            } else if (callEx.argumentList) {
                                var typeArgumentInferenceContext = new TypeScript.InvocationTypeArgumentInferenceContext(this, context, constructSignatures[i], callEx.argumentList);
                                inferredOrExplicitTypeArgs = this.inferArgumentTypesForSignature(typeArgumentInferenceContext, new TypeComparisonInfo(), context);
                                triedToInferTypeArgs = true;
                            } else {
                                // Pretend to infer the constraints. This is useful for the following case:
                                // class C<T extends number, U> { }
                                // var c = new C; // c should have type C<number, {}>, just like calling it with new C()
                                inferredOrExplicitTypeArgs = TypeScript.ArrayUtilities.select(typeParameters, function (typeParameter) {
                                    return typeParameter.getDefaultConstraint(_this.semanticInfoChain);
                                });
                            }

                            // if we could infer Args, or we have type arguments, then attempt to specialize the signature
                            TypeScript.Debug.assert(inferredOrExplicitTypeArgs && inferredOrExplicitTypeArgs.length == typeParameters.length);

                            // When specializing the constraints, seed the replacement map with any substitutions already specified by
                            // the target function's type
                            var mutableTypeReplacementMap = new TypeScript.PullInstantiationHelpers.MutableTypeParameterSubstitutionMap(targetTypeReplacementMap ? targetTypeReplacementMap : []);
                            TypeScript.PullInstantiationHelpers.updateMutableTypeParameterSubstitutionMap(typeParameters, inferredOrExplicitTypeArgs, mutableTypeReplacementMap);
                            var typeReplacementMap = mutableTypeReplacementMap.typeParameterSubstitutionMap;

                            if (explicitTypeArgs) {
                                for (var j = 0; j < typeParameters.length; j++) {
                                    typeConstraint = typeParameters[j].getConstraint();

                                    // test specialization type for assignment compatibility with the constraint
                                    if (typeConstraint) {
                                        if (typeConstraint.isGeneric()) {
                                            typeConstraint = this.instantiateType(typeConstraint, typeReplacementMap);
                                        }

                                        // Section 3.4.2 (November 18, 2013):
                                        // A type argument satisfies a type parameter constraint if the type argument is assignable
                                        // to(section 3.8.4) the constraint type once type arguments are substituted for type parameters.
                                        if (!this.sourceIsAssignableToTarget(inferredOrExplicitTypeArgs[j], typeConstraint, targetAST, context, null, true)) {
                                            var enclosingSymbol = this.getEnclosingSymbolForAST(targetAST);
                                            constraintDiagnostic = this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Type_0_does_not_satisfy_the_constraint_1, [inferredOrExplicitTypeArgs[j].toString(enclosingSymbol, true), typeConstraint.toString(enclosingSymbol, true)]);
                                            couldNotAssignToConstraint = true;
                                        }

                                        if (couldNotAssignToConstraint) {
                                            break;
                                        }
                                    }
                                }
                            }

                            if (couldNotAssignToConstraint) {
                                continue;
                            }

                            specializedSignature = this.instantiateSignature(constructSignatures[i], typeReplacementMap);

                            if (specializedSignature) {
                                resolvedSignatures[resolvedSignatures.length] = specializedSignature;
                            }
                        } else {
                            if (!(callEx.argumentList && callEx.argumentList.typeArgumentList && callEx.argumentList.typeArgumentList.typeArguments.length)) {
                                resolvedSignatures[resolvedSignatures.length] = constructSignatures[i];
                            }
                        }
                    }

                    // PULLTODO: Try to avoid copying here...
                    constructSignatures = resolvedSignatures;
                }

                var signature = this.resolveOverloads(callEx, constructSignatures, callEx.argumentList && callEx.argumentList.typeArgumentList !== null, context, diagnostics);

                // Store any additional resolution results if needed before we return
                additionalResults.targetSymbol = targetSymbol;
                additionalResults.resolvedSignatures = constructSignatures;
                additionalResults.candidateSignature = signature;
                additionalResults.actualParametersContextTypeSymbols = [];

                if (!constructSignatures.length) {
                    if (constraintDiagnostic) {
                        this.postOverloadResolutionDiagnostics(constraintDiagnostic, additionalResults, context);
                    } else if (typeArgumentCountDiagnostic) {
                        this.postOverloadResolutionDiagnostics(typeArgumentCountDiagnostic, additionalResults, context);
                    }

                    return this.getNewErrorTypeSymbol();
                }

                var errorCondition = null;

                // if we haven't been able to choose an overload, default to the first one
                if (!signature) {
                    for (var i = 0; i < diagnostics.length; i++) {
                        this.postOverloadResolutionDiagnostics(diagnostics[i], additionalResults, context);
                    }

                    this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Could_not_select_overload_for_new_expression), additionalResults, context);

                    // Remember the error
                    errorCondition = this.getNewErrorTypeSymbol();

                    if (!constructSignatures.length) {
                        // POST diagnostics
                        return errorCondition;
                    }

                    // First, pick the first signature as the candidate signature
                    signature = constructSignatures[0];
                }

                returnType = signature.returnType;

                // if it's a default constructor, and we have a type argument, we need to specialize
                if (returnType && !signature.isGeneric() && returnType.isGeneric() && !returnType.getIsSpecialized()) {
                    if (explicitTypeArgs && explicitTypeArgs.length) {
                        returnType = this.createInstantiatedType(returnType, explicitTypeArgs);
                    } else {
                        returnType = this.instantiateTypeToAny(returnType, context);
                    }
                }

                if (usedCallSignaturesInstead) {
                    if (returnType !== this.semanticInfoChain.voidTypeSymbol) {
                        this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Only_a_void_function_can_be_called_with_the_new_keyword), additionalResults, context);

                        // POST diagnostics
                        return this.getNewErrorTypeSymbol();
                    } else {
                        returnType = this.semanticInfoChain.anyTypeSymbol;
                    }
                }

                if (!returnType) {
                    returnType = signature.returnType;

                    if (!returnType) {
                        returnType = targetTypeSymbol;
                    }
                }

                // contextually type arguments
                var actualParametersContextTypeSymbols = [];
                if (callEx.argumentList && callEx.argumentList.arguments) {
                    var len = callEx.argumentList.arguments.length;
                    var params = signature.parameters;
                    var contextualType = null;
                    var signatureDecl = signature.getDeclarations()[0];

                    for (var i = 0; i < len; i++) {
                        if (params.length) {
                            if (i < params.length - 1 || (i < params.length && !signature.hasVarArgs)) {
                                this.resolveDeclaredSymbol(params[i], context);
                                contextualType = params[i].type;
                            } else if (signature.hasVarArgs) {
                                contextualType = params[params.length - 1].type;
                                if (contextualType.isArrayNamedTypeReference()) {
                                    contextualType = contextualType.getElementType();
                                }
                            }
                        }

                        if (contextualType) {
                            context.pushNewContextualType(contextualType);
                            actualParametersContextTypeSymbols[i] = contextualType;
                        }

                        this.resolveAST(callEx.argumentList.arguments[i], contextualType !== null, context);

                        if (contextualType) {
                            context.popAnyContextualType();
                            contextualType = null;
                        }
                    }
                }

                // Store any additional resolution results if needed before we return
                additionalResults.targetSymbol = targetSymbol;
                additionalResults.resolvedSignatures = constructSignatures;
                additionalResults.candidateSignature = signature;
                additionalResults.actualParametersContextTypeSymbols = actualParametersContextTypeSymbols;

                if (errorCondition) {
                    // POST diagnostics
                    return errorCondition;
                }

                if (!returnType) {
                    returnType = this.semanticInfoChain.anyTypeSymbol;
                }

                return returnType;
            } else if (callEx.argumentList) {
                this.resolveAST(callEx.argumentList.arguments, false, context);
            }

            this.postOverloadResolutionDiagnostics(this.semanticInfoChain.diagnosticFromAST(targetAST, TypeScript.DiagnosticCode.Cannot_use_new_with_an_expression_whose_type_lacks_a_signature), additionalResults, context);

            // POST diagnostics
            return this.getNewErrorTypeSymbol();
        };

        // Here, we are instantiating signatureAToInstantiate in the context of contextSignatureB.
        // The A and B reference section 3.8.5 of the spec:
        // A is instantiated in the context of B. If A is a non-generic signature, the result of
        // this process is simply A. Otherwise, type arguments for A are inferred from B producing
        // an instantiation of A that can be related to B
        // The shouldFixContextualSignatureParameterTypes flag should be set to true when inferences
        // are being made for type parameters of the contextual signature (like for inferential
        // typing in section 4.12.2). It should be set to false for relation checking (sections
        // 3.8.3 & 3.8.4).
        PullTypeResolver.prototype.instantiateSignatureInContext = function (signatureAToInstantiate, contextualSignatureB, context, shouldFixContextualSignatureParameterTypes) {
            var typeReplacementMap = [];
            var inferredTypeArgs;
            var specializedSignature;
            var typeParameters = signatureAToInstantiate.getTypeParameters();
            var typeConstraint = null;

            var typeArgumentInferenceContext = new TypeScript.ContextualSignatureInstantiationTypeArgumentInferenceContext(this, context, signatureAToInstantiate, contextualSignatureB, shouldFixContextualSignatureParameterTypes);
            inferredTypeArgs = this.inferArgumentTypesForSignature(typeArgumentInferenceContext, new TypeComparisonInfo(), context);

            var functionTypeA = signatureAToInstantiate.functionType;
            var functionTypeB = contextualSignatureB.functionType;
            var enclosingTypeParameterMap;

            if (functionTypeA) {
                enclosingTypeParameterMap = functionTypeA.getTypeParameterSubstitutionMap();

                for (var id in enclosingTypeParameterMap) {
                    typeReplacementMap[id] = enclosingTypeParameterMap[id];
                }
            }

            if (functionTypeB) {
                enclosingTypeParameterMap = functionTypeB.getTypeParameterSubstitutionMap();

                for (var id in enclosingTypeParameterMap) {
                    typeReplacementMap[id] = enclosingTypeParameterMap[id];
                }
            }

            TypeScript.PullInstantiationHelpers.updateTypeParameterSubstitutionMap(typeParameters, inferredTypeArgs, typeReplacementMap);

            return this.instantiateSignature(signatureAToInstantiate, typeReplacementMap);
        };

        PullTypeResolver.prototype.resolveCastExpression = function (assertionExpression, context) {
            var typeAssertionType = this.resolveTypeReference(assertionExpression.type, context).type;

            if (this.canTypeCheckAST(assertionExpression, context)) {
                this.typeCheckCastExpression(assertionExpression, context, typeAssertionType);
            }

            // October 11, 2013:
            // In a type assertion expression of the form < T > e, e is contextually typed (section
            // 4.19) by T and the resulting type of e is required to be assignable to or from T, or
            // otherwise a compile - time error occurs.
            //
            // The type of the result is T.
            return typeAssertionType;
        };

        PullTypeResolver.prototype.typeCheckCastExpression = function (assertionExpression, context, typeAssertionType) {
            this.setTypeChecked(assertionExpression, context);

            // October 11, 2013:
            // In a type assertion expression of the form < T > e, e is contextually typed (section
            // 4.19) by T and the resulting type of e is required to be assignable to or from T, or
            // otherwise a compile - time error occurs.
            //
            // The type of the result is T.
            context.pushNewContextualType(typeAssertionType);
            var exprType = this.resolveAST(assertionExpression.expression, true, context).type;
            context.popAnyContextualType();

            // TODO: why are we resolving these symbols here?
            this.resolveDeclaredSymbol(typeAssertionType, context);
            this.resolveDeclaredSymbol(exprType, context);

            var comparisonInfo = new TypeComparisonInfo();

            // Be careful to check exprType assignable to typeAssertionType first. Only widen if
            // this direction is not assignable to avoid extra implicit any errors that widening
            // would cause.
            var isAssignable = this.sourceIsAssignableToTarget(exprType, typeAssertionType, assertionExpression, context, comparisonInfo);

            if (!isAssignable) {
                var widenedExprType = exprType.widenedType(this, assertionExpression.expression, context);
                isAssignable = this.sourceIsAssignableToTarget(typeAssertionType, widenedExprType, assertionExpression, context, comparisonInfo);
            }

            if (!isAssignable) {
                var enclosingSymbol = this.getEnclosingSymbolForAST(assertionExpression);
                if (comparisonInfo.message) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(assertionExpression, TypeScript.DiagnosticCode.Neither_type_0_nor_type_1_is_assignable_to_the_other_NL_2, [exprType.toString(enclosingSymbol), typeAssertionType.toString(enclosingSymbol), comparisonInfo.message]));
                } else {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(assertionExpression, TypeScript.DiagnosticCode.Neither_type_0_nor_type_1_is_assignable_to_the_other, [exprType.toString(enclosingSymbol), typeAssertionType.toString(enclosingSymbol)]));
                }
            }
        };

        PullTypeResolver.prototype.resolveAssignmentExpression = function (binaryExpression, context) {
            // September 17, 2013: An assignment of the form
            //
            //      VarExpr = ValueExpr
            //
            // requires VarExpr to be classified as a reference(section 4.1).ValueExpr is
            // contextually typed(section 4.19) by the type of VarExpr, and the type of ValueExpr
            // must be assignable to(section 3.8.4) the type of VarExpr, or otherwise a compile -
            // time error occurs.The result is a value with the type of ValueExpr.
            var leftExpr = this.resolveAST(binaryExpression.left, false, context);
            var leftType = leftExpr.type;

            context.pushNewContextualType(leftType);
            var rightType = this.resolveAST(binaryExpression.right, true, context).type;
            context.popAnyContextualType();

            rightType = this.getInstanceTypeForAssignment(binaryExpression.left, rightType, context);

            // Check if LHS is a valid target
            if (this.canTypeCheckAST(binaryExpression, context)) {
                this.setTypeChecked(binaryExpression, context);

                if (!this.isReference(binaryExpression.left, leftExpr)) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(binaryExpression.left, TypeScript.DiagnosticCode.Invalid_left_hand_side_of_assignment_expression));
                } else {
                    this.checkAssignability(binaryExpression.left, rightType, leftExpr.type, context);
                }
            }

            return rightType;
        };

        PullTypeResolver.prototype.getInstanceTypeForAssignment = function (lhs, type, context) {
            var typeToReturn = type;
            if (typeToReturn && typeToReturn.isAlias()) {
                typeToReturn = typeToReturn.getExportAssignedTypeSymbol();
            }

            if (typeToReturn && typeToReturn.isContainer() && !typeToReturn.isEnum()) {
                var instanceTypeSymbol = typeToReturn.getInstanceType();

                if (!instanceTypeSymbol) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(lhs, TypeScript.DiagnosticCode.Tried_to_set_variable_type_to_uninitialized_module_type_0, [type.toString()]));
                    typeToReturn = null;
                } else {
                    typeToReturn = instanceTypeSymbol;
                }
            }

            return typeToReturn;
        };

        PullTypeResolver.prototype.widenType = function (type, ast, context) {
            if (type === this.semanticInfoChain.undefinedTypeSymbol || type === this.semanticInfoChain.nullTypeSymbol || type.isError()) {
                return this.semanticInfoChain.anyTypeSymbol;
            }

            if (type.isArrayNamedTypeReference()) {
                return this.widenArrayType(type, ast, context);
            } else if (type.kind === TypeScript.PullElementKind.ObjectLiteral) {
                return this.widenObjectLiteralType(type, ast, context);
            }

            return type;
        };

        PullTypeResolver.prototype.widenArrayType = function (type, ast, context) {
            // Call into the symbol to get the widened type so we pick up the cached version if there is one
            var elementType = type.getElementType().widenedType(this, ast, context);

            if (this.compilationSettings.noImplicitAny() && ast) {
                // If we widened from non-'any' type to 'any', then report error.
                if (elementType === this.semanticInfoChain.anyTypeSymbol && type.getElementType() !== this.semanticInfoChain.anyTypeSymbol) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.Array_Literal_implicitly_has_an_any_type_from_widening));
                }
            }

            return this.getArrayType(elementType);
        };

        PullTypeResolver.prototype.widenObjectLiteralType = function (type, ast, context) {
            if (!this.needsToWidenObjectLiteralType(type, ast, context)) {
                return type;
            }

            // The name here should be "", and the kind should be ObjectLiteral
            TypeScript.Debug.assert(type.name === "");
            var newObjectTypeSymbol = new TypeScript.PullTypeSymbol(type.name, type.kind, this.semanticInfoChain);
            var declsOfObjectType = type.getDeclarations();
            TypeScript.Debug.assert(declsOfObjectType.length === 1);
            newObjectTypeSymbol.addDeclaration(declsOfObjectType[0]);
            var members = type.getMembers();

            for (var i = 0; i < members.length; i++) {
                var memberType = members[i].type;

                // Call into the symbol to get the widened type so we pick up the cached version if there is one
                var widenedMemberType = members[i].type.widenedType(this, ast, context);
                var newMember = new TypeScript.PullSymbol(members[i].name, members[i].kind, this.semanticInfoChain);

                // Since this is an object literal, we only care about one decl for this member.
                // It has more than one decl in an error case where there was a duplicate member
                // declaration. For example:
                // var obj = { a: 3, a: 4 };
                // This will have two decls for "a", but an error is already given in computeObjectLiteralExpression.
                var declsOfMember = members[i].getDeclarations();

                //Debug.assert(declsOfMember.length === 1);
                //Debug.assert(members[i].isResolved);
                newMember.addDeclaration(declsOfMember[0]);
                newMember.type = widenedMemberType;
                newObjectTypeSymbol.addMember(newMember);
                newMember.setResolved();

                if (this.compilationSettings.noImplicitAny() && ast && widenedMemberType === this.semanticInfoChain.anyTypeSymbol && memberType !== this.semanticInfoChain.anyTypeSymbol) {
                    // Property was widened from non-any to any
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.Object_literal_s_property_0_implicitly_has_an_any_type_from_widening, [members[i].name]));
                }
            }

            var indexers = type.getIndexSignatures();
            for (var i = 0; i < indexers.length; i++) {
                var newIndexer = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.IndexSignature, this.semanticInfoChain);
                var parameter = indexers[i].parameters[0];
                var newParameter = new TypeScript.PullSymbol(parameter.name, parameter.kind, this.semanticInfoChain);
                newParameter.type = parameter.type;
                newIndexer.addParameter(newParameter);
                newIndexer.returnType = indexers[i].returnType;
                newObjectTypeSymbol.addIndexSignature(newIndexer);
            }

            return newObjectTypeSymbol;
        };

        PullTypeResolver.prototype.needsToWidenObjectLiteralType = function (type, ast, context) {
            var members = type.getMembers();
            for (var i = 0; i < members.length; i++) {
                var memberType = members[i].type;
                if (memberType !== memberType.widenedType(this, ast, context)) {
                    return true;
                }
            }

            return false;
        };

        // If the expression being typed is not contextually typed, pass in null for contextualType
        PullTypeResolver.prototype.findBestCommonType = function (contextualType, nonContextualCandidates, context) {
            var len = nonContextualCandidates.getLength();

            // October 16, 2013: Section 4.12.2: Where a contextual type would be included
            // in a candidate set for a best common type(such as when inferentially typing
            // an object or array literal), an inferential type is not.
            if (contextualType !== null && !context.isInferentiallyTyping() && this.typeIsBestCommonTypeCandidate(contextualType, nonContextualCandidates, context)) {
                return contextualType;
            }

            for (var i = 0; i < len; i++) {
                var candidateType = nonContextualCandidates.getTypeAtIndex(i);
                if (this.typeIsBestCommonTypeCandidate(candidateType, nonContextualCandidates, context)) {
                    return candidateType;
                }
            }

            // October 16, 2013: It is possible that no such [common] type exists, in which case
            // the best common type is an empty object type.
            return this.semanticInfoChain.emptyTypeSymbol;
        };

        PullTypeResolver.prototype.typeIsBestCommonTypeCandidate = function (candidateType, collection, context) {
            for (var i = 0; i < collection.getLength(); i++) {
                var otherType = collection.getTypeAtIndex(i);
                if (candidateType === otherType) {
                    continue;
                }

                if (!this.sourceIsSubtypeOfTarget(otherType, candidateType, null, context)) {
                    return false;
                }
            }

            return true;
        };

        // Type Identity
        PullTypeResolver.prototype.typesAreIdenticalInEnclosingTypes = function (t1, t2, context) {
            t1 = this.getSymbolForRelationshipCheck(t1);
            t2 = this.getSymbolForRelationshipCheck(t2);

            if (t1 === t2) {
                return true;
            }

            if (t1 && t2) {
                // Section 3.8.7 - Recursive Types
                //  When comparing two types S and T for identity(section 3.8.2), subtype(section 3.8.3), and assignability(section 3.8.4) relationships,
                //  if either type originates in an infinitely expanding type reference, S and T are not compared by the rules in the preceding sections.Instead, for the relationship to be considered true,
                //  -	S and T must both be type references to the same named type, and
                //  -	the relationship in question must be true for each corresponding pair of type arguments in the type argument lists of S and T.
                if (context.oneOfClassificationsIsInfinitelyExpanding()) {
                    return this.infinitelyExpandingTypesAreIdentical(t1, t2, context);
                }
            }

            return this.typesAreIdentical(t1, t2, context);
        };

        PullTypeResolver.prototype.typesAreIdenticalWithNewEnclosingTypes = function (t1, t2, context) {
            var enclosingTypeWalkerStates = context.resetEnclosingTypeWalkerStates();
            var areTypesIdentical = this.typesAreIdentical(t1, t2, context);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return areTypesIdentical;
        };

        PullTypeResolver.prototype.typesAreIdentical = function (t1, t2, context) {
            t1 = this.getSymbolForRelationshipCheck(t1);
            t2 = this.getSymbolForRelationshipCheck(t2);

            // This clause will cover both primitive types (since the type objects are shared),
            // as well as shared brands
            if (t1 === t2) {
                return true;
            }

            if (!t1 || !t2) {
                return false;
            }

            // identity check for enums is 't1 === t2'
            // if it returns false and one of elements is enum - they are not identical
            if (TypeScript.hasFlag(t1.kind, TypeScript.PullElementKind.Enum) || TypeScript.hasFlag(t2.kind, TypeScript.PullElementKind.Enum)) {
                return false;
            }

            if (t1.isPrimitive() && t1.isStringConstant() && t2.isPrimitive() && t2.isStringConstant()) {
                // Both are string constants
                return TypeScript.stripStartAndEndQuotes(t1.name) === TypeScript.stripStartAndEndQuotes(t2.name);
            }

            if (t1.isPrimitive() || t2.isPrimitive()) {
                return false;
            }

            if (t1.isError() && t2.isError()) {
                return true;
            }

            var isIdentical = this.identicalCache.valueAt(t1.pullSymbolID, t2.pullSymbolID);
            if (isIdentical != undefined) {
                return isIdentical;
            }

            if (t1.isTypeParameter() !== t2.isTypeParameter()) {
                return false;
            } else if (t1.isTypeParameter()) {
                // We compare parent declarations instead of container symbols because type parameter symbols are shared
                // accross overload groups
                var t1ParentDeclaration = t1.getDeclarations()[0].getParentDecl();
                var t2ParentDeclaration = t2.getDeclarations()[0].getParentDecl();

                if (t1ParentDeclaration === t2ParentDeclaration) {
                    return this.symbolsShareDeclaration(t1, t2);
                } else {
                    return false;
                }
            }

            if (t1.isPrimitive() !== t2.isPrimitive()) {
                return false;
            }

            this.identicalCache.setValueAt(t1.pullSymbolID, t2.pullSymbolID, true);
            var statesWhenStartedWalkingTypes = context.startWalkingTypes(t1, t2);
            isIdentical = this.typesAreIdenticalWorker(t1, t2, context);
            context.endWalkingTypes(statesWhenStartedWalkingTypes);
            this.identicalCache.setValueAt(t1.pullSymbolID, t2.pullSymbolID, isIdentical);

            return isIdentical;
        };

        PullTypeResolver.prototype.typesAreIdenticalWorker = function (t1, t2, context) {
            if (t1.getIsSpecialized() && t2.getIsSpecialized()) {
                // If types are specialized from same root symbol, comparing type arguments should be enough
                if (TypeScript.PullHelpers.getRootType(t1) === TypeScript.PullHelpers.getRootType(t2) && TypeScript.PullHelpers.getRootType(t1).isNamedTypeSymbol()) {
                    var t1TypeArguments = t1.getTypeArguments();
                    var t2TypeArguments = t2.getTypeArguments();

                    if (t1TypeArguments && t2TypeArguments) {
                        for (var i = 0; i < t1TypeArguments.length; i++) {
                            // The type arguments are not enclosed in current enclosing contexts
                            if (!this.typesAreIdenticalWithNewEnclosingTypes(t1TypeArguments[i], t2TypeArguments[i], context)) {
                                return false;
                            }
                        }
                    }

                    return true;
                }
            }

            // properties are identical in name, optionality, and type
            if (t1.hasMembers() && t2.hasMembers()) {
                var t1Members = t1.getAllMembers(TypeScript.PullElementKind.SomeValue, 0 /* all */);
                var t2Members = t2.getAllMembers(TypeScript.PullElementKind.SomeValue, 0 /* all */);

                if (t1Members.length !== t2Members.length) {
                    return false;
                }

                var t1MemberSymbol = null;
                var t2MemberSymbol = null;

                var t1MemberType = null;
                var t2MemberType = null;

                for (var iMember = 0; iMember < t1Members.length; iMember++) {
                    // Spec section 3.8.2:
                    // Two members are considered identical when
                    // they are public properties with identical names, optionality, and types,
                    // they are private properties originating in the same declaration and having identical types
                    t1MemberSymbol = t1Members[iMember];
                    t2MemberSymbol = this.getNamedPropertySymbol(t1MemberSymbol.name, TypeScript.PullElementKind.SomeValue, t2);

                    if (!this.propertiesAreIdentical(t1MemberSymbol, t2MemberSymbol, context)) {
                        return false;
                    }
                }
            } else if (t1.hasMembers() || t2.hasMembers()) {
                return false;
            }

            var t1CallSigs = t1.getCallSignatures();
            var t2CallSigs = t2.getCallSignatures();

            var t1ConstructSigs = t1.getConstructSignatures();
            var t2ConstructSigs = t2.getConstructSignatures();

            var t1IndexSigs = t1.getIndexSignatures();
            var t2IndexSigs = t2.getIndexSignatures();

            if (!this.signatureGroupsAreIdentical(t1CallSigs, t2CallSigs, context)) {
                return false;
            }

            if (!this.signatureGroupsAreIdentical(t1ConstructSigs, t2ConstructSigs, context)) {
                return false;
            }

            if (!this.signatureGroupsAreIdentical(t1IndexSigs, t2IndexSigs, context)) {
                return false;
            }

            return true;
        };

        PullTypeResolver.prototype.propertiesAreIdentical = function (propertySymbol1, propertySymbol2, context) {
            // Spec section 3.8.2:
            // Two members are considered identical when
            // they are public properties with identical names, optionality, and types,
            // they are private properties originating in the same declaration and having identical types
            if (!propertySymbol2 || (propertySymbol1.isOptional !== propertySymbol2.isOptional)) {
                return false;
            }

            var t1MemberSymbolIsPrivate = propertySymbol1.anyDeclHasFlag(TypeScript.PullElementFlags.Private);
            var t2MemberSymbolIsPrivate = propertySymbol2.anyDeclHasFlag(TypeScript.PullElementFlags.Private);

            // if visibility doesn't match, the types don't match
            if (t1MemberSymbolIsPrivate !== t2MemberSymbolIsPrivate) {
                return false;
            } else if (t2MemberSymbolIsPrivate && t1MemberSymbolIsPrivate) {
                var t1MemberSymbolDecl = propertySymbol1.getDeclarations()[0];
                var sourceDecl = propertySymbol2.getDeclarations()[0];
                if (t1MemberSymbolDecl !== sourceDecl) {
                    return false;
                }
            }

            var t1MemberType = propertySymbol1.type;
            var t2MemberType = propertySymbol2.type;

            context.walkMemberTypes(propertySymbol1.name);
            var areMemberTypesIdentical = this.typesAreIdenticalInEnclosingTypes(t1MemberType, t2MemberType, context);
            context.postWalkMemberTypes();
            return areMemberTypesIdentical;
        };

        PullTypeResolver.prototype.propertiesAreIdenticalWithNewEnclosingTypes = function (type1, type2, property1, property2, context) {
            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(type1, type2);
            var arePropertiesIdentical = this.propertiesAreIdentical(property1, property2, context);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return arePropertiesIdentical;
        };

        PullTypeResolver.prototype.signatureGroupsAreIdentical = function (sg1, sg2, context) {
            // covers the null case
            if (sg1 === sg2) {
                return true;
            }

            // covers the mixed-null case
            if (!sg1 || !sg2) {
                return false;
            }

            if (sg1.length !== sg2.length) {
                return false;
            }

            for (var i = 0; i < sg1.length; i++) {
                context.walkSignatures(sg1[i].kind, i);
                var areSignaturesIdentical = this.signaturesAreIdentical(sg1[i], sg2[i], context, true);
                context.postWalkSignatures();
                if (!areSignaturesIdentical) {
                    return false;
                }
            }

            return true;
        };

        PullTypeResolver.prototype.constraintsAreIdentical = function (tp1, tp2, context) {
            TypeScript.Debug.assert(tp1 && tp2);
            if (tp1.length !== tp2.length) {
                return false;
            }

            for (var i = 0; i < tp1.length; i++) {
                // Verify the pairwise identity of the constraints
                context.walkTypeParameterConstraints(i);
                var areConstraintsIdentical = this.typesAreIdentical(tp1[i].getConstraint(), tp2[i].getConstraint(), context);
                context.postWalkTypeParameterConstraints();
                if (!areConstraintsIdentical) {
                    return false;
                }
            }

            return true;
        };

        PullTypeResolver.prototype.setTypeParameterIdentity = function (tp1, tp2, val) {
            if (tp1 && tp2 && tp1.length === tp2.length) {
                for (var i = 0; i < tp1.length; i++) {
                    this.identicalCache.setValueAt(tp1[i].pullSymbolID, tp2[i].pullSymbolID, val);
                }
            }
        };

        PullTypeResolver.prototype.signaturesAreIdenticalWithNewEnclosingTypes = function (s1, s2, context, includingReturnType) {
            if (typeof includingReturnType === "undefined") { includingReturnType = true; }
            // If signatures are identitical is called directally we need to get the enclosingType and
            // current symbol correctly
            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(s1, s2);
            var areSignaturesIdentical = this.signaturesAreIdentical(s1, s2, context, includingReturnType);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return areSignaturesIdentical;
        };

        PullTypeResolver.prototype.signaturesAreIdentical = function (s1, s2, context, includingReturnType) {
            if (typeof includingReturnType === "undefined") { includingReturnType = true; }
            if (s1 === s2) {
                return true;
            }

            var signaturesIdentical = this.identicalCache.valueAt(s1.pullSymbolID, s2.pullSymbolID);
            if (signaturesIdentical || (signaturesIdentical != undefined && includingReturnType)) {
                return signaturesIdentical;
            }

            var oldValue = signaturesIdentical;
            this.identicalCache.setValueAt(s1.pullSymbolID, s2.pullSymbolID, true);

            signaturesIdentical = this.signaturesAreIdenticalWorker(s1, s2, context, includingReturnType);

            if (includingReturnType) {
                // Can cache the result
                this.identicalCache.setValueAt(s1.pullSymbolID, s2.pullSymbolID, signaturesIdentical);
            } else {
                // Not checking return type, revert the result
                this.identicalCache.setValueAt(s1.pullSymbolID, s2.pullSymbolID, oldValue);
            }

            return signaturesIdentical;
        };

        PullTypeResolver.prototype.signaturesAreIdenticalWorker = function (s1, s2, context, includingReturnType) {
            if (typeof includingReturnType === "undefined") { includingReturnType = true; }
            if (s1.hasVarArgs !== s2.hasVarArgs) {
                return false;
            }

            if (s1.nonOptionalParamCount !== s2.nonOptionalParamCount) {
                return false;
            }

            if (s1.parameters.length !== s2.parameters.length) {
                return false;
            }

            // The spec says to assume type parameters are pairwise identical in order to compare
            // the signatures. We skip that here because we are about to instantiate the signatures
            // to any to avoid a generative recursion when comparing generic signatures.
            return this.signatureConstraints_Parameters_AndReturnTypesAreIdenticalAfterInstantiationToAny(s1, s2, context, includingReturnType);
        };

        PullTypeResolver.prototype.signatureConstraints_Parameters_AndReturnTypesAreIdenticalAfterInstantiationToAny = function (s1, s2, context, includingReturnType) {
            if (!this.constraintsAreIdentical(s1.getTypeParameters(), s2.getTypeParameters(), context)) {
                return false;
            }

            // This is not in the spec yet, but we need to instantiate signatures to any before
            // comparing them to avoid a generative recursion. Considering them pairwise
            // identical is not enough to achieve this. Consider the following example:
            //
            // interface IPromise<T> {
            //     then<U>(callback: (x: T) => IPromise<U>): IPromise<U>;
            // }
            // interface Promise<T> {
            //     then<U>(callback: (x: T) => Promise<U>): Promise<U>;
            // }
            // var x: IPromise<string>;
            // var x: Promise<string>;
            //
            // Comparing IPromise<U> and Promise<U> would lead to an infinite expansion, since
            // each instantiation introduces a new U. Therefore, the U must be erased to any.
            s1 = this.instantiateSignatureToAny(s1);
            s2 = this.instantiateSignatureToAny(s2);

            if (includingReturnType) {
                TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(s1);
                TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(s2);
                context.walkReturnTypes();
                var areReturnTypesIdentical = this.typesAreIdenticalInEnclosingTypes(s1.returnType, s2.returnType, context);
                context.postWalkReturnTypes();
                if (!areReturnTypesIdentical) {
                    return false;
                }
            }

            var s1Params = s1.parameters;
            var s2Params = s2.parameters;

            for (var iParam = 0; iParam < s1Params.length; iParam++) {
                TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(s1Params[iParam]);
                TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(s2Params[iParam]);
                context.walkParameterTypes(iParam);
                var areParameterTypesIdentical = this.typesAreIdenticalInEnclosingTypes(s1Params[iParam].type, s2Params[iParam].type, context);
                context.postWalkParameterTypes();

                if (!areParameterTypesIdentical) {
                    return false;
                }
            }

            return true;
        };

        PullTypeResolver.prototype.signatureReturnTypesAreIdentical = function (s1, s2, context) {
            // Set the cache pairwise identity of type parameters, so if parameters refer to them, they would be treated as identical
            var s1TypeParameters = s1.getTypeParameters();
            var s2TypeParameters = s2.getTypeParameters();
            this.setTypeParameterIdentity(s1TypeParameters, s2TypeParameters, true);

            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(s1, s2);
            context.walkReturnTypes();
            var returnTypeIsIdentical = this.typesAreIdenticalInEnclosingTypes(s1.returnType, s2.returnType, context);

            // context.postWalkReturnTypes(); - this is not needed because we are restoring the old walkers
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);

            // Reset the cahce with pairwise identity of type parameters
            this.setTypeParameterIdentity(s1TypeParameters, s2TypeParameters, undefined);

            return returnTypeIsIdentical;
        };

        // Assignment Compatibility and Subtyping
        PullTypeResolver.prototype.symbolsShareDeclaration = function (symbol1, symbol2) {
            var decls1 = symbol1.getDeclarations();
            var decls2 = symbol2.getDeclarations();

            if (decls1.length && decls2.length) {
                return decls1[0] === decls2[0];
            }

            return false;
        };

        PullTypeResolver.prototype.sourceIsSubtypeOfTarget = function (source, target, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            return this.sourceIsRelatableToTarget(source, target, false, this.subtypeCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
        };

        PullTypeResolver.prototype.sourceMembersAreAssignableToTargetMembers = function (source, target, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(source, target);
            var areSourceMembersAreAssignableToTargetMembers = this.sourceMembersAreRelatableToTargetMembers(source, target, true, this.assignableCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return areSourceMembersAreAssignableToTargetMembers;
        };

        PullTypeResolver.prototype.sourcePropertyIsAssignableToTargetProperty = function (source, target, sourceProp, targetProp, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(source, target);
            var isSourcePropertyIsAssignableToTargetProperty = this.sourcePropertyIsRelatableToTargetProperty(source, target, sourceProp, targetProp, true, this.assignableCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return isSourcePropertyIsAssignableToTargetProperty;
        };

        PullTypeResolver.prototype.sourceCallSignaturesAreAssignableToTargetCallSignatures = function (source, target, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(source, target);
            var areSourceCallSignaturesAssignableToTargetCallSignatures = this.sourceCallSignaturesAreRelatableToTargetCallSignatures(source, target, true, this.assignableCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return areSourceCallSignaturesAssignableToTargetCallSignatures;
        };

        PullTypeResolver.prototype.sourceConstructSignaturesAreAssignableToTargetConstructSignatures = function (source, target, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(source, target);
            var areSourceConstructSignaturesAssignableToTargetConstructSignatures = this.sourceConstructSignaturesAreRelatableToTargetConstructSignatures(source, target, true, this.assignableCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return areSourceConstructSignaturesAssignableToTargetConstructSignatures;
        };

        PullTypeResolver.prototype.sourceIndexSignaturesAreAssignableToTargetIndexSignatures = function (source, target, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(source, target);
            var areSourceIndexSignaturesAssignableToTargetIndexSignatures = this.sourceIndexSignaturesAreRelatableToTargetIndexSignatures(source, target, true, this.assignableCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return areSourceIndexSignaturesAssignableToTargetIndexSignatures;
        };

        PullTypeResolver.prototype.typeIsAssignableToFunction = function (source, ast, context) {
            // Note that object types containing one or more call or construct signatures are
            // automatically assignable to Function, provided they do not hide properties of
            // Function, giving them incompatible types. This is a result of the apparent type
            // rules in section 3.1.
            if (source.isFunctionType()) {
                return true;
            }

            return this.cachedFunctionInterfaceType() && this.sourceIsAssignableToTarget(source, this.cachedFunctionInterfaceType(), ast, context);
        };

        PullTypeResolver.prototype.signatureIsAssignableToTarget = function (s1, s2, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var enclosingTypeWalkerStates = context.setEnclosingTypeForSymbols(s1, s2);
            var isSignatureIsAssignableToTarget = this.signatureIsRelatableToTarget(s1, s2, true, this.assignableCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return isSignatureIsAssignableToTarget;
        };

        PullTypeResolver.prototype.sourceIsAssignableToTarget = function (source, target, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            return this.sourceIsRelatableToTarget(source, target, true, this.assignableCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
        };

        PullTypeResolver.prototype.sourceIsAssignableToTargetWithNewEnclosingTypes = function (source, target, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            return this.sourceIsRelatableToTargetWithNewEnclosingTypes(source, target, true, this.assignableCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
        };

        PullTypeResolver.prototype.getSymbolForRelationshipCheck = function (symbol) {
            if (symbol && symbol.isTypeReference()) {
                return symbol.getReferencedTypeSymbol();
            }

            return symbol;
        };

        PullTypeResolver.prototype.sourceIsRelatableToTargetInEnclosingTypes = function (source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            source = this.getSymbolForRelationshipCheck(source);
            target = this.getSymbolForRelationshipCheck(target);

            if (source === target) {
                return true;
            }

            if (source && target) {
                // Section 3.8.7 - Recursive Types
                //  When comparing two types S and T for identity(section 3.8.2), subtype(section 3.8.3), and assignability(section 3.8.4) relationships,
                //  if either type originates in an infinitely expanding type reference, S and T are not compared by the rules in the preceding sections.Instead, for the relationship to be considered true,
                //  -	S and T must both be type references to the same named type, and
                //  -	the relationship in question must be true for each corresponding pair of type arguments in the type argument lists of S and T.
                if (context.oneOfClassificationsIsInfinitelyExpanding()) {
                    return this.infinitelyExpandingSourceTypeIsRelatableToTargetType(source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
                }
            }

            return this.sourceIsRelatableToTarget(source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
        };

        PullTypeResolver.prototype.sourceIsRelatableToTargetWithNewEnclosingTypes = function (source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var enclosingTypeWalkerStates = context.resetEnclosingTypeWalkerStates();
            var isSourceRelatable = this.sourceIsRelatableToTarget(source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
            return isSourceRelatable;
        };

        PullTypeResolver.prototype.sourceIsRelatableToTargetInCache = function (source, target, comparisonCache, comparisonInfo) {
            var isRelatable = comparisonCache.valueAt(source.pullSymbolID, target.pullSymbolID);

            // If the source is relatable, return immediately
            if (isRelatable) {
                return { isRelatable: isRelatable };
            }

            // if comparison info is not asked, we can return cached false value,
            // otherwise we need to redo the check to fill in the comparison info
            if (isRelatable != undefined && !comparisonInfo) {
                return { isRelatable: isRelatable };
            }

            return null;
        };

        PullTypeResolver.prototype.sourceIsRelatableToTarget = function (source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            source = this.getSymbolForRelationshipCheck(source);
            target = this.getSymbolForRelationshipCheck(target);

            if (source === target) {
                return true;
            }

            // An error has already been reported in this case
            if (!(source && target)) {
                return true;
            }

            // Note, for subtype the apparent type rules are different for type parameters. This
            // is not yet reflected in the spec.
            var sourceApparentType = this.getApparentType(source);

            // In the case of a 'false', we want to short-circuit a recursive typecheck
            var isRelatableInfo = this.sourceIsRelatableToTargetInCache(source, target, comparisonCache, comparisonInfo);
            if (isRelatableInfo) {
                return isRelatableInfo.isRelatable;
            }

            if (source === this.semanticInfoChain.stringTypeSymbol && target.isPrimitive() && target.isStringConstant()) {
                return comparisonInfo && comparisonInfo.stringConstantVal && (comparisonInfo.stringConstantVal.kind() === 14 /* StringLiteral */) && (TypeScript.stripStartAndEndQuotes(comparisonInfo.stringConstantVal.text()) === TypeScript.stripStartAndEndQuotes(target.name));
            }

            // this is one difference between subtyping and assignment compatibility
            if (assignableTo) {
                if (this.isAnyOrEquivalent(source) || this.isAnyOrEquivalent(target)) {
                    return true;
                }
            } else {
                // This is one difference between assignment compatibility and subtyping
                if (this.isAnyOrEquivalent(target)) {
                    return true;
                }
            }

            if (target === this.semanticInfoChain.stringTypeSymbol && source.isPrimitive() && source.isStringConstant()) {
                return true;
            }

            if (source.isPrimitive() && source.isStringConstant() && target.isPrimitive() && target.isStringConstant()) {
                // Both are string constants
                return TypeScript.stripStartAndEndQuotes(source.name) === TypeScript.stripStartAndEndQuotes(target.name);
            }

            if (source === this.semanticInfoChain.undefinedTypeSymbol) {
                return true;
            }

            if ((source === this.semanticInfoChain.nullTypeSymbol) && (target !== this.semanticInfoChain.undefinedTypeSymbol && target != this.semanticInfoChain.voidTypeSymbol)) {
                return true;
            }

            if (target === this.semanticInfoChain.voidTypeSymbol) {
                if (source === this.semanticInfoChain.undefinedTypeSymbol || source == this.semanticInfoChain.nullTypeSymbol) {
                    return true;
                }

                return false;
            } else if (source === this.semanticInfoChain.voidTypeSymbol) {
                if (target === this.semanticInfoChain.anyTypeSymbol) {
                    return true;
                }

                return false;
            }

            if (target === this.semanticInfoChain.numberTypeSymbol && TypeScript.PullHelpers.symbolIsEnum(source)) {
                return true;
            }

            if (source === this.semanticInfoChain.numberTypeSymbol && TypeScript.PullHelpers.symbolIsEnum(target)) {
                return assignableTo;
            }

            if (TypeScript.PullHelpers.symbolIsEnum(target) && TypeScript.PullHelpers.symbolIsEnum(source)) {
                return this.symbolsShareDeclaration(target, source);
            }

            if ((source.kind & TypeScript.PullElementKind.Enum) || (target.kind & TypeScript.PullElementKind.Enum)) {
                return false;
            }

            // Note: this code isn't necessary, but is helpful for error reporting purposes.
            // Instead of reporting something like:
            //
            // Cannot convert 'A[]' to 'B[]':
            //  Types of property 'pop' of types 'A[]' and 'B[]' are incompatible:
            //    Call signatures of types '() => A' and '() => B' are incompatible:
            //      Type 'A' is missing property 'C' from type 'B'.
            //
            // We instead report:
            // Cannot convert 'A[]' to 'B[]':
            //   Type 'A' is missing property 'C' from type 'B'.
            if (source.getIsSpecialized() && target.getIsSpecialized()) {
                if (TypeScript.PullHelpers.getRootType(source) === TypeScript.PullHelpers.getRootType(target) && TypeScript.PullHelpers.getRootType(source).isNamedTypeSymbol()) {
                    var sourceTypeArguments = source.getTypeArguments();
                    var targetTypeArguments = target.getTypeArguments();

                    if (sourceTypeArguments && targetTypeArguments) {
                        comparisonCache.setValueAt(source.pullSymbolID, target.pullSymbolID, true);

                        for (var i = 0; i < sourceTypeArguments.length; i++) {
                            if (!this.sourceIsRelatableToTargetWithNewEnclosingTypes(sourceTypeArguments[i], targetTypeArguments[i], assignableTo, comparisonCache, ast, context, null, isComparingInstantiatedSignatures)) {
                                break;
                            }
                        }

                        if (i === sourceTypeArguments.length) {
                            return true;
                        } else {
                            comparisonCache.setValueAt(source.pullSymbolID, target.pullSymbolID, undefined);
                            // don't return from here - if we've failed, keep checking (this will allow contravariant checks against generic methods to properly pass or fail)
                        }
                    }
                }
            }

            if (target.isTypeParameter()) {
                if (source.isTypeParameter()) {
                    // SPEC Nov 18
                    // S is assignable to a type T, and T is assignable from S, if ...
                    // S and T are type parameters, and S is directly or indirectly constrained to T.
                    if (!source.getConstraint()) {
                        // if the source is another type parameter (with no constraints), they can only be assignable if they share
                        // a declaration
                        return this.typesAreIdentical(target, source, context);
                    } else {
                        return this.isSourceTypeParameterConstrainedToTargetTypeParameter(source, target);
                    }
                } else {
                    // if the source is not another type parameter, and we're specializing at a constraint site, we consider the
                    // target to be a subtype of its constraint
                    if (isComparingInstantiatedSignatures) {
                        target = target.getBaseConstraint(this.semanticInfoChain);
                    } else {
                        return this.typesAreIdentical(target, sourceApparentType, context);
                    }
                }
            }

            // this check ensures that we only operate on object types from this point forward,
            // since the checks involving primitives occurred above
            if (sourceApparentType.isPrimitive() || target.isPrimitive()) {
                // we already know that they're not the same, and that neither is 'any'
                return false;
            }

            comparisonCache.setValueAt(source.pullSymbolID, target.pullSymbolID, true);

            var symbolsWhenStartedWalkingTypes = context.startWalkingTypes(sourceApparentType, target);
            var isRelatable = this.sourceIsRelatableToTargetWorker(sourceApparentType, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            context.endWalkingTypes(symbolsWhenStartedWalkingTypes);

            comparisonCache.setValueAt(source.pullSymbolID, target.pullSymbolID, isRelatable);
            return isRelatable;
        };

        PullTypeResolver.prototype.isSourceTypeParameterConstrainedToTargetTypeParameter = function (source, target) {
            var current = source;
            while (current && current.isTypeParameter()) {
                if (current === target) {
                    return true;
                }

                current = current.getConstraint();
            }
            return false;
        };

        PullTypeResolver.prototype.sourceIsRelatableToTargetWorker = function (source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            if (target.hasMembers() && !this.sourceMembersAreRelatableToTargetMembers(source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures)) {
                return false;
            }

            if (!this.sourceCallSignaturesAreRelatableToTargetCallSignatures(source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures)) {
                return false;
            }

            if (!this.sourceConstructSignaturesAreRelatableToTargetConstructSignatures(source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures)) {
                return false;
            }

            if (!this.sourceIndexSignaturesAreRelatableToTargetIndexSignatures(source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures)) {
                return false;
            }

            return true;
        };

        PullTypeResolver.prototype.sourceMembersAreRelatableToTargetMembers = function (source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var targetProps = target.getAllMembers(TypeScript.PullElementKind.SomeValue, 0 /* all */);

            for (var itargetProp = 0; itargetProp < targetProps.length; itargetProp++) {
                var targetProp = targetProps[itargetProp];

                // November 18, 2013, Sections 3.8.3 + 3.8.4
                // ..., where S' denotes the apparent type (section 3.8.1) of S
                // Note that by this point, we should already have the apparent type of 'source',
                // not including augmentation, so the only thing left to do is augment the type as
                // we look for the property.
                var sourceProp = this._getNamedPropertySymbolOfAugmentedType(targetProp.name, source);

                this.resolveDeclaredSymbol(targetProp, context);

                var targetPropType = targetProp.type;

                if (!sourceProp) {
                    if (!(targetProp.isOptional)) {
                        if (comparisonInfo) {
                            var enclosingSymbol = this.getEnclosingSymbolForAST(ast);
                            comparisonInfo.addMessage(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Type_0_is_missing_property_1_from_type_2, [source.toString(enclosingSymbol), targetProp.getScopedNameEx().toString(), target.toString(enclosingSymbol)]));
                        }
                        return false;
                    }
                    continue;
                }

                if (!this.sourcePropertyIsRelatableToTargetProperty(source, target, sourceProp, targetProp, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures)) {
                    return false;
                }
            }

            return true;
        };

        PullTypeResolver.prototype.infinitelyExpandingSourceTypeIsRelatableToTargetType = function (sourceType, targetType, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            // Section 3.8.7 - Recursive Types
            //  When comparing two types S and T for identity(section 3.8.2), subtype(section 3.8.3), and
            //  assignability(section 3.8.4) relationships,
            //  if either type originates in an infinitely expanding type reference, S and T are not compared
            //  by the rules in the preceding sections.Instead, for the relationship to be considered true,
            //  -	S and T must both be type references to the same named type, and
            //  -	the relationship in question must be true for each corresponding pair of type arguments in
            //      the type argument lists of S and T.
            var widenedTargetType = targetType.widenedType(this, null, context);
            var widenedSourceType = sourceType.widenedType(this, null, context);

            // Check if the type is not any/null or undefined
            if ((widenedSourceType !== this.semanticInfoChain.anyTypeSymbol) && (widenedTargetType !== this.semanticInfoChain.anyTypeSymbol)) {
                var sourceTypeNamedTypeReference = TypeScript.PullHelpers.getRootType(sourceType);
                var targetTypeNamedTypeReference = TypeScript.PullHelpers.getRootType(targetType);

                //  -	S and T must both be type references to the same named type, and
                if (sourceTypeNamedTypeReference !== targetTypeNamedTypeReference) {
                    comparisonCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, false);
                    if (comparisonInfo) {
                        var enclosingSymbol = this.getEnclosingSymbolForAST(ast);
                        comparisonInfo.addMessage(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Types_0_and_1_originating_in_infinitely_expanding_type_reference_do_not_refer_to_same_named_type, [sourceType.getScopedNameEx(enclosingSymbol).toString(), targetType.toString(enclosingSymbol)]));
                    }
                    return false;
                }

                var sourceTypeArguments = sourceType.getTypeArguments();
                var targetTypeArguments = targetType.getTypeArguments();

                // Verify if all type arguments can relate
                if (!sourceTypeArguments && !targetTypeArguments) {
                    // Both interface have 0 type arguments, so they relate
                    comparisonCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, true);
                    return true;
                }

                // If the number of type arguments mismatch (because of incomplete list - types are incompatible
                if (!(sourceTypeArguments && targetTypeArguments) || sourceTypeArguments.length !== targetTypeArguments.length) {
                    comparisonCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, false);
                    if (comparisonInfo) {
                        var enclosingSymbol = this.getEnclosingSymbolForAST(ast);
                        comparisonInfo.addMessage(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Types_0_and_1_originating_in_infinitely_expanding_type_reference_have_incompatible_type_arguments, [sourceType.toString(enclosingSymbol), targetType.toString(enclosingSymbol)]));
                    }
                    return false;
                }

                var comparisonInfoTypeArgumentsCheck = null;
                if (comparisonInfo && !comparisonInfo.onlyCaptureFirstError) {
                    comparisonInfoTypeArgumentsCheck = new TypeComparisonInfo(comparisonInfo);
                }
                var isRelatable = true;
                for (var i = 0; i < sourceTypeArguments.length && isRelatable; i++) {
                    //  -	the relationship in question must be true for each corresponding pair of type arguments
                    //      in the type argument lists of S and T.
                    context.walkTypeArgument(i);

                    if (!this.sourceIsRelatableToTargetInEnclosingTypes(sourceTypeArguments[i], targetTypeArguments[i], assignableTo, comparisonCache, ast, context, comparisonInfoTypeArgumentsCheck, isComparingInstantiatedSignatures)) {
                        isRelatable = false;
                        if (comparisonInfo) {
                            var message;
                            var enclosingSymbol = this.getEnclosingSymbolForAST(ast);

                            if (comparisonInfoTypeArgumentsCheck && comparisonInfoTypeArgumentsCheck.message) {
                                message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Types_0_and_1_originating_in_infinitely_expanding_type_reference_have_incompatible_type_arguments_NL_2, [sourceType.toString(enclosingSymbol), targetType.toString(enclosingSymbol), comparisonInfoTypeArgumentsCheck.message]);
                            } else {
                                message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Types_0_and_1_originating_in_infinitely_expanding_type_reference_have_incompatible_type_arguments, [sourceType.toString(enclosingSymbol), targetType.toString(enclosingSymbol)]);
                            }
                            comparisonInfo.addMessage(message);
                        }
                    }

                    context.postWalkTypeArgument();
                }
            }

            comparisonCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, isRelatable);
            return isRelatable;
        };

        PullTypeResolver.prototype.infinitelyExpandingTypesAreIdentical = function (sourceType, targetType, context) {
            // Section 3.8.7 - Recursive Types
            //  When comparing two types S and T for identity(section 3.8.2), subtype(section 3.8.3), and
            //  assignability(section 3.8.4) relationships,
            //  if either type originates in an infinitely expanding type reference, S and T are not compared
            //  by the rules in the preceding sections.Instead, for the relationship to be considered true,
            //  -	S and T must both be type references to the same named type, and
            //  -	the relationship in question must be true for each corresponding pair of type arguments in
            //      the type argument lists of S and T.
            var widenedTargetType = targetType.widenedType(this, null, null);
            var widenedSourceType = sourceType.widenedType(this, null, null);

            // Check if the type is not any/null or undefined
            if ((widenedSourceType !== this.semanticInfoChain.anyTypeSymbol) && (widenedTargetType !== this.semanticInfoChain.anyTypeSymbol)) {
                //  -	S and T must both be type references to the same named type, and
                var sourceTypeNamedTypeReference = TypeScript.PullHelpers.getRootType(sourceType);
                var targetTypeNamedTypeReference = TypeScript.PullHelpers.getRootType(targetType);
                if (sourceTypeNamedTypeReference !== targetTypeNamedTypeReference) {
                    this.identicalCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, false);
                    return false;
                }

                //  -	the relationship in question must be true for each corresponding pair of type arguments in
                //      the type argument lists of S and T.
                var sourceTypeArguments = sourceType.getTypeArguments();
                var targetTypeArguments = targetType.getTypeArguments();

                if (!sourceTypeArguments && !targetTypeArguments) {
                    // Both types do not refere to any type arguments so they are identical
                    this.identicalCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, true);
                    return true;
                }

                if (!(sourceTypeArguments && targetTypeArguments) || sourceTypeArguments.length !== targetTypeArguments.length) {
                    // Mismatch in type arguments length - may be missing type arguments - it is error
                    this.identicalCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, false);
                    return false;
                }

                for (var i = 0; i < sourceTypeArguments.length; i++) {
                    // Each pair of type argument needs to be identical for the type to be identical
                    context.walkTypeArgument(i);
                    var areIdentical = this.typesAreIdenticalInEnclosingTypes(sourceTypeArguments[i], targetTypeArguments[i], context);
                    context.postWalkTypeArgument();

                    if (!areIdentical) {
                        this.identicalCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, false);
                        return false;
                    }
                }
            }

            this.identicalCache.setValueAt(sourceType.pullSymbolID, targetType.pullSymbolID, true);
            return true;
        };

        PullTypeResolver.prototype.sourcePropertyIsRelatableToTargetProperty = function (source, target, sourceProp, targetProp, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var _this = this;
            var sourceAndTargetAreConstructors = source.isConstructor() && target.isConstructor();

            // source\target are not always equivalent to getContainer().
            // i.e.in cases of inheritance chains source will be derived type and getContainer() will yield some type from the middle of hierarchy
            var getNames = function (takeTypesFromPropertyContainers) {
                var enclosingSymbol = _this.getEnclosingSymbolForAST(ast);
                var sourceType = takeTypesFromPropertyContainers ? sourceProp.getContainer() : source;
                var targetType = takeTypesFromPropertyContainers ? targetProp.getContainer() : target;
                if (sourceAndTargetAreConstructors) {
                    sourceType = sourceType.getAssociatedContainerType();
                    targetType = targetType.getAssociatedContainerType();
                }
                return {
                    propertyName: targetProp.getScopedNameEx().toString(),
                    sourceTypeName: sourceType.toString(enclosingSymbol),
                    targetTypeName: targetType.toString(enclosingSymbol)
                };
            };

            var targetPropIsPrivate = targetProp.anyDeclHasFlag(TypeScript.PullElementFlags.Private);
            var sourcePropIsPrivate = sourceProp.anyDeclHasFlag(TypeScript.PullElementFlags.Private);

            // if visibility doesn't match, the types don't match
            if (targetPropIsPrivate !== sourcePropIsPrivate) {
                if (comparisonInfo) {
                    var names = getNames(true);
                    var code;
                    if (targetPropIsPrivate) {
                        // Overshadowing property in source that is already defined as private in target
                        code = sourceAndTargetAreConstructors ? TypeScript.DiagnosticCode.Static_property_0_defined_as_public_in_type_1_is_defined_as_private_in_type_2 : TypeScript.DiagnosticCode.Property_0_defined_as_public_in_type_1_is_defined_as_private_in_type_2;
                    } else {
                        // Public property of target is private in source
                        code = sourceAndTargetAreConstructors ? TypeScript.DiagnosticCode.Static_property_0_defined_as_private_in_type_1_is_defined_as_public_in_type_2 : TypeScript.DiagnosticCode.Property_0_defined_as_private_in_type_1_is_defined_as_public_in_type_2;
                    }
                    comparisonInfo.addMessage(TypeScript.getDiagnosticMessage(code, [names.propertyName, names.sourceTypeName, names.targetTypeName]));
                }
                return false;
            } else if (sourcePropIsPrivate && targetPropIsPrivate) {
                var targetDecl = targetProp.getDeclarations()[0];
                var sourceDecl = sourceProp.getDeclarations()[0];

                if (targetDecl !== sourceDecl) {
                    if (comparisonInfo) {
                        var names = getNames(true);

                        // Both types define property with same name as private
                        var code = sourceAndTargetAreConstructors ? TypeScript.DiagnosticCode.Types_0_and_1_define_static_property_2_as_private : TypeScript.DiagnosticCode.Types_0_and_1_define_property_2_as_private;
                        comparisonInfo.addMessage(TypeScript.getDiagnosticMessage(code, [names.sourceTypeName, names.targetTypeName, names.propertyName]));
                    }

                    return false;
                }
            }

            // If the target property is required, and the source property is optional, they are not compatible
            if (sourceProp.isOptional && !targetProp.isOptional) {
                if (comparisonInfo) {
                    var names = getNames(true);
                    comparisonInfo.addMessage(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Property_0_defined_as_optional_in_type_1_but_is_required_in_type_2, [names.propertyName, names.sourceTypeName, names.targetTypeName]));
                }
                return false;
            }

            this.resolveDeclaredSymbol(sourceProp, context);

            var sourcePropType = sourceProp.type;
            var targetPropType = targetProp.type;

            // In the case of a 'false', we want to short-circuit a recursive typecheck
            var isRelatableInfo = this.sourceIsRelatableToTargetInCache(sourcePropType, targetPropType, comparisonCache, comparisonInfo);
            if (isRelatableInfo) {
                return isRelatableInfo.isRelatable;
            }

            var comparisonInfoPropertyTypeCheck = null;
            if (comparisonInfo && !comparisonInfo.onlyCaptureFirstError) {
                comparisonInfoPropertyTypeCheck = new TypeComparisonInfo(comparisonInfo);
            }

            context.walkMemberTypes(targetProp.name);
            var isSourcePropertyRelatableToTargetProperty = this.sourceIsRelatableToTargetInEnclosingTypes(sourcePropType, targetPropType, assignableTo, comparisonCache, ast, context, comparisonInfoPropertyTypeCheck, isComparingInstantiatedSignatures);
            context.postWalkMemberTypes();

            // Update error message correctly
            if (!isSourcePropertyRelatableToTargetProperty && comparisonInfo) {
                var enclosingSymbol = this.getEnclosingSymbolForAST(ast);
                var message;
                var names = getNames(false);
                if (comparisonInfoPropertyTypeCheck && comparisonInfoPropertyTypeCheck.message) {
                    var code = sourceAndTargetAreConstructors ? TypeScript.DiagnosticCode.Types_of_static_property_0_of_class_1_and_class_2_are_incompatible_NL_3 : TypeScript.DiagnosticCode.Types_of_property_0_of_types_1_and_2_are_incompatible_NL_3;
                    message = TypeScript.getDiagnosticMessage(code, [names.propertyName, names.sourceTypeName, names.targetTypeName, comparisonInfoPropertyTypeCheck.message]);
                } else {
                    var code = sourceAndTargetAreConstructors ? TypeScript.DiagnosticCode.Types_of_static_property_0_of_class_1_and_class_2_are_incompatible : TypeScript.DiagnosticCode.Types_of_property_0_of_types_1_and_2_are_incompatible;
                    message = TypeScript.getDiagnosticMessage(code, [names.propertyName, names.sourceTypeName, names.targetTypeName]);
                }
                comparisonInfo.addMessage(message);
            }

            return isSourcePropertyRelatableToTargetProperty;
        };

        PullTypeResolver.prototype.sourceCallSignaturesAreRelatableToTargetCallSignatures = function (source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var targetCallSigs = target.getCallSignatures();

            // check signature groups
            if (targetCallSigs.length) {
                var comparisonInfoSignatuesTypeCheck = null;
                if (comparisonInfo && !comparisonInfo.onlyCaptureFirstError) {
                    comparisonInfoSignatuesTypeCheck = new TypeComparisonInfo(comparisonInfo);
                }

                var sourceCallSigs = source.getCallSignatures();
                if (!this.signatureGroupIsRelatableToTarget(source, target, sourceCallSigs, targetCallSigs, assignableTo, comparisonCache, ast, context, comparisonInfoSignatuesTypeCheck, isComparingInstantiatedSignatures)) {
                    if (comparisonInfo) {
                        var message;
                        var enclosingSymbol = this.getEnclosingSymbolForAST(ast);
                        if (sourceCallSigs.length && targetCallSigs.length) {
                            if (comparisonInfoSignatuesTypeCheck && comparisonInfoSignatuesTypeCheck.message) {
                                message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Call_signatures_of_types_0_and_1_are_incompatible_NL_2, [source.toString(enclosingSymbol), target.toString(enclosingSymbol), comparisonInfoSignatuesTypeCheck.message]);
                            } else {
                                message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Call_signatures_of_types_0_and_1_are_incompatible, [source.toString(enclosingSymbol), target.toString(enclosingSymbol)]);
                            }
                        } else {
                            var hasSig = targetCallSigs.length ? target.toString(enclosingSymbol) : source.toString(enclosingSymbol);
                            var lacksSig = !targetCallSigs.length ? target.toString(enclosingSymbol) : source.toString(enclosingSymbol);
                            message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Type_0_requires_a_call_signature_but_type_1_lacks_one, [hasSig, lacksSig]);
                        }
                        comparisonInfo.addMessage(message);
                    }
                    return false;
                }
            }

            return true;
        };

        PullTypeResolver.prototype.sourceConstructSignaturesAreRelatableToTargetConstructSignatures = function (source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            // check signature groups
            var targetConstructSigs = target.getConstructSignatures();
            if (targetConstructSigs.length) {
                var comparisonInfoSignatuesTypeCheck = null;
                if (comparisonInfo && !comparisonInfo.onlyCaptureFirstError) {
                    comparisonInfoSignatuesTypeCheck = new TypeComparisonInfo(comparisonInfo);
                }

                var sourceConstructSigs = source.getConstructSignatures();
                if (!this.signatureGroupIsRelatableToTarget(source, target, sourceConstructSigs, targetConstructSigs, assignableTo, comparisonCache, ast, context, comparisonInfoSignatuesTypeCheck, isComparingInstantiatedSignatures)) {
                    if (comparisonInfo) {
                        var enclosingSymbol = this.getEnclosingSymbolForAST(ast);
                        var message;
                        if (sourceConstructSigs.length && targetConstructSigs.length) {
                            if (comparisonInfoSignatuesTypeCheck && comparisonInfoSignatuesTypeCheck.message) {
                                message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Construct_signatures_of_types_0_and_1_are_incompatible_NL_2, [source.toString(enclosingSymbol), target.toString(enclosingSymbol), comparisonInfoSignatuesTypeCheck.message]);
                            } else {
                                message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Construct_signatures_of_types_0_and_1_are_incompatible, [source.toString(enclosingSymbol), target.toString(enclosingSymbol)]);
                            }
                        } else {
                            var hasSig = targetConstructSigs.length ? target.toString(enclosingSymbol) : source.toString(enclosingSymbol);
                            var lacksSig = !targetConstructSigs.length ? target.toString(enclosingSymbol) : source.toString(enclosingSymbol);
                            message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Type_0_requires_a_construct_signature_but_type_1_lacks_one, [hasSig, lacksSig]);
                        }
                        comparisonInfo.addMessage(message);
                    }
                    return false;
                }
            }

            return true;
        };

        PullTypeResolver.prototype.sourceIndexSignaturesAreRelatableToTargetIndexSignatures = function (source, target, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var targetIndexSigs = this.getBothKindsOfIndexSignaturesExcludingAugmentedType(target, context);
            var targetStringSig = targetIndexSigs.stringSignature;
            var targetNumberSig = targetIndexSigs.numericSignature;

            if (targetStringSig || targetNumberSig) {
                var sourceIndexSigs = this.getBothKindsOfIndexSignaturesIncludingAugmentedType(source, context);
                var enclosingTypeIndexSigs = context.getBothKindOfIndexSignatures(true, false);
                var sourceStringSig = sourceIndexSigs.stringSignature;
                var sourceNumberSig = sourceIndexSigs.numericSignature;

                var comparable = true;
                var comparisonInfoSignatuesTypeCheck = null;
                if (comparisonInfo && !comparisonInfo.onlyCaptureFirstError) {
                    comparisonInfoSignatuesTypeCheck = new TypeComparisonInfo(comparisonInfo);
                }

                if (targetStringSig) {
                    // Spec section 3.8.3	Subtypes and Supertypes
                    // S is a subtype of a type T, and T is a supertype of S, if one of the following is true,
                    // where S? denotes the apparent type(section 3.8.1) of S:
                    //      - M is a string index signature of type U and
                    //        S? contains a string index signature of a type that is assignable to U.
                    // Spec section 3.8.4	Assignment Compatibility
                    // S is assignable to a type T, and T is assignable from S, if one of the following is true,
                    // where S? denotes the apparent type(section 3.8.1) of S:
                    //      - M is a string index signature of type U and
                    //        S? contains a string index signature of a type that is assignable to U.
                    if (sourceStringSig) {
                        context.walkIndexSignatureReturnTypes(enclosingTypeIndexSigs, true, true);
                        comparable = this.sourceIsRelatableToTargetInEnclosingTypes(sourceStringSig.returnType, targetStringSig.returnType, assignableTo, comparisonCache, ast, context, comparisonInfoSignatuesTypeCheck, isComparingInstantiatedSignatures);
                        context.postWalkIndexSignatureReturnTypes();
                    } else {
                        comparable = false;
                    }
                }

                if (comparable && targetNumberSig) {
                    // Spec section 3.8.3	Subtypes and Supertypes
                    // S is a subtype of a type T, and T is a supertype of S, if one of the following is true,
                    // where S? denotes the apparent type(section 3.8.1) of S:
                    //      - M is a numeric index signature of type U and
                    //        S? contains a string or numeric index signature of a type that is a subtype of U.
                    // Spec section 3.8.4	Assignment Compatibility
                    // S is assignable to a type T, and T is assignable from S, if one of the following is true,
                    // where S? denotes the apparent type(section 3.8.1) of S:
                    //      - M is a numeric index signature of type U and
                    //        S? contains a string or numeric index signature of a type that is assignable to U.
                    if (sourceNumberSig) {
                        context.walkIndexSignatureReturnTypes(enclosingTypeIndexSigs, false, false);
                        comparable = this.sourceIsRelatableToTargetInEnclosingTypes(sourceNumberSig.returnType, targetNumberSig.returnType, assignableTo, comparisonCache, ast, context, comparisonInfoSignatuesTypeCheck, isComparingInstantiatedSignatures);
                        context.postWalkIndexSignatureReturnTypes();
                    } else if (sourceStringSig) {
                        context.walkIndexSignatureReturnTypes(enclosingTypeIndexSigs, true, false);
                        comparable = this.sourceIsRelatableToTargetInEnclosingTypes(sourceStringSig.returnType, targetNumberSig.returnType, assignableTo, comparisonCache, ast, context, comparisonInfoSignatuesTypeCheck, isComparingInstantiatedSignatures);
                        context.postWalkIndexSignatureReturnTypes();
                    } else {
                        comparable = false;
                    }
                }

                if (!comparable) {
                    if (comparisonInfo) {
                        var message;
                        var enclosingSymbol = this.getEnclosingSymbolForAST(ast);
                        if (comparisonInfoSignatuesTypeCheck && comparisonInfoSignatuesTypeCheck.message) {
                            message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Index_signatures_of_types_0_and_1_are_incompatible_NL_2, [source.toString(enclosingSymbol), target.toString(enclosingSymbol), comparisonInfoSignatuesTypeCheck.message]);
                        } else {
                            message = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Index_signatures_of_types_0_and_1_are_incompatible, [source.toString(enclosingSymbol), target.toString(enclosingSymbol)]);
                        }
                        comparisonInfo.addMessage(message);
                    }
                    return false;
                }
            }

            return true;
        };

        // REVIEW: TypeChanges: Return an error context object so the user can get better diagnostic info
        PullTypeResolver.prototype.signatureGroupIsRelatableToTarget = function (source, target, sourceSG, targetSG, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            if (sourceSG === targetSG) {
                return true;
            }

            if (!(sourceSG.length && targetSG.length)) {
                return false;
            }

            var foundMatch = false;

            var targetExcludeDefinition = targetSG.length > 1;
            var sourceExcludeDefinition = sourceSG.length > 1;
            var sigsCompared = 0;
            var comparisonInfoSignatuesTypeCheck = null;
            if (comparisonInfo) {
                comparisonInfoSignatuesTypeCheck = new TypeComparisonInfo(comparisonInfo, true);
                comparisonInfoSignatuesTypeCheck.message = comparisonInfo.message;
            }
            for (var iMSig = 0; iMSig < targetSG.length; iMSig++) {
                var mSig = targetSG[iMSig];

                if (mSig.isStringConstantOverloadSignature() || (targetExcludeDefinition && mSig.isDefinition())) {
                    continue;
                }

                for (var iNSig = 0; iNSig < sourceSG.length; iNSig++) {
                    var nSig = sourceSG[iNSig];

                    if (nSig.isStringConstantOverloadSignature() || (sourceExcludeDefinition && nSig.isDefinition())) {
                        continue;
                    }

                    context.walkSignatures(nSig.kind, iNSig, iMSig);
                    var isSignatureRelatableToTarget = this.signatureIsRelatableToTarget(nSig, mSig, assignableTo, comparisonCache, ast, context, sigsCompared == 0 ? comparisonInfoSignatuesTypeCheck : null, isComparingInstantiatedSignatures);
                    context.postWalkSignatures();

                    sigsCompared++;

                    if (isSignatureRelatableToTarget) {
                        foundMatch = true;
                        break;
                    }
                }

                if (foundMatch) {
                    foundMatch = false;
                    continue;
                }

                // Give information about check fail only if we are comparing one signature.
                // This helps in perf (without comparisonInfo we can even use checks that were determined to be false)
                // Yet we can give useful info if we are comparing two types with one signature
                if (comparisonInfo && sigsCompared == 1) {
                    comparisonInfo.message = comparisonInfoSignatuesTypeCheck.message;
                }

                return false;
            }

            return true;
        };

        PullTypeResolver.prototype.signatureIsRelatableToTarget = function (sourceSig, targetSig, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var isRelatableInfo = this.sourceIsRelatableToTargetInCache(sourceSig, targetSig, comparisonCache, comparisonInfo);
            if (isRelatableInfo) {
                return isRelatableInfo.isRelatable;
            }

            comparisonCache.setValueAt(sourceSig.pullSymbolID, targetSig.pullSymbolID, true);
            var isRelatable = this.signatureIsRelatableToTargetWorker(sourceSig, targetSig, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
            comparisonCache.setValueAt(sourceSig.pullSymbolID, targetSig.pullSymbolID, isRelatable);
            return isRelatable;
        };

        PullTypeResolver.prototype.signatureIsRelatableToTargetWorker = function (sourceSig, targetSig, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures) {
            var _this = this;
            var sourceParameters = sourceSig.parameters;
            var targetParameters = targetSig.parameters;

            if (!sourceParameters || !targetParameters) {
                return false;
            }

            var targetNonOptionalParamCount = targetSig.nonOptionalParamCount;
            var sourceNonOptionalParamCount = sourceSig.nonOptionalParamCount;

            if (!targetSig.hasVarArgs && sourceNonOptionalParamCount > targetParameters.length) {
                if (comparisonInfo) {
                    comparisonInfo.addMessage(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Call_signature_expects_0_or_fewer_parameters, [targetParameters.length]));
                }
                return false;
            }

            // If signatures are relatable if sourceSig and targetSig are identical
            if (this.signaturesAreIdentical(sourceSig, targetSig, context)) {
                return true;
            }

            // From the January 23 version of the spec, following the design change:
            // Section 3.8.3 + 3.8.4: M is a non-specialized call or construct signature and S'
            // contains a call or construct signature N where, when M and N are instantiated using
            // type Any as the type argument for all type parameters declared by M and N (if any)
            targetSig = this.instantiateSignatureToAny(targetSig);
            sourceSig = this.instantiateSignatureToAny(sourceSig);

            var sourceReturnType = sourceSig.returnType;
            var targetReturnType = targetSig.returnType;

            if (targetReturnType !== this.semanticInfoChain.voidTypeSymbol) {
                context.walkReturnTypes();
                var returnTypesAreRelatable = this.sourceIsRelatableToTargetInEnclosingTypes(sourceReturnType, targetReturnType, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
                context.postWalkReturnTypes();
                if (!returnTypesAreRelatable) {
                    return false;
                }
            }

            return targetSig.forAllCorrespondingParameterTypesInThisAndOtherSignature(sourceSig, function (targetParamType, sourceParamType, iParam) {
                context.walkParameterTypes(iParam);
                var areParametersRelatable = _this.sourceIsRelatableToTargetInEnclosingTypes(sourceParamType, targetParamType, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
                if (!areParametersRelatable) {
                    // Switch type1 and type2 enclosing types since we are doing reverse check
                    context.swapEnclosingTypeWalkers();
                    areParametersRelatable = _this.sourceIsRelatableToTargetInEnclosingTypes(targetParamType, sourceParamType, assignableTo, comparisonCache, ast, context, comparisonInfo, isComparingInstantiatedSignatures);
                    context.swapEnclosingTypeWalkers();
                }
                context.postWalkParameterTypes();

                return areParametersRelatable;
            });
        };

        // Overload resolution
        PullTypeResolver.prototype.resolveOverloads = function (application, group, haveTypeArgumentsAtCallSite, context, diagnostics) {
            var _this = this;
            var hasOverloads = group.length > 1;
            var comparisonInfo = new TypeComparisonInfo();
            var args = application.argumentList ? application.argumentList.arguments : null;

            var initialCandidates = TypeScript.ArrayUtilities.where(group, function (signature) {
                // Filter out definition if overloads are available
                if (hasOverloads && signature.isDefinition()) {
                    return false;
                }

                // Filter out nongeneric signatures if type arguments are supplied
                var rootSignature = signature.getRootSymbol();
                if (haveTypeArgumentsAtCallSite && !rootSignature.isGeneric()) {
                    return false;
                }

                // Filter out overloads with the wrong arity
                return _this.overloadHasCorrectArity(signature, args);
            });

            // Now that we have trimmed initial candidates, find which ones are applicable per spec
            //    section 4.12.1
            // October 11, 2013: If the list of candidate signatures is empty, the function call is
            //    an error.
            // Otherwise, if the candidate list contains one or more signatures for which the type
            //    of each argument expression is a subtype of each corresponding parameter type,
            //    the return type of the first of those signatures becomes the return type of the
            //    function call.
            // Otherwise, the return type of the first signature in the candidate list becomes
            //    the return type of the function call.
            var firstAssignableButNotSupertypeSignature = null;
            var firstAssignableWithProvisionalErrorsSignature = null;

            for (var i = 0; i < initialCandidates.length; i++) {
                var applicability = this.overloadIsApplicable(initialCandidates[i], args, context, comparisonInfo);
                if (applicability === 3 /* Subtype */) {
                    return initialCandidates[i];
                } else if (applicability === 2 /* AssignableWithNoProvisionalErrors */ && !firstAssignableButNotSupertypeSignature) {
                    firstAssignableButNotSupertypeSignature = initialCandidates[i];
                } else if (applicability === 1 /* AssignableButWithProvisionalErrors */ && !firstAssignableWithProvisionalErrorsSignature) {
                    firstAssignableWithProvisionalErrorsSignature = initialCandidates[i];
                }
            }

            // Choose the best signature we have (between assignable candidates and ones with provisional errors)
            // In particular, do not error when we have one that fits but with provisional errors
            if (firstAssignableButNotSupertypeSignature || firstAssignableWithProvisionalErrorsSignature) {
                return firstAssignableButNotSupertypeSignature || firstAssignableWithProvisionalErrorsSignature;
            } else {
                var target = this.getCallTargetErrorSpanAST(application);
                if (comparisonInfo.message) {
                    diagnostics.push(this.semanticInfoChain.diagnosticFromAST(target, TypeScript.DiagnosticCode.Supplied_parameters_do_not_match_any_signature_of_call_target_NL_0, [comparisonInfo.message]));
                } else {
                    diagnostics.push(this.semanticInfoChain.diagnosticFromAST(target, TypeScript.DiagnosticCode.Supplied_parameters_do_not_match_any_signature_of_call_target, null));
                }
            }

            return null;
        };

        PullTypeResolver.prototype.getCallTargetErrorSpanAST = function (callEx) {
            if (callEx.expression.kind() === 212 /* MemberAccessExpression */) {
                var memberAccessExpression = callEx.expression;
                if (memberAccessExpression.name.fullWidth() > 0) {
                    return memberAccessExpression.name;
                }
            }

            return callEx.expression;
        };

        PullTypeResolver.prototype.overloadHasCorrectArity = function (signature, args) {
            if (args == null) {
                return signature.nonOptionalParamCount === 0;
            }

            // First, figure out how many arguments there are. This is usually args.length, but if we have trailing separators,
            // we need to pretend we have one more "phantom" argument that the user is currently typing. This is useful for signature help.
            // Example: foo(1, 2,
            // should have 3 arguments
            var numberOfArgs = (args.length && args.length === args.separatorCount()) ? args.separatorCount() + 1 : args.length;
            if (numberOfArgs < signature.nonOptionalParamCount) {
                return false;
            }
            if (!signature.hasVarArgs && numberOfArgs > signature.parameters.length) {
                return false;
            }

            return true;
        };

        PullTypeResolver.prototype.overloadIsApplicable = function (signature, args, context, comparisonInfo) {
            // Already checked for arity, so it's automatically applicable if there are no args
            if (args === null) {
                return 3 /* Subtype */;
            }

            var isInVarArg = false;
            var parameters = signature.parameters;
            var paramType = null;

            // Start by assuming that the argument types are all subtypes of the corresponding parameter types
            // Indeed this is the case for a call with no arguments.
            var overloadApplicability = 3 /* Subtype */;

            for (var i = 0; i < args.length; i++) {
                if (!isInVarArg) {
                    this.resolveDeclaredSymbol(parameters[i], context);

                    if (parameters[i].isVarArg) {
                        // If the vararg has no element type, it is malformed, so just use the any symbol (we will have errored when resolving the signature).
                        paramType = parameters[i].type.getElementType() || this.getNewErrorTypeSymbol(parameters[i].type.getName());
                        isInVarArg = true;
                    } else {
                        paramType = parameters[i].type;
                    }
                }

                // We aggregate the statuses across arguments by taking the less flattering of the two statuses.
                // In the case where we get a completely unassignable argument, we can short circuit and just throw out the signature.
                var statusOfCurrentArgument = this.overloadIsApplicableForArgument(paramType, args[i], i, context, comparisonInfo);

                if (statusOfCurrentArgument === 0 /* NotAssignable */) {
                    return 0 /* NotAssignable */;
                } else if (statusOfCurrentArgument === 1 /* AssignableButWithProvisionalErrors */) {
                    overloadApplicability = 1 /* AssignableButWithProvisionalErrors */;
                } else if (overloadApplicability !== 1 /* AssignableButWithProvisionalErrors */ && statusOfCurrentArgument === 2 /* AssignableWithNoProvisionalErrors */) {
                    overloadApplicability = 2 /* AssignableWithNoProvisionalErrors */;
                }
                // else we have nothing to downgrade - just stick with what we have
            }

            return overloadApplicability;
        };

        PullTypeResolver.prototype.overloadIsApplicableForArgument = function (paramType, arg, argIndex, context, comparisonInfo) {
            if (paramType.isAny()) {
                return 3 /* Subtype */;
            } else if (paramType.isError()) {
                // This is for the case where the parameter type itself was malformed. We will treat this like a provisional error because
                // we will get an error for this in the overload defition group, and we want to avoid choosing this overload if possible.
                return 1 /* AssignableButWithProvisionalErrors */;
            } else if (arg.kind() === 219 /* SimpleArrowFunctionExpression */) {
                var simpleArrowFunction = arg;
                return this.overloadIsApplicableForAnyFunctionExpressionArgument(paramType, arg, null, [simpleArrowFunction.parameter], null, simpleArrowFunction.block, simpleArrowFunction.expression, argIndex, context, comparisonInfo);
            } else if (arg.kind() === 218 /* ParenthesizedArrowFunctionExpression */) {
                var arrowFunction = arg;
                return this.overloadIsApplicableForAnyFunctionExpressionArgument(paramType, arg, arrowFunction.callSignature.typeParameterList, arrowFunction.callSignature.parameterList.parameters, TypeScript.ASTHelpers.getType(arrowFunction), arrowFunction.block, arrowFunction.expression, argIndex, context, comparisonInfo);
            } else if (arg.kind() === 222 /* FunctionExpression */) {
                var functionExpression = arg;
                return this.overloadIsApplicableForAnyFunctionExpressionArgument(paramType, arg, functionExpression.callSignature.typeParameterList, functionExpression.callSignature.parameterList.parameters, TypeScript.ASTHelpers.getType(functionExpression), functionExpression.block, null, argIndex, context, comparisonInfo);
            } else if (arg.kind() === 215 /* ObjectLiteralExpression */) {
                return this.overloadIsApplicableForObjectLiteralArgument(paramType, arg, argIndex, context, comparisonInfo);
            } else if (arg.kind() === 214 /* ArrayLiteralExpression */) {
                return this.overloadIsApplicableForArrayLiteralArgument(paramType, arg, argIndex, context, comparisonInfo);
            } else {
                return this.overloadIsApplicableForOtherArgument(paramType, arg, argIndex, context, comparisonInfo);
            }
        };

        PullTypeResolver.prototype.overloadIsApplicableForAnyFunctionExpressionArgument = function (paramType, arg, typeParameters, parameters, returnTypeAnnotation, block, bodyExpression, argIndex, context, comparisonInfo) {
            if (this.cachedFunctionInterfaceType() && paramType === this.cachedFunctionInterfaceType()) {
                return 2 /* AssignableWithNoProvisionalErrors */;
            }

            context.pushProvisionalType(paramType);

            var argSym = this.resolveAnyFunctionExpression(arg, typeParameters, parameters, returnTypeAnnotation, block, bodyExpression, true, context);

            var applicabilityStatus = this.overloadIsApplicableForArgumentHelper(paramType, argSym.type, argIndex, comparisonInfo, arg, context);

            context.popAnyContextualType();

            return applicabilityStatus;
        };

        PullTypeResolver.prototype.overloadIsApplicableForObjectLiteralArgument = function (paramType, arg, argIndex, context, comparisonInfo) {
            // attempt to contextually type the object literal
            if (this.cachedObjectInterfaceType() && paramType === this.cachedObjectInterfaceType()) {
                return 2 /* AssignableWithNoProvisionalErrors */;
            }

            context.pushProvisionalType(paramType);
            var argSym = this.resolveObjectLiteralExpression(arg, true, context);

            var applicabilityStatus = this.overloadIsApplicableForArgumentHelper(paramType, argSym.type, argIndex, comparisonInfo, arg, context);

            context.popAnyContextualType();

            return applicabilityStatus;
        };

        PullTypeResolver.prototype.overloadIsApplicableForArrayLiteralArgument = function (paramType, arg, argIndex, context, comparisonInfo) {
            // attempt to contextually type the array literal
            if (paramType === this.cachedArrayInterfaceType()) {
                return 2 /* AssignableWithNoProvisionalErrors */;
            }

            context.pushProvisionalType(paramType);
            var argSym = this.resolveArrayLiteralExpression(arg, true, context);

            var applicabilityStatus = this.overloadIsApplicableForArgumentHelper(paramType, argSym.type, argIndex, comparisonInfo, arg, context);

            context.popAnyContextualType();

            return applicabilityStatus;
        };

        PullTypeResolver.prototype.overloadIsApplicableForOtherArgument = function (paramType, arg, argIndex, context, comparisonInfo) {
            // No need to contextually type or mark as provisional
            var argSym = this.resolveAST(arg, false, context);

            // If it is an alias, get its type
            if (argSym.type.isAlias()) {
                var aliasSym = argSym.type;
                argSym = aliasSym.getExportAssignedTypeSymbol();
            }

            // Just in case the argument is a string literal, and are checking overload on const, we set this stringConstantVal
            // (sourceIsAssignableToTarget will internally check if the argument is actually a string)
            comparisonInfo.stringConstantVal = arg;
            return this.overloadIsApplicableForArgumentHelper(paramType, argSym.type, argIndex, comparisonInfo, arg, context);
        };

        // The inner method that decides if an overload is applicable. It can return any of 4 applicability statuses
        // Spec October 11, 2013: Section 4.12.1: for each argument expression e and its corresponding parameter P,
        // when e is contextually typed(section 4.19) by the type of P, no errors ensue and the type of e is assignable
        // to (section 3.8.4) the type of P.
        // Note this also tracks whether the argument type is a subtype of the parameter type
        PullTypeResolver.prototype.overloadIsApplicableForArgumentHelper = function (paramType, argSym, argumentIndex, comparisonInfo, arg, context) {
            // Make a temporary comparison info to catch an error in case the parameter is not a supertype (we don't want to report such errors)
            var tempComparisonInfo = new TypeComparisonInfo();
            tempComparisonInfo.stringConstantVal = comparisonInfo.stringConstantVal;
            if (!context.hasProvisionalErrors() && this.sourceIsSubtypeOfTarget(argSym.type, paramType, arg, context, tempComparisonInfo)) {
                return 3 /* Subtype */;
            }

            // Now check for normal assignability using the original comparison info (or use the temporary one if the original one already has an error).
            if (this.sourceIsAssignableToTarget(argSym.type, paramType, arg, context, comparisonInfo.message ? tempComparisonInfo : comparisonInfo)) {
                return context.hasProvisionalErrors() ? 1 /* AssignableButWithProvisionalErrors */ : 2 /* AssignableWithNoProvisionalErrors */;
            }

            if (!comparisonInfo.message) {
                var enclosingSymbol = this.getEnclosingSymbolForAST(arg);
                comparisonInfo.addMessage(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Could_not_apply_type_0_to_argument_1_which_is_of_type_2, [paramType.toString(enclosingSymbol), (argumentIndex + 1), argSym.getTypeName(enclosingSymbol)]));
            }

            return 0 /* NotAssignable */;
        };

        PullTypeResolver.prototype.inferArgumentTypesForSignature = function (argContext, comparisonInfo, context) {
            var inferenceResultTypes = argContext.inferTypeArguments();
            var typeParameters = argContext.signatureBeingInferred.getTypeParameters();
            TypeScript.Debug.assert(typeParameters.length == inferenceResultTypes.length);

            // Fall back to constraints if constraints are not satisfied
            var typeReplacementMapForConstraints = null;
            for (var i = 0; i < inferenceResultTypes.length; i++) {
                if (typeParameters[i].getConstraint()) {
                    typeReplacementMapForConstraints = typeReplacementMapForConstraints || TypeScript.PullInstantiationHelpers.createTypeParameterSubstitutionMap(typeParameters, inferenceResultTypes);
                    var associatedConstraint = this.instantiateType(typeParameters[i].getConstraint(), typeReplacementMapForConstraints);
                    if (!this.sourceIsAssignableToTargetWithNewEnclosingTypes(inferenceResultTypes[i], associatedConstraint, null, context, null, false)) {
                        inferenceResultTypes[i] = associatedConstraint;
                    }
                }
            }

            //  Do not let local type parameters escape at call sites
            //  Because we're comparing for equality between two signatures (where one is instantiated
            //  against the type parameters of the other), we want to know * exactly * what the
            //  instantiation would be give the set of type parameters.In the case where the two
            //  signatures are otherwise equal, we don't want to sub in '{ }' for any of the type parameters,
            //  since that would short - circuit the equality check.The substitution is only desirable at call sites,
            //  where type parameters can leak out of scope, but during contextual instantiation
            //  the type parameters * should * be considered in scope
            // We know that if we are inferring at a call expression we are not doing
            // contextual signature instantiation
            if (argContext.isInvocationInferenceContext()) {
                // Need to know if the type parameters are in scope. If not, they are not legal inference
                // candidates unless we are in contextual signature instantiation
                var invocationContext = argContext;
                if (!this.typeParametersAreInScopeAtArgumentList(typeParameters, invocationContext.argumentList)) {
                    for (var i = 0; i < inferenceResultTypes.length; i++) {
                        // Check if the inferred type wraps any one of the type parameters
                        if (inferenceResultTypes[i].wrapsSomeTypeParameter(argContext.candidateCache)) {
                            inferenceResultTypes[i] = this.semanticInfoChain.anyTypeSymbol;
                        }
                    }
                }
            }

            return inferenceResultTypes;
        };

        PullTypeResolver.prototype.typeParametersAreInScopeAtArgumentList = function (typeParameters, args) {
            // If the parent path from the current enclosing decl contains the type parameters'
            // parent decl, then the type parameters must be in scope
            var enclosingDecl = this.getEnclosingDeclForAST(args);
            var typeParameterParentDecl = typeParameters[0].getDeclarations()[0].getParentDecl();
            return enclosingDecl.getParentPath().indexOf(typeParameterParentDecl) > -1;
        };

        PullTypeResolver.prototype.relateTypeToTypeParametersInEnclosingType = function (expressionType, parameterType, argContext, context) {
            if (expressionType && parameterType) {
                if (context.oneOfClassificationsIsInfinitelyExpanding()) {
                    this.relateInifinitelyExpandingTypeToTypeParameters(expressionType, parameterType, argContext, context);
                    return;
                }
            }
            this.relateTypeToTypeParameters(expressionType, parameterType, argContext, context);
        };

        PullTypeResolver.prototype.relateTypeToTypeParametersWithNewEnclosingTypes = function (expressionType, parameterType, argContext, context) {
            var enclosingTypeWalkerStates = context.resetEnclosingTypeWalkerStates();
            this.relateTypeToTypeParameters(expressionType, parameterType, argContext, context);
            context.setEnclosingTypeWalkerStates(enclosingTypeWalkerStates);
        };

        PullTypeResolver.prototype.relateTypeToTypeParameters = function (expressionType, parameterType, argContext, context) {
            if (!expressionType || !parameterType) {
                return;
            }

            if (expressionType.isError()) {
                expressionType = this.semanticInfoChain.anyTypeSymbol;
            }

            if (parameterType.isTypeParameter()) {
                var typeParameter = parameterType;
                argContext.addCandidateForInference(typeParameter, expressionType);
                return;
            }

            // This is an optimization. Essentially the only way we can make an inference by diving
            // into a type is if our type parameters T occur inside that type. Because we don't have
            // nested named types, this can only occur if the type is anonymous, or if it is generic
            // and T is a type argument to that type.
            if (parameterType.isNamedTypeSymbol() && !parameterType.isGeneric() && !parameterType.getTypeArguments()) {
                return;
            }

            // As an optimization, if both types are generic and the same type, relate their type arguments
            if (TypeScript.PullInstantiationHelpers.twoTypesAreInstantiationsOfSameNamedGenericType(expressionType, parameterType)) {
                this.relateTypeArgumentsOfTypeToTypeParameters(expressionType, parameterType, argContext, context);
            } else {
                // Relate structurally
                var symbolsWhenStartedWalkingTypes = context.startWalkingTypes(expressionType, parameterType);
                this.relateObjectTypeToTypeParameters(expressionType, parameterType, argContext, context);
                context.endWalkingTypes(symbolsWhenStartedWalkingTypes);
            }
        };

        PullTypeResolver.prototype.relateTypeArgumentsOfTypeToTypeParameters = function (expressionType, parameterType, argContext, context) {
            var parameterSideTypeArguments = parameterType.getTypeArguments();
            var argumentSideTypeArguments = expressionType.getTypeArguments();

            TypeScript.Debug.assert(parameterSideTypeArguments && argumentSideTypeArguments && parameterSideTypeArguments.length === argumentSideTypeArguments.length);
            for (var i = 0; i < parameterSideTypeArguments.length; i++) {
                this.relateTypeToTypeParametersWithNewEnclosingTypes(argumentSideTypeArguments[i], parameterSideTypeArguments[i], argContext, context);
            }
        };

        PullTypeResolver.prototype.relateInifinitelyExpandingTypeToTypeParameters = function (expressionType, parameterType, argContext, context) {
            if (!expressionType || !parameterType) {
                return;
            }

            // Section 3.8.7 - Recursive Types
            // Likewise, when making type inferences(section 3.8.6) from a type S to a type T,
            // if either type originates in an infinitely expanding type reference, then
            //     if S and T are type references to the same named type, inferences are made from each type argument in S to each type argument in T,
            //     otherwise, no inferences are made.
            var expressionTypeNamedTypeReference = TypeScript.PullHelpers.getRootType(expressionType);
            var parameterTypeNamedTypeReference = TypeScript.PullHelpers.getRootType(parameterType);
            if (expressionTypeNamedTypeReference !== parameterTypeNamedTypeReference) {
                return;
            }

            var expressionTypeTypeArguments = expressionType.getTypeArguments();
            var parameterTypeArguments = parameterType.getTypeArguments();

            if (expressionTypeTypeArguments && parameterTypeArguments && expressionTypeTypeArguments.length === parameterTypeArguments.length) {
                for (var i = 0; i < expressionTypeTypeArguments.length; i++) {
                    this.relateTypeArgumentsOfTypeToTypeParameters(expressionType, parameterType, argContext, context);
                }
            }
        };

        PullTypeResolver.prototype.relateFunctionSignatureToTypeParameters = function (expressionSignature, parameterSignature, argContext, context) {
            var _this = this;
            var expressionReturnType = expressionSignature.returnType;
            var parameterReturnType = parameterSignature.returnType;

            parameterSignature.forAllCorrespondingParameterTypesInThisAndOtherSignature(expressionSignature, function (parameterSignatureParameterType, expressionSignatureParameterType, i) {
                context.walkParameterTypes(i);
                _this.relateTypeToTypeParametersInEnclosingType(expressionSignatureParameterType, parameterSignatureParameterType, argContext, context);
                context.postWalkParameterTypes();
                return true;
            });

            context.walkReturnTypes();
            this.relateTypeToTypeParametersInEnclosingType(expressionReturnType, parameterReturnType, argContext, context);
            context.postWalkReturnTypes();
        };

        PullTypeResolver.prototype.relateObjectTypeToTypeParameters = function (objectType, parameterType, argContext, context) {
            var parameterTypeMembers = parameterType.getMembers();
            var parameterSignatures;

            var objectMember;
            var objectSignatures;

            if (argContext.alreadyRelatingTypes(objectType, parameterType)) {
                return;
            }

            for (var i = 0; i < parameterTypeMembers.length; i++) {
                objectMember = this.getNamedPropertySymbol(parameterTypeMembers[i].name, TypeScript.PullElementKind.SomeValue, objectType);
                if (objectMember) {
                    // TODO: resolveDeclaredSymbol shouldn't be necessary here, but full fix requires changing underlying
                    // symbols to resolve themselves, which should be done at a later time.
                    this.resolveDeclaredSymbol(objectMember);
                    this.resolveDeclaredSymbol(parameterTypeMembers[i]);
                    context.walkMemberTypes(parameterTypeMembers[i].name);
                    this.relateTypeToTypeParametersInEnclosingType(objectMember.type, parameterTypeMembers[i].type, argContext, context);
                    context.postWalkMemberTypes();
                }
            }

            // If M is a call signature then for each call signature N in S, if the number of non-optional
            // parameters in N is greater than or equal to that of M, N is instantiated with each of its
            // type parameter constraints as type arguments (if any) and inferences are made from parameter
            // types in N to parameter types in the same position in M, and from the return type of N to the
            // return type of M.
            this.relateSignatureGroupToTypeParameters(objectType.getCallSignatures(), parameterType.getCallSignatures(), TypeScript.PullElementKind.CallSignature, argContext, context);

            // If M is a construct signature then for each construct signature N in S, if the number of non-optional
            // parameters in N is greater than or equal to that of M, N is instantiated with each of its
            // type parameter constraints as type arguments (if any) and inferences are made from parameter
            // types in N to parameter types in the same position in M, and from the return type of N to the
            // return type of M.
            this.relateSignatureGroupToTypeParameters(objectType.getConstructSignatures(), parameterType.getConstructSignatures(), TypeScript.PullElementKind.ConstructSignature, argContext, context);

            var parameterIndexSignatures = this.getBothKindsOfIndexSignaturesExcludingAugmentedType(parameterType, context);
            var objectIndexSignatures = this.getBothKindsOfIndexSignaturesExcludingAugmentedType(objectType, context);
            var indexSigInfo = context.getBothKindOfIndexSignatures(false, false);

            // - If M is a string index signature and S contains a string index signature N, inferences are made from the type of N to the type of M.
            // - If M is a numeric index signature and S contains a numeric index signature N, inferences are made from the type of N to the type of M.
            if (parameterIndexSignatures.stringSignature && objectIndexSignatures.stringSignature) {
                context.walkIndexSignatureReturnTypes(indexSigInfo, true, true, true);
                this.relateFunctionSignatureToTypeParameters(objectIndexSignatures.stringSignature, parameterIndexSignatures.stringSignature, argContext, context);
                context.postWalkIndexSignatureReturnTypes(true);
            }
            if (parameterIndexSignatures.numericSignature && objectIndexSignatures.numericSignature) {
                context.walkIndexSignatureReturnTypes(indexSigInfo, false, false, true);
                this.relateFunctionSignatureToTypeParameters(objectIndexSignatures.numericSignature, parameterIndexSignatures.numericSignature, argContext, context);
                context.postWalkIndexSignatureReturnTypes(true);
            }
        };

        // If M is a call/construct signature then for each call/construct signature N in S, if the number of non-optional
        // parameters in N is greater than or equal to that of M, N is instantiated with each of its
        // type parameter constraints as type arguments (if any) and inferences are made from parameter
        // types in N to parameter types in the same position in M, and from the return type of N to the
        // return type of M.
        PullTypeResolver.prototype.relateSignatureGroupToTypeParameters = function (argumentSignatures, parameterSignatures, signatureKind, // Call or construct
argContext, context) {
            for (var i = 0; i < parameterSignatures.length; i++) {
                var paramSignature = parameterSignatures[i];
                if (argumentSignatures.length > 0) {
                    paramSignature = this.instantiateSignatureToAny(paramSignature);
                }
                for (var j = 0; j < argumentSignatures.length; j++) {
                    var argumentSignature = argumentSignatures[j];
                    if (argumentSignature.nonOptionalParamCount > paramSignature.nonOptionalParamCount) {
                        continue;
                    }

                    argumentSignature = this.instantiateSignatureToAny(argumentSignature);

                    // In relateTypeToTypeParameters, the argument type (expressionType) is passed in first
                    // (before the parameter type), so the correct order here is j, i
                    context.walkSignatures(signatureKind, j, i);
                    this.relateFunctionSignatureToTypeParameters(argumentSignature, paramSignature, argContext, context);
                    context.postWalkSignatures();
                }
            }
        };

        // November 18, 2013, Section 4.12.2:
        // If e is an expression of a function type that contains exactly one generic call signature
        // and no other members, and T is a function type with exactly one non-generic call signature
        // and no other members, then any inferences made for type parameters referenced by the
        // parameters of T's call signature are fixed and, if e's call signature can successfully be
        // instantiated in the context of T's call signature(section 3.8.5), e's type is changed to
        // a function type with that instantiated signature.
        PullTypeResolver.prototype.alterPotentialGenericFunctionTypeToInstantiatedFunctionTypeForTypeArgumentInference = function (expressionSymbol, context) {
            // In this case getContextualType will give us the inferential type
            var inferentialType = context.getContextualType();
            TypeScript.Debug.assert(inferentialType);
            var expressionType = expressionSymbol.type;
            if (this.isFunctionTypeWithExactlyOneCallSignatureAndNoOtherMembers(expressionType, true) && this.isFunctionTypeWithExactlyOneCallSignatureAndNoOtherMembers(inferentialType, false)) {
                // Here we overwrite contextualType because we will want to use the version of the type
                // that was instantiated with the fixed type parameters from the argument inference
                // context
                var genericExpressionSignature = expressionType.getCallSignatures()[0];
                var contextualSignature = inferentialType.getCallSignatures()[0];

                // Contextual signature instantiation will return null if the instantiation is unsuccessful
                // We pass true so that the parameters of the contextual signature will be fixed per the spec.
                var instantiatedSignature = this.instantiateSignatureInContext(genericExpressionSignature, contextualSignature, context, true);
                if (instantiatedSignature === null) {
                    return expressionSymbol;
                }

                // Create new type with just the given call signature
                var newType = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.FunctionType, this.semanticInfoChain);
                newType.appendCallSignature(instantiatedSignature);
                return newType;
            }

            return expressionSymbol;
        };

        PullTypeResolver.prototype.isFunctionTypeWithExactlyOneCallSignatureAndNoOtherMembers = function (type, callSignatureShouldBeGeneric) {
            TypeScript.Debug.assert(type);
            if (type.getCallSignatures().length !== 1) {
                return false;
            }

            var callSignatureIsGeneric = type.getCallSignatures()[0].isGeneric();
            if (callSignatureIsGeneric !== callSignatureShouldBeGeneric) {
                return false;
            }

            var typeHasOtherMembers = type.getConstructSignatures().length || type.getIndexSignatures().length || type.getAllMembers(TypeScript.PullElementKind.SomeValue, 0 /* all */).length;
            if (typeHasOtherMembers) {
                return false;
            }

            return true;
        };

        PullTypeResolver.prototype.instantiateTypeToAny = function (typeToSpecialize, context) {
            var typeParameters = typeToSpecialize.getTypeParameters();

            if (!typeParameters.length) {
                return typeToSpecialize;
            }

            var typeArguments = null;

            if (!this._cachedAnyTypeArgs) {
                this._cachedAnyTypeArgs = [
                    [this.semanticInfoChain.anyTypeSymbol],
                    [this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol],
                    [this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol],
                    [this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol],
                    [this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol]
                ];
            }

            if (typeParameters.length < this._cachedAnyTypeArgs.length) {
                typeArguments = this._cachedAnyTypeArgs[typeParameters.length - 1];
            } else {
                // REVIEW: might want to cache these arg lists
                typeArguments = [];

                for (var i = 0; i < typeParameters.length; i++) {
                    typeArguments[typeArguments.length] = this.semanticInfoChain.anyTypeSymbol;
                }
            }

            var type = this.createInstantiatedType(typeToSpecialize, typeArguments);

            return type;
        };

        PullTypeResolver.prototype.instantiateSignatureToAny = function (signature) {
            if (!signature.isGeneric()) {
                return signature;
            }

            var typeParameters = signature.getTypeParameters();
            if (!this._cachedAnyTypeArgs) {
                this._cachedAnyTypeArgs = [
                    [this.semanticInfoChain.anyTypeSymbol],
                    [this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol],
                    [this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol],
                    [this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol],
                    [this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol, this.semanticInfoChain.anyTypeSymbol]
                ];
            }

            if (typeParameters.length < this._cachedAnyTypeArgs.length) {
                var typeArguments = this._cachedAnyTypeArgs[typeParameters.length - 1];
            } else {
                // REVIEW: might want to cache these arg lists
                var typeArguments = [];

                for (var i = 0; i < typeParameters.length; i++) {
                    typeArguments[typeArguments.length] = this.semanticInfoChain.anyTypeSymbol;
                }
            }

            var typeParameterArgumentMap = TypeScript.PullInstantiationHelpers.createTypeParameterSubstitutionMap(typeParameters, typeArguments);
            return this.instantiateSignature(signature, typeParameterArgumentMap);
        };

        // type check infrastructure
        PullTypeResolver.typeCheck = function (compilationSettings, semanticInfoChain, document) {
            var sourceUnit = document.sourceUnit();

            var resolver = semanticInfoChain.getResolver();
            var context = new TypeScript.PullTypeResolutionContext(resolver, true, TypeScript.syntaxTree(sourceUnit).fileName());

            if (resolver.canTypeCheckAST(sourceUnit, context)) {
                resolver.resolveAST(sourceUnit, false, context);
                resolver.validateVariableDeclarationGroups(semanticInfoChain.getDeclForAST(sourceUnit), context);

                while (resolver.typeCheckCallBacks.length) {
                    var callBack = resolver.typeCheckCallBacks.pop();
                    callBack(context);
                }

                resolver.processPostTypeCheckWorkItems(context);
            }
        };

        PullTypeResolver.prototype.validateVariableDeclarationGroups = function (enclosingDecl, context) {
            var _this = this;
            this.scanVariableDeclarationGroups(enclosingDecl, function (_) {
            }, function (subsequentDecl, firstSymbol) {
                // do not report 'must have same type' error for parameters - it makes no sense for them
                // having 'duplicate name' error that can be raised during parameter binding is enough
                if (TypeScript.hasFlag(subsequentDecl.kind, TypeScript.PullElementKind.Parameter) || TypeScript.hasFlag(subsequentDecl.flags, TypeScript.PullElementFlags.PropertyParameter)) {
                    return;
                }

                var boundDeclAST = _this.semanticInfoChain.getASTForDecl(subsequentDecl);

                var symbol = subsequentDecl.getSymbol(_this.semanticInfoChain);
                var symbolType = symbol.type;
                var firstSymbolType = firstSymbol.type;

                if (symbolType && firstSymbolType && symbolType !== firstSymbolType && !_this.typesAreIdentical(symbolType, firstSymbolType, context)) {
                    context.postDiagnostic(_this.semanticInfoChain.diagnosticFromAST(boundDeclAST, TypeScript.DiagnosticCode.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, [symbol.getScopedName(), firstSymbolType.toString(firstSymbol), symbolType.toString(symbol)]));
                }
            });
        };

        PullTypeResolver.prototype.typeCheckFunctionOverloads = function (funcDecl, context, signature, allSignatures) {
            if (!signature) {
                var functionSignatureInfo = TypeScript.PullHelpers.getSignatureForFuncDecl(this.semanticInfoChain.getDeclForAST(funcDecl), this.semanticInfoChain);
                signature = functionSignatureInfo.signature;
                allSignatures = functionSignatureInfo.allSignatures;
            }
            var functionDeclaration = this.semanticInfoChain.getDeclForAST(funcDecl);
            var funcSymbol = functionDeclaration.getSymbol(this.semanticInfoChain);

            // Find the definition signature for this signature group
            var definitionSignature = null;
            for (var i = allSignatures.length - 1; i >= 0; i--) {
                if (allSignatures[i].isDefinition()) {
                    definitionSignature = allSignatures[i];
                    break;
                }
            }

            // Verify assignment compatibility or in case of constantOverload signature, if its subtype of atleast one signature
            var isConstantOverloadSignature = signature.isStringConstantOverloadSignature();
            if (isConstantOverloadSignature) {
                if (signature.isDefinition()) {
                    // Report error - definition signature cannot specify constant type
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDecl, TypeScript.DiagnosticCode.Overload_signature_implementation_cannot_use_specialized_type));
                } else {
                    var foundSubtypeSignature = false;
                    for (var i = 0; i < allSignatures.length; i++) {
                        if (allSignatures[i].isDefinition() || allSignatures[i] === signature) {
                            continue;
                        }

                        if (!allSignatures[i].isResolved) {
                            this.resolveDeclaredSymbol(allSignatures[i], context);
                        }

                        if (allSignatures[i].isStringConstantOverloadSignature()) {
                            continue;
                        }

                        if (this.signatureIsAssignableToTarget(signature, allSignatures[i], null, context)) {
                            foundSubtypeSignature = true;
                            break;
                        }
                    }

                    if (!foundSubtypeSignature) {
                        // Could not find the overload signature subtype
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDecl, TypeScript.DiagnosticCode.Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature));
                    }
                }
            } else if (definitionSignature && definitionSignature !== signature) {
                var comparisonInfo = new TypeComparisonInfo();

                if (!definitionSignature.isResolved) {
                    this.resolveDeclaredSymbol(definitionSignature, context);
                }

                if (!this.signatureIsAssignableToTarget(definitionSignature, signature, funcDecl, context, comparisonInfo)) {
                    // definition signature is not assignable to functionSignature then its incorrect overload signature
                    if (comparisonInfo.message) {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDecl, TypeScript.DiagnosticCode.Overload_signature_is_not_compatible_with_function_definition_NL_0, [comparisonInfo.message]));
                    } else {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDecl, TypeScript.DiagnosticCode.Overload_signature_is_not_compatible_with_function_definition));
                    }
                }
            }

            var signatureForVisibilityCheck = definitionSignature;
            if (!definitionSignature) {
                if (allSignatures[0] === signature) {
                    return;
                }
                signatureForVisibilityCheck = allSignatures[0];
            }

            if (funcDecl.kind() !== 137 /* ConstructorDeclaration */ && functionDeclaration.kind !== TypeScript.PullElementKind.ConstructSignature && signatureForVisibilityCheck && signature !== signatureForVisibilityCheck) {
                var errorCode;

                // verify it satisfies all the properties of first signature
                if (signatureForVisibilityCheck.anyDeclHasFlag(TypeScript.PullElementFlags.Private) !== signature.anyDeclHasFlag(TypeScript.PullElementFlags.Private)) {
                    errorCode = TypeScript.DiagnosticCode.Overload_signatures_must_all_be_public_or_private;
                } else if (signatureForVisibilityCheck.anyDeclHasFlag(1 /* Exported */) !== signature.anyDeclHasFlag(1 /* Exported */)) {
                    errorCode = TypeScript.DiagnosticCode.Overload_signatures_must_all_be_exported_or_not_exported;
                } else if (signatureForVisibilityCheck.anyDeclHasFlag(TypeScript.PullElementFlags.Ambient) !== signature.anyDeclHasFlag(TypeScript.PullElementFlags.Ambient)) {
                    errorCode = TypeScript.DiagnosticCode.Overload_signatures_must_all_be_ambient_or_non_ambient;
                } else if (signatureForVisibilityCheck.anyDeclHasFlag(TypeScript.PullElementFlags.Optional) !== signature.anyDeclHasFlag(TypeScript.PullElementFlags.Optional)) {
                    errorCode = TypeScript.DiagnosticCode.Overload_signatures_must_all_be_optional_or_required;
                }

                if (errorCode) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(funcDecl, errorCode));
                }
            }
        };

        // Privacy checking
        PullTypeResolver.prototype.checkSymbolPrivacy = function (declSymbol, symbol, privacyErrorReporter) {
            if (!symbol || symbol.kind === TypeScript.PullElementKind.Primitive) {
                return;
            }

            if (symbol.isType()) {
                var typeSymbol = symbol;
                var isNamedType = typeSymbol.isNamedTypeSymbol();

                if (typeSymbol.isArrayNamedTypeReference()) {
                    this.checkSymbolPrivacy(declSymbol, typeSymbol.getElementType(), privacyErrorReporter);
                    return;
                }

                if (!isNamedType) {
                    var typeOfSymbol = typeSymbol.getTypeOfSymbol();
                    if (typeOfSymbol) {
                        this.checkSymbolPrivacy(declSymbol, typeOfSymbol, privacyErrorReporter);
                        return;
                    }
                }

                if (typeSymbol.inSymbolPrivacyCheck) {
                    return;
                }

                typeSymbol.inSymbolPrivacyCheck = true;

                var typars = typeSymbol.getTypeArgumentsOrTypeParameters();
                if (typars) {
                    for (var i = 0; i < typars.length; i++) {
                        this.checkSymbolPrivacy(declSymbol, typars[i], privacyErrorReporter);
                    }
                }

                if (!isNamedType) {
                    var members = typeSymbol.getMembers();
                    for (var i = 0; i < members.length; i++) {
                        this.checkSymbolPrivacy(declSymbol, members[i].type, privacyErrorReporter);
                    }

                    this.checkTypePrivacyOfSignatures(declSymbol, typeSymbol.getCallSignatures(), privacyErrorReporter);
                    this.checkTypePrivacyOfSignatures(declSymbol, typeSymbol.getConstructSignatures(), privacyErrorReporter);
                    this.checkTypePrivacyOfSignatures(declSymbol, typeSymbol.getIndexSignatures(), privacyErrorReporter);
                } else if (typeSymbol.kind === TypeScript.PullElementKind.TypeParameter) {
                    this.checkSymbolPrivacy(declSymbol, typeSymbol.getConstraint(), privacyErrorReporter);
                }

                typeSymbol.inSymbolPrivacyCheck = false;

                if (!isNamedType) {
                    return;
                }
            }

            // Check flags for the symbol itself
            if (declSymbol.isExternallyVisible()) {
                // Check if type symbol is externally visible
                var symbolIsVisible = symbol.isExternallyVisible();

                // If Visible check if the type is part of dynamic module
                if (symbolIsVisible && symbol.kind !== TypeScript.PullElementKind.TypeParameter) {
                    var symbolPath = symbol.pathToRoot();
                    var declSymbolPath = declSymbol.pathToRoot();

                    // Symbols are from different dynamic modules
                    if (symbolPath[symbolPath.length - 1].kind === TypeScript.PullElementKind.DynamicModule && declSymbolPath[declSymbolPath.length - 1].kind === TypeScript.PullElementKind.DynamicModule && declSymbolPath[declSymbolPath.length - 1] !== symbolPath[symbolPath.length - 1]) {
                        // Declaration symbol is from different modules
                        // Type may not be visible without import statement
                        symbolIsVisible = false;
                        var declSymbolScope = declSymbolPath[declSymbolPath.length - 1];
                        for (var i = symbolPath.length - 1; i >= 0; i--) {
                            var aliasSymbols = symbolPath[i].getExternalAliasedSymbols(declSymbolScope);
                            if (aliasSymbols) {
                                // Visible type.
                                symbolIsVisible = true;
                                aliasSymbols[0].setTypeUsedExternally();
                                break;
                            }
                        }
                        symbol = symbolPath[symbolPath.length - 1];
                    }
                } else if (symbol.kind === TypeScript.PullElementKind.TypeAlias) {
                    var aliasSymbol = symbol;
                    symbolIsVisible = true;
                    aliasSymbol.setTypeUsedExternally();
                }

                if (!symbolIsVisible) {
                    // declaration is visible from outside but the type isnt - Report error
                    privacyErrorReporter(symbol);
                }
            }
        };

        PullTypeResolver.prototype.checkTypePrivacyOfSignatures = function (declSymbol, signatures, privacyErrorReporter) {
            for (var i = 0; i < signatures.length; i++) {
                var signature = signatures[i];
                if (signatures.length > 1 && signature.isDefinition()) {
                    continue;
                }

                var typeParams = signature.getTypeParameters();
                for (var j = 0; j < typeParams.length; j++) {
                    this.checkSymbolPrivacy(declSymbol, typeParams[j], privacyErrorReporter);
                }

                var params = signature.parameters;
                for (var j = 0; j < params.length; j++) {
                    var paramType = params[j].type;
                    this.checkSymbolPrivacy(declSymbol, paramType, privacyErrorReporter);
                }

                var returnType = signature.returnType;
                this.checkSymbolPrivacy(declSymbol, returnType, privacyErrorReporter);
            }
        };

        PullTypeResolver.prototype.typeParameterOfTypeDeclarationPrivacyErrorReporter = function (classOrInterface, typeParameterAST, typeParameter, symbol, context) {
            var decl = this.semanticInfoChain.getDeclForAST(classOrInterface);
            var enclosingDecl = this.getEnclosingDecl(decl);
            var enclosingSymbol = enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null;
            var messageCode;

            var typeParameters = classOrInterface.kind() === 131 /* ClassDeclaration */ ? classOrInterface.typeParameterList : classOrInterface.typeParameterList;

            var typeSymbol = symbol;
            var typeSymbolName = typeSymbol.getScopedName(enclosingSymbol);
            if (typeSymbol.isContainer() && !typeSymbol.isEnum()) {
                if (!TypeScript.isQuoted(typeSymbolName)) {
                    typeSymbolName = "'" + typeSymbolName + "'";
                }
                if (classOrInterface.kind() === 131 /* ClassDeclaration */) {
                    // Class
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_exported_class_is_using_inaccessible_module_1;
                } else {
                    // Interface
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_exported_interface_is_using_inaccessible_module_1;
                }
            } else {
                if (classOrInterface.kind() === 131 /* ClassDeclaration */) {
                    // Class
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_exported_class_has_or_is_using_private_type_1;
                } else {
                    // Interface
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_exported_interface_has_or_is_using_private_type_1;
                }
            }

            var messageArguments = [typeParameter.getScopedName(enclosingSymbol, false, true), typeSymbolName];
            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(typeParameterAST, messageCode, messageArguments));
        };

        PullTypeResolver.prototype.baseListPrivacyErrorReporter = function (classOrInterface, declSymbol, baseAst, isExtendedType, symbol, context) {
            var decl = this.semanticInfoChain.getDeclForAST(classOrInterface);
            var enclosingDecl = this.getEnclosingDecl(decl);
            var enclosingSymbol = enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null;
            var messageCode;

            var typeSymbol = symbol;
            var typeSymbolName = typeSymbol.getScopedName(enclosingSymbol);
            if (typeSymbol.isContainer() && !typeSymbol.isEnum()) {
                if (!TypeScript.isQuoted(typeSymbolName)) {
                    typeSymbolName = "'" + typeSymbolName + "'";
                }
                if (classOrInterface.kind() === 131 /* ClassDeclaration */) {
                    // Class
                    if (isExtendedType) {
                        messageCode = TypeScript.DiagnosticCode.Exported_class_0_extends_class_from_inaccessible_module_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Exported_class_0_implements_interface_from_inaccessible_module_1;
                    }
                } else {
                    // Interface
                    messageCode = TypeScript.DiagnosticCode.Exported_interface_0_extends_interface_from_inaccessible_module_1;
                }
            } else {
                if (classOrInterface.kind() === 131 /* ClassDeclaration */) {
                    // Class
                    if (isExtendedType) {
                        messageCode = TypeScript.DiagnosticCode.Exported_class_0_extends_private_class_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Exported_class_0_implements_private_interface_1;
                    }
                } else {
                    // Interface
                    messageCode = TypeScript.DiagnosticCode.Exported_interface_0_extends_private_interface_1;
                }
            }

            var messageArguments = [declSymbol.getScopedName(enclosingSymbol), typeSymbolName];
            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(baseAst, messageCode, messageArguments));
        };

        PullTypeResolver.prototype.variablePrivacyErrorReporter = function (declAST, declSymbol, symbol, context) {
            var typeSymbol = symbol;
            var enclosingDecl = this.getEnclosingDecl(declSymbol.getDeclarations()[0]);
            var enclosingSymbol = enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null;

            var isProperty = declSymbol.kind === TypeScript.PullElementKind.Property;
            var isPropertyOfClass = false;
            var declParent = declSymbol.getContainer();
            if (declParent && (declParent.kind === TypeScript.PullElementKind.Class || declParent.kind === TypeScript.PullElementKind.ConstructorMethod)) {
                isPropertyOfClass = true;
            }

            var messageCode;
            var typeSymbolName = typeSymbol.getScopedName(enclosingSymbol);
            if (typeSymbol.isContainer() && !typeSymbol.isEnum()) {
                if (!TypeScript.isQuoted(typeSymbolName)) {
                    typeSymbolName = "'" + typeSymbolName + "'";
                }

                if (declSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.Static)) {
                    messageCode = TypeScript.DiagnosticCode.Public_static_property_0_of_exported_class_is_using_inaccessible_module_1;
                } else if (isProperty) {
                    if (isPropertyOfClass) {
                        messageCode = TypeScript.DiagnosticCode.Public_property_0_of_exported_class_is_using_inaccessible_module_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Property_0_of_exported_interface_is_using_inaccessible_module_1;
                    }
                } else {
                    messageCode = TypeScript.DiagnosticCode.Exported_variable_0_is_using_inaccessible_module_1;
                }
            } else {
                if (declSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.Static)) {
                    messageCode = TypeScript.DiagnosticCode.Public_static_property_0_of_exported_class_has_or_is_using_private_type_1;
                } else if (isProperty) {
                    if (isPropertyOfClass) {
                        messageCode = TypeScript.DiagnosticCode.Public_property_0_of_exported_class_has_or_is_using_private_type_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Property_0_of_exported_interface_has_or_is_using_private_type_1;
                    }
                } else {
                    messageCode = TypeScript.DiagnosticCode.Exported_variable_0_has_or_is_using_private_type_1;
                }
            }

            var messageArguments = [declSymbol.getScopedName(enclosingSymbol), typeSymbolName];
            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(declAST, messageCode, messageArguments));
        };

        PullTypeResolver.prototype.checkFunctionTypePrivacy = function (funcDeclAST, isStatic, typeParameters, parameters, returnTypeAnnotation, block, context) {
            var _this = this;
            if (funcDeclAST.kind() === 222 /* FunctionExpression */ || funcDeclAST.kind() === 241 /* FunctionPropertyAssignment */ || (funcDeclAST.kind() === 139 /* GetAccessor */ && funcDeclAST.parent.parent.kind() === 215 /* ObjectLiteralExpression */) || (funcDeclAST.kind() === 140 /* SetAccessor */ && funcDeclAST.parent.parent.kind() === 215 /* ObjectLiteralExpression */)) {
                return;
            }

            var functionDecl = this.semanticInfoChain.getDeclForAST(funcDeclAST);
            var functionSymbol = functionDecl.getSymbol(this.semanticInfoChain);
            ;
            var functionSignature;

            var isGetter = funcDeclAST.kind() === 139 /* GetAccessor */;
            var isSetter = funcDeclAST.kind() === 140 /* SetAccessor */;
            var isIndexSignature = functionDecl.kind === TypeScript.PullElementKind.IndexSignature;

            if (isGetter || isSetter) {
                var accessorSymbol = functionSymbol;
                functionSignature = (isGetter ? accessorSymbol.getGetter() : accessorSymbol.getSetter()).type.getCallSignatures()[0];
            } else {
                if (!functionSymbol) {
                    var parentDecl = functionDecl.getParentDecl();
                    functionSymbol = parentDecl.getSymbol(this.semanticInfoChain);
                    if (functionSymbol && functionSymbol.isType() && !functionSymbol.isNamedTypeSymbol()) {
                        // Call Signature from the non named type
                        return;
                    }
                } else if (functionSymbol.kind === TypeScript.PullElementKind.Method && !isStatic && !functionSymbol.getContainer().isNamedTypeSymbol()) {
                    // method of the unnmaed type
                    return;
                }
                functionSignature = functionDecl.getSignatureSymbol(this.semanticInfoChain);
            }

            // TypeParameters
            if (typeParameters && !isGetter && !isSetter && !isIndexSignature && funcDeclAST.kind() !== 137 /* ConstructorDeclaration */) {
                for (var i = 0; i < typeParameters.typeParameters.length; i++) {
                    var typeParameterAST = typeParameters.typeParameters[i];
                    var typeParameter = this.resolveTypeParameterDeclaration(typeParameterAST, context);
                    this.checkSymbolPrivacy(functionSymbol, typeParameter, function (symbol) {
                        return _this.functionTypeArgumentArgumentTypePrivacyErrorReporter(funcDeclAST, isStatic, typeParameterAST, typeParameter, symbol, context);
                    });
                }
            }

            // Check function parameters
            if (!isGetter && !isIndexSignature) {
                var funcParams = functionSignature.parameters;
                for (var i = 0; i < funcParams.length; i++) {
                    this.checkSymbolPrivacy(functionSymbol, funcParams[i].type, function (symbol) {
                        return _this.functionArgumentTypePrivacyErrorReporter(funcDeclAST, isStatic, parameters, i, funcParams[i], symbol, context);
                    });
                }
            }

            // Check return type
            if (!isSetter) {
                this.checkSymbolPrivacy(functionSymbol, functionSignature.returnType, function (symbol) {
                    return _this.functionReturnTypePrivacyErrorReporter(funcDeclAST, isStatic, returnTypeAnnotation, block, functionSignature.returnType, symbol, context);
                });
            }
        };

        PullTypeResolver.prototype.functionTypeArgumentArgumentTypePrivacyErrorReporter = function (declAST, isStatic, typeParameterAST, typeParameter, symbol, context) {
            var decl = this.semanticInfoChain.getDeclForAST(declAST);
            var enclosingDecl = this.getEnclosingDecl(decl);
            var enclosingSymbol = enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null;

            var isMethod = decl.kind === TypeScript.PullElementKind.Method;
            var isMethodOfClass = false;
            var declParent = decl.getParentDecl();
            if (declParent && (declParent.kind === TypeScript.PullElementKind.Class || isStatic)) {
                isMethodOfClass = true;
            }

            var typeSymbol = symbol;
            var typeSymbolName = typeSymbol.getScopedName(enclosingSymbol);
            var messageCode;
            if (typeSymbol.isContainer() && !typeSymbol.isEnum()) {
                if (!TypeScript.isQuoted(typeSymbolName)) {
                    typeSymbolName = "'" + typeSymbolName + "'";
                }

                if (decl.kind === TypeScript.PullElementKind.ConstructSignature) {
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_constructor_signature_from_exported_interface_is_using_inaccessible_module_1;
                } else if (decl.kind === TypeScript.PullElementKind.CallSignature) {
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_call_signature_from_exported_interface_is_using_inaccessible_module_1;
                } else if (isMethod) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_public_static_method_from_exported_class_is_using_inaccessible_module_1;
                    } else if (isMethodOfClass) {
                        messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_public_method_from_exported_class_is_using_inaccessible_module_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_method_from_exported_interface_is_using_inaccessible_module_1;
                    }
                } else {
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_exported_function_is_using_inaccessible_module_1;
                }
            } else {
                if (decl.kind === TypeScript.PullElementKind.ConstructSignature) {
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_type_1;
                } else if (decl.kind === TypeScript.PullElementKind.CallSignature) {
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_type_1;
                } else if (isMethod) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_type_1;
                    } else if (isMethodOfClass) {
                        messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_public_method_from_exported_class_has_or_is_using_private_type_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_method_from_exported_interface_has_or_is_using_private_type_1;
                    }
                } else {
                    messageCode = TypeScript.DiagnosticCode.TypeParameter_0_of_exported_function_has_or_is_using_private_type_1;
                }
            }

            if (messageCode) {
                var messageArgs = [typeParameter.getScopedName(enclosingSymbol, false, true), typeSymbolName];
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(typeParameterAST, messageCode, messageArgs));
            }
        };

        PullTypeResolver.prototype.functionArgumentTypePrivacyErrorReporter = function (declAST, isStatic, parameters, argIndex, paramSymbol, symbol, context) {
            var decl = this.semanticInfoChain.getDeclForAST(declAST);
            var enclosingDecl = this.getEnclosingDecl(decl);
            var enclosingSymbol = enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null;

            var isGetter = declAST.kind() === 139 /* GetAccessor */;
            var isSetter = declAST.kind() === 140 /* SetAccessor */;
            var isMethod = decl.kind === TypeScript.PullElementKind.Method;
            var isMethodOfClass = false;
            var declParent = decl.getParentDecl();
            if (declParent && (declParent.kind === TypeScript.PullElementKind.Class || isStatic)) {
                isMethodOfClass = true;
            }

            var typeSymbol = symbol;
            var typeSymbolName = typeSymbol.getScopedName(enclosingSymbol);
            var messageCode;
            if (typeSymbol.isContainer() && !typeSymbol.isEnum()) {
                if (!TypeScript.isQuoted(typeSymbolName)) {
                    typeSymbolName = "'" + typeSymbolName + "'";
                }

                if (declAST.kind() === 137 /* ConstructorDeclaration */) {
                    messageCode = TypeScript.DiagnosticCode.Parameter_0_of_constructor_from_exported_class_is_using_inaccessible_module_1;
                } else if (isSetter) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_public_static_property_setter_from_exported_class_is_using_inaccessible_module_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_public_property_setter_from_exported_class_is_using_inaccessible_module_1;
                    }
                } else if (decl.kind === TypeScript.PullElementKind.ConstructSignature) {
                    messageCode = TypeScript.DiagnosticCode.Parameter_0_of_constructor_signature_from_exported_interface_is_using_inaccessible_module_1;
                } else if (decl.kind === TypeScript.PullElementKind.CallSignature) {
                    messageCode = TypeScript.DiagnosticCode.Parameter_0_of_call_signature_from_exported_interface_is_using_inaccessible_module_1;
                } else if (isMethod) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_public_static_method_from_exported_class_is_using_inaccessible_module_1;
                    } else if (isMethodOfClass) {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_public_method_from_exported_class_is_using_inaccessible_module_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_method_from_exported_interface_is_using_inaccessible_module_1;
                    }
                } else if (!isGetter) {
                    messageCode = TypeScript.DiagnosticCode.Parameter_0_of_exported_function_is_using_inaccessible_module_1;
                }
            } else {
                if (declAST.kind() === 137 /* ConstructorDeclaration */) {
                    messageCode = TypeScript.DiagnosticCode.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_type_1;
                } else if (isSetter) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_type_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_type_1;
                    }
                } else if (decl.kind === TypeScript.PullElementKind.ConstructSignature) {
                    messageCode = TypeScript.DiagnosticCode.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_type_1;
                } else if (decl.kind === TypeScript.PullElementKind.CallSignature) {
                    messageCode = TypeScript.DiagnosticCode.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_type_1;
                } else if (isMethod) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_type_1;
                    } else if (isMethodOfClass) {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_type_1;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_type_1;
                    }
                } else if (!isGetter && decl.kind !== TypeScript.PullElementKind.IndexSignature) {
                    messageCode = TypeScript.DiagnosticCode.Parameter_0_of_exported_function_has_or_is_using_private_type_1;
                }
            }

            if (messageCode) {
                var parameter = parameters[argIndex];

                var messageArgs = [paramSymbol.getScopedName(enclosingSymbol), typeSymbolName];
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(parameter, messageCode, messageArgs));
            }
        };

        PullTypeResolver.prototype.functionReturnTypePrivacyErrorReporter = function (declAST, isStatic, returnTypeAnnotation, block, funcReturnType, symbol, context) {
            var _this = this;
            var decl = this.semanticInfoChain.getDeclForAST(declAST);
            var enclosingDecl = this.getEnclosingDecl(decl);

            var isGetter = declAST.kind() === 139 /* GetAccessor */;
            var isSetter = declAST.kind() === 140 /* SetAccessor */;
            var isMethod = decl.kind === TypeScript.PullElementKind.Method;
            var isMethodOfClass = false;
            var declParent = decl.getParentDecl();
            if (declParent && (declParent.kind === TypeScript.PullElementKind.Class || isStatic)) {
                isMethodOfClass = true;
            }

            var messageCode = null;
            var typeSymbol = symbol;
            var typeSymbolName = typeSymbol.getScopedName(enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null);
            if (typeSymbol.isContainer() && !typeSymbol.isEnum()) {
                if (!TypeScript.isQuoted(typeSymbolName)) {
                    typeSymbolName = "'" + typeSymbolName + "'";
                }

                if (isGetter) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_public_static_property_getter_from_exported_class_is_using_inaccessible_module_0;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_public_property_getter_from_exported_class_is_using_inaccessible_module_0;
                    }
                } else if (decl.kind === TypeScript.PullElementKind.ConstructSignature) {
                    messageCode = TypeScript.DiagnosticCode.Return_type_of_constructor_signature_from_exported_interface_is_using_inaccessible_module_0;
                } else if (decl.kind === TypeScript.PullElementKind.CallSignature) {
                    messageCode = TypeScript.DiagnosticCode.Return_type_of_call_signature_from_exported_interface_is_using_inaccessible_module_0;
                } else if (decl.kind === TypeScript.PullElementKind.IndexSignature) {
                    messageCode = TypeScript.DiagnosticCode.Return_type_of_index_signature_from_exported_interface_is_using_inaccessible_module_0;
                } else if (isMethod) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_public_static_method_from_exported_class_is_using_inaccessible_module_0;
                    } else if (isMethodOfClass) {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_public_method_from_exported_class_is_using_inaccessible_module_0;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_method_from_exported_interface_is_using_inaccessible_module_0;
                    }
                } else if (!isSetter && declAST.kind() !== 137 /* ConstructorDeclaration */) {
                    messageCode = TypeScript.DiagnosticCode.Return_type_of_exported_function_is_using_inaccessible_module_0;
                }
            } else {
                if (isGetter) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_type_0;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_type_0;
                    }
                } else if (decl.kind === TypeScript.PullElementKind.ConstructSignature) {
                    messageCode = TypeScript.DiagnosticCode.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_type_0;
                } else if (decl.kind === TypeScript.PullElementKind.CallSignature) {
                    messageCode = TypeScript.DiagnosticCode.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_type_0;
                } else if (decl.kind === TypeScript.PullElementKind.IndexSignature) {
                    messageCode = TypeScript.DiagnosticCode.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_type_0;
                } else if (isMethod) {
                    if (isStatic) {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_type_0;
                    } else if (isMethodOfClass) {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_public_method_from_exported_class_has_or_is_using_private_type_0;
                    } else {
                        messageCode = TypeScript.DiagnosticCode.Return_type_of_method_from_exported_interface_has_or_is_using_private_type_0;
                    }
                } else if (!isSetter && declAST.kind() !== 137 /* ConstructorDeclaration */) {
                    messageCode = TypeScript.DiagnosticCode.Return_type_of_exported_function_has_or_is_using_private_type_0;
                }
            }

            if (messageCode) {
                var messageArguments = [typeSymbolName];
                var reportOnFuncDecl = false;

                if (returnTypeAnnotation) {
                    // NOTE: we don't want to report this diagnostics.  They'll already have been
                    // reported when we first hit the return statement.
                    var returnExpressionSymbol = this.resolveTypeReference(returnTypeAnnotation, context);

                    if (TypeScript.PullHelpers.typeSymbolsAreIdentical(returnExpressionSymbol, funcReturnType)) {
                        // Error coming from return annotation
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(returnTypeAnnotation, messageCode, messageArguments));
                    }
                }

                if (block) {
                    var reportErrorOnReturnExpressions = function (ast, walker) {
                        var go = true;
                        if (TypeScript.SyntaxUtilities.isAnyFunctionExpressionOrDeclaration(ast)) {
                            // don't recurse into a function decl - we don't want to confuse a nested
                            // return type with the top-level function's return type
                            go = false;
                        } else if (ast.kind() === 150 /* ReturnStatement */) {
                            var returnStatement = ast;
                            var returnExpressionSymbol = _this.resolveAST(returnStatement.expression, false, context).type;

                            // Check if return statement's type matches the one that we concluded
                            if (TypeScript.PullHelpers.typeSymbolsAreIdentical(returnExpressionSymbol, funcReturnType)) {
                                context.postDiagnostic(_this.semanticInfoChain.diagnosticFromAST(returnStatement, messageCode, messageArguments));
                            } else {
                                reportOnFuncDecl = true;
                            }
                            go = false;
                        }

                        walker.options.goChildren = go;
                        return ast;
                    };

                    TypeScript.getAstWalkerFactory().walk(block, reportErrorOnReturnExpressions);
                }

                if (reportOnFuncDecl) {
                    // Show on function decl
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(declAST, messageCode, messageArguments));
                }
            }
        };

        PullTypeResolver.prototype.enclosingClassIsDerived = function (classDecl) {
            TypeScript.Debug.assert(classDecl.kind === TypeScript.PullElementKind.Class);

            var classSymbol = classDecl.getSymbol(this.semanticInfoChain);
            return classSymbol.getExtendedTypes().length > 0;
        };

        PullTypeResolver.prototype.isSuperInvocationExpression = function (ast) {
            if (ast.kind() === 213 /* InvocationExpression */) {
                var invocationExpression = ast;
                if (invocationExpression.expression.kind() === 50 /* SuperKeyword */) {
                    return true;
                }
            }

            return false;
        };

        PullTypeResolver.prototype.isSuperInvocationExpressionStatement = function (node) {
            if (node && node.kind() === 149 /* ExpressionStatement */) {
                var expressionStatement = node;
                if (this.isSuperInvocationExpression(expressionStatement.expression)) {
                    return true;
                }
            }
            return false;
        };

        PullTypeResolver.prototype.getFirstStatementOfBlockOrNull = function (block) {
            if (block && block.statements && block.statements.length > 0) {
                return block.statements[0];
            }

            return null;
        };

        PullTypeResolver.prototype.superCallMustBeFirstStatementInConstructor = function (constructorDecl) {
            TypeScript.Debug.assert(constructorDecl.kind === TypeScript.PullElementKind.ConstructorMethod);

            /*
            The first statement in the body of a constructor must be a super call if both of the following are true:
            ?   The containing class is a derived class.
            ?   The constructor declares parameter properties or the containing class declares instance member variables with initializers.
            In such a required super call, it is a compile-time error for argument expressions to reference this.
            */
            if (constructorDecl) {
                var enclosingClass = constructorDecl.getParentDecl();

                var classSymbol = enclosingClass.getSymbol(this.semanticInfoChain);
                if (classSymbol.getExtendedTypes().length === 0) {
                    return false;
                }

                var classMembers = classSymbol.getMembers();
                for (var i = 0, n1 = classMembers.length; i < n1; i++) {
                    var member = classMembers[i];

                    if (member.kind === TypeScript.PullElementKind.Property) {
                        var declarations = member.getDeclarations();
                        for (var j = 0, n2 = declarations.length; j < n2; j++) {
                            var declaration = declarations[j];
                            var ast = this.semanticInfoChain.getASTForDecl(declaration);
                            if (ast.kind() === 242 /* Parameter */) {
                                return true;
                            }

                            if (ast.kind() === 136 /* MemberVariableDeclaration */) {
                                var variableDeclarator = ast;
                                if (variableDeclarator.variableDeclarator.equalsValueClause) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }

            return false;
        };

        PullTypeResolver.prototype.checkForThisCaptureInArrowFunction = function (expression) {
            var enclosingDecl = this.getEnclosingDeclForAST(expression);

            var declPath = enclosingDecl.getParentPath();

            // work back up the decl path, until you can find a class
            // PULLTODO: Obviously not completely correct, but this sufficiently unblocks testing of the pull model
            if (declPath.length) {
                var inArrowFunction = false;
                for (var i = declPath.length - 1; i >= 0; i--) {
                    var decl = declPath[i];
                    var declKind = decl.kind;
                    var declFlags = decl.flags;

                    if (declKind === TypeScript.PullElementKind.FunctionExpression && TypeScript.hasFlag(declFlags, TypeScript.PullElementFlags.ArrowFunction)) {
                        inArrowFunction = true;
                        continue;
                    }

                    if (inArrowFunction) {
                        if (declKind === TypeScript.PullElementKind.Function || declKind === TypeScript.PullElementKind.Method || declKind === TypeScript.PullElementKind.ConstructorMethod || declKind === TypeScript.PullElementKind.GetAccessor || declKind === TypeScript.PullElementKind.SetAccessor || declKind === TypeScript.PullElementKind.FunctionExpression || declKind === TypeScript.PullElementKind.Class || declKind === TypeScript.PullElementKind.Container || declKind === TypeScript.PullElementKind.DynamicModule || declKind === TypeScript.PullElementKind.Script) {
                            decl.setFlags(decl.flags | TypeScript.PullElementFlags.MustCaptureThis);

                            // If we're accessing 'this' in a class, then the class constructor
                            // needs to be marked as capturing 'this'.
                            if (declKind === TypeScript.PullElementKind.Class) {
                                var constructorSymbol = decl.getSymbol(this.semanticInfoChain).getConstructorMethod();
                                var constructorDecls = constructorSymbol.getDeclarations();
                                for (var i = 0; i < constructorDecls.length; i++) {
                                    constructorDecls[i].flags = constructorDecls[i].flags | TypeScript.PullElementFlags.MustCaptureThis;
                                }
                            }
                            break;
                        }
                    } else if (declKind === TypeScript.PullElementKind.Function || declKind === TypeScript.PullElementKind.FunctionExpression) {
                        break;
                    }
                }
            }
        };

        PullTypeResolver.prototype.typeCheckMembersAgainstIndexer = function (containerType, containerTypeDecl, context) {
            // Check all the members defined in this symbol's declarations (no base classes)
            var indexSignatures = this.getBothKindsOfIndexSignaturesExcludingAugmentedType(containerType, context);
            var stringSignature = indexSignatures.stringSignature;
            var numberSignature = indexSignatures.numericSignature;

            if (stringSignature || numberSignature) {
                var members = containerTypeDecl.getChildDecls();
                for (var i = 0; i < members.length; i++) {
                    // Make sure the member is actually contained by the containerType, and not its associated constructor type
                    var member = members[i];
                    if ((member.name || (member.kind === TypeScript.PullElementKind.Property && member.name === "")) && member.kind !== TypeScript.PullElementKind.ConstructorMethod && !TypeScript.hasFlag(member.flags, TypeScript.PullElementFlags.Static)) {
                        // Decide whether to check against the number or string signature
                        var memberSymbol = member.getSymbol(this.semanticInfoChain);
                        var relevantSignature = this.determineRelevantIndexerForMember(memberSymbol, numberSignature, stringSignature);
                        if (relevantSignature) {
                            var comparisonInfo = new TypeComparisonInfo();
                            if (!this.sourceIsAssignableToTarget(memberSymbol.type, relevantSignature.returnType, member.ast(), context, comparisonInfo)) {
                                this.reportErrorThatMemberIsNotSubtypeOfIndexer(memberSymbol, relevantSignature, member.ast(), context, comparisonInfo);
                            }
                        }
                    }
                }
            }
        };

        PullTypeResolver.prototype.determineRelevantIndexerForMember = function (member, numberIndexSignature, stringIndexSignature) {
            if (numberIndexSignature && TypeScript.PullHelpers.isNameNumeric(member.name)) {
                return numberIndexSignature;
            } else if (stringIndexSignature) {
                return stringIndexSignature;
            }

            return null;
        };

        PullTypeResolver.prototype.reportErrorThatMemberIsNotSubtypeOfIndexer = function (member, indexSignature, astForError, context, comparisonInfo) {
            var enclosingSymbol = this.getEnclosingSymbolForAST(astForError);

            if (indexSignature.parameters[0].type === this.semanticInfoChain.numberTypeSymbol) {
                if (comparisonInfo.message) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(astForError, TypeScript.DiagnosticCode.All_numerically_named_properties_must_be_assignable_to_numeric_indexer_type_0_NL_1, [indexSignature.returnType.toString(enclosingSymbol), comparisonInfo.message]));
                } else {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(astForError, TypeScript.DiagnosticCode.All_numerically_named_properties_must_be_assignable_to_numeric_indexer_type_0, [indexSignature.returnType.toString(enclosingSymbol)]));
                }
            } else {
                if (comparisonInfo.message) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(astForError, TypeScript.DiagnosticCode.All_named_properties_must_be_assignable_to_string_indexer_type_0_NL_1, [indexSignature.returnType.toString(enclosingSymbol), comparisonInfo.message]));
                } else {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(astForError, TypeScript.DiagnosticCode.All_named_properties_must_be_assignable_to_string_indexer_type_0, [indexSignature.returnType.toString(enclosingSymbol)]));
                }
            }
        };

        PullTypeResolver.prototype.typeCheckIfTypeMemberPropertyOkToOverride = function (typeSymbol, extendedType, typeMember, extendedTypeMember, enclosingDecl, comparisonInfo) {
            if (!typeSymbol.isClass()) {
                return true;
            }

            var typeMemberKind = typeMember.kind;
            var extendedMemberKind = extendedTypeMember.kind;

            if (typeMemberKind === extendedMemberKind) {
                return true;
            }

            var errorCode;
            if (typeMemberKind === TypeScript.PullElementKind.Property) {
                if (typeMember.isAccessor()) {
                    errorCode = TypeScript.DiagnosticCode.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
                } else {
                    errorCode = TypeScript.DiagnosticCode.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
                }
            } else if (typeMemberKind === TypeScript.PullElementKind.Method) {
                if (extendedTypeMember.isAccessor()) {
                    errorCode = TypeScript.DiagnosticCode.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
                } else {
                    errorCode = TypeScript.DiagnosticCode.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property;
                }
            }

            var message = TypeScript.getDiagnosticMessage(errorCode, [typeSymbol.toString(), typeMember.getScopedNameEx().toString(), extendedType.toString()]);
            comparisonInfo.addMessage(message);
            return false;
        };

        PullTypeResolver.prototype.typeCheckIfTypeExtendsType = function (classOrInterface, name, typeSymbol, extendedType, enclosingDecl, context) {
            var typeMembers = typeSymbol.getMembers();

            var comparisonInfo = new TypeComparisonInfo();
            var foundError = false;
            var foundError1 = false;
            var foundError2 = false;

            for (var i = 0; i < typeMembers.length; i++) {
                var propName = typeMembers[i].name;
                var extendedTypeProp = extendedType.findMember(propName, true);
                if (extendedTypeProp) {
                    this.resolveDeclaredSymbol(extendedTypeProp, context);
                    foundError1 = !this.typeCheckIfTypeMemberPropertyOkToOverride(typeSymbol, extendedType, typeMembers[i], extendedTypeProp, enclosingDecl, comparisonInfo);

                    if (!foundError1) {
                        foundError2 = !this.sourcePropertyIsAssignableToTargetProperty(typeSymbol, extendedType, typeMembers[i], extendedTypeProp, classOrInterface, context, comparisonInfo);
                    }

                    if (foundError1 || foundError2) {
                        foundError = true;
                        break;
                    }
                }
            }

            // Check call signatures
            if (!foundError && typeSymbol.hasOwnCallSignatures()) {
                foundError = !this.sourceCallSignaturesAreAssignableToTargetCallSignatures(typeSymbol, extendedType, classOrInterface, context, comparisonInfo);
            }

            // Check construct signatures
            if (!foundError && typeSymbol.hasOwnConstructSignatures()) {
                foundError = !this.sourceConstructSignaturesAreAssignableToTargetConstructSignatures(typeSymbol, extendedType, classOrInterface, context, comparisonInfo);
            }

            // Check index signatures
            if (!foundError && typeSymbol.hasOwnIndexSignatures()) {
                foundError = !this.sourceIndexSignaturesAreAssignableToTargetIndexSignatures(typeSymbol, extendedType, classOrInterface, context, comparisonInfo);
            }

            if (!foundError && typeSymbol.isClass()) {
                // If there is base class verify the constructor type is subtype of base class
                var typeConstructorType = typeSymbol.getConstructorMethod().type;
                var typeConstructorTypeMembers = typeConstructorType.getMembers();
                if (typeConstructorTypeMembers.length) {
                    var extendedConstructorType = extendedType.getConstructorMethod().type;
                    var comparisonInfoForPropTypeCheck = new TypeComparisonInfo(comparisonInfo);

                    for (var i = 0; i < typeConstructorTypeMembers.length; i++) {
                        var propName = typeConstructorTypeMembers[i].name;
                        var extendedConstructorTypeProp = extendedConstructorType.findMember(propName, true);
                        if (extendedConstructorTypeProp) {
                            if (!extendedConstructorTypeProp.isResolved) {
                                this.resolveDeclaredSymbol(extendedConstructorTypeProp, context);
                            }

                            if (!this.sourcePropertyIsAssignableToTargetProperty(typeConstructorType, extendedConstructorType, typeConstructorTypeMembers[i], extendedConstructorTypeProp, classOrInterface, context, comparisonInfo)) {
                                foundError = true;
                                break;
                            }
                        }
                    }
                }
            }

            if (foundError) {
                var errorCode;
                if (typeSymbol.isClass()) {
                    errorCode = TypeScript.DiagnosticCode.Class_0_cannot_extend_class_1_NL_2;
                } else {
                    if (extendedType.isClass()) {
                        errorCode = TypeScript.DiagnosticCode.Interface_0_cannot_extend_class_1_NL_2;
                    } else {
                        errorCode = TypeScript.DiagnosticCode.Interface_0_cannot_extend_interface_1_NL_2;
                    }
                }

                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(name, errorCode, [typeSymbol.getScopedName(), extendedType.getScopedName(), comparisonInfo.message]));
            }
        };

        PullTypeResolver.prototype.typeCheckIfClassImplementsType = function (classDecl, classSymbol, implementedType, enclosingDecl, context) {
            var comparisonInfo = new TypeComparisonInfo();
            var foundError = !this.sourceMembersAreAssignableToTargetMembers(classSymbol, implementedType, classDecl, context, comparisonInfo);
            if (!foundError) {
                foundError = !this.sourceCallSignaturesAreAssignableToTargetCallSignatures(classSymbol, implementedType, classDecl, context, comparisonInfo);
                if (!foundError) {
                    foundError = !this.sourceConstructSignaturesAreAssignableToTargetConstructSignatures(classSymbol, implementedType, classDecl, context, comparisonInfo);
                    if (!foundError) {
                        foundError = !this.sourceIndexSignaturesAreAssignableToTargetIndexSignatures(classSymbol, implementedType, classDecl, context, comparisonInfo);
                    }
                }
            }

            // Report error
            if (foundError) {
                var enclosingSymbol = this.getEnclosingSymbolForAST(classDecl);
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(classDecl.identifier, TypeScript.DiagnosticCode.Class_0_declares_interface_1_but_does_not_implement_it_NL_2, [classSymbol.getScopedName(enclosingSymbol), implementedType.getScopedName(enclosingSymbol), comparisonInfo.message]));
            }
        };

        PullTypeResolver.prototype.computeValueSymbolFromAST = function (valueDeclAST, context) {
            // Disable type check because we do not want to report errors about missing symbols when resolving the
            // expression as the value expression
            var prevInTypeCheck = context.inTypeCheck;
            context.inTypeCheck = false;

            var typeSymbolAlias = this.semanticInfoChain.getAliasSymbolForAST(valueDeclAST);

            if (valueDeclAST.kind() == 11 /* IdentifierName */) {
                var valueSymbol = this.computeNameExpression(valueDeclAST, context);
            } else {
                TypeScript.Debug.assert(valueDeclAST.kind() == 121 /* QualifiedName */);
                var qualifiedName = valueDeclAST;

                // Compute lhs so we can compute dotted expression of the lhs.
                // We cant directly resolve this expression because otherwise we would end up using cached value of lhs
                // and that might not be the right one when resolving this expression as value expression
                var lhs = this.computeValueSymbolFromAST(qualifiedName.left, context);
                var valueSymbol = this.computeDottedNameExpressionFromLHS(lhs.symbol, qualifiedName.left, qualifiedName.right, context, false);
            }
            var valueSymbolAlias = this.semanticInfoChain.getAliasSymbolForAST(valueDeclAST);

            // Reset the alias value
            this.semanticInfoChain.setAliasSymbolForAST(valueDeclAST, typeSymbolAlias);
            context.inTypeCheck = prevInTypeCheck;

            return { symbol: valueSymbol, alias: valueSymbolAlias };
        };

        PullTypeResolver.prototype.hasClassTypeSymbolConflictAsValue = function (baseDeclAST, typeSymbol, enclosingDecl, context) {
            var typeSymbolAlias = this.semanticInfoChain.getAliasSymbolForAST(baseDeclAST);

            var valueDeclAST = baseDeclAST.kind() == 126 /* GenericType */ ? baseDeclAST.name : baseDeclAST;
            var valueSymbolInfo = this.computeValueSymbolFromAST(valueDeclAST, context);
            var valueSymbol = valueSymbolInfo.symbol;
            var valueSymbolAlias = valueSymbolInfo.alias;

            // If aliases are same
            if (typeSymbolAlias && valueSymbolAlias) {
                return typeSymbolAlias !== valueSymbolAlias;
            }

            // Verify if value refers to same class;
            if (!valueSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.ClassConstructorVariable)) {
                return true;
            }

            var associatedContainerType = valueSymbol.type ? valueSymbol.type.getAssociatedContainerType() : null;

            if (associatedContainerType) {
                // We may have specialized the typeSymbol to any for error recovery, as in the following example:
                // class A<T> { }
                // class B extends A { }
                // Since A was not given type arguments (which is an error), we may have specialized it to any, in which case A<any> != A<T>.
                // So we need to compare associatedContainerType to the rootSymbol (the unspecialized version) of typeSymbol
                return associatedContainerType !== typeSymbol.getRootSymbol();
            }

            return true;
        };

        PullTypeResolver.prototype.typeCheckBase = function (classOrInterface, name, typeSymbol, baseDeclAST, isExtendedType, enclosingDecl, context) {
            var _this = this;
            var typeDecl = this.semanticInfoChain.getDeclForAST(classOrInterface);

            var baseType = this.resolveTypeReference(baseDeclAST, context).type;

            if (!baseType) {
                return;
            }

            var typeDeclIsClass = typeSymbol.isClass();

            if (!typeSymbol.isValidBaseKind(baseType, isExtendedType)) {
                // Report error about invalid base kind
                if (!baseType.isError()) {
                    if (isExtendedType) {
                        if (typeDeclIsClass) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(baseDeclAST, TypeScript.DiagnosticCode.A_class_may_only_extend_another_class));
                        } else {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(baseDeclAST, TypeScript.DiagnosticCode.An_interface_may_only_extend_a_class_or_another_interface));
                        }
                    } else {
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(baseDeclAST, TypeScript.DiagnosticCode.A_class_may_only_implement_another_class_or_interface));
                    }
                }
                return;
            } else if (typeDeclIsClass && isExtendedType) {
                // Verify if the class extends another class verify the value position resolves to the same type expression
                if (this.hasClassTypeSymbolConflictAsValue(baseDeclAST, baseType, enclosingDecl, context)) {
                    // Report error
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(baseDeclAST, TypeScript.DiagnosticCode.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_1, [TypeScript.ASTHelpers.getNameOfIdenfierOrQualifiedName(baseDeclAST.kind() == 126 /* GenericType */ ? baseDeclAST.name : baseDeclAST), baseType.toString(enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null)]));
                }
            }

            // Check if its a recursive extend/implement type
            if (baseType.hasBase(typeSymbol)) {
                typeSymbol.setHasBaseTypeConflict();
                baseType.setHasBaseTypeConflict();

                // Report error
                context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(name, TypeScript.DiagnosticCode.Type_0_recursively_references_itself_as_a_base_type, [typeSymbol.getScopedName()]));
                return;
            }

            if (isExtendedType) {
                // Verify all own overriding members are subtype
                this.typeCheckCallBacks.push(function (context) {
                    return _this.typeCheckIfTypeExtendsType(classOrInterface, name, typeSymbol, baseType, enclosingDecl, context);
                });
            } else {
                TypeScript.Debug.assert(classOrInterface.kind() === 131 /* ClassDeclaration */);

                // If class implementes interface or class, verify all the public members are implemented
                this.typeCheckCallBacks.push(function (context) {
                    return _this.typeCheckIfClassImplementsType(classOrInterface, typeSymbol, baseType, enclosingDecl, context);
                });
            }

            // Privacy error:
            this.checkSymbolPrivacy(typeSymbol, baseType, function (errorSymbol) {
                return _this.baseListPrivacyErrorReporter(classOrInterface, typeSymbol, baseDeclAST, isExtendedType, errorSymbol, context);
            });
        };

        PullTypeResolver.prototype.typeCheckBases = function (classOrInterface, name, heritageClauses, typeSymbol, enclosingDecl, context) {
            var _this = this;
            var extendsClause = TypeScript.ASTHelpers.getExtendsHeritageClause(heritageClauses);
            var implementsClause = TypeScript.ASTHelpers.getImplementsHeritageClause(heritageClauses);
            if (!extendsClause && !implementsClause) {
                return;
            }

            if (extendsClause) {
                for (var i = 0; i < extendsClause.typeNames.length; i++) {
                    this.typeCheckBase(classOrInterface, name, typeSymbol, extendsClause.typeNames[i], true, enclosingDecl, context);
                }
            }

            if (typeSymbol.isClass()) {
                if (implementsClause) {
                    for (var i = 0; i < implementsClause.typeNames.length; i++) {
                        this.typeCheckBase(classOrInterface, name, typeSymbol, implementsClause.typeNames[i], false, enclosingDecl, context);
                    }
                }
            } else if (extendsClause && !typeSymbol.hasBaseTypeConflict() && typeSymbol.getExtendedTypes().length > 1) {
                // October 16, 2013: Section 7.1:
                // Inherited properties with the same name must be identical (section 3.8.2).
                // If it is an interface it can extend multiple base types. We need to check for clashes
                // between inherited properties with the same name, per the spec. Note that we only do this
                // once per symbol, not once per declaration. We use the first declaration that has an
                // extends clause. Here is an example:
                // interface A {
                //    m: string;
                // }
                // interface B {
                //    m: number;
                // }
                // interface C extends A {}
                // interface C extends B {}
                // Here, we only report the error on the first C, because it is the first declaration
                // that has an extends clause. Since an interface cannot have an implements clause
                // (by the grammar) we only have to check that it has a heritage clause.
                var firstInterfaceASTWithExtendsClause = TypeScript.ArrayUtilities.firstOrDefault(typeSymbol.getDeclarations(), function (decl) {
                    return decl.ast().heritageClauses !== null;
                }).ast();
                if (classOrInterface === firstInterfaceASTWithExtendsClause) {
                    // Checking type compatibility between bases requires knowing the types of all
                    // base type members. Therefore, we have to delay this operation until all
                    // resolution has taken place. Doing the check immediately may cause a recursive
                    // resolution that results in a rogue "any".
                    this.typeCheckCallBacks.push(function (context) {
                        _this.checkTypeCompatibilityBetweenBases(classOrInterface.identifier, typeSymbol, context);
                    });
                }
            }
        };

        PullTypeResolver.prototype.checkTypeCompatibilityBetweenBases = function (name, typeSymbol, context) {
            // The membersBag will map each member name to its type and which base type we got it from
            var derivedIndexSignatures = typeSymbol.getOwnIndexSignatures();

            var inheritedMembersMap = TypeScript.createIntrinsicsObject();
            var inheritedIndexSignatures = new InheritedIndexSignatureInfo();

            var typeHasOwnNumberIndexer = false;
            var typeHasOwnStringIndexer = false;

            // Determine if this type has any index signatures of its own
            if (typeSymbol.hasOwnIndexSignatures()) {
                var ownIndexSignatures = typeSymbol.getOwnIndexSignatures();
                for (var i = 0; i < ownIndexSignatures.length; i++) {
                    if (ownIndexSignatures[i].parameters[0].type === this.semanticInfoChain.numberTypeSymbol) {
                        typeHasOwnNumberIndexer = true;
                    } else {
                        typeHasOwnStringIndexer = true;
                    }
                }
            }
            var baseTypes = typeSymbol.getExtendedTypes();
            for (var i = 0; i < baseTypes.length; i++) {
                // Check the member identity and the index signature identity between this base
                // and bases checked so far. Only report the first error.
                if (this.checkNamedPropertyIdentityBetweenBases(name, typeSymbol, baseTypes[i], inheritedMembersMap, context) || this.checkIndexSignatureIdentityBetweenBases(name, typeSymbol, baseTypes[i], inheritedIndexSignatures, typeHasOwnNumberIndexer, typeHasOwnStringIndexer, context)) {
                    return;
                }
            }

            // Check that number indexer is a subtype of the string indexer. If that check succeeds,
            // check all the inherited members against the relevant signature
            if (this.checkThatInheritedNumberSignatureIsSubtypeOfInheritedStringSignature(name, typeSymbol, inheritedIndexSignatures, context)) {
                return;
            }

            this.checkInheritedMembersAgainstInheritedIndexSignatures(name, typeSymbol, inheritedIndexSignatures, inheritedMembersMap, context);
        };

        // This method returns true if there was an error given, and false if there was no error.
        // The boolean value is used by the caller for short circuiting.
        PullTypeResolver.prototype.checkNamedPropertyIdentityBetweenBases = function (interfaceName, interfaceSymbol, baseTypeSymbol, inheritedMembersMap, context) {
            // October 16, 2013: Section 7.1:
            // Inherited properties with the same name must be identical (section 3.8.2).
            var baseMembers = baseTypeSymbol.getAllMembers(TypeScript.PullElementKind.Property | TypeScript.PullElementKind.Method, 0 /* all */);
            for (var i = 0; i < baseMembers.length; i++) {
                var member = baseMembers[i];
                var memberName = member.name;

                // Skip the member if it is shadowed in the derived type
                if (interfaceSymbol.findMember(memberName, false)) {
                    continue;
                }

                this.resolveDeclaredSymbol(member, context);

                // Error if there is already a member in the bag with that name, and it is not identical
                if (inheritedMembersMap[memberName]) {
                    var prevMember = inheritedMembersMap[memberName];
                    if (prevMember.baseOrigin !== baseTypeSymbol && !this.propertiesAreIdenticalWithNewEnclosingTypes(baseTypeSymbol, prevMember.baseOrigin, member, prevMember.memberSymbol, context)) {
                        var innerDiagnostic = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Named_properties_0_of_types_1_and_2_are_not_identical, [memberName, prevMember.baseOrigin.getScopedName(), baseTypeSymbol.getScopedName()]);
                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(interfaceName, TypeScript.DiagnosticCode.Interface_0_cannot_simultaneously_extend_types_1_and_2_NL_3, [interfaceSymbol.getDisplayName(), prevMember.baseOrigin.getScopedName(), baseTypeSymbol.getScopedName(), innerDiagnostic]));
                        return true;
                    }
                } else {
                    inheritedMembersMap[memberName] = new MemberWithBaseOrigin(member, baseTypeSymbol);
                }
            }

            return false;
        };

        // This method returns true if there was an error given, and false if there was no error.
        // The boolean value is used by the caller for short circuiting.
        PullTypeResolver.prototype.checkIndexSignatureIdentityBetweenBases = function (interfaceName, interfaceSymbol, baseTypeSymbol, allInheritedSignatures, derivedTypeHasOwnNumberSignature, derivedTypeHasOwnStringSignature, context) {
            if (derivedTypeHasOwnNumberSignature && derivedTypeHasOwnStringSignature) {
                return false;
            }

            // October 16, 2013:
            // Section 3.7.4:
            // An object type can contain at most one string index signature and one numeric index signature.
            var indexSignaturesFromThisBaseType = baseTypeSymbol.getIndexSignatures();
            for (var i = 0; i < indexSignaturesFromThisBaseType.length; i++) {
                var currentInheritedSignature = indexSignaturesFromThisBaseType[i];

                var parameterTypeIsString = currentInheritedSignature.parameters[0].type === this.semanticInfoChain.stringTypeSymbol;
                var parameterTypeIsNumber = currentInheritedSignature.parameters[0].type === this.semanticInfoChain.numberTypeSymbol;

                // Skip the signature if it is shadowed in the derived type
                if (parameterTypeIsString && derivedTypeHasOwnStringSignature || parameterTypeIsNumber && derivedTypeHasOwnNumberSignature) {
                    continue;
                }

                // Now error if there is already an inherited signature of the same kind as this one
                if (parameterTypeIsString) {
                    if (allInheritedSignatures.stringSignatureWithBaseOrigin) {
                        if (allInheritedSignatures.stringSignatureWithBaseOrigin.baseOrigin !== baseTypeSymbol && !this.typesAreIdentical(allInheritedSignatures.stringSignatureWithBaseOrigin.signature.returnType, currentInheritedSignature.returnType, context)) {
                            var innerDiagnostic = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Types_of_string_indexer_of_types_0_and_1_are_not_identical, [allInheritedSignatures.stringSignatureWithBaseOrigin.baseOrigin.getScopedName(), baseTypeSymbol.getScopedName()]);
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(interfaceName, TypeScript.DiagnosticCode.Interface_0_cannot_simultaneously_extend_types_1_and_2_NL_3, [interfaceSymbol.getDisplayName(), allInheritedSignatures.stringSignatureWithBaseOrigin.baseOrigin.getScopedName(), baseTypeSymbol.getScopedName(), innerDiagnostic]));
                            return true;
                        }
                    } else {
                        allInheritedSignatures.stringSignatureWithBaseOrigin = new SignatureWithBaseOrigin(currentInheritedSignature, baseTypeSymbol);
                    }
                } else if (parameterTypeIsNumber) {
                    if (allInheritedSignatures.numberSignatureWithBaseOrigin) {
                        if (allInheritedSignatures.numberSignatureWithBaseOrigin.baseOrigin !== baseTypeSymbol && !this.typesAreIdentical(allInheritedSignatures.numberSignatureWithBaseOrigin.signature.returnType, currentInheritedSignature.returnType, context)) {
                            var innerDiagnostic = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Types_of_number_indexer_of_types_0_and_1_are_not_identical, [allInheritedSignatures.numberSignatureWithBaseOrigin.baseOrigin.getScopedName(), baseTypeSymbol.getScopedName()]);
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(interfaceName, TypeScript.DiagnosticCode.Interface_0_cannot_simultaneously_extend_types_1_and_2_NL_3, [interfaceSymbol.getDisplayName(), allInheritedSignatures.numberSignatureWithBaseOrigin.baseOrigin.getScopedName(), baseTypeSymbol.getScopedName(), innerDiagnostic]));
                            return true;
                        }
                    } else {
                        allInheritedSignatures.numberSignatureWithBaseOrigin = new SignatureWithBaseOrigin(currentInheritedSignature, baseTypeSymbol);
                    }
                }
            }

            return false;
        };

        // This method returns true if there was an error given, and false if there was no error.
        // The boolean value is used by the caller for short circuiting.
        PullTypeResolver.prototype.checkInheritedMembersAgainstInheritedIndexSignatures = function (interfaceName, interfaceSymbol, inheritedIndexSignatures, inheritedMembers, context) {
            if (!inheritedIndexSignatures.stringSignatureWithBaseOrigin && !inheritedIndexSignatures.numberSignatureWithBaseOrigin) {
                return false;
            }

            // Now check that each named member is a subtype of its corresponding index signature type
            // October 16, 2013: Section 7.1:
            // All properties of the interface must satisfy the constraints implied by the index
            // signatures of the interface as specified in section 3.7.4.
            var comparisonInfo = new TypeComparisonInfo();
            var stringSignature = inheritedIndexSignatures.stringSignatureWithBaseOrigin && inheritedIndexSignatures.stringSignatureWithBaseOrigin.signature;
            var numberSignature = inheritedIndexSignatures.numberSignatureWithBaseOrigin && inheritedIndexSignatures.numberSignatureWithBaseOrigin.signature;
            for (var memberName in inheritedMembers) {
                var memberWithBaseOrigin = inheritedMembers[memberName];
                if (!memberWithBaseOrigin) {
                    continue;
                }

                var relevantSignature = this.determineRelevantIndexerForMember(memberWithBaseOrigin.memberSymbol, numberSignature, stringSignature);
                if (!relevantSignature) {
                    continue;
                }

                var relevantSignatureIsNumberSignature = relevantSignature.parameters[0].type === this.semanticInfoChain.numberTypeSymbol;
                var signatureBaseOrigin = relevantSignatureIsNumberSignature ? inheritedIndexSignatures.numberSignatureWithBaseOrigin.baseOrigin : inheritedIndexSignatures.stringSignatureWithBaseOrigin.baseOrigin;

                if (signatureBaseOrigin === memberWithBaseOrigin.baseOrigin) {
                    continue;
                }

                var memberIsSubtype = this.sourceIsAssignableToTarget(memberWithBaseOrigin.memberSymbol.type, relevantSignature.returnType, interfaceName, context, comparisonInfo);

                if (!memberIsSubtype) {
                    var enclosingSymbol = this.getEnclosingSymbolForAST(interfaceName);
                    if (relevantSignatureIsNumberSignature) {
                        var innerDiagnostic = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Type_of_property_0_in_type_1_is_not_assignable_to_number_indexer_type_in_type_2_NL_3, [memberName, memberWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), inheritedIndexSignatures.numberSignatureWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), comparisonInfo.message]);

                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(interfaceName, TypeScript.DiagnosticCode.Interface_0_cannot_simultaneously_extend_types_1_and_2_NL_3, [interfaceSymbol.getDisplayName(enclosingSymbol), memberWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), inheritedIndexSignatures.numberSignatureWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), innerDiagnostic]));
                    } else {
                        var innerDiagnostic = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Type_of_property_0_in_type_1_is_not_assignable_to_string_indexer_type_in_type_2_NL_3, [memberName, memberWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), inheritedIndexSignatures.stringSignatureWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), comparisonInfo.message]);

                        context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(interfaceName, TypeScript.DiagnosticCode.Interface_0_cannot_simultaneously_extend_types_1_and_2_NL_3, [interfaceSymbol.getDisplayName(enclosingSymbol), memberWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), inheritedIndexSignatures.stringSignatureWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), innerDiagnostic]));
                    }
                    return true;
                }
            }

            return false;
        };

        // This function assumes that we have neither a derived string indexer nor a derived
        // number indexer
        PullTypeResolver.prototype.checkThatInheritedNumberSignatureIsSubtypeOfInheritedStringSignature = function (interfaceName, interfaceSymbol, inheritedIndexSignatures, context) {
            if (inheritedIndexSignatures.numberSignatureWithBaseOrigin && inheritedIndexSignatures.stringSignatureWithBaseOrigin) {
                // If they originate in the same base, a separate error would have been reported
                if (inheritedIndexSignatures.numberSignatureWithBaseOrigin.baseOrigin === inheritedIndexSignatures.stringSignatureWithBaseOrigin.baseOrigin) {
                    return false;
                }

                var comparisonInfo = new TypeComparisonInfo();
                var signatureIsSubtype = this.sourceIsAssignableToTarget(inheritedIndexSignatures.numberSignatureWithBaseOrigin.signature.returnType, inheritedIndexSignatures.stringSignatureWithBaseOrigin.signature.returnType, interfaceName, context, comparisonInfo);

                if (!signatureIsSubtype) {
                    var enclosingSymbol = this.getEnclosingSymbolForAST(interfaceName);
                    var innerDiagnostic = TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Type_of_number_indexer_in_type_0_is_not_assignable_to_string_indexer_type_in_type_1_NL_2, [
                        inheritedIndexSignatures.numberSignatureWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol),
                        inheritedIndexSignatures.stringSignatureWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), comparisonInfo.message]);
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(interfaceName, TypeScript.DiagnosticCode.Interface_0_cannot_simultaneously_extend_types_1_and_2_NL_3, [
                        interfaceSymbol.getDisplayName(enclosingSymbol), inheritedIndexSignatures.numberSignatureWithBaseOrigin.baseOrigin.getScopedName(),
                        inheritedIndexSignatures.stringSignatureWithBaseOrigin.baseOrigin.getScopedName(enclosingSymbol), innerDiagnostic]));
                    return true;
                }
            }

            return false;
        };

        PullTypeResolver.prototype.checkAssignability = function (ast, source, target, context) {
            var comparisonInfo = new TypeComparisonInfo();

            var isAssignable = this.sourceIsAssignableToTarget(source, target, ast, context, comparisonInfo);

            if (!isAssignable) {
                var enclosingSymbol = this.getEnclosingSymbolForAST(ast);
                if (comparisonInfo.message) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1_NL_2, [source.toString(enclosingSymbol), target.toString(enclosingSymbol), comparisonInfo.message]));
                } else {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(ast, TypeScript.DiagnosticCode.Type_0_is_not_assignable_to_type_1, [source.toString(enclosingSymbol), target.toString(enclosingSymbol)]));
                }
            }
        };

        PullTypeResolver.prototype.isReference = function (ast, astSymbol) {
            // November 18, 2013
            // References are the subset of expressions that are permitted as the target of an
            // assignment.Specifically, references are combinations of identifiers(section 4.3),
            // parentheses(section 4.7), and property accesses(section 4.10).All other expression
            //  constructs described in this chapter are classified as values.
            if (ast.kind() === 217 /* ParenthesizedExpression */) {
                // A parenthesized LHS is valid if the expression it wraps is valid.
                return this.isReference(ast.expression, astSymbol);
            }

            if (ast.kind() !== 11 /* IdentifierName */ && ast.kind() !== 212 /* MemberAccessExpression */ && ast.kind() !== 221 /* ElementAccessExpression */) {
                return false;
            }

            // November 18, 2013
            // An identifier expression that references a variable or parameter is classified as a reference.
            // An identifier expression that references any other kind of entity is classified as a value(and therefore cannot be the target of an assignment).
            if (ast.kind() === 11 /* IdentifierName */) {
                if (astSymbol.kind === TypeScript.PullElementKind.Variable && astSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.Enum)) {
                    return false;
                }

                if (astSymbol.kind === TypeScript.PullElementKind.Variable && astSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.SomeInitializedModule)) {
                    return false;
                }

                if (astSymbol.kind === TypeScript.PullElementKind.ConstructorMethod || astSymbol.kind === TypeScript.PullElementKind.Function) {
                    return false;
                }
            }

            // Disallow assignment to an enum member (NOTE: not reflected in spec).
            if (ast.kind() === 212 /* MemberAccessExpression */ && astSymbol.kind === TypeScript.PullElementKind.EnumMember) {
                return false;
            }

            return true;
        };

        PullTypeResolver.prototype.checkForSuperMemberAccess = function (expression, name, resolvedName, context) {
            if (resolvedName) {
                if (expression.kind() === 50 /* SuperKeyword */ && !resolvedName.isError() && resolvedName.kind !== TypeScript.PullElementKind.Method) {
                    context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(name, TypeScript.DiagnosticCode.Only_public_methods_of_the_base_class_are_accessible_via_the_super_keyword));
                    return true;
                }
            }

            return false;
        };

        PullTypeResolver.prototype.getEnclosingDeclForAST = function (ast) {
            return this.semanticInfoChain.getEnclosingDecl(ast);
        };

        PullTypeResolver.prototype.getEnclosingSymbolForAST = function (ast) {
            var enclosingDecl = this.getEnclosingDeclForAST(ast);
            return enclosingDecl ? enclosingDecl.getSymbol(this.semanticInfoChain) : null;
        };

        PullTypeResolver.prototype.checkForPrivateMemberAccess = function (name, expressionType, resolvedName, context) {
            if (resolvedName) {
                if (resolvedName.anyDeclHasFlag(TypeScript.PullElementFlags.Private)) {
                    var memberContainer = resolvedName.getContainer();
                    if (memberContainer && memberContainer.kind === TypeScript.PullElementKind.ConstructorType) {
                        memberContainer = memberContainer.getAssociatedContainerType();
                    }

                    if (memberContainer && memberContainer.isClass()) {
                        // We're accessing a private member of a class.  We can only do that if we're
                        // actually contained within that class.
                        var memberClass = memberContainer.getDeclarations()[0].ast();
                        TypeScript.Debug.assert(memberClass);

                        var containingClass = this.getEnclosingClassDeclaration(name);

                        if (!containingClass || containingClass !== memberClass) {
                            context.postDiagnostic(this.semanticInfoChain.diagnosticFromAST(name, TypeScript.DiagnosticCode._0_1_is_inaccessible, [memberContainer.toString(null, false), name.text()]));
                            return true;
                        }
                    }
                }
            }

            return false;
        };

        PullTypeResolver.prototype.instantiateType = function (type, typeParameterArgumentMap) {
            // if the type is a primitive type, nothing to do here
            if (type.isPrimitive()) {
                return type;
            }

            // if the type is an error, nothing to do here
            if (type.isError()) {
                return type;
            }

            if (typeParameterArgumentMap[type.pullSymbolID]) {
                return typeParameterArgumentMap[type.pullSymbolID];
            }

            type._resolveDeclaredSymbol();

            if (type.wrapsSomeTypeParameter(typeParameterArgumentMap)) {
                return TypeScript.InstantiatedTypeReferenceSymbol.create(this, type, typeParameterArgumentMap);
            }

            return type;
        };

        PullTypeResolver.prototype.instantiateSignature = function (signature, typeParameterSubstitutionMap) {
            return this.getOrCreateSignatureWithSubstitutionOrInstantiation(signature, typeParameterSubstitutionMap, true);
        };

        PullTypeResolver.prototype.getOrCreateSignatureWithSubstitution = function (signature, typeParameterSubstitutionMap) {
            return this.getOrCreateSignatureWithSubstitutionOrInstantiation(signature, typeParameterSubstitutionMap, false);
        };

        // This method is a helper to be called by instantiateSignature, as well as getOrCreateSignatureWithSubstitution,
        // since they are almost the same. The only difference is that one produces an InstantiatedSignatureSymbol,
        // and the other produces
        PullTypeResolver.prototype.getOrCreateSignatureWithSubstitutionOrInstantiation = function (signature, typeParameterSubstitutionMap, isInstantiation) {
            if (!signature.wrapsSomeTypeParameter(typeParameterSubstitutionMap)) {
                return signature;
            }

            var rootSignature = signature.getRootSymbol();
            var mutableTypeParameterMap = new TypeScript.PullInstantiationHelpers.MutableTypeParameterSubstitutionMap(typeParameterSubstitutionMap);
            TypeScript.PullInstantiationHelpers.instantiateTypeArgument(this, signature, mutableTypeParameterMap);

            // Note that instantiated signatures and signatures with substitution are stored in the
            // same cache! The reason this is safe is that the substitution map uniquely identifies
            // a signature as instantiated or not. Namely, there are 3 cases:
            //
            // 1. The map does not contain any substitutions for the signature's own type parameters:
            //    In this case, the signature has a substitution for surrounding type parameters,
            //    but it is not an instantiated signature.
            // 2. The map contains substitutions for the signature's own type parameters, but the
            //    substituted types are not synthesized type parameters:
            //    In this case, we have an instantiated signature, since a signature with substitution
            //    either lacks mappings for its own type parameters, or has them mapped to synthesized
            //    type parameters.
            // 3. The map contains substitutions for the signature's own type parameters, and the
            //    substituted types are synthesized type parameters:
            //    In this case, it clearly could be a signature with substitution. Also, it cannot
            //    be an instantiated signature because an instantiated signature has type arguments.
            //    These type arguments can be referenced types or referenced values with certain types.
            //    But a synthesized type parameter is impossible to reference, even through a value.
            //
            // This is the reasoning. We also have the assert below to enforce this.
            var instantiatedSignatureOrSignatureWithSubstitution = rootSignature.getSpecialization(mutableTypeParameterMap.typeParameterSubstitutionMap);
            if (instantiatedSignatureOrSignatureWithSubstitution) {
                var symbolFromCacheIsInstantiatedSignature = instantiatedSignatureOrSignatureWithSubstitution.getIsInstantiated();
                TypeScript.Debug.assert(symbolFromCacheIsInstantiatedSignature === isInstantiation);
                return instantiatedSignatureOrSignatureWithSubstitution;
            }

            // Cleanup the type parameter argument map
            TypeScript.PullInstantiationHelpers.cleanUpTypeParameterSubstitutionMap(signature, mutableTypeParameterMap);
            typeParameterSubstitutionMap = mutableTypeParameterMap.typeParameterSubstitutionMap;

            // Create a new one
            instantiatedSignatureOrSignatureWithSubstitution = isInstantiation ? new TypeScript.InstantiatedSignatureSymbol(rootSignature, typeParameterSubstitutionMap) : new TypeScript.SignatureSymbolWithSubstitution(rootSignature, typeParameterSubstitutionMap);

            // if the instantiation occurred via a recursive funciton invocation, the return type may be null so we should set it to any
            instantiatedSignatureOrSignatureWithSubstitution.returnType = this.instantiateType((rootSignature.returnType || this.semanticInfoChain.anyTypeSymbol), typeParameterSubstitutionMap);
            instantiatedSignatureOrSignatureWithSubstitution.functionType = this.instantiateType(rootSignature.functionType, typeParameterSubstitutionMap);

            var parameters = rootSignature.parameters;
            var parameter = null;

            if (parameters) {
                for (var j = 0; j < parameters.length; j++) {
                    parameter = new TypeScript.PullSymbol(parameters[j].name, TypeScript.PullElementKind.Parameter, this.semanticInfoChain);
                    parameter.setRootSymbol(parameters[j]);

                    if (parameters[j].isOptional) {
                        parameter.isOptional = true;
                    }
                    if (parameters[j].isVarArg) {
                        parameter.isVarArg = true;
                        instantiatedSignatureOrSignatureWithSubstitution.hasVarArgs = true;
                    }
                    instantiatedSignatureOrSignatureWithSubstitution.addParameter(parameter, parameter.isOptional);

                    parameter.type = this.instantiateType(parameters[j].type, typeParameterSubstitutionMap);
                }
            }

            return instantiatedSignatureOrSignatureWithSubstitution;
        };

        PullTypeResolver.prototype.checkFunctionOverloadChains = function (parent, moduleElements) {
            var decl = this.getEnclosingDeclForAST(parent);
            if (!TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Ambient)) {
                var inFunctionOverloadChain = false;
                var functionOverloadChainName = null;

                for (var i = 0, n = moduleElements.length; i < n; i++) {
                    var moduleElement = moduleElements[i];
                    var lastElement = i === (n - 1);

                    if (inFunctionOverloadChain) {
                        if (moduleElement.kind() !== 129 /* FunctionDeclaration */) {
                            this.semanticInfoChain.addDiagnosticFromAST(TypeScript.firstToken(moduleElement), TypeScript.DiagnosticCode.Function_implementation_expected);
                            return;
                        }

                        var functionDeclaration = moduleElement;
                        if (TypeScript.tokenValueText(functionDeclaration.identifier) !== functionOverloadChainName) {
                            this.semanticInfoChain.addDiagnosticFromAST(functionDeclaration.identifier, TypeScript.DiagnosticCode.Function_overload_name_must_be_0, [functionOverloadChainName]);
                            return;
                        }
                    }

                    if (moduleElement.kind() === 129 /* FunctionDeclaration */) {
                        functionDeclaration = moduleElement;
                        if (!TypeScript.SyntaxUtilities.containsToken(functionDeclaration.modifiers, 63 /* DeclareKeyword */)) {
                            inFunctionOverloadChain = functionDeclaration.block === null;
                            functionOverloadChainName = TypeScript.tokenValueText(functionDeclaration.identifier);

                            if (inFunctionOverloadChain) {
                                if (lastElement) {
                                    this.semanticInfoChain.addDiagnosticFromAST(TypeScript.firstToken(moduleElement), TypeScript.DiagnosticCode.Function_implementation_expected);
                                    return;
                                } else {
                                    // We're a function without a body, and there's another element
                                    // after us.  If it's another overload that doesn't have a body,
                                    // then report an error that we're missing an implementation here.
                                    var nextElement = TypeScript.childAt(moduleElements, i + 1);
                                    if (nextElement.kind() === 129 /* FunctionDeclaration */) {
                                        var nextFunction = nextElement;

                                        if (TypeScript.tokenValueText(nextFunction.identifier) !== functionOverloadChainName && nextFunction.block === null) {
                                            this.semanticInfoChain.addDiagnosticFromAST(functionDeclaration.identifier, TypeScript.DiagnosticCode.Function_implementation_expected);
                                            return;
                                        }
                                    }
                                }
                            }
                        } else {
                            inFunctionOverloadChain = false;
                            functionOverloadChainName = "";
                        }
                    }
                }
            }
        };

        PullTypeResolver.prototype.checkClassOverloadChains = function (node) {
            var decl = this.getEnclosingDeclForAST(node);
            if (!TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Ambient) && !TypeScript.SyntaxUtilities.containsToken(node.modifiers, 63 /* DeclareKeyword */)) {
                var inFunctionOverloadChain = false;
                var inConstructorOverloadChain = false;

                var functionOverloadChainName = null;
                var isInStaticOverloadChain = null;
                var memberFunctionDeclaration = null;

                for (var i = 0, n = node.classElements.length; i < n; i++) {
                    var classElement = node.classElements[i];
                    var lastElement = i === (n - 1);
                    var isStaticOverload = null;

                    if (inFunctionOverloadChain) {
                        if (classElement.kind() !== 135 /* MemberFunctionDeclaration */) {
                            this.semanticInfoChain.addDiagnosticFromAST(TypeScript.firstToken(classElement), TypeScript.DiagnosticCode.Function_implementation_expected);
                            return;
                        }

                        memberFunctionDeclaration = classElement;
                        if (TypeScript.tokenValueText(memberFunctionDeclaration.propertyName) !== functionOverloadChainName) {
                            this.semanticInfoChain.addDiagnosticFromAST(memberFunctionDeclaration.propertyName, TypeScript.DiagnosticCode.Function_overload_name_must_be_0, [functionOverloadChainName]);
                            return;
                        }

                        isStaticOverload = TypeScript.SyntaxUtilities.containsToken(memberFunctionDeclaration.modifiers, 58 /* StaticKeyword */);
                        if (isStaticOverload !== isInStaticOverloadChain) {
                            var diagnostic = isInStaticOverloadChain ? TypeScript.DiagnosticCode.Function_overload_must_be_static : TypeScript.DiagnosticCode.Function_overload_must_not_be_static;
                            this.semanticInfoChain.addDiagnosticFromAST(memberFunctionDeclaration.propertyName, diagnostic);
                            return;
                        }
                    } else if (inConstructorOverloadChain) {
                        if (classElement.kind() !== 137 /* ConstructorDeclaration */) {
                            this.semanticInfoChain.addDiagnosticFromAST(TypeScript.firstToken(classElement), TypeScript.DiagnosticCode.Constructor_implementation_expected);
                            return;
                        }
                    }

                    if (classElement.kind() === 135 /* MemberFunctionDeclaration */) {
                        memberFunctionDeclaration = classElement;

                        inFunctionOverloadChain = memberFunctionDeclaration.block === null;
                        functionOverloadChainName = TypeScript.tokenValueText(memberFunctionDeclaration.propertyName);
                        isInStaticOverloadChain = TypeScript.SyntaxUtilities.containsToken(memberFunctionDeclaration.modifiers, 58 /* StaticKeyword */);

                        if (inFunctionOverloadChain) {
                            if (lastElement) {
                                this.semanticInfoChain.addDiagnosticFromAST(TypeScript.firstToken(classElement), TypeScript.DiagnosticCode.Function_implementation_expected);
                                return;
                            } else {
                                // We're a function without a body, and there's another element
                                // after us.  If it's another overload that doesn't have a body,
                                // then report an error that we're missing an implementation here.
                                var nextElement = TypeScript.childAt(node.classElements, i + 1);
                                if (nextElement.kind() === 135 /* MemberFunctionDeclaration */) {
                                    var nextMemberFunction = nextElement;

                                    if (TypeScript.tokenValueText(nextMemberFunction.propertyName) !== functionOverloadChainName && nextMemberFunction.block === null) {
                                        this.semanticInfoChain.addDiagnosticFromAST(memberFunctionDeclaration.propertyName, TypeScript.DiagnosticCode.Function_implementation_expected);
                                        return;
                                    }
                                }
                            }
                        }
                    } else if (classElement.kind() === 137 /* ConstructorDeclaration */) {
                        var constructorDeclaration = classElement;

                        inConstructorOverloadChain = constructorDeclaration.block === null;
                        if (lastElement && inConstructorOverloadChain) {
                            this.semanticInfoChain.addDiagnosticFromAST(TypeScript.firstToken(classElement), TypeScript.DiagnosticCode.Constructor_implementation_expected);
                            return;
                        }
                    }
                }
            }
        };

        PullTypeResolver.prototype.checkForReservedName = function (parent, name, diagnosticKey) {
            switch (TypeScript.tokenValueText(name)) {
                case "any":
                case "number":
                case "boolean":
                case "string":
                case "void":
                    this.semanticInfoChain.addDiagnosticFromAST(name, diagnosticKey, [TypeScript.tokenValueText(name)]);
            }
        };

        PullTypeResolver.prototype.checkForMultipleExportAssignments = function (moduleElements) {
            var seenExportAssignment = false;
            for (var i = 0, n = moduleElements.length; i < n; i++) {
                var child = moduleElements[i];
                if (child.kind() === 134 /* ExportAssignment */) {
                    if (seenExportAssignment) {
                        this.semanticInfoChain.addDiagnosticFromAST(child, TypeScript.DiagnosticCode.A_module_cannot_have_multiple_export_assignments);
                    }
                    seenExportAssignment = true;
                }
            }
        };

        PullTypeResolver.prototype.checkForDisallowedExports = function (moduleElements) {
            var seenExportedElement = false;
            for (var i = 0, n = moduleElements.length; i < n; i++) {
                var child = moduleElements[i];

                if (TypeScript.SyntaxUtilities.hasExportKeyword(child)) {
                    seenExportedElement = true;
                    break;
                }
            }

            if (seenExportedElement) {
                for (var i = 0, n = moduleElements.length; i < n; i++) {
                    var child = moduleElements[i];

                    if (child.kind() === 134 /* ExportAssignment */) {
                        this.semanticInfoChain.addDiagnosticFromAST(child, TypeScript.DiagnosticCode.Export_assignment_not_allowed_in_module_with_exported_element);
                        return;
                    }
                }
            }
        };
        PullTypeResolver.globalTypeCheckPhase = 0;
        return PullTypeResolver;
    })();
    TypeScript.PullTypeResolver = PullTypeResolver;

    var TypeComparisonInfo = (function () {
        function TypeComparisonInfo(sourceComparisonInfo, useSameIndent) {
            this.onlyCaptureFirstError = false;
            this.message = "";
            this.stringConstantVal = null;
            this.indent = 1;
            if (sourceComparisonInfo) {
                this.onlyCaptureFirstError = sourceComparisonInfo.onlyCaptureFirstError;
                this.stringConstantVal = sourceComparisonInfo.stringConstantVal;
                this.indent = sourceComparisonInfo.indent;
                if (!useSameIndent) {
                    this.indent++;
                }
            }
        }
        TypeComparisonInfo.prototype.indentString = function () {
            var result = "";

            for (var i = 0; i < this.indent; i++) {
                result += "\t";
            }

            return result;
        };

        TypeComparisonInfo.prototype.addMessage = function (message) {
            if (!this.onlyCaptureFirstError && this.message) {
                this.message = this.message + TypeScript.newLine() + this.indentString() + message;
            } else {
                this.message = this.indentString() + message;
            }
        };
        return TypeComparisonInfo;
    })();
    TypeScript.TypeComparisonInfo = TypeComparisonInfo;

    function getPropertyAssignmentNameTextFromIdentifier(identifier) {
        if (identifier.kind() === 11 /* IdentifierName */) {
            return { actualText: identifier.text(), memberName: TypeScript.tokenValueText(identifier) };
        } else if (identifier.kind() === 14 /* StringLiteral */) {
            return { actualText: identifier.text(), memberName: TypeScript.tokenValueText(identifier) };
        } else if (identifier.kind() === 13 /* NumericLiteral */) {
            return { actualText: identifier.text(), memberName: TypeScript.tokenValueText(identifier) };
        } else {
            throw TypeScript.Errors.invalidOperation();
        }
    }
    TypeScript.getPropertyAssignmentNameTextFromIdentifier = getPropertyAssignmentNameTextFromIdentifier;

    function isTypesOnlyLocation(ast) {
        while (ast && ast.parent) {
            switch (ast.parent.kind()) {
                case 244 /* TypeAnnotation */:
                    return true;
                case 127 /* TypeQuery */:
                    // Inside a type query is actually an expression.
                    return false;
                case 125 /* ConstructorType */:
                    var constructorType = ast.parent;
                    if (constructorType.type === ast) {
                        return true;
                    }
                    break;
                case 123 /* FunctionType */:
                    var functionType = ast.parent;
                    if (functionType.type === ast) {
                        return true;
                    }
                    break;
                case 239 /* Constraint */:
                    var constraint = ast.parent;
                    if (constraint.type === ast) {
                        return true;
                    }
                    break;
                case 220 /* CastExpression */:
                    var castExpression = ast.parent;
                    return castExpression.type === ast;
                case 230 /* ExtendsHeritageClause */:
                case 231 /* ImplementsHeritageClause */:
                    return true;
                case 228 /* TypeArgumentList */:
                    return true;
                case 131 /* ClassDeclaration */:
                case 128 /* InterfaceDeclaration */:
                case 130 /* ModuleDeclaration */:
                case 129 /* FunctionDeclaration */:
                case 145 /* MethodSignature */:
                case 212 /* MemberAccessExpression */:
                case 242 /* Parameter */:
                    return false;
            }

            ast = ast.parent;
        }

        return false;
    }
    TypeScript.isTypesOnlyLocation = isTypesOnlyLocation;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    // PULLTODO: Get rid of these
    TypeScript.declCacheHit = 0;
    TypeScript.declCacheMiss = 0;
    TypeScript.symbolCacheHit = 0;
    TypeScript.symbolCacheMiss = 0;

    var sentinalEmptyArray = [];

    var SemanticInfoChain = (function () {
        function SemanticInfoChain(compiler, logger) {
            this.compiler = compiler;
            this.logger = logger;
            this.documents = [];
            this.fileNameToDocument = TypeScript.createIntrinsicsObject();
            this.anyTypeDecl = null;
            this.booleanTypeDecl = null;
            this.numberTypeDecl = null;
            this.stringTypeDecl = null;
            this.nullTypeDecl = null;
            this.undefinedTypeDecl = null;
            this.voidTypeDecl = null;
            this.undefinedValueDecl = null;
            this.anyTypeSymbol = null;
            this.booleanTypeSymbol = null;
            this.numberTypeSymbol = null;
            this.stringTypeSymbol = null;
            this.nullTypeSymbol = null;
            this.undefinedTypeSymbol = null;
            this.voidTypeSymbol = null;
            this.undefinedValueSymbol = null;
            this.emptyTypeSymbol = null;
            // <-- Data to clear when we get invalidated
            this.astSymbolMap = [];
            this.astAliasSymbolMap = [];
            this.astCallResolutionDataMap = [];
            this.declSymbolMap = [];
            this.declSignatureSymbolMap = [];
            this.declCache = null;
            this.symbolCache = null;
            this.fileNameToDiagnostics = null;
            this._binder = null;
            this._resolver = null;
            this._topLevelDecls = null;
            this._fileNames = null;
            var globalDecl = new TypeScript.RootPullDecl(SemanticInfoChain.EmptyASTToDeclMap, "", "", 0 /* Global */, 0 /* None */, false);
            this.documents[0] = new TypeScript.Document(this.compiler.compilationSettings(), "", [], null, 0 /* None */, 0, false, null, globalDecl);

            this.anyTypeDecl = new TypeScript.NormalPullDecl("any", "any", TypeScript.PullElementKind.Primitive, 0 /* None */, globalDecl);
            this.booleanTypeDecl = new TypeScript.NormalPullDecl("boolean", "boolean", TypeScript.PullElementKind.Primitive, 0 /* None */, globalDecl);
            this.numberTypeDecl = new TypeScript.NormalPullDecl("number", "number", TypeScript.PullElementKind.Primitive, 0 /* None */, globalDecl);
            this.stringTypeDecl = new TypeScript.NormalPullDecl("string", "string", TypeScript.PullElementKind.Primitive, 0 /* None */, globalDecl);
            this.voidTypeDecl = new TypeScript.NormalPullDecl("void", "void", TypeScript.PullElementKind.Primitive, 0 /* None */, globalDecl);

            // add the global primitive values for "null" and "undefined"
            // Because you cannot reference them by name, they're not parented by any actual decl.
            this.nullTypeDecl = new TypeScript.RootPullDecl(SemanticInfoChain.EmptyASTToDeclMap, "null", "", TypeScript.PullElementKind.Primitive, 0 /* None */, false);
            this.undefinedTypeDecl = new TypeScript.RootPullDecl(SemanticInfoChain.EmptyASTToDeclMap, "undefined", "", TypeScript.PullElementKind.Primitive, 0 /* None */, false);
            this.undefinedValueDecl = new TypeScript.NormalPullDecl("undefined", "undefined", TypeScript.PullElementKind.Variable, TypeScript.PullElementFlags.Ambient, globalDecl);

            this.invalidate();
        }
        SemanticInfoChain.prototype.getDocument = function (fileName) {
            fileName = TypeScript.switchToForwardSlashes(fileName);
            var document = this.fileNameToDocument[fileName];
            return document || null;
        };

        SemanticInfoChain.prototype.lineMap = function (fileName) {
            return this.getDocument(fileName).lineMap();
        };

        // Returns the names of the files we own, in the same order that they were added to us.
        SemanticInfoChain.prototype.fileNames = function () {
            if (this._fileNames === null) {
                // Skip the first semantic info (the synthesized one for the global decls).
                this._fileNames = this.documents.slice(1).map(function (s) {
                    return s.fileName;
                });
            }

            return this._fileNames;
        };

        // Must pass in a new decl, or an old symbol that has a decl available for ownership transfer
        SemanticInfoChain.prototype.bindPrimitiveSymbol = function (decl, newSymbol) {
            newSymbol.addDeclaration(decl);
            this.setSymbolForDecl(decl, newSymbol);
            newSymbol.setResolved();

            return newSymbol;
        };

        // Creates a new type symbol to be bound to this decl. Must be called during
        // invalidation after every edit.
        SemanticInfoChain.prototype.addPrimitiveTypeSymbol = function (decl) {
            var newSymbol = new TypeScript.PullPrimitiveTypeSymbol(decl.name, this);
            return this.bindPrimitiveSymbol(decl, newSymbol);
        };

        // Creates a new value symbol to be bound to this decl, and has the specified type.
        // Must be called during invalidation after every edit.
        SemanticInfoChain.prototype.addPrimitiveValueSymbol = function (decl, type) {
            var newSymbol = new TypeScript.PullSymbol(decl.name, TypeScript.PullElementKind.Variable, this);
            newSymbol.type = type;
            return this.bindPrimitiveSymbol(decl, newSymbol);
        };

        SemanticInfoChain.prototype.resetGlobalSymbols = function () {
            // add primitive types
            this.anyTypeSymbol = this.addPrimitiveTypeSymbol(this.anyTypeDecl);
            this.booleanTypeSymbol = this.addPrimitiveTypeSymbol(this.booleanTypeDecl);
            this.numberTypeSymbol = this.addPrimitiveTypeSymbol(this.numberTypeDecl);
            this.stringTypeSymbol = this.addPrimitiveTypeSymbol(this.stringTypeDecl);
            this.voidTypeSymbol = this.addPrimitiveTypeSymbol(this.voidTypeDecl);
            this.nullTypeSymbol = this.addPrimitiveTypeSymbol(this.nullTypeDecl);
            this.undefinedTypeSymbol = this.addPrimitiveTypeSymbol(this.undefinedTypeDecl);
            this.undefinedValueSymbol = this.addPrimitiveValueSymbol(this.undefinedValueDecl, this.undefinedTypeSymbol);

            // other decls not reachable from the globalDecl
            var emptyTypeDecl = new TypeScript.PullSynthesizedDecl("{}", "{}", TypeScript.PullElementKind.ObjectType, 0 /* None */, null);
            var emptyTypeSymbol = new TypeScript.PullTypeSymbol("{}", TypeScript.PullElementKind.ObjectType, this);
            this.setSymbolForDecl(emptyTypeDecl, emptyTypeSymbol);
            emptyTypeSymbol.addDeclaration(emptyTypeDecl);
            emptyTypeSymbol.setResolved();
            this.emptyTypeSymbol = emptyTypeSymbol;
        };

        SemanticInfoChain.prototype.addDocument = function (document) {
            var fileName = document.fileName;
            fileName = TypeScript.switchToForwardSlashes(fileName);

            var existingIndex = TypeScript.ArrayUtilities.indexOf(this.documents, function (u) {
                return u.fileName === fileName;
            });
            if (existingIndex < 0) {
                // Adding the script for the first time.
                this.documents.push(document);
            } else {
                this.documents[existingIndex] = document;
            }

            this.fileNameToDocument[fileName] = document;

            // We changed the scripts we're responsible for.  Invalidate all existing cached
            // semantic information.
            this.invalidate();
        };

        SemanticInfoChain.prototype.removeDocument = function (fileName) {
            TypeScript.Debug.assert(fileName !== "", "Can't remove the semantic info for the global decl.");
            fileName = TypeScript.switchToForwardSlashes(fileName);
            var index = TypeScript.ArrayUtilities.indexOf(this.documents, function (u) {
                return u.fileName === fileName;
            });
            if (index > 0) {
                this.fileNameToDocument[fileName] = undefined;
                this.documents.splice(index, 1);
                this.invalidate();
            }
        };

        SemanticInfoChain.prototype.getDeclPathCacheID = function (declPath, declKind) {
            var cacheID = "";

            for (var i = 0; i < declPath.length; i++) {
                cacheID += "#" + declPath[i];
            }

            return cacheID + "#" + declKind.toString();
        };

        // Looks for a top level decl matching the name/kind pair passed in.  This should be used
        // by methods in the binder to see if there is an existing symbol that a declaration should
        // merge into, or if the declaration should create a new symbol.
        //
        // The doNotGoPastThisDecl argument is important.  it should be the declaration that the
        // binder is currently creating a symbol for.  The chain will search itself from first to
        // last semantic info, and will not go past the file that that decl is declared in.
        // Furthermore, while searching hte file that that decl is declared in, it will also not
        // consider any decls at a later position in the file.
        //
        // In this manner, it will only find symbols declared 'before' the decl currently being
        // bound.  This gives us a nice ordering guarantee for open ended symbols.  Specifically
        // we'll create a symbol for the first file (in compiler order) that it was found it,
        // and we'll merge all later declarations into that symbol.  This means, for example, that
        // if a consumer tries to augment a lib.d.ts type, that the symbol will be created for
        // lib.d.ts (as that is in the chain prior to all user files).
        SemanticInfoChain.prototype.findTopLevelSymbol = function (name, kind, doNotGoPastThisDecl) {
            var cacheID = this.getDeclPathCacheID([name], kind);

            var symbol = this.symbolCache[cacheID];

            if (!symbol) {
                for (var i = 0, n = this.documents.length; i < n; i++) {
                    var topLevelDecl = this.documents[i].topLevelDecl();

                    var symbol = this.findTopLevelSymbolInDecl(topLevelDecl, name, kind, doNotGoPastThisDecl);
                    if (symbol) {
                        break;
                    }

                    // We finished searching up to the file that included the stopping point decl.
                    // no need to continue.
                    if (doNotGoPastThisDecl && topLevelDecl.name === doNotGoPastThisDecl.fileName()) {
                        return null;
                    }
                }

                if (symbol) {
                    this.symbolCache[cacheID] = symbol;
                }
            }

            return symbol;
        };

        SemanticInfoChain.prototype.findTopLevelSymbolInDecl = function (topLevelDecl, name, kind, doNotGoPastThisDecl) {
            // If we're currently searching the file that includes the decl we don't want to go
            // past, then we have to stop searching at the position of that decl.  Otherwise, we
            // search the entire file.
            var _syntaxTree = TypeScript.syntaxTree(topLevelDecl.ast());
            var doNotGoPastThisPosition = doNotGoPastThisDecl && doNotGoPastThisDecl.fileName() === topLevelDecl.fileName() ? TypeScript.start(doNotGoPastThisDecl.ast(), _syntaxTree.text) : -1;

            var foundDecls = topLevelDecl.searchChildDecls(name, kind);

            for (var j = 0; j < foundDecls.length; j++) {
                var foundDecl = foundDecls[j];

                // This decl was at or past the stopping point.  Don't search any further.
                if (doNotGoPastThisPosition !== -1 && foundDecl.ast() && TypeScript.start(foundDecl.ast(), _syntaxTree.text) > doNotGoPastThisPosition) {
                    break;
                }

                var symbol = foundDecls[j].getSymbol(this);
                if (symbol) {
                    return symbol;
                }
            }

            return null;
        };

        SemanticInfoChain.prototype.findExternalModule = function (id) {
            id = TypeScript.normalizePath(id);

            // SPEC: Nov 18
            // An external import declaration that specifies a relative external module name (section 11.2.1) resolves the name
            // relative to the directory of the containing source file.
            // If a source file with the resulting path and file extension '.ts' exists, that file is added as a dependency.
            // Otherwise, if a source file with the resulting path and file extension '.d.ts' exists, that file is added as a dependency.
            var tsFile = id + ".ts";
            var tsCacheID = this.getDeclPathCacheID([tsFile], TypeScript.PullElementKind.DynamicModule);
            symbol = this.symbolCache[tsCacheID];
            if (symbol != undefined) {
                return symbol;
            }

            var dtsFile = id + ".d.ts";
            var dtsCacheID = this.getDeclPathCacheID([dtsFile], TypeScript.PullElementKind.DynamicModule);
            var symbol = this.symbolCache[dtsCacheID];
            if (symbol) {
                return symbol;
            }

            var dtsSymbol;
            for (var i = 0; i < this.documents.length; i++) {
                var document = this.documents[i];
                var topLevelDecl = document.topLevelDecl();

                if (topLevelDecl.isExternalModule()) {
                    var isTsFile = document.fileName === tsFile;
                    if (isTsFile || document.fileName === dtsFile) {
                        var dynamicModuleDecl = topLevelDecl.getChildDecls()[0];
                        symbol = dynamicModuleDecl.getSymbol(this);

                        if (isTsFile) {
                            this.symbolCache[tsCacheID] = symbol;

                            // .ts file found - can return immediately
                            return symbol;
                        } else {
                            // .d.ts file found - save the symbol and continue looking for .ts file
                            dtsSymbol = symbol;
                        }
                    }
                }
            }

            if (dtsSymbol) {
                this.symbolCache[dtsCacheID] = symbol;
                return dtsSymbol;
            }

            this.symbolCache[dtsCacheID] = null;
            this.symbolCache[tsCacheID] = null;

            return null;
        };

        SemanticInfoChain.prototype.findAmbientExternalModuleInGlobalContext = function (id) {
            var cacheID = this.getDeclPathCacheID([id], TypeScript.PullElementKind.DynamicModule);

            var symbol = this.symbolCache[cacheID];
            if (symbol == undefined) {
                symbol = null;
                for (var i = 0; i < this.documents.length; i++) {
                    var document = this.documents[i];
                    var topLevelDecl = document.topLevelDecl();

                    if (!topLevelDecl.isExternalModule()) {
                        var dynamicModules = topLevelDecl.searchChildDecls(id, TypeScript.PullElementKind.DynamicModule);
                        if (dynamicModules.length) {
                            symbol = dynamicModules[0].getSymbol(this);
                            break;
                        }
                    }
                }

                this.symbolCache[cacheID] = symbol;
            }

            return symbol;
        };

        // a decl path is a list of decls that reference the components of a declaration from the global scope down
        // E.g., string would be "['string']" and "A.B.C" would be "['A','B','C']"
        SemanticInfoChain.prototype.findDecls = function (declPath, declKind) {
            var cacheID = this.getDeclPathCacheID(declPath, declKind);

            if (declPath.length) {
                var cachedDecls = this.declCache[cacheID];

                if (cachedDecls && cachedDecls.length) {
                    TypeScript.declCacheHit++;
                    return cachedDecls;
                }
            }

            TypeScript.declCacheMiss++;

            var declsToSearch = this.topLevelDecls();

            var decls = TypeScript.sentinelEmptyArray;
            var path;
            var foundDecls = TypeScript.sentinelEmptyArray;

            for (var i = 0; i < declPath.length; i++) {
                path = declPath[i];
                decls = TypeScript.sentinelEmptyArray;

                var kind = (i === declPath.length - 1) ? declKind : TypeScript.PullElementKind.SomeContainer;
                for (var j = 0; j < declsToSearch.length; j++) {
                    foundDecls = declsToSearch[j].searchChildDecls(path, kind);

                    for (var k = 0; k < foundDecls.length; k++) {
                        if (decls === TypeScript.sentinelEmptyArray) {
                            decls = [];
                        }
                        decls[decls.length] = foundDecls[k];
                    }
                }

                declsToSearch = decls;

                if (!declsToSearch) {
                    break;
                }
            }

            if (decls.length) {
                this.declCache[cacheID] = decls;
            }

            return decls;
        };

        SemanticInfoChain.prototype.findDeclsFromPath = function (declPath, declKind) {
            var declString = [];

            for (var i = 0, n = declPath.length; i < n; i++) {
                if (declPath[i].kind & TypeScript.PullElementKind.Script) {
                    continue;
                }

                declString.push(declPath[i].name);
            }

            return this.findDecls(declString, declKind);
        };

        SemanticInfoChain.prototype.findSymbol = function (declPath, declType) {
            var cacheID = this.getDeclPathCacheID(declPath, declType);

            if (declPath.length) {
                var cachedSymbol = this.symbolCache[cacheID];

                if (cachedSymbol) {
                    TypeScript.symbolCacheHit++;
                    return cachedSymbol;
                }
            }

            TypeScript.symbolCacheMiss++;

            // symbol wasn't cached, so get the decl
            var decls = this.findDecls(declPath, declType);
            var symbol = null;

            if (decls.length) {
                // it might happen that container also has a value side: i.e fundule\clodule.
                // if value side is not bound yet then binding of the module (caused by getSymbol) will create a fresh variable symbol for the value side
                // instead of sharing one with function\enum\class => big problems with name resolution in future.
                // To avoid we make sure that symbol for value decl is already bound prior to getSymbol call for the container decl(if value decl is present)
                var decl = decls[0];
                if (TypeScript.hasFlag(decl.kind, TypeScript.PullElementKind.SomeContainer)) {
                    var valueDecl = decl.getValueDecl();
                    if (valueDecl) {
                        valueDecl.ensureSymbolIsBound(this);
                    }
                }
                symbol = decl.getSymbol(this);

                if (symbol) {
                    for (var i = 1; i < decls.length; i++) {
                        decls[i].ensureSymbolIsBound(this);
                    }

                    this.symbolCache[cacheID] = symbol;
                }
            }

            return symbol;
        };

        SemanticInfoChain.prototype.cacheGlobalSymbol = function (symbol, kind) {
            var cacheID1 = this.getDeclPathCacheID([symbol.name], kind);
            var cacheID2 = this.getDeclPathCacheID([symbol.name], symbol.kind);

            if (!this.symbolCache[cacheID1]) {
                this.symbolCache[cacheID1] = symbol;
            }

            if (!this.symbolCache[cacheID2]) {
                this.symbolCache[cacheID2] = symbol;
            }
        };

        SemanticInfoChain.prototype.invalidate = function (oldSettings, newSettings) {
            if (typeof oldSettings === "undefined") { oldSettings = null; }
            if (typeof newSettings === "undefined") { newSettings = null; }
            // A file has changed, increment the type check phase so that future type chech
            // operations will proceed.
            TypeScript.PullTypeResolver.globalTypeCheckPhase++;

            // this.logger.log("Invalidating SemanticInfoChain...");
            var cleanStart = new Date().getTime();

            this.astSymbolMap.length = 0;
            this.astAliasSymbolMap.length = 0;
            this.astCallResolutionDataMap.length = 0;

            this.declCache = TypeScript.createIntrinsicsObject();
            this.symbolCache = TypeScript.createIntrinsicsObject();
            this.fileNameToDiagnostics = TypeScript.createIntrinsicsObject();
            this._binder = null;
            this._resolver = null;
            this._topLevelDecls = null;
            this._fileNames = null;

            this.declSymbolMap.length = 0;
            this.declSignatureSymbolMap.length = 0;

            // Reset global counters
            TypeScript.pullSymbolID = 0;

            this.resetGlobalSymbols();

            var cleanEnd = new Date().getTime();
            // this.logger.log("   time to invalidate: " + (cleanEnd - cleanStart));
        };

        SemanticInfoChain.prototype.setSymbolForAST = function (ast, symbol) {
            TypeScript.Debug.assert(!TypeScript.isShared(ast));
            this.astSymbolMap[TypeScript.syntaxID(ast)] = symbol;
        };

        SemanticInfoChain.prototype.getSymbolForAST = function (ast) {
            return this.astSymbolMap[TypeScript.syntaxID(ast)] || null;
        };

        SemanticInfoChain.prototype.setAliasSymbolForAST = function (ast, symbol) {
            TypeScript.Debug.assert(!TypeScript.isShared(ast));
            this.astAliasSymbolMap[TypeScript.syntaxID(ast)] = symbol;
        };

        SemanticInfoChain.prototype.getAliasSymbolForAST = function (ast) {
            return TypeScript.isShared(ast) ? null : this.astAliasSymbolMap[TypeScript.syntaxID(ast)];
        };

        SemanticInfoChain.prototype.getCallResolutionDataForAST = function (ast) {
            return TypeScript.isShared(ast) ? null : this.astCallResolutionDataMap[TypeScript.syntaxID(ast)];
        };

        SemanticInfoChain.prototype.setCallResolutionDataForAST = function (ast, callResolutionData) {
            TypeScript.Debug.assert(!TypeScript.isShared(ast));
            if (callResolutionData) {
                this.astCallResolutionDataMap[TypeScript.syntaxID(ast)] = callResolutionData;
            }
        };

        SemanticInfoChain.prototype.setSymbolForDecl = function (decl, symbol) {
            this.declSymbolMap[decl.declID] = symbol;
        };

        SemanticInfoChain.prototype.getSymbolForDecl = function (decl) {
            return this.declSymbolMap[decl.declID];
        };

        SemanticInfoChain.prototype.setSignatureSymbolForDecl = function (decl, signatureSymbol) {
            this.declSignatureSymbolMap[decl.declID] = signatureSymbol;
        };

        SemanticInfoChain.prototype.getSignatureSymbolForDecl = function (decl) {
            return this.declSignatureSymbolMap[decl.declID];
        };

        SemanticInfoChain.prototype.addDiagnostic = function (diagnostic) {
            var fileName = diagnostic.fileName();
            var diagnostics = this.fileNameToDiagnostics[fileName];
            if (!diagnostics) {
                diagnostics = [];
                this.fileNameToDiagnostics[fileName] = diagnostics;
            }

            diagnostics.push(diagnostic);
        };

        SemanticInfoChain.prototype.getDiagnostics = function (fileName) {
            var diagnostics = this.fileNameToDiagnostics[fileName];
            return diagnostics || [];
        };

        SemanticInfoChain.prototype.getBinder = function () {
            if (!this._binder) {
                this._binder = new TypeScript.PullSymbolBinder(this);
            }

            return this._binder;
        };

        SemanticInfoChain.prototype.getResolver = function () {
            if (!this._resolver) {
                this._resolver = new TypeScript.PullTypeResolver(this.compiler.compilationSettings(), this);
            }

            return this._resolver;
        };

        SemanticInfoChain.prototype.addSyntheticIndexSignature = function (containingDecl, containingSymbol, ast, indexParamName, indexParamType, returnType) {
            var indexSignature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.IndexSignature, this);
            var indexParameterSymbol = new TypeScript.PullSymbol(indexParamName, TypeScript.PullElementKind.Parameter, this);
            indexParameterSymbol.type = indexParamType;
            indexSignature.addParameter(indexParameterSymbol);
            indexSignature.returnType = returnType;
            indexSignature.setResolved();
            indexParameterSymbol.setResolved();

            containingSymbol.addIndexSignature(indexSignature);

            var indexSigDecl = new TypeScript.PullSynthesizedDecl("", "", TypeScript.PullElementKind.IndexSignature, TypeScript.PullElementFlags.Signature, containingDecl);
            var indexParamDecl = new TypeScript.PullSynthesizedDecl(indexParamName, indexParamName, TypeScript.PullElementKind.Parameter, 0 /* None */, indexSigDecl);
            indexSigDecl.setSignatureSymbol(indexSignature, this);
            this.setSymbolForDecl(indexParamDecl, indexParameterSymbol);
            indexSignature.addDeclaration(indexSigDecl);
            indexParameterSymbol.addDeclaration(indexParamDecl);
        };

        SemanticInfoChain.prototype.getDeclForAST = function (ast) {
            var document = this.getDocument(TypeScript.syntaxTree(ast).fileName());

            if (document) {
                return document._getDeclForAST(ast);
            }

            return null;
        };

        SemanticInfoChain.prototype.getEnclosingDecl = function (ast) {
            return this.getDocument(TypeScript.syntaxTree(ast).fileName()).getEnclosingDecl(ast);
        };

        SemanticInfoChain.prototype.setDeclForAST = function (ast, decl) {
            this.getDocument(decl.fileName())._setDeclForAST(ast, decl);
        };

        SemanticInfoChain.prototype.getASTForDecl = function (decl) {
            var document = this.getDocument(decl.fileName());
            if (document) {
                return document._getASTForDecl(decl);
            }

            return null;
        };

        SemanticInfoChain.prototype.setASTForDecl = function (decl, ast) {
            this.getDocument(decl.fileName())._setASTForDecl(decl, ast);
        };

        SemanticInfoChain.prototype.topLevelDecl = function (fileName) {
            var document = this.getDocument(fileName);
            if (document) {
                return document.topLevelDecl();
            }

            return null;
        };

        SemanticInfoChain.prototype.topLevelDecls = function () {
            if (!this._topLevelDecls) {
                this._topLevelDecls = TypeScript.ArrayUtilities.select(this.documents, function (u) {
                    return u.topLevelDecl();
                });
            }

            return this._topLevelDecls;
        };

        SemanticInfoChain.prototype.addDiagnosticFromAST = function (ast, diagnosticKey, _arguments) {
            if (typeof _arguments === "undefined") { _arguments = null; }
            this.addDiagnostic(this.diagnosticFromAST(ast, diagnosticKey, _arguments));
        };

        SemanticInfoChain.prototype.diagnosticFromAST = function (ast, diagnosticKey, _arguments) {
            if (typeof _arguments === "undefined") { _arguments = null; }
            var syntaxTree = TypeScript.syntaxTree(ast);
            return new TypeScript.Diagnostic(syntaxTree.fileName(), syntaxTree.lineMap(), TypeScript.start(ast, syntaxTree.text), TypeScript.width(ast, syntaxTree.text), diagnosticKey, _arguments);
        };

        SemanticInfoChain.prototype.diagnosticFromDecl = function (decl, diagnosticKey, _arguments) {
            if (typeof _arguments === "undefined") { _arguments = null; }
            return this.diagnosticFromAST(decl.ast(), diagnosticKey, _arguments);
        };

        SemanticInfoChain.prototype.locationFromAST = function (ast) {
            var syntaxTree = TypeScript.syntaxTree(ast);
            return new TypeScript.Location(syntaxTree.fileName(), syntaxTree.lineMap(), TypeScript.start(ast, syntaxTree.text), TypeScript.width(ast, syntaxTree.text));
        };

        SemanticInfoChain.prototype.duplicateIdentifierDiagnosticFromAST = function (ast, identifier) {
            return this.diagnosticFromAST(ast, TypeScript.DiagnosticCode.Duplicate_identifier_0, [identifier]);
        };

        SemanticInfoChain.prototype.addDuplicateIdentifierDiagnosticFromAST = function (ast, identifier) {
            this.addDiagnostic(this.duplicateIdentifierDiagnosticFromAST(ast, identifier));
        };
        SemanticInfoChain.EmptyASTToDeclMap = {
            _getASTForDecl: function (decl) {
                return null;
            }
        };
        return SemanticInfoChain;
    })();
    TypeScript.SemanticInfoChain = SemanticInfoChain;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    var DeclCollectionContext = (function () {
        function DeclCollectionContext(document, propagateEnumConstants) {
            this.document = document;
            this.propagateEnumConstants = propagateEnumConstants;
            this.isDeclareFile = false;
            this.parentChain = [];
        }
        DeclCollectionContext.prototype.getParent = function () {
            return this.parentChain ? this.parentChain[this.parentChain.length - 1] : null;
        };

        DeclCollectionContext.prototype.pushParent = function (parentDecl) {
            if (parentDecl) {
                this.parentChain[this.parentChain.length] = parentDecl;
            }
        };

        DeclCollectionContext.prototype.popParent = function () {
            this.parentChain.length--;
        };

        DeclCollectionContext.prototype.setDeclForAST = function (ast, decl) {
            TypeScript.Debug.assert(decl.fileName() === this.document.fileName);
            this.document._setDeclForAST(ast, decl);
        };

        DeclCollectionContext.prototype.setASTForDecl = function (decl, ast) {
            TypeScript.Debug.assert(decl.fileName() === this.document.fileName);
            this.document._setASTForDecl(decl, ast);
        };
        return DeclCollectionContext;
    })();

    function moduleElementsHasExportAssignment(moduleElements) {
        for (var i = 0, n = moduleElements.length; i < n; i++) {
            if (moduleElements[i].kind() === 134 /* ExportAssignment */) {
                return true;
            }
        }

        return false;
    }

    function containingModuleHasExportAssignment(ast) {
        ast = ast.parent;
        while (ast) {
            if (ast.kind() === 130 /* ModuleDeclaration */) {
                var moduleDecl = ast;
                return moduleElementsHasExportAssignment(moduleDecl.moduleElements);
            } else if (ast.kind() === 120 /* SourceUnit */) {
                var sourceUnit = ast;
                return moduleElementsHasExportAssignment(sourceUnit.moduleElements);
            }

            ast = ast.parent;
        }

        return false;
    }

    function isParsingAmbientModule(ast, context) {
        ast = ast.parent;
        while (ast) {
            if (ast.kind() === 130 /* ModuleDeclaration */) {
                if (TypeScript.hasModifier(ast.modifiers, TypeScript.PullElementFlags.Ambient)) {
                    return true;
                }
            }

            ast = ast.parent;
        }

        return false;
    }

    function preCollectImportDecls(ast, context) {
        var importDecl = ast;
        var declFlags = 0 /* None */;

        var parent = context.getParent();

        if (TypeScript.hasModifier(importDecl.modifiers, 1 /* Exported */) && !containingModuleHasExportAssignment(ast)) {
            declFlags |= 1 /* Exported */;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(importDecl.identifier), importDecl.identifier.text(), TypeScript.PullElementKind.TypeAlias, declFlags, parent);
        context.setDeclForAST(ast, decl);
        context.setASTForDecl(decl, ast);
        // Note: it is intentional that a import does not get added to hte context stack.  An
        // import does not introduce a new name scope, so it shouldn't be in the context decl stack.
        // context.pushParent(decl);
    }

    function preCollectScriptDecls(sourceUnit, context) {
        var fileName = TypeScript.syntaxTree(sourceUnit).fileName();

        var isExternalModule = context.document.syntaxTree().isExternalModule();

        var decl = new TypeScript.RootPullDecl(context.document, fileName, fileName, TypeScript.PullElementKind.Script, 0 /* None */, isExternalModule);
        context.setDeclForAST(sourceUnit, decl);
        context.setASTForDecl(decl, sourceUnit);

        context.isDeclareFile = context.document.isDeclareFile();

        context.pushParent(decl);

        // if it's an external module, create another decl to represent that module inside the top
        // level script module.
        if (isExternalModule) {
            var declFlags = 1 /* Exported */;
            if (TypeScript.isDTSFile(fileName)) {
                declFlags |= TypeScript.PullElementFlags.Ambient;
            }

            var moduleContainsExecutableCode = containsExecutableCode(sourceUnit.moduleElements);
            var kind = TypeScript.PullElementKind.DynamicModule;
            var valueText = TypeScript.quoteStr(fileName);

            var decl = new TypeScript.NormalPullDecl(valueText, fileName, kind, declFlags, context.getParent());

            context.setASTForDecl(decl, sourceUnit);

            // Note: we're overring what the script points to.  For files with an external module,
            // the script node will point at the external module declaration.
            context.setDeclForAST(sourceUnit, decl);

            if (!moduleElementsHasExportAssignment(sourceUnit.moduleElements) || moduleContainsExecutableCode) {
                createModuleVariableDecl(decl, sourceUnit, context);
            }

            context.pushParent(decl);
        }
    }

    function preCollectEnumDecls(enumDecl, context) {
        var declFlags = 0 /* None */;
        var enumName = TypeScript.tokenValueText(enumDecl.identifier);

        if ((TypeScript.hasModifier(enumDecl.modifiers, 1 /* Exported */) || isParsingAmbientModule(enumDecl, context)) && !containingModuleHasExportAssignment(enumDecl)) {
            declFlags |= 1 /* Exported */;
        }

        if (TypeScript.hasModifier(enumDecl.modifiers, TypeScript.PullElementFlags.Ambient) || isParsingAmbientModule(enumDecl, context) || context.isDeclareFile) {
            declFlags |= TypeScript.PullElementFlags.Ambient;
        }

        // Consider an enum 'always initialized'.
        declFlags |= TypeScript.PullElementFlags.Enum;
        var kind = TypeScript.PullElementKind.Enum;

        var enumDeclaration = new TypeScript.NormalPullDecl(enumName, enumDecl.identifier.text(), kind, declFlags, context.getParent());
        context.setDeclForAST(enumDecl, enumDeclaration);
        context.setASTForDecl(enumDeclaration, enumDecl);

        // create the value decl
        var valueDecl = new TypeScript.NormalPullDecl(enumDeclaration.name, enumDeclaration.getDisplayName(), TypeScript.PullElementKind.Variable, enumDeclaration.flags, context.getParent());
        enumDeclaration.setValueDecl(valueDecl);
        context.setASTForDecl(valueDecl, enumDecl);

        context.pushParent(enumDeclaration);
    }

    function createEnumElementDecls(propertyDecl, context) {
        var parent = context.getParent();

        var decl = new TypeScript.PullEnumElementDecl(TypeScript.tokenValueText(propertyDecl.propertyName), propertyDecl.propertyName.text(), parent);
        context.setDeclForAST(propertyDecl, decl);
        context.setASTForDecl(decl, propertyDecl);
        // Note: it is intentional that a enum element does not get added to hte context stack.  An
        // enum element does not introduce a new name scope, so it shouldn't be in the context decl stack.
        // context.pushParent(decl);
    }

    function preCollectModuleDecls(moduleDecl, context) {
        var declFlags = 0 /* None */;

        var moduleContainsExecutableCode = containsExecutableCode(moduleDecl.moduleElements);

        var isDynamic = moduleDecl.stringLiteral !== null;

        if ((TypeScript.hasModifier(moduleDecl.modifiers, 1 /* Exported */) || isParsingAmbientModule(moduleDecl, context)) && !containingModuleHasExportAssignment(moduleDecl)) {
            declFlags |= 1 /* Exported */;
        }

        if (TypeScript.hasModifier(moduleDecl.modifiers, TypeScript.PullElementFlags.Ambient) || isParsingAmbientModule(moduleDecl, context) || context.isDeclareFile) {
            declFlags |= TypeScript.PullElementFlags.Ambient;
        }

        var kind = isDynamic ? TypeScript.PullElementKind.DynamicModule : TypeScript.PullElementKind.Container;

        if (moduleDecl.stringLiteral) {
            var valueText = TypeScript.quoteStr(TypeScript.tokenValueText(moduleDecl.stringLiteral));
            var text = moduleDecl.stringLiteral.text();

            var decl = new TypeScript.NormalPullDecl(valueText, text, kind, declFlags, context.getParent());

            context.setDeclForAST(moduleDecl, decl);
            context.setDeclForAST(moduleDecl.stringLiteral, decl);
            context.setASTForDecl(decl, moduleDecl.stringLiteral);

            if (!moduleElementsHasExportAssignment(moduleDecl.moduleElements) || moduleContainsExecutableCode) {
                createModuleVariableDecl(decl, moduleDecl.stringLiteral, context);
            }

            context.pushParent(decl);
        } else {
            // Module has a name or dotted name.
            var moduleNames = TypeScript.ASTHelpers.getModuleNames(moduleDecl.name);
            for (var i = 0, n = moduleNames.length; i < n; i++) {
                var moduleName = moduleNames[i];

                // All the inner module decls are exported.
                var specificFlags = declFlags;
                if (i > 0) {
                    specificFlags |= 1 /* Exported */;
                }

                var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(moduleName), moduleName.text(), kind, specificFlags, context.getParent());

                //// The innermost moduleDecl maps to the entire ModuleDeclaration node.
                //// All the other ones map to the name node.  i.e. module A.B.C { }
                ////
                //// The decl for C points to the entire module declaration.  The decls for A and B
                //// will point at the A and B nodes respectively.
                //var ast = (i === (moduleName.length - 1))
                //    ? moduleDecl
                //    : moduleName;
                context.setDeclForAST(moduleDecl, decl);
                context.setDeclForAST(moduleName, decl);
                context.setASTForDecl(decl, moduleName);

                if (moduleContainsExecutableCode) {
                    createModuleVariableDecl(decl, moduleName, context);
                }

                context.pushParent(decl);
            }
        }
    }

    function createModuleVariableDecl(decl, moduleNameAST, context) {
        decl.setFlags(decl.flags | getInitializationFlag(decl));

        // create the value decl
        var valueDecl = new TypeScript.NormalPullDecl(decl.name, decl.getDisplayName(), TypeScript.PullElementKind.Variable, decl.flags, context.getParent());
        decl.setValueDecl(valueDecl);
        context.setASTForDecl(valueDecl, moduleNameAST);
    }

    function containsExecutableCode(members) {
        for (var i = 0, n = members.length; i < n; i++) {
            var member = members[i];

            // October 11, 2013
            // Internal modules are either instantiated or non-instantiated. A non-instantiated
            // module is an internal module containing only interface types and other non -
            // instantiated modules.
            //
            // Note: small spec deviation.  We don't consider an import statement sufficient to
            // consider a module instantiated (except the case of 'export import' handled below ).
            // After all, if there is an import, but no actual code that references the imported value,
            // then there's no need to emit the import or the module.
            if (member.kind() === 130 /* ModuleDeclaration */) {
                var moduleDecl = member;

                // If we have a module in us, and it contains executable code, then we
                // contain executable code.
                if (containsExecutableCode(moduleDecl.moduleElements)) {
                    return true;
                }
            } else if (member.kind() === 133 /* ImportDeclaration */) {
                // pessimistically assume 'export import' declaration will be the alias to something instantiated
                // we cannot figure out it exactly until the resolution time.
                if (TypeScript.hasModifier(member.modifiers, 1 /* Exported */)) {
                    return true;
                }
            } else if (member.kind() !== 128 /* InterfaceDeclaration */ && member.kind() !== 134 /* ExportAssignment */) {
                // In case of export assignment we should be really checking meaning of Export assignment identifier, but thats TODO for later
                // If we contain anything that's not an interface declaration, then we contain
                // executable code.
                return true;
            }
        }

        return false;
    }

    function preCollectClassDecls(classDecl, context) {
        var declFlags = 0 /* None */;

        if ((TypeScript.hasModifier(classDecl.modifiers, 1 /* Exported */) || isParsingAmbientModule(classDecl, context)) && !containingModuleHasExportAssignment(classDecl)) {
            declFlags |= 1 /* Exported */;
        }

        if (TypeScript.hasModifier(classDecl.modifiers, TypeScript.PullElementFlags.Ambient) || isParsingAmbientModule(classDecl, context) || context.isDeclareFile) {
            declFlags |= TypeScript.PullElementFlags.Ambient;
        }

        var parent = context.getParent();

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(classDecl.identifier), classDecl.identifier.text(), TypeScript.PullElementKind.Class, declFlags, parent);

        var constructorDecl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(classDecl.identifier), classDecl.identifier.text(), TypeScript.PullElementKind.Variable, declFlags | TypeScript.PullElementFlags.ClassConstructorVariable, parent);

        decl.setValueDecl(constructorDecl);

        context.setDeclForAST(classDecl, decl);
        context.setASTForDecl(decl, classDecl);
        context.setASTForDecl(constructorDecl, classDecl);

        context.pushParent(decl);
    }

    function preCollectObjectTypeDecls(objectType, context) {
        // if this is the 'body' of an interface declaration, then we don't want to create a decl
        // here.  We want the interface decl to be the parent decl of all the members we visit.
        if (objectType.parent.kind() === 128 /* InterfaceDeclaration */) {
            return;
        }

        var declFlags = 0 /* None */;

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl("", "", TypeScript.PullElementKind.ObjectType, declFlags, parent);
        context.setDeclForAST(objectType, decl);
        context.setASTForDecl(decl, objectType);

        context.pushParent(decl);
    }

    function preCollectInterfaceDecls(interfaceDecl, context) {
        var declFlags = 0 /* None */;

        if ((TypeScript.hasModifier(interfaceDecl.modifiers, 1 /* Exported */) || isParsingAmbientModule(interfaceDecl, context)) && !containingModuleHasExportAssignment(interfaceDecl)) {
            declFlags |= 1 /* Exported */;
        }

        var parent = context.getParent();

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(interfaceDecl.identifier), interfaceDecl.identifier.text(), TypeScript.PullElementKind.Interface, declFlags, parent);
        context.setDeclForAST(interfaceDecl, decl);
        context.setASTForDecl(decl, interfaceDecl);

        context.pushParent(decl);
    }

    function preCollectParameterDecl(argDecl, context) {
        var declFlags = 0 /* None */;

        if (TypeScript.hasModifier(argDecl.modifiers, TypeScript.PullElementFlags.Private)) {
            declFlags |= TypeScript.PullElementFlags.Private;
        } else {
            declFlags |= TypeScript.PullElementFlags.Public;
        }

        if (argDecl.questionToken !== null || argDecl.equalsValueClause !== null || argDecl.dotDotDotToken !== null) {
            declFlags |= TypeScript.PullElementFlags.Optional;
        }

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(argDecl.identifier), argDecl.identifier.text(), TypeScript.PullElementKind.Parameter, declFlags, parent);

        // If it has a default arg, record the fact that the parent has default args (we will need this during resolution)
        if (argDecl.equalsValueClause) {
            parent.flags |= TypeScript.PullElementFlags.HasDefaultArgs;
        }

        if (parent.kind === TypeScript.PullElementKind.ConstructorMethod) {
            decl.setFlag(TypeScript.PullElementFlags.ConstructorParameter);
        }

        // if it's a property type, we'll need to add it to the parent's parent as well
        var isPublicOrPrivate = TypeScript.hasModifier(argDecl.modifiers, TypeScript.PullElementFlags.Public) || TypeScript.hasModifier(argDecl.modifiers, TypeScript.PullElementFlags.Private);
        var isInConstructor = parent.kind === TypeScript.PullElementKind.ConstructorMethod;
        if (isPublicOrPrivate && isInConstructor) {
            var parentsParent = context.parentChain[context.parentChain.length - 2];

            // optional parameters don't introduce optional properties - always drop isOptional flag on the property declaration
            var propDeclFlags = declFlags & ~TypeScript.PullElementFlags.Optional;
            var propDecl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(argDecl.identifier), argDecl.identifier.text(), TypeScript.PullElementKind.Property, propDeclFlags, parentsParent);
            propDecl.setValueDecl(decl);
            decl.setFlag(TypeScript.PullElementFlags.PropertyParameter);
            propDecl.setFlag(TypeScript.PullElementFlags.PropertyParameter);

            if (parent.kind === TypeScript.PullElementKind.ConstructorMethod) {
                propDecl.setFlag(TypeScript.PullElementFlags.ConstructorParameter);
            }

            context.setASTForDecl(decl, argDecl);
            context.setASTForDecl(propDecl, argDecl);
            context.setDeclForAST(argDecl, propDecl);
        } else {
            context.setASTForDecl(decl, argDecl);
            context.setDeclForAST(argDecl, decl);
        }

        // Record this decl in its parent in the declGroup with the corresponding name
        parent.addVariableDeclToGroup(decl);
        // Note: it is intentional that a parameter does not get added to hte context stack.  A
        // parameter does not introduce a new name scope, so it shouldn't be in the context decl stack.
        // context.pushParent(decl);
    }

    function preCollectTypeParameterDecl(typeParameterDecl, context) {
        var declFlags = 0 /* None */;

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(typeParameterDecl.identifier), typeParameterDecl.identifier.text(), TypeScript.PullElementKind.TypeParameter, declFlags, parent);
        context.setASTForDecl(decl, typeParameterDecl);
        context.setDeclForAST(typeParameterDecl, decl);
        // Note: it is intentional that a type parameter does not get added to hte context stack.
        // A type parameter does not introduce a new name scope, so it shouldn't be in the
        // context decl stack.
        // context.pushParent(decl);
    }

    // interface properties
    function createPropertySignature(propertyDecl, context) {
        var declFlags = TypeScript.PullElementFlags.Public;
        var parent = context.getParent();
        var declType = TypeScript.PullElementKind.Property;

        if (propertyDecl.questionToken !== null) {
            declFlags |= TypeScript.PullElementFlags.Optional;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(propertyDecl.propertyName), propertyDecl.propertyName.text(), declType, declFlags, parent);
        context.setDeclForAST(propertyDecl, decl);
        context.setASTForDecl(decl, propertyDecl);
        // Note: it is intentional that a var decl does not get added to hte context stack.  A var
        // decl does not introduce a new name scope, so it shouldn't be in the context decl stack.
        // context.pushParent(decl);
    }

    // class member variables
    function createMemberVariableDeclaration(memberDecl, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.Property;

        if (TypeScript.hasModifier(memberDecl.modifiers, TypeScript.PullElementFlags.Private)) {
            declFlags |= TypeScript.PullElementFlags.Private;
        } else {
            declFlags |= TypeScript.PullElementFlags.Public;
        }

        if (TypeScript.hasModifier(memberDecl.modifiers, TypeScript.PullElementFlags.Static)) {
            declFlags |= TypeScript.PullElementFlags.Static;
        }

        var parent = context.getParent();

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(memberDecl.variableDeclarator.propertyName), memberDecl.variableDeclarator.propertyName.text(), declType, declFlags, parent);
        context.setDeclForAST(memberDecl, decl);
        context.setDeclForAST(memberDecl.variableDeclarator, decl);
        context.setASTForDecl(decl, memberDecl);
        // Note: it is intentional that a var decl does not get added to hte context stack.  A var
        // decl does not introduce a new name scope, so it shouldn't be in the context decl stack.
        // context.pushParent(decl);
    }

    function createVariableDeclaration(varDecl, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.Variable;

        var modifiers = TypeScript.ASTHelpers.getVariableDeclaratorModifiers(varDecl);
        if ((TypeScript.hasModifier(modifiers, 1 /* Exported */) || isParsingAmbientModule(varDecl, context)) && !containingModuleHasExportAssignment(varDecl)) {
            declFlags |= 1 /* Exported */;
        }

        if (TypeScript.hasModifier(modifiers, TypeScript.PullElementFlags.Ambient) || isParsingAmbientModule(varDecl, context) || context.isDeclareFile) {
            declFlags |= TypeScript.PullElementFlags.Ambient;
        }

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(varDecl.propertyName), varDecl.propertyName.text(), declType, declFlags, parent);
        context.setDeclForAST(varDecl, decl);
        context.setASTForDecl(decl, varDecl);

        if (parent) {
            // Record this decl in its parent in the declGroup with the corresponding name
            parent.addVariableDeclToGroup(decl);
        }
        // Note: it is intentional that a var decl does not get added to hte context stack.  A var
        // decl does not introduce a new name scope, so it shouldn't be in the context decl stack.
        // context.pushParent(decl);
    }

    function preCollectVarDecls(ast, context) {
        if (ast.parent.kind() === 136 /* MemberVariableDeclaration */) {
            // Already handled this node.
            return;
        }

        var varDecl = ast;
        createVariableDeclaration(varDecl, context);
    }

    // function type expressions
    function createFunctionTypeDeclaration(functionTypeDeclAST, context) {
        var declFlags = TypeScript.PullElementFlags.Signature;
        var declType = TypeScript.PullElementKind.FunctionType;

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl("", "", declType, declFlags, parent);
        context.setDeclForAST(functionTypeDeclAST, decl);
        context.setASTForDecl(decl, functionTypeDeclAST);

        context.pushParent(decl);
    }

    // constructor types
    function createConstructorTypeDeclaration(constructorTypeDeclAST, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.ConstructorType;

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl("", "", declType, declFlags, parent);
        context.setDeclForAST(constructorTypeDeclAST, decl);
        context.setASTForDecl(decl, constructorTypeDeclAST);

        context.pushParent(decl);
    }

    // function declaration
    function createFunctionDeclaration(funcDeclAST, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.Function;

        if ((TypeScript.hasModifier(funcDeclAST.modifiers, 1 /* Exported */) || isParsingAmbientModule(funcDeclAST, context)) && !containingModuleHasExportAssignment(funcDeclAST)) {
            declFlags |= 1 /* Exported */;
        }

        if (TypeScript.hasModifier(funcDeclAST.modifiers, TypeScript.PullElementFlags.Ambient) || isParsingAmbientModule(funcDeclAST, context) || context.isDeclareFile) {
            declFlags |= TypeScript.PullElementFlags.Ambient;
        }

        if (!funcDeclAST.block) {
            declFlags |= TypeScript.PullElementFlags.Signature;
        }

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(funcDeclAST.identifier), funcDeclAST.identifier.text(), declType, declFlags, parent);
        context.setDeclForAST(funcDeclAST, decl);
        context.setASTForDecl(decl, funcDeclAST);

        context.pushParent(decl);
    }

    // function expression
    function createAnyFunctionExpressionDeclaration(functionExpressionDeclAST, id, context, displayName) {
        if (typeof displayName === "undefined") { displayName = null; }
        var declFlags = 0 /* None */;

        if (functionExpressionDeclAST.kind() === 219 /* SimpleArrowFunctionExpression */ || functionExpressionDeclAST.kind() === 218 /* ParenthesizedArrowFunctionExpression */) {
            declFlags |= TypeScript.PullElementFlags.ArrowFunction;
        }

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var name = id ? id.text() : "";
        var displayNameText = displayName ? displayName.text() : "";
        var decl = new TypeScript.PullFunctionExpressionDecl(name, declFlags, parent, displayNameText);
        context.setDeclForAST(functionExpressionDeclAST, decl);
        context.setASTForDecl(decl, functionExpressionDeclAST);

        context.pushParent(decl);
    }

    function createMemberFunctionDeclaration(funcDecl, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.Method;

        if (TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Static)) {
            declFlags |= TypeScript.PullElementFlags.Static;
        }

        if (TypeScript.hasModifier(funcDecl.modifiers, TypeScript.PullElementFlags.Private)) {
            declFlags |= TypeScript.PullElementFlags.Private;
        } else {
            declFlags |= TypeScript.PullElementFlags.Public;
        }

        if (!funcDecl.block) {
            declFlags |= TypeScript.PullElementFlags.Signature;
        }

        var parent = context.getParent();

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(funcDecl.propertyName), funcDecl.propertyName.text(), declType, declFlags, parent);
        context.setDeclForAST(funcDecl, decl);
        context.setASTForDecl(decl, funcDecl);

        context.pushParent(decl);
    }

    // index signatures
    function createIndexSignatureDeclaration(indexSignatureDeclAST, context) {
        var declFlags = TypeScript.PullElementFlags.Signature;
        var declType = TypeScript.PullElementKind.IndexSignature;

        var parent = context.getParent();

        var decl = new TypeScript.NormalPullDecl("", "", declType, declFlags, parent);
        context.setDeclForAST(indexSignatureDeclAST, decl);
        context.setASTForDecl(decl, indexSignatureDeclAST);

        context.pushParent(decl);
    }

    // call signatures
    function createCallSignatureDeclaration(callSignature, context) {
        var isChildOfObjectType = callSignature.parent && callSignature.parent.parent && callSignature.parent.kind() === 2 /* SeparatedList */ && callSignature.parent.parent.kind() === 122 /* ObjectType */;

        if (!isChildOfObjectType) {
            // This was a call signature that was part of some other entity (like a function
            // declaration or construct signature).  Those are already handled specially and
            // we don't want to end up making another call signature for them.  We only want
            // to make an actual call signature if we're a standalone call signature in an
            // object/interface type.
            return;
        }

        var declFlags = TypeScript.PullElementFlags.Signature;
        var declType = TypeScript.PullElementKind.CallSignature;

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl("", "", declType, declFlags, parent);
        context.setDeclForAST(callSignature, decl);
        context.setASTForDecl(decl, callSignature);

        context.pushParent(decl);
    }

    function createMethodSignatureDeclaration(method, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.Method;

        declFlags |= TypeScript.PullElementFlags.Public;
        declFlags |= TypeScript.PullElementFlags.Signature;

        if (method.questionToken !== null) {
            declFlags |= TypeScript.PullElementFlags.Optional;
        }

        var parent = context.getParent();

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(method.propertyName), method.propertyName.text(), declType, declFlags, parent);
        context.setDeclForAST(method, decl);
        context.setASTForDecl(decl, method);

        context.pushParent(decl);
    }

    // construct signatures
    function createConstructSignatureDeclaration(constructSignatureDeclAST, context) {
        var declFlags = TypeScript.PullElementFlags.Signature;
        var declType = TypeScript.PullElementKind.ConstructSignature;

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl("", "", declType, declFlags, parent);
        context.setDeclForAST(constructSignatureDeclAST, decl);
        context.setASTForDecl(decl, constructSignatureDeclAST);

        context.pushParent(decl);
    }

    // class constructors
    function createClassConstructorDeclaration(constructorDeclAST, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.ConstructorMethod;

        if (!constructorDeclAST.block) {
            declFlags |= TypeScript.PullElementFlags.Signature;
        }

        var parent = context.getParent();

        if (parent) {
            // if the parent is exported, the constructor decl must be as well
            var parentFlags = parent.flags;

            if (parentFlags & 1 /* Exported */) {
                declFlags |= 1 /* Exported */;
            }
        }

        var decl = new TypeScript.NormalPullDecl(parent.name, parent.getDisplayName(), declType, declFlags, parent);
        context.setDeclForAST(constructorDeclAST, decl);
        context.setASTForDecl(decl, constructorDeclAST);

        context.pushParent(decl);
    }

    function createGetAccessorDeclaration(getAccessorDeclAST, context) {
        var declFlags = TypeScript.PullElementFlags.Public;
        var declType = TypeScript.PullElementKind.GetAccessor;

        if (TypeScript.hasModifier(getAccessorDeclAST.modifiers, TypeScript.PullElementFlags.Static)) {
            declFlags |= TypeScript.PullElementFlags.Static;
        }

        if (TypeScript.hasModifier(getAccessorDeclAST.modifiers, TypeScript.PullElementFlags.Private)) {
            declFlags |= TypeScript.PullElementFlags.Private;
        } else {
            declFlags |= TypeScript.PullElementFlags.Public;
        }

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(getAccessorDeclAST.propertyName), getAccessorDeclAST.propertyName.text(), declType, declFlags, parent);
        context.setDeclForAST(getAccessorDeclAST, decl);
        context.setASTForDecl(decl, getAccessorDeclAST);

        context.pushParent(decl);
    }

    function createFunctionExpressionDeclaration(expression, context) {
        createAnyFunctionExpressionDeclaration(expression, expression.identifier, context);
    }

    function createSetAccessorDeclaration(setAccessorDeclAST, context) {
        var declFlags = TypeScript.PullElementFlags.Public;
        var declType = TypeScript.PullElementKind.SetAccessor;

        if (TypeScript.hasModifier(setAccessorDeclAST.modifiers, TypeScript.PullElementFlags.Static)) {
            declFlags |= TypeScript.PullElementFlags.Static;
        }

        if (TypeScript.hasModifier(setAccessorDeclAST.modifiers, TypeScript.PullElementFlags.Private)) {
            declFlags |= TypeScript.PullElementFlags.Private;
        } else {
            declFlags |= TypeScript.PullElementFlags.Public;
        }

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(setAccessorDeclAST.propertyName), setAccessorDeclAST.propertyName.text(), declType, declFlags, parent);
        context.setDeclForAST(setAccessorDeclAST, decl);
        context.setASTForDecl(decl, setAccessorDeclAST);

        context.pushParent(decl);
    }

    function preCollectCatchDecls(ast, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.CatchBlock;

        var parent = context.getParent();

        if (parent && (parent.kind === TypeScript.PullElementKind.WithBlock || (parent.flags & TypeScript.PullElementFlags.DeclaredInAWithBlock))) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl("", "", declType, declFlags, parent);
        context.setDeclForAST(ast, decl);
        context.setASTForDecl(decl, ast);

        context.pushParent(decl);

        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.CatchVariable;

        // Create a decl for the catch clause variable.
        var parent = context.getParent();

        if (TypeScript.hasFlag(parent.flags, TypeScript.PullElementFlags.DeclaredInAWithBlock)) {
            declFlags |= TypeScript.PullElementFlags.DeclaredInAWithBlock;
        }

        var decl = new TypeScript.NormalPullDecl(TypeScript.tokenValueText(ast.identifier), ast.identifier.text(), declType, declFlags, parent);
        context.setDeclForAST(ast.identifier, decl);
        context.setASTForDecl(decl, ast.identifier);

        if (parent) {
            // Record this decl in its parent in the declGroup with the corresponding name
            parent.addVariableDeclToGroup(decl);
        }
    }

    function preCollectWithDecls(ast, context) {
        var declFlags = 0 /* None */;
        var declType = TypeScript.PullElementKind.WithBlock;

        var parent = context.getParent();

        var decl = new TypeScript.NormalPullDecl("", "", declType, declFlags, parent);
        context.setDeclForAST(ast, decl);
        context.setASTForDecl(decl, ast);

        context.pushParent(decl);
    }

    function preCollectObjectLiteralDecls(ast, context) {
        var decl = new TypeScript.NormalPullDecl("", "", TypeScript.PullElementKind.ObjectLiteral, 0 /* None */, context.getParent());

        context.setDeclForAST(ast, decl);
        context.setASTForDecl(decl, ast);

        context.pushParent(decl);
    }

    function preCollectSimplePropertyAssignmentDecls(propertyAssignment, context) {
        var assignmentText = TypeScript.getPropertyAssignmentNameTextFromIdentifier(propertyAssignment.propertyName);

        var decl = new TypeScript.NormalPullDecl(assignmentText.memberName, assignmentText.actualText, TypeScript.PullElementKind.Property, TypeScript.PullElementFlags.Public, context.getParent());

        context.setDeclForAST(propertyAssignment, decl);
        context.setASTForDecl(decl, propertyAssignment);
        // Note: it is intentional that a property assignment does not get added to hte context
        // stack.  A prop assignment does not introduce a new name scope, so it shouldn't be in
        // the context decl stack.
        // context.pushParent(decl);
    }

    function preCollectFunctionPropertyAssignmentDecls(propertyAssignment, context) {
        var assignmentText = TypeScript.getPropertyAssignmentNameTextFromIdentifier(propertyAssignment.propertyName);

        var decl = new TypeScript.NormalPullDecl(assignmentText.memberName, assignmentText.actualText, TypeScript.PullElementKind.Property, TypeScript.PullElementFlags.Public, context.getParent());

        context.setDeclForAST(propertyAssignment, decl);
        context.setASTForDecl(decl, propertyAssignment);

        createAnyFunctionExpressionDeclaration(propertyAssignment, propertyAssignment.propertyName, context, propertyAssignment.propertyName);
    }

    function preCollectDecls(ast, context) {
        switch (ast.kind()) {
            case 120 /* SourceUnit */:
                preCollectScriptDecls(ast, context);
                break;
            case 132 /* EnumDeclaration */:
                preCollectEnumDecls(ast, context);
                break;
            case 243 /* EnumElement */:
                createEnumElementDecls(ast, context);
                break;
            case 130 /* ModuleDeclaration */:
                preCollectModuleDecls(ast, context);
                break;
            case 131 /* ClassDeclaration */:
                preCollectClassDecls(ast, context);
                break;
            case 128 /* InterfaceDeclaration */:
                preCollectInterfaceDecls(ast, context);
                break;
            case 122 /* ObjectType */:
                preCollectObjectTypeDecls(ast, context);
                break;
            case 242 /* Parameter */:
                preCollectParameterDecl(ast, context);
                break;
            case 136 /* MemberVariableDeclaration */:
                createMemberVariableDeclaration(ast, context);
                break;
            case 141 /* PropertySignature */:
                createPropertySignature(ast, context);
                break;
            case 225 /* VariableDeclarator */:
                preCollectVarDecls(ast, context);
                break;
            case 137 /* ConstructorDeclaration */:
                createClassConstructorDeclaration(ast, context);
                break;
            case 139 /* GetAccessor */:
                createGetAccessorDeclaration(ast, context);
                break;
            case 140 /* SetAccessor */:
                createSetAccessorDeclaration(ast, context);
                break;
            case 222 /* FunctionExpression */:
                createFunctionExpressionDeclaration(ast, context);
                break;
            case 135 /* MemberFunctionDeclaration */:
                createMemberFunctionDeclaration(ast, context);
                break;
            case 144 /* IndexSignature */:
                createIndexSignatureDeclaration(ast, context);
                break;
            case 123 /* FunctionType */:
                createFunctionTypeDeclaration(ast, context);
                break;
            case 125 /* ConstructorType */:
                createConstructorTypeDeclaration(ast, context);
                break;
            case 142 /* CallSignature */:
                createCallSignatureDeclaration(ast, context);
                break;
            case 143 /* ConstructSignature */:
                createConstructSignatureDeclaration(ast, context);
                break;
            case 145 /* MethodSignature */:
                createMethodSignatureDeclaration(ast, context);
                break;
            case 129 /* FunctionDeclaration */:
                createFunctionDeclaration(ast, context);
                break;
            case 219 /* SimpleArrowFunctionExpression */:
            case 218 /* ParenthesizedArrowFunctionExpression */:
                createAnyFunctionExpressionDeclaration(ast, null, context);
                break;
            case 133 /* ImportDeclaration */:
                preCollectImportDecls(ast, context);
                break;
            case 238 /* TypeParameter */:
                preCollectTypeParameterDecl(ast, context);
                break;
            case 236 /* CatchClause */:
                preCollectCatchDecls(ast, context);
                break;
            case 163 /* WithStatement */:
                preCollectWithDecls(ast, context);
                break;
            case 215 /* ObjectLiteralExpression */:
                preCollectObjectLiteralDecls(ast, context);
                break;
            case 240 /* SimplePropertyAssignment */:
                preCollectSimplePropertyAssignmentDecls(ast, context);
                break;
            case 241 /* FunctionPropertyAssignment */:
                preCollectFunctionPropertyAssignmentDecls(ast, context);
                break;
        }
    }

    function isContainer(decl) {
        return decl.kind === TypeScript.PullElementKind.Container || decl.kind === TypeScript.PullElementKind.DynamicModule || decl.kind === TypeScript.PullElementKind.Enum;
    }

    function getInitializationFlag(decl) {
        if (decl.kind & TypeScript.PullElementKind.Container) {
            return TypeScript.PullElementFlags.InitializedModule;
        } else if (decl.kind & TypeScript.PullElementKind.DynamicModule) {
            return TypeScript.PullElementFlags.InitializedDynamicModule;
        }

        return 0 /* None */;
    }

    function hasInitializationFlag(decl) {
        var kind = decl.kind;

        if (kind & TypeScript.PullElementKind.Container) {
            return (decl.flags & TypeScript.PullElementFlags.InitializedModule) !== 0;
        } else if (kind & TypeScript.PullElementKind.DynamicModule) {
            return (decl.flags & TypeScript.PullElementFlags.InitializedDynamicModule) !== 0;
        }

        return false;
    }

    function postCollectDecls(ast, context) {
        var currentDecl = context.getParent();

        // We only want to pop the module decls when we're done with the module itself, and not
        // when we are done with the module names.
        if (ast.kind() === 11 /* IdentifierName */ || ast.kind() === 14 /* StringLiteral */) {
            if (currentDecl.kind === TypeScript.PullElementKind.Container || currentDecl.kind === TypeScript.PullElementKind.DynamicModule) {
                return;
            }
        }

        if (ast.kind() === 130 /* ModuleDeclaration */) {
            var moduleDeclaration = ast;
            if (moduleDeclaration.stringLiteral) {
                TypeScript.Debug.assert(currentDecl.ast() === moduleDeclaration.stringLiteral);
                context.popParent();
            } else {
                var moduleNames = TypeScript.ASTHelpers.getModuleNames(moduleDeclaration.name);
                for (var i = moduleNames.length - 1; i >= 0; i--) {
                    var moduleName = moduleNames[i];
                    TypeScript.Debug.assert(currentDecl.ast() === moduleName);
                    context.popParent();
                    currentDecl = context.getParent();
                }
            }
        }

        if (ast.kind() === 132 /* EnumDeclaration */) {
            // Now that we've created all the child decls for the enum elements, determine what
            // (if any) their constant values should be.
            computeEnumElementConstantValues(ast, currentDecl, context);
        }

        while (currentDecl.getParentDecl() && currentDecl.ast() === ast) {
            context.popParent();
            currentDecl = context.getParent();
        }
    }

    function computeEnumElementConstantValues(ast, enumDecl, context) {
        TypeScript.Debug.assert(enumDecl.kind === TypeScript.PullElementKind.Enum);

        // If this is a non ambient enum, then it starts with a constant section of enum elements.
        // Thus, elements without an initializer in these sections will be assumed to have a
        // constant value.
        //
        // However, if this an enum in an ambient context, then non initialized elements are
        // thought to have a computed value and are not in a constant section.
        var isAmbientEnum = TypeScript.hasFlag(enumDecl.flags, TypeScript.PullElementFlags.Ambient);
        var inConstantSection = !isAmbientEnum;
        var currentConstantValue = 0;
        var enumMemberDecls = enumDecl.getChildDecls();

        for (var i = 0, n = ast.enumElements.length; i < n; i++) {
            var enumElement = ast.enumElements[i];
            var enumElementDecl = TypeScript.ArrayUtilities.first(enumMemberDecls, function (d) {
                return d.ast() === enumElement;
            });

            TypeScript.Debug.assert(enumElementDecl.kind === TypeScript.PullElementKind.EnumMember);

            if (enumElement.equalsValueClause === null) {
                // Didn't have an initializer.  If we're in a constant section, then this appears
                // to have the value of the current constant.  If we're in a non-constant section
                // then this gets no value.
                if (inConstantSection) {
                    enumElementDecl.constantValue = currentConstantValue;
                    currentConstantValue++;
                }
            } else {
                // Enum element had an initializer.  If it's a constant, then then enum gets that
                // value, and we transition to (or stay in) a constant section (as long as we're
                // not in an ambient context.
                //
                // If it's not a constant, then we transition to a non-constant section.
                enumElementDecl.constantValue = computeEnumElementConstantValue(enumElement.equalsValueClause.value, enumMemberDecls, context);
                if (enumElementDecl.constantValue !== null && !isAmbientEnum) {
                    // This enum element had a constant value.  We're now in a constant section.
                    // Any successive enum elements should get their values from this constant
                    // value onwards.
                    inConstantSection = true;
                    currentConstantValue = enumElementDecl.constantValue + 1;
                } else {
                    // Didn't get a constant value.  We're not in a constant section.
                    inConstantSection = false;
                }
            }

            TypeScript.Debug.assert(enumElementDecl.constantValue !== undefined);
        }
    }

    function computeEnumElementConstantValue(expression, enumMemberDecls, context) {
        TypeScript.Debug.assert(expression);

        if (TypeScript.ASTHelpers.isIntegerLiteralAST(expression)) {
            // Always produce a value for an integer literal.
            var token;
            switch (expression.kind()) {
                case 164 /* PlusExpression */:
                case 165 /* NegateExpression */:
                    token = expression.operand;
                    break;
                default:
                    token = expression;
            }

            var value = TypeScript.tokenValue(token);
            return value && expression.kind() === 165 /* NegateExpression */ ? -value : value;
        } else if (context.propagateEnumConstants) {
            switch (expression.kind()) {
                case 11 /* IdentifierName */:
                    // If it's a name, see if we already had an enum value named this.  If so,
                    // return that value.  Note, only search backward in the enum for a match.
                    var name = expression;
                    var matchingEnumElement = TypeScript.ArrayUtilities.firstOrDefault(enumMemberDecls, function (d) {
                        return d.name === TypeScript.tokenValueText(name);
                    });

                    return matchingEnumElement ? matchingEnumElement.constantValue : null;

                case 202 /* LeftShiftExpression */:
                    // Handle the common case of a left shifted value.
                    var binaryExpression = expression;
                    var left = computeEnumElementConstantValue(binaryExpression.left, enumMemberDecls, context);
                    var right = computeEnumElementConstantValue(binaryExpression.right, enumMemberDecls, context);
                    if (left === null || right === null) {
                        return null;
                    }

                    return left << right;

                case 189 /* BitwiseOrExpression */:
                    // Handle the common case of an or'ed value.
                    var binaryExpression = expression;
                    var left = computeEnumElementConstantValue(binaryExpression.left, enumMemberDecls, context);
                    var right = computeEnumElementConstantValue(binaryExpression.right, enumMemberDecls, context);
                    if (left === null || right === null) {
                        return null;
                    }

                    return left | right;
            }

            // TODO: add more cases.
            return null;
        } else {
            // Wasn't an integer literal, and we're not aggressively propagating constants.
            // There is no constant value for this expression.
            return null;
        }
    }

    (function (DeclarationCreator) {
        function create(document, compilationSettings) {
            var start = new Date().getTime();
            var declCollectionContext = new DeclCollectionContext(document, compilationSettings.propagateEnumConstants());

            // create decls
            TypeScript.getAstWalkerFactory().simpleWalk(document.sourceUnit(), preCollectDecls, postCollectDecls, declCollectionContext);
            TypeScript.createDeclarationsTime += new Date().getTime() - start;
            return declCollectionContext.getParent();
        }
        DeclarationCreator.create = create;
    })(TypeScript.DeclarationCreator || (TypeScript.DeclarationCreator = {}));
    var DeclarationCreator = TypeScript.DeclarationCreator;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    var PullSymbolBinder = (function () {
        function PullSymbolBinder(semanticInfoChain) {
            this.semanticInfoChain = semanticInfoChain;
            this.declsBeingBound = [];
            this.inBindingOtherDeclsWalker = new TypeScript.PullHelpers.OtherPullDeclsWalker();
        }
        PullSymbolBinder.prototype.getParent = function (decl, returnInstanceType) {
            if (typeof returnInstanceType === "undefined") { returnInstanceType = false; }
            var parentDecl = decl.getParentDecl();

            if (parentDecl.kind === TypeScript.PullElementKind.Script) {
                return null;
            }

            var parent = parentDecl.getSymbol(this.semanticInfoChain);

            if (!parent && parentDecl && !parentDecl.hasBeenBound(this.semanticInfoChain)) {
                this.bindDeclToPullSymbol(parentDecl);
            }

            parent = parentDecl.getSymbol(this.semanticInfoChain);
            if (parent) {
                var parentDeclKind = parentDecl.kind;
                if (parentDeclKind === TypeScript.PullElementKind.GetAccessor) {
                    parent = parent.getGetter();
                } else if (parentDeclKind === TypeScript.PullElementKind.SetAccessor) {
                    parent = parent.getSetter();
                }
            }

            if (parent) {
                if (returnInstanceType && parent.isType() && parent.isContainer()) {
                    var instanceSymbol = parent.getInstanceSymbol();

                    if (instanceSymbol) {
                        return instanceSymbol.type;
                    }
                }

                return parent.type;
            }

            return null;
        };

        PullSymbolBinder.prototype.findDeclsInContext = function (startingDecl, declKind, searchGlobally) {
            if (!searchGlobally) {
                var parentDecl = startingDecl.getParentDecl();
                return parentDecl.searchChildDecls(startingDecl.name, declKind);
            }

            var contextSymbolPath = startingDecl.getParentPath();

            // next, link back up to the enclosing context
            if (contextSymbolPath.length) {
                var copyOfContextSymbolPath = [];

                for (var i = 0; i < contextSymbolPath.length; i++) {
                    if (contextSymbolPath[i].kind & TypeScript.PullElementKind.Script) {
                        continue;
                    }
                    copyOfContextSymbolPath[copyOfContextSymbolPath.length] = contextSymbolPath[i].name;
                }

                return this.semanticInfoChain.findDecls(copyOfContextSymbolPath, declKind);
            }
        };

        // Called by all the bind methods when searching for existing symbols to reuse. Returns the symbol, or null if it does not exist.
        PullSymbolBinder.prototype.getExistingSymbol = function (decl, searchKind, parent) {
            var lookingForValue = (searchKind & TypeScript.PullElementKind.SomeValue) !== 0;
            var lookingForType = (searchKind & TypeScript.PullElementKind.SomeType) !== 0;
            var lookingForContainer = (searchKind & TypeScript.PullElementKind.SomeContainer) !== 0;
            var name = decl.name;
            if (parent) {
                var isExported = (decl.flags & 1 /* Exported */) !== 0;

                // First search for a nonmember
                var prevSymbol = null;
                if (lookingForValue) {
                    prevSymbol = parent.findContainedNonMember(name);
                } else if (lookingForType) {
                    prevSymbol = parent.findContainedNonMemberType(name, searchKind);
                } else if (lookingForContainer) {
                    prevSymbol = parent.findContainedNonMemberContainer(name, searchKind);
                }
                var prevIsExported = !prevSymbol;
                if (!prevSymbol) {
                    if (lookingForValue) {
                        prevSymbol = parent.findMember(name, false);
                    } else if (lookingForType) {
                        prevSymbol = parent.findNestedType(name, searchKind);
                    } else if (lookingForContainer) {
                        prevSymbol = parent.findNestedContainer(name, searchKind);
                    }
                }

                // If they are both exported, then they should definitely merge
                if (isExported && prevIsExported) {
                    return prevSymbol;
                }
                if (prevSymbol) {
                    // Check if they have the same parent (we use the LAST declaration to get the most positive answer on this)
                    var prevDecls = prevSymbol.getDeclarations();
                    var lastPrevDecl = prevDecls[prevDecls.length - 1];
                    var parentDecl = decl.getParentDecl();
                    var prevParentDecl = lastPrevDecl && lastPrevDecl.getParentDecl();
                    if (parentDecl !== prevParentDecl) {
                        // no merge
                        return null;
                    }

                    // They share the same parent, so merge them
                    return prevSymbol;
                }
            } else {
                var parentDecl = decl.getParentDecl();
                if (parentDecl && parentDecl.kind === TypeScript.PullElementKind.Script) {
                    return this.semanticInfoChain.findTopLevelSymbol(name, searchKind, decl);
                } else {
                    // The decl is in a control block (catch/with) that has no parent symbol. Luckily this type of parent can only have one decl.
                    var prevDecls = parentDecl && parentDecl.searchChildDecls(name, searchKind);
                    return prevDecls[0] && prevDecls[0].getSymbol(this.semanticInfoChain);
                }
            }

            // Did not find a symbol
            return null;
        };

        // Reports an error and returns false if exports do not match. Otherwise, returns true.
        PullSymbolBinder.prototype.checkThatExportsMatch = function (decl, prevSymbol, reportError) {
            if (typeof reportError === "undefined") { reportError = true; }
            // Get export status of each (check against the last decl of the previous symbol)
            var isExported = (decl.flags & 1 /* Exported */) !== 0;
            var prevDecls = prevSymbol.getDeclarations();
            var prevIsExported = (prevDecls[prevDecls.length - 1].flags & 1 /* Exported */) !== 0;
            if ((isExported !== prevIsExported) && !prevSymbol.isSignature() && (decl.kind & TypeScript.PullElementKind.SomeSignature) === 0) {
                if (reportError) {
                    var ast = this.semanticInfoChain.getASTForDecl(decl);
                    this.semanticInfoChain.addDiagnosticFromAST(ast, TypeScript.DiagnosticCode.All_declarations_of_merged_declaration_0_must_be_exported_or_not_exported, [decl.getDisplayName()]);
                }
                return false;
            }

            return true;
        };

        PullSymbolBinder.prototype.getIndexForInsertingSignatureAtEndOfEnclosingDeclInSignatureList = function (signature, currentSignatures) {
            var signatureDecl = signature.getDeclarations()[0];
            TypeScript.Debug.assert(signatureDecl);
            var enclosingDecl = signatureDecl.getParentDecl();
            var indexToInsert = TypeScript.ArrayUtilities.indexOf(currentSignatures, function (someSignature) {
                return someSignature.getDeclarations()[0].getParentDecl() !== enclosingDecl;
            });
            return indexToInsert < 0 ? currentSignatures.length : indexToInsert;
        };

        //
        // decl binding
        //
        PullSymbolBinder.prototype.bindEnumDeclarationToPullSymbol = function (enumContainerDecl) {
            // 1. Test for existing decl - if it exists, use its symbol
            // 2. If no other decl exists, create a new symbol and use that one
            var enumName = enumContainerDecl.name;

            var enumContainerSymbol = null;
            var enumInstanceSymbol = null;
            var moduleInstanceTypeSymbol = null;

            var enumInstanceDecl = enumContainerDecl.getValueDecl();

            var enumDeclKind = enumContainerDecl.kind;

            var parent = this.getParent(enumContainerDecl);
            var parentInstanceSymbol = this.getParent(enumContainerDecl, true);
            var parentDecl = enumContainerDecl.getParentDecl();
            var enumAST = this.semanticInfoChain.getASTForDecl(enumContainerDecl);

            var isExported = enumContainerDecl.flags & 1 /* Exported */;

            var createdNewSymbol = false;

            enumContainerSymbol = this.getExistingSymbol(enumContainerDecl, TypeScript.PullElementKind.Enum, parent);

            if (enumContainerSymbol) {
                if (enumContainerSymbol.kind !== enumDeclKind) {
                    // duplicate symbol error
                    this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(enumAST.identifier, enumContainerDecl.getDisplayName());
                    enumContainerSymbol = null;
                } else if (!this.checkThatExportsMatch(enumContainerDecl, enumContainerSymbol)) {
                    enumContainerSymbol = null;
                }
            }

            if (enumContainerSymbol) {
                enumInstanceSymbol = enumContainerSymbol.getInstanceSymbol();
            } else {
                enumContainerSymbol = new TypeScript.PullContainerSymbol(enumName, enumDeclKind, this.semanticInfoChain);
                createdNewSymbol = true;

                if (!parent) {
                    this.semanticInfoChain.cacheGlobalSymbol(enumContainerSymbol, TypeScript.PullElementKind.Enum);
                }
            }

            // We add the declaration early so that during any recursive binding of other module decls with the same name, this declaration is present.
            enumContainerSymbol.addDeclaration(enumContainerDecl);
            enumContainerDecl.setSymbol(enumContainerSymbol, this.semanticInfoChain);

            this.semanticInfoChain.setSymbolForAST(enumAST.identifier, enumContainerSymbol);
            this.semanticInfoChain.setSymbolForAST(enumAST, enumContainerSymbol);

            if (!enumInstanceSymbol) {
                // search for a complementary instance symbol first
                var variableSymbol = null;
                if (parentInstanceSymbol) {
                    if (isExported) {
                        // We search twice because export visibility does not need to agree
                        variableSymbol = parentInstanceSymbol.findMember(enumName, false);

                        if (!variableSymbol) {
                            variableSymbol = parentInstanceSymbol.findContainedNonMember(enumName);
                        }
                    } else {
                        variableSymbol = parentInstanceSymbol.findContainedNonMember(enumName);

                        if (!variableSymbol) {
                            variableSymbol = parentInstanceSymbol.findMember(enumName, false);
                        }
                    }

                    if (variableSymbol) {
                        var declarations = variableSymbol.getDeclarations();

                        if (declarations.length) {
                            var variableSymbolParentDecl = declarations[0].getParentDecl();

                            if (parentDecl !== variableSymbolParentDecl) {
                                variableSymbol = null;
                            }
                        }
                    }
                } else if (!(enumContainerDecl.flags & 1 /* Exported */)) {
                    // Search locally to this file for a previous declaration that's suitable for augmentation
                    var siblingDecls = parentDecl.getChildDecls();
                    var augmentedDecl = null;

                    for (var i = 0; i < siblingDecls.length; i++) {
                        if (siblingDecls[i] === enumContainerDecl) {
                            break;
                        }

                        if ((siblingDecls[i].name === enumName) && (siblingDecls[i].kind & TypeScript.PullElementKind.SomeValue)) {
                            augmentedDecl = siblingDecls[i];
                            break;
                        }
                    }

                    if (augmentedDecl) {
                        variableSymbol = augmentedDecl.getSymbol(this.semanticInfoChain);

                        if (variableSymbol) {
                            if (variableSymbol.isContainer()) {
                                variableSymbol = variableSymbol.getInstanceSymbol();
                            } else if (variableSymbol && variableSymbol.isType()) {
                                variableSymbol = variableSymbol.getConstructorMethod();
                            }
                        }
                    }
                }

                // The instance symbol is further set up in bindVariableDeclaration
                if (variableSymbol) {
                    enumInstanceSymbol = variableSymbol;
                    moduleInstanceTypeSymbol = variableSymbol.type;
                } else {
                    enumInstanceSymbol = new TypeScript.PullSymbol(enumName, TypeScript.PullElementKind.Variable, this.semanticInfoChain);
                }

                enumContainerSymbol.setInstanceSymbol(enumInstanceSymbol);

                if (!moduleInstanceTypeSymbol) {
                    moduleInstanceTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.ObjectType, this.semanticInfoChain);
                    enumInstanceSymbol.type = moduleInstanceTypeSymbol;
                }

                moduleInstanceTypeSymbol.addDeclaration(enumContainerDecl);

                if (!moduleInstanceTypeSymbol.getAssociatedContainerType()) {
                    moduleInstanceTypeSymbol.setAssociatedContainerType(enumContainerSymbol);
                }
            }

            if (createdNewSymbol && parent) {
                if (enumContainerDecl.flags & 1 /* Exported */) {
                    parent.addEnclosedMemberType(enumContainerSymbol);
                } else {
                    parent.addEnclosedNonMemberType(enumContainerSymbol);
                }
            }

            if (createdNewSymbol) {
                // if the enum container was created, add in the index signature
                this.bindEnumIndexerDeclsToPullSymbols(enumContainerSymbol);
            }
            var valueDecl = enumContainerDecl.getValueDecl();

            if (valueDecl) {
                valueDecl.ensureSymbolIsBound(this.semanticInfoChain);
            }
        };

        PullSymbolBinder.prototype.bindEnumIndexerDeclsToPullSymbols = function (enumContainerSymbol) {
            // Add synthetic index signature to the enum instance
            var enumContainerInstanceTypeSymbol = enumContainerSymbol.getInstanceSymbol().type;

            var syntheticIndexerParameterSymbol = new TypeScript.PullSymbol("x", TypeScript.PullElementKind.Parameter, this.semanticInfoChain);
            syntheticIndexerParameterSymbol.type = this.semanticInfoChain.numberTypeSymbol;
            syntheticIndexerParameterSymbol.setResolved();
            syntheticIndexerParameterSymbol.setIsSynthesized();

            var syntheticIndexerSignatureSymbol = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.IndexSignature, this.semanticInfoChain);
            syntheticIndexerSignatureSymbol.addParameter(syntheticIndexerParameterSymbol);
            syntheticIndexerSignatureSymbol.returnType = this.semanticInfoChain.stringTypeSymbol;
            syntheticIndexerSignatureSymbol.setResolved();
            syntheticIndexerSignatureSymbol.setIsSynthesized();

            enumContainerInstanceTypeSymbol.addIndexSignature(syntheticIndexerSignatureSymbol);
        };

        PullSymbolBinder.prototype.findExistingVariableSymbolForModuleValueDecl = function (decl) {
            var isExported = TypeScript.hasFlag(decl.flags, 1 /* Exported */);
            var modName = decl.name;
            var parentInstanceSymbol = this.getParent(decl, true);
            var parentDecl = decl.getParentDecl();

            var variableSymbol = null;

            // search for a complementary instance symbol first
            if (parentInstanceSymbol) {
                if (isExported) {
                    // We search twice because export visibility does not need to agree
                    variableSymbol = parentInstanceSymbol.findMember(modName, false);

                    if (!variableSymbol) {
                        variableSymbol = parentInstanceSymbol.findContainedNonMember(modName);
                    }
                } else {
                    variableSymbol = parentInstanceSymbol.findContainedNonMember(modName);

                    if (!variableSymbol) {
                        variableSymbol = parentInstanceSymbol.findMember(modName, false);
                    }
                }

                // use currentModuleValueDecl to emphasise that we are merging value side of the module
                if (variableSymbol) {
                    var declarations = variableSymbol.getDeclarations();

                    if (declarations.length) {
                        var variableSymbolParentDecl = declarations[0].getParentDecl();
                        var isExportedOrHasTheSameParent = isExported || (parentDecl === variableSymbolParentDecl);

                        // previously defined variable symbol can be reused if
                        // - current decl is either exported or has the same parent with the previosly defined symbol
                        // AND
                        // exports match for both current and previous decl
                        var canReuseVariableSymbol = isExportedOrHasTheSameParent && this.checkThatExportsMatch(decl, variableSymbol, false);

                        if (!canReuseVariableSymbol) {
                            variableSymbol = null;
                        }
                    }
                }
            } else if (!isExported) {
                // Search locally to this file for a declaration that's suitable for augmentation.
                // Note: we have to check all declarations because it may be hte case (due to
                // recursive binding), that a later module gets bound before us.
                var siblingDecls = parentDecl.getChildDecls();

                for (var i = 0; i < siblingDecls.length; i++) {
                    var sibling = siblingDecls[i];

                    var siblingIsSomeValue = TypeScript.hasFlag(sibling.kind, TypeScript.PullElementKind.SomeValue);
                    var siblingIsFunctionOrHasImplictVarFlag = TypeScript.hasFlag(sibling.kind, TypeScript.PullElementKind.SomeFunction) || TypeScript.hasFlag(sibling.flags, TypeScript.PullElementFlags.ImplicitVariable);

                    // We need to determine of this sibling is something this module definition can augment
                    // Augmentable items are: Function declarations, Classes (whos value decl is its constructor method), Enums
                    var isSiblingAnAugmentableVariable = sibling !== decl && sibling !== decl.getValueDecl() && sibling.name === modName && siblingIsSomeValue && siblingIsFunctionOrHasImplictVarFlag;

                    if (isSiblingAnAugmentableVariable) {
                        // IMPORTANT: We don't want to just call sibling.getSymbol(this.semanticInfoChain) here.
                        // That would force the sibling to get bound.  Something we don't want
                        // to do while binding ourselves (to avoid recursion issues).
                        if (sibling.hasSymbol(this.semanticInfoChain)) {
                            variableSymbol = sibling.getSymbol(this.semanticInfoChain);
                            if (variableSymbol.isContainer()) {
                                variableSymbol = variableSymbol.getInstanceSymbol();
                            } else if (variableSymbol && variableSymbol.isType()) {
                                variableSymbol = variableSymbol.getConstructorMethod();
                            }

                            break;
                        }
                    }
                }
            }
            return variableSymbol;
        };

        PullSymbolBinder.prototype.bindModuleDeclarationToPullSymbol = function (moduleContainerDecl) {
            // 1. Test for existing symbol - if it exists, use its symbol
            // 2. If no other symbols exists, create a new symbol and use that one
            var modName = moduleContainerDecl.name;

            var moduleContainerTypeSymbol = null;
            var moduleKind = moduleContainerDecl.kind;

            var parent = this.getParent(moduleContainerDecl);
            var parentInstanceSymbol = this.getParent(moduleContainerDecl, true);
            var parentDecl = moduleContainerDecl.getParentDecl();
            var moduleNameAST = this.semanticInfoChain.getASTForDecl(moduleContainerDecl);
            var moduleDeclAST = TypeScript.ASTHelpers.getEnclosingModuleDeclaration(moduleNameAST);

            if (!moduleDeclAST) {
                TypeScript.Debug.assert(moduleKind === TypeScript.PullElementKind.DynamicModule);
                TypeScript.Debug.assert(moduleNameAST.kind() === 120 /* SourceUnit */);

                // This is the module decl for the top level synthesized external module.
                moduleDeclAST = moduleNameAST;
            }

            var isExported = TypeScript.hasFlag(moduleContainerDecl.flags, 1 /* Exported */);
            var searchKind = TypeScript.PullElementKind.SomeContainer;
            var isInitializedModule = (moduleContainerDecl.flags & TypeScript.PullElementFlags.SomeInitializedModule) !== 0;

            if (parent && moduleKind === TypeScript.PullElementKind.DynamicModule) {
                // Dynamic modules cannot be parented
                this.semanticInfoChain.addDiagnosticFromAST(moduleNameAST, TypeScript.DiagnosticCode.Ambient_external_module_declaration_must_be_defined_in_global_context, null);
            }

            var createdNewSymbol = false;

            moduleContainerTypeSymbol = this.getExistingSymbol(moduleContainerDecl, searchKind, parent);

            if (moduleContainerTypeSymbol) {
                if (moduleContainerTypeSymbol.kind !== moduleKind) {
                    // duplicate symbol error
                    if (isInitializedModule) {
                        this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(moduleNameAST, moduleContainerDecl.getDisplayName());
                    }

                    moduleContainerTypeSymbol = null;
                } else if (moduleKind === TypeScript.PullElementKind.DynamicModule) {
                    // Dynamic modules cannot be reopened.
                    this.semanticInfoChain.addDiagnosticFromAST(moduleNameAST, TypeScript.DiagnosticCode.Ambient_external_module_declaration_cannot_be_reopened);
                } else if (!this.checkThatExportsMatch(moduleContainerDecl, moduleContainerTypeSymbol)) {
                    moduleContainerTypeSymbol = null;
                }
            }

            if (!moduleContainerTypeSymbol) {
                moduleContainerTypeSymbol = new TypeScript.PullContainerSymbol(modName, moduleKind, this.semanticInfoChain);
                createdNewSymbol = true;

                if (!parent) {
                    this.semanticInfoChain.cacheGlobalSymbol(moduleContainerTypeSymbol, searchKind);
                }
            }

            // We add the declaration early so that during any recursive binding of other module decls with the same name, this declaration is present.
            moduleContainerTypeSymbol.addDeclaration(moduleContainerDecl);
            moduleContainerDecl.setSymbol(moduleContainerTypeSymbol, this.semanticInfoChain);

            this.semanticInfoChain.setSymbolForAST(moduleNameAST, moduleContainerTypeSymbol);
            this.semanticInfoChain.setSymbolForAST(moduleDeclAST, moduleContainerTypeSymbol);

            var currentModuleValueDecl = moduleContainerDecl.getValueDecl();

            // If we have an enum with more than one declaration, then this enum's first element
            // must have an initializer.
            var moduleDeclarations = moduleContainerTypeSymbol.getDeclarations();

            if (createdNewSymbol) {
                if (parent) {
                    if (moduleContainerDecl.flags & 1 /* Exported */) {
                        parent.addEnclosedMemberContainer(moduleContainerTypeSymbol);
                    } else {
                        parent.addEnclosedNonMemberContainer(moduleContainerTypeSymbol);
                    }
                }
            }

            // do not create symbol for the module instance upfront - in some cases it can be harmful.
            // var x: B.C; // 1
            // declare function B(): B.C;
            // declare module B {
            //   export class C {
            //   }
            //}
            // When binding B.C in line 1 we first will bind module B as container (*) ->then we'll bind value side of the module.
            // During binding of the value side will discover that there are 2 value declarations with name B in scope, one - function, another - value decl for the module.
            // Function will be bound first so when we start binding module value decl - we'll find existing symbol that correspond for function and reuse it.
            // If we create instance symbol at point (*) - it will never be used.
            // To avoid this problem we'll bind value decl first and then check if it has symbol - if yes - this symbol will be used as module instance symbol
            if (currentModuleValueDecl) {
                currentModuleValueDecl.ensureSymbolIsBound(this.semanticInfoChain);

                var instanceSymbol = null;
                var instanceTypeSymbol = null;
                if (currentModuleValueDecl.hasSymbol(this.semanticInfoChain)) {
                    instanceSymbol = currentModuleValueDecl.getSymbol(this.semanticInfoChain);
                } else {
                    // We associate the value decl to the module instance symbol. This should have
                    // already been achieved by ensureSymbolIsBound, but if bindModuleDeclarationToPullSymbol
                    // was called recursively while in the middle of binding the value decl, the cycle
                    // will be short-circuited. With a more organized binding pattern, this situation
                    // shouldn't be possible.
                    instanceSymbol = new TypeScript.PullSymbol(modName, TypeScript.PullElementKind.Variable, this.semanticInfoChain);
                    currentModuleValueDecl.setSymbol(instanceSymbol, this.semanticInfoChain);
                    if (!instanceSymbol.hasDeclaration(currentModuleValueDecl)) {
                        instanceSymbol.addDeclaration(currentModuleValueDecl);
                    }
                }

                if (!instanceSymbol.type) {
                    instanceSymbol.type = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.ObjectType, this.semanticInfoChain);
                }

                moduleContainerTypeSymbol.setInstanceSymbol(instanceSymbol);

                if (!instanceSymbol.type.getAssociatedContainerType()) {
                    instanceSymbol.type.setAssociatedContainerType(moduleContainerTypeSymbol);
                }
            }
        };

        // aliases
        PullSymbolBinder.prototype.bindImportDeclaration = function (importDeclaration) {
            var declFlags = importDeclaration.flags;
            var declKind = importDeclaration.kind;
            var importDeclAST = this.semanticInfoChain.getASTForDecl(importDeclaration);

            var isExported = false;
            var importSymbol = null;
            var declName = importDeclaration.name;
            var parentHadSymbol = false;
            var parent = this.getParent(importDeclaration);

            importSymbol = this.getExistingSymbol(importDeclaration, TypeScript.PullElementKind.SomeContainer, parent);

            if (importSymbol) {
                parentHadSymbol = true;
            }

            if (importSymbol) {
                this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(importDeclAST, importDeclaration.getDisplayName());
                importSymbol = null;
            }

            if (!importSymbol) {
                importSymbol = new TypeScript.PullTypeAliasSymbol(declName, this.semanticInfoChain);

                if (!parent) {
                    this.semanticInfoChain.cacheGlobalSymbol(importSymbol, TypeScript.PullElementKind.SomeContainer);
                }
            }

            importSymbol.addDeclaration(importDeclaration);
            importDeclaration.setSymbol(importSymbol, this.semanticInfoChain);

            this.semanticInfoChain.setSymbolForAST(importDeclAST, importSymbol);

            if (parent && !parentHadSymbol) {
                if (declFlags & 1 /* Exported */) {
                    parent.addEnclosedMemberContainer(importSymbol);
                } else {
                    parent.addEnclosedNonMemberContainer(importSymbol);
                }
            }
        };

        // Preserves required binding order for a declaration with given name to prevent cases like:
        // module A { export module B { var x = 1} }
        // module A { export class B { c } }
        // Here if class declaration is bound before module declaration (i.e. because of IDE activities)
        // we won't report expected 'duplicate identifier' error for the class.
        PullSymbolBinder.prototype.ensurePriorDeclarationsAreBound = function (container, currentDecl) {
            if (!container) {
                return;
            }

            var parentDecls = container.getDeclarations();
            for (var i = 0; i < parentDecls.length; ++i) {
                var parentDecl = parentDecls[i];
                var childDecls = parentDecl.getChildDecls();
                for (var j = 0; j < childDecls.length; ++j) {
                    var childDecl = childDecls[j];
                    if (childDecl === currentDecl) {
                        return;
                    }

                    if (childDecl.name === currentDecl.name) {
                        childDecl.ensureSymbolIsBound(this.semanticInfoChain);
                    }
                }
            }
        };

        // classes
        PullSymbolBinder.prototype.bindClassDeclarationToPullSymbol = function (classDecl) {
            var className = classDecl.name;
            var classSymbol = null;

            var constructorSymbol = null;
            var constructorTypeSymbol = null;

            var classAST = this.semanticInfoChain.getASTForDecl(classDecl);

            var parent = this.getParent(classDecl);

            // TODO: we should in general get all the decls from the parent and bind all of them together,
            // but thats a major change and we should fix it without losing perf, so adding just a todo here.
            this.ensurePriorDeclarationsAreBound(parent, classDecl);

            var parentDecl = classDecl.getParentDecl();
            var isExported = classDecl.flags & 1 /* Exported */;
            var isGeneric = false;

            classSymbol = this.getExistingSymbol(classDecl, TypeScript.PullElementKind.SomeType, parent);

            // Only error if it is an interface (for classes and enums we will error when we bind the implicit variable)
            if (classSymbol && classSymbol.kind === TypeScript.PullElementKind.Interface) {
                this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(classAST.identifier, classDecl.getDisplayName());
                classSymbol = null;
            }

            classSymbol = new TypeScript.PullTypeSymbol(className, TypeScript.PullElementKind.Class, this.semanticInfoChain);

            if (!parent) {
                this.semanticInfoChain.cacheGlobalSymbol(classSymbol, TypeScript.PullElementKind.Class);
            }

            classSymbol.addDeclaration(classDecl);
            classDecl.setSymbol(classSymbol, this.semanticInfoChain);

            this.semanticInfoChain.setSymbolForAST(classAST.identifier, classSymbol);
            this.semanticInfoChain.setSymbolForAST(classAST, classSymbol);

            if (parent) {
                if (classDecl.flags & 1 /* Exported */) {
                    parent.addEnclosedMemberType(classSymbol);
                } else {
                    parent.addEnclosedNonMemberType(classSymbol);
                }
            }

            var typeParameterDecls = classDecl.getTypeParameters();

            for (var i = 0; i < typeParameterDecls.length; i++) {
                var typeParameterSymbol = classSymbol.findTypeParameter(typeParameterDecls[i].name);

                if (typeParameterSymbol) {
                    var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameterSymbol.getDeclarations()[0]);
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameterSymbol.getName()]);
                }

                typeParameterSymbol = new TypeScript.PullTypeParameterSymbol(typeParameterDecls[i].name, this.semanticInfoChain);

                classSymbol.addTypeParameter(typeParameterSymbol);
                typeParameterSymbol.addDeclaration(typeParameterDecls[i]);
                typeParameterDecls[i].setSymbol(typeParameterSymbol, this.semanticInfoChain);
            }

            constructorSymbol = classSymbol.getConstructorMethod();
            constructorTypeSymbol = constructorSymbol ? constructorSymbol.type : null;

            if (!constructorSymbol) {
                // First, try to find a sibling value decl that is already bound. If there is one, reuse it.
                var siblingValueDecls = null;
                if (parentDecl) {
                    siblingValueDecls = parentDecl.searchChildDecls(className, TypeScript.PullElementKind.SomeValue);

                    // The first decl should have the right symbol
                    if (siblingValueDecls && siblingValueDecls[0] && siblingValueDecls[0].hasSymbol(this.semanticInfoChain)) {
                        constructorSymbol = siblingValueDecls[0].getSymbol(this.semanticInfoChain);
                    }
                }

                if (constructorSymbol) {
                    constructorTypeSymbol = constructorSymbol.type;
                } else {
                    constructorSymbol = new TypeScript.PullSymbol(className, TypeScript.PullElementKind.ConstructorMethod, this.semanticInfoChain);
                    constructorTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.ConstructorType, this.semanticInfoChain);
                    constructorSymbol.setIsSynthesized();
                    constructorSymbol.type = constructorTypeSymbol;
                }

                classSymbol.setConstructorMethod(constructorSymbol);
                classSymbol.setHasDefaultConstructor();
            }

            if (constructorSymbol.getIsSynthesized()) {
                constructorSymbol.addDeclaration(classDecl.getValueDecl());
                constructorTypeSymbol.addDeclaration(classDecl);
            } else {
                classSymbol.setHasDefaultConstructor(false);
            }

            constructorTypeSymbol.setAssociatedContainerType(classSymbol);

            var valueDecl = classDecl.getValueDecl();

            if (valueDecl) {
                valueDecl.ensureSymbolIsBound(this.semanticInfoChain);
            }

            // Create the constructorTypeSymbol
            this.bindStaticPrototypePropertyOfClass(classAST, classSymbol, constructorTypeSymbol);
        };

        // interfaces
        PullSymbolBinder.prototype.bindInterfaceDeclarationToPullSymbol = function (interfaceDecl) {
            // 1. Test for existing decl - if it exists, use its symbol
            // 2. If no other decl exists, create a new symbol and use that one
            var interfaceName = interfaceDecl.name;
            var interfaceSymbol = null;

            var interfaceAST = this.semanticInfoChain.getASTForDecl(interfaceDecl);
            var createdNewSymbol = false;
            var parent = this.getParent(interfaceDecl);

            // We're not yet ready to support interfaces augmenting classes (or vice versa)
            var acceptableSharedKind = TypeScript.PullElementKind.Interface;

            interfaceSymbol = this.getExistingSymbol(interfaceDecl, TypeScript.PullElementKind.SomeType, parent);

            if (interfaceSymbol) {
                if (!(interfaceSymbol.kind & acceptableSharedKind)) {
                    this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(interfaceAST.identifier, interfaceDecl.getDisplayName());
                    interfaceSymbol = null;
                } else if (!this.checkThatExportsMatch(interfaceDecl, interfaceSymbol)) {
                    interfaceSymbol = null;
                }
            }

            if (!interfaceSymbol) {
                interfaceSymbol = new TypeScript.PullTypeSymbol(interfaceName, TypeScript.PullElementKind.Interface, this.semanticInfoChain);
                createdNewSymbol = true;

                if (!parent) {
                    this.semanticInfoChain.cacheGlobalSymbol(interfaceSymbol, acceptableSharedKind);
                }
            }

            interfaceSymbol.addDeclaration(interfaceDecl);
            interfaceDecl.setSymbol(interfaceSymbol, this.semanticInfoChain);

            if (createdNewSymbol) {
                if (parent) {
                    if (interfaceDecl.flags & 1 /* Exported */) {
                        parent.addEnclosedMemberType(interfaceSymbol);
                    } else {
                        parent.addEnclosedNonMemberType(interfaceSymbol);
                    }
                }
            }

            var typeParameters = interfaceDecl.getTypeParameters();
            var typeParameter;
            var typeParameterDecls = null;

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameter = interfaceSymbol.findTypeParameter(typeParameters[i].name);

                if (!typeParameter) {
                    typeParameter = new TypeScript.PullTypeParameterSymbol(typeParameters[i].name, this.semanticInfoChain);

                    interfaceSymbol.addTypeParameter(typeParameter);
                } else {
                    typeParameterDecls = typeParameter.getDeclarations();

                    for (var j = 0; j < typeParameterDecls.length; j++) {
                        var typeParameterDeclParent = typeParameterDecls[j].getParentDecl();

                        if (typeParameterDeclParent && typeParameterDeclParent === interfaceDecl) {
                            var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameterDecls[0]);
                            this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameter.getName()]);

                            break;
                        }
                    }
                }

                typeParameter.addDeclaration(typeParameters[i]);
                typeParameters[i].setSymbol(typeParameter, this.semanticInfoChain);
            }
        };

        PullSymbolBinder.prototype.bindObjectTypeDeclarationToPullSymbol = function (objectDecl) {
            var objectSymbolAST = this.semanticInfoChain.getASTForDecl(objectDecl);

            var objectSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.ObjectType, this.semanticInfoChain);

            objectSymbol.addDeclaration(objectDecl);
            objectDecl.setSymbol(objectSymbol, this.semanticInfoChain);

            this.semanticInfoChain.setSymbolForAST(objectSymbolAST, objectSymbol);

            var childDecls = objectDecl.getChildDecls();

            for (var i = 0; i < childDecls.length; i++) {
                this.bindDeclToPullSymbol(childDecls[i]);
            }
        };

        PullSymbolBinder.prototype.bindConstructorTypeDeclarationToPullSymbol = function (constructorTypeDeclaration) {
            var declKind = constructorTypeDeclaration.kind;
            var declFlags = constructorTypeDeclaration.flags;
            var constructorTypeAST = this.semanticInfoChain.getASTForDecl(constructorTypeDeclaration);

            var constructorTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.ConstructorType, this.semanticInfoChain);

            constructorTypeDeclaration.setSymbol(constructorTypeSymbol, this.semanticInfoChain);
            constructorTypeSymbol.addDeclaration(constructorTypeDeclaration);
            this.semanticInfoChain.setSymbolForAST(constructorTypeAST, constructorTypeSymbol);

            var signature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.ConstructSignature, this.semanticInfoChain);

            var funcDecl = this.semanticInfoChain.getASTForDecl(constructorTypeDeclaration);
            if (TypeScript.lastParameterIsRest(funcDecl.parameterList.parameters)) {
                signature.hasVarArgs = true;
            }

            signature.addDeclaration(constructorTypeDeclaration);
            constructorTypeDeclaration.setSignatureSymbol(signature, this.semanticInfoChain);

            this.bindParameterSymbols(funcDecl, funcDecl.parameterList.parameters, constructorTypeSymbol, signature);

            var typeParameters = constructorTypeDeclaration.getTypeParameters();
            var typeParameter;

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameter = constructorTypeSymbol.findTypeParameter(typeParameters[i].name);

                if (!typeParameter) {
                    typeParameter = new TypeScript.PullTypeParameterSymbol(typeParameters[i].name, this.semanticInfoChain);

                    signature.addTypeParameter(typeParameter);
                } else {
                    var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameter.getDeclarations()[0]);
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameter.name]);
                }

                typeParameter.addDeclaration(typeParameters[i]);
                typeParameters[i].setSymbol(typeParameter, this.semanticInfoChain);
            }

            // add the implicit construct member for this function type
            constructorTypeSymbol.appendConstructSignature(signature);
        };

        // variables
        PullSymbolBinder.prototype.bindVariableDeclarationToPullSymbol = function (variableDeclaration) {
            var declFlags = variableDeclaration.flags;
            var declKind = variableDeclaration.kind;

            var varDeclAST = this.semanticInfoChain.getASTForDecl(variableDeclaration);
            var nameAST = varDeclAST.kind() === 131 /* ClassDeclaration */ ? varDeclAST.identifier : varDeclAST.kind() === 225 /* VariableDeclarator */ ? varDeclAST.propertyName : varDeclAST.kind() === 132 /* EnumDeclaration */ ? varDeclAST.identifier : varDeclAST;

            var isExported = (declFlags & 1 /* Exported */) !== 0;

            var variableSymbol = null;

            var declName = variableDeclaration.name;

            var parentHadSymbol = false;

            var parent = this.getParent(variableDeclaration, true);

            var parentDecl = variableDeclaration.getParentDecl();

            var isImplicit = (declFlags & TypeScript.PullElementFlags.ImplicitVariable) !== 0;
            var isModuleValue = (declFlags & (TypeScript.PullElementFlags.InitializedModule)) !== 0;
            var isEnumValue = (declFlags & TypeScript.PullElementFlags.Enum) !== 0;
            var isClassConstructorVariable = (declFlags & TypeScript.PullElementFlags.ClassConstructorVariable) !== 0;
            variableSymbol = this.getExistingSymbol(variableDeclaration, TypeScript.PullElementKind.SomeValue, parent);

            if (!variableSymbol && isModuleValue) {
                variableSymbol = this.findExistingVariableSymbolForModuleValueDecl(variableDeclaration.getContainerDecl());
            }

            if (variableSymbol && !variableSymbol.isType()) {
                parentHadSymbol = true;
            }

            var decl;
            var decls;
            var ast;
            var members;

            if (variableSymbol) {
                var prevKind = variableSymbol.kind;
                var prevIsEnum = variableSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.Enum);
                var prevIsClassConstructorVariable = variableSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.ClassConstructorVariable);
                var prevIsModuleValue = variableSymbol.allDeclsHaveFlag(TypeScript.PullElementFlags.InitializedModule);
                var prevIsImplicit = variableSymbol.anyDeclHasFlag(TypeScript.PullElementFlags.ImplicitVariable);
                var prevIsFunction = TypeScript.ArrayUtilities.any(variableSymbol.getDeclarations(), function (decl) {
                    return decl.kind === TypeScript.PullElementKind.Function;
                });
                var prevIsAmbient = variableSymbol.allDeclsHaveFlag(TypeScript.PullElementFlags.Ambient);
                var isAmbientOrPrevIsAmbient = prevIsAmbient || (variableDeclaration.flags & TypeScript.PullElementFlags.Ambient) !== 0;
                var prevDecl = variableSymbol.getDeclarations()[0];
                var prevParentDecl = prevDecl.getParentDecl();
                var bothAreGlobal = parentDecl && (parentDecl.kind === TypeScript.PullElementKind.Script) && (prevParentDecl.kind === TypeScript.PullElementKind.Script);
                var shareParent = bothAreGlobal || prevDecl.getParentDecl() === variableDeclaration.getParentDecl();
                var prevIsParam = shareParent && prevKind === TypeScript.PullElementKind.Parameter && declKind == TypeScript.PullElementKind.Variable;

                var acceptableRedeclaration = prevIsParam || (isImplicit && ((!isEnumValue && !isClassConstructorVariable && prevIsFunction) || ((isModuleValue || isEnumValue) && (prevIsModuleValue || prevIsEnum)) || (isClassConstructorVariable && prevIsModuleValue && isAmbientOrPrevIsAmbient) || (isModuleValue && prevIsClassConstructorVariable)));

                // if the previous declaration is a non-ambient class, it must be located in the same file as this declaration
                if (acceptableRedeclaration && (prevIsClassConstructorVariable || prevIsFunction) && !isAmbientOrPrevIsAmbient) {
                    if (prevDecl.fileName() !== variableDeclaration.fileName()) {
                        this.semanticInfoChain.addDiagnostic(this.semanticInfoChain.diagnosticFromDecl(variableDeclaration, TypeScript.DiagnosticCode.Module_0_cannot_merge_with_previous_declaration_of_1_in_a_different_file_2, [declName, declName, prevDecl.fileName()]));
                        variableSymbol.type = this.semanticInfoChain.getResolver().getNewErrorTypeSymbol(declName);
                    }
                }

                if (!acceptableRedeclaration || prevIsParam) {
                    // If neither of them are implicit (both explicitly declared as vars), we won't error now. We'll check that the types match during type check.
                    // However, we will error when a variable clobbers a function, or when the two explicit var declarations are not in the same parent declaration
                    if (!prevIsParam && (isImplicit || prevIsImplicit || TypeScript.hasFlag(prevKind, TypeScript.PullElementKind.SomeFunction)) || !shareParent) {
                        this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(nameAST, variableDeclaration.getDisplayName());
                        variableSymbol.type = this.semanticInfoChain.getResolver().getNewErrorTypeSymbol(declName);
                    } else {
                        this.checkThatExportsMatch(variableDeclaration, variableSymbol);
                        variableSymbol = null;
                        parentHadSymbol = false;
                    }
                }

                // If we haven't given an error so far and we merged two decls, check that the exports match
                // Only report the error if they are not both initialized modules (if they are, the bind module code would report the error)
                if (variableSymbol && !(variableSymbol.type && variableSymbol.type.isError()) && !this.checkThatExportsMatch(variableDeclaration, variableSymbol, !(isModuleValue && prevIsModuleValue))) {
                    variableSymbol.type = this.semanticInfoChain.getResolver().getNewErrorTypeSymbol(declName);
                }
            }

            if ((declFlags & TypeScript.PullElementFlags.ImplicitVariable) === 0) {
                if (!variableSymbol) {
                    variableSymbol = new TypeScript.PullSymbol(declName, declKind, this.semanticInfoChain);
                    if (!parent && parentDecl.kind === TypeScript.PullElementKind.Script) {
                        this.semanticInfoChain.cacheGlobalSymbol(variableSymbol, declKind);
                    }
                }

                variableSymbol.addDeclaration(variableDeclaration);
                variableDeclaration.setSymbol(variableSymbol, this.semanticInfoChain);

                this.semanticInfoChain.setSymbolForAST(nameAST, variableSymbol);
                this.semanticInfoChain.setSymbolForAST(varDeclAST, variableSymbol);
            } else if (!parentHadSymbol) {
                if (isClassConstructorVariable) {
                    // it's really an implicit class decl, so we need to set the type of the symbol to
                    // the constructor type
                    // Note that we would have already found the class symbol in the search above
                    var classTypeSymbol = variableSymbol;

                    // PULLTODO: In both this case and the case below, we should have already received the
                    // class or module symbol as the variableSymbol found above
                    if (parent) {
                        members = parent.getMembers();

                        for (var i = 0; i < members.length; i++) {
                            if ((members[i].name === declName) && (members[i].kind === TypeScript.PullElementKind.Class)) {
                                classTypeSymbol = members[i];
                                break;
                            }
                        }
                    }

                    if (!classTypeSymbol) {
                        var containerDecl = variableDeclaration.getContainerDecl();
                        classTypeSymbol = containerDecl.getSymbol(this.semanticInfoChain);
                        if (!classTypeSymbol) {
                            classTypeSymbol = this.semanticInfoChain.findTopLevelSymbol(declName, TypeScript.PullElementKind.SomeType, variableDeclaration);
                        }
                    }

                    if (classTypeSymbol && (classTypeSymbol.kind !== TypeScript.PullElementKind.Class)) {
                        classTypeSymbol = null;
                    }

                    if (classTypeSymbol && classTypeSymbol.isClass()) {
                        //replaceProperty = variableSymbol && variableSymbol.getIsSynthesized();
                        //if (replaceProperty) {
                        //    previousProperty = variableSymbol;
                        //}
                        variableSymbol = classTypeSymbol.getConstructorMethod();
                        variableDeclaration.setSymbol(variableSymbol, this.semanticInfoChain);

                        // set the ISyntaxElement to the constructor method's if possible
                        decls = classTypeSymbol.getDeclarations();

                        if (decls.length) {
                            decl = decls[decls.length - 1];
                            ast = this.semanticInfoChain.getASTForDecl(decl);
                        }
                    } else {
                        // PULLTODO: Clodules/Interfaces on classes
                        if (!variableSymbol) {
                            variableSymbol = new TypeScript.PullSymbol(declName, declKind, this.semanticInfoChain);
                        }

                        variableSymbol.addDeclaration(variableDeclaration);
                        variableDeclaration.setSymbol(variableSymbol, this.semanticInfoChain);

                        variableSymbol.type = this.semanticInfoChain.anyTypeSymbol;
                    }
                } else if (declFlags & TypeScript.PullElementFlags.SomeInitializedModule) {
                    var moduleContainerTypeSymbol = null;
                    var moduleParent = this.getParent(variableDeclaration);

                    if (moduleParent) {
                        members = moduleParent.getMembers();

                        for (var i = 0; i < members.length; i++) {
                            if ((members[i].name === declName) && (members[i].isContainer())) {
                                moduleContainerTypeSymbol = members[i];
                                break;
                            }
                        }
                    }

                    if (!moduleContainerTypeSymbol) {
                        var containerDecl = variableDeclaration.getContainerDecl();
                        moduleContainerTypeSymbol = containerDecl.getSymbol(this.semanticInfoChain);
                        if (!moduleContainerTypeSymbol) {
                            moduleContainerTypeSymbol = this.semanticInfoChain.findTopLevelSymbol(declName, TypeScript.PullElementKind.SomeContainer, variableDeclaration);

                            if (!moduleContainerTypeSymbol) {
                                moduleContainerTypeSymbol = this.semanticInfoChain.findTopLevelSymbol(declName, TypeScript.PullElementKind.Enum, variableDeclaration);
                            }
                        }
                    }

                    if (moduleContainerTypeSymbol && (!moduleContainerTypeSymbol.isContainer())) {
                        moduleContainerTypeSymbol = null;
                    }

                    if (moduleContainerTypeSymbol) {
                        variableSymbol = moduleContainerTypeSymbol.getInstanceSymbol();
                        if (!variableSymbol) {
                            variableSymbol = new TypeScript.PullSymbol(declName, declKind, this.semanticInfoChain);
                            variableSymbol.type = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.ObjectType, this.semanticInfoChain);
                        }

                        // If this method calls bindModuleDeclarationToPullSymbol recursively,
                        // we may associate the variable decl with its symbol in that recursive
                        // call before we do it here. Therefore, make sure the symbol doesn't already
                        // have the decl before adding it. Just like in bindModuleDeclarationToPullSymbol,
                        // we shouldn't need this maneuver with a more iterative binding pattern.
                        if (!variableSymbol.hasDeclaration(variableDeclaration)) {
                            variableSymbol.addDeclaration(variableDeclaration);
                        }
                        variableDeclaration.setSymbol(variableSymbol, this.semanticInfoChain);
                    } else {
                        TypeScript.Debug.assert(false, "Attempted to bind invalid implicit variable symbol");
                    }
                }
            } else {
                if (!variableSymbol.hasDeclaration(variableDeclaration)) {
                    variableSymbol.addDeclaration(variableDeclaration);
                }
                variableDeclaration.setSymbol(variableSymbol, this.semanticInfoChain);
            }

            var containerDecl = variableDeclaration.getContainerDecl();
            if (variableSymbol && variableSymbol.type && containerDecl && !variableSymbol.type.hasDeclaration(containerDecl)) {
                variableSymbol.type.addDeclaration(containerDecl);
            }

            if (parent && !parentHadSymbol) {
                if (declFlags & 1 /* Exported */) {
                    parent.addMember(variableSymbol);
                } else {
                    parent.addEnclosedNonMember(variableSymbol);
                }
            }
        };

        PullSymbolBinder.prototype.bindCatchVariableToPullSymbol = function (variableDeclaration) {
            var declFlags = variableDeclaration.flags;
            var declKind = variableDeclaration.kind;
            var identifier = this.semanticInfoChain.getASTForDecl(variableDeclaration);

            var declName = variableDeclaration.name;

            var variableSymbol = new TypeScript.PullSymbol(declName, declKind, this.semanticInfoChain);

            variableSymbol.addDeclaration(variableDeclaration);
            variableDeclaration.setSymbol(variableSymbol, this.semanticInfoChain);

            // Catch variable are of type 'any'.  So we don't need to actually resolve anything later.
            variableSymbol.type = this.semanticInfoChain.anyTypeSymbol;

            this.semanticInfoChain.setSymbolForAST(identifier, variableSymbol);
        };

        // properties
        PullSymbolBinder.prototype.bindEnumMemberDeclarationToPullSymbol = function (propertyDeclaration) {
            var declFlags = propertyDeclaration.flags;
            var declKind = propertyDeclaration.kind;
            var propDeclAST = this.semanticInfoChain.getASTForDecl(propertyDeclaration);

            var declName = propertyDeclaration.name;

            var parentHadSymbol = false;

            var parent = this.getParent(propertyDeclaration, true);

            var propertySymbol = parent.findMember(declName, false);

            if (propertySymbol) {
                this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(propDeclAST.propertyName, propertyDeclaration.getDisplayName());
            }

            if (propertySymbol) {
                parentHadSymbol = true;
            }

            if (!parentHadSymbol) {
                propertySymbol = new TypeScript.PullSymbol(declName, declKind, this.semanticInfoChain);
            }

            propertySymbol.addDeclaration(propertyDeclaration);
            propertyDeclaration.setSymbol(propertySymbol, this.semanticInfoChain);

            this.semanticInfoChain.setSymbolForAST(propDeclAST.propertyName, propertySymbol);
            this.semanticInfoChain.setSymbolForAST(propDeclAST, propertySymbol);

            if (parent && !parentHadSymbol) {
                parent.addMember(propertySymbol);
            }
        };

        PullSymbolBinder.prototype.bindPropertyDeclarationToPullSymbol = function (propertyDeclaration) {
            var declFlags = propertyDeclaration.flags;
            var declKind = propertyDeclaration.kind;

            var ast = this.semanticInfoChain.getASTForDecl(propertyDeclaration);
            var astName = ast.kind() === 136 /* MemberVariableDeclaration */ ? ast.variableDeclarator.propertyName : ast.kind() === 141 /* PropertySignature */ ? ast.propertyName : ast.kind() === 242 /* Parameter */ ? ast.identifier : ast.propertyName;

            var isStatic = false;
            var isOptional = false;

            var propertySymbol = null;

            if (TypeScript.hasFlag(declFlags, TypeScript.PullElementFlags.Static)) {
                isStatic = true;
            }

            if (TypeScript.hasFlag(declFlags, TypeScript.PullElementFlags.Optional)) {
                isOptional = true;
            }

            var declName = propertyDeclaration.name;

            var parentHadSymbol = false;

            var parent = this.getParent(propertyDeclaration, true);

            if (parent.isClass() && isStatic) {
                parent = parent.getConstructorMethod().type;
            }

            propertySymbol = parent.findMember(declName, false);

            if (propertySymbol) {
                this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(astName, propertyDeclaration.getDisplayName());
            }

            if (propertySymbol) {
                parentHadSymbol = true;
            }

            var classTypeSymbol;

            if (!parentHadSymbol) {
                propertySymbol = new TypeScript.PullSymbol(declName, declKind, this.semanticInfoChain);
            }

            propertySymbol.addDeclaration(propertyDeclaration);
            propertyDeclaration.setSymbol(propertySymbol, this.semanticInfoChain);

            this.semanticInfoChain.setSymbolForAST(astName, propertySymbol);
            this.semanticInfoChain.setSymbolForAST(ast, propertySymbol);

            if (isOptional) {
                propertySymbol.isOptional = true;
            }

            if (parent && !parentHadSymbol) {
                parent.addMember(propertySymbol);
            }
        };

        // parameters
        PullSymbolBinder.prototype.bindParameterSymbols = function (functionDeclaration, parameterList, funcType, signatureSymbol) {
            // create a symbol for each ast
            // if it's a property, add the symbol to the enclosing type's member list
            var parameters = [];
            var params = TypeScript.createIntrinsicsObject();
            var funcDecl = this.semanticInfoChain.getDeclForAST(functionDeclaration);

            if (parameterList) {
                for (var i = 0, n = parameterList.length; i < n; i++) {
                    var argDecl = parameterList[i];
                    var id = argDecl.identifier;
                    var decl = this.semanticInfoChain.getDeclForAST(argDecl);
                    var isProperty = TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.PropertyParameter);
                    var parameterSymbol = new TypeScript.PullSymbol(TypeScript.tokenValueText(id), TypeScript.PullElementKind.Parameter, this.semanticInfoChain);

                    if ((i === (n - 1)) && TypeScript.lastParameterIsRest(parameterList)) {
                        parameterSymbol.isVarArg = true;
                    }

                    if (params[TypeScript.tokenValueText(id)]) {
                        this.semanticInfoChain.addDiagnosticFromAST(argDecl, TypeScript.DiagnosticCode.Duplicate_identifier_0, [id.text()]);
                    } else {
                        params[TypeScript.tokenValueText(id)] = true;
                    }

                    if (decl) {
                        var isParameterOptional = false;

                        if (isProperty) {
                            decl.ensureSymbolIsBound(this.semanticInfoChain);
                            var valDecl = decl.getValueDecl();

                            // if this is a parameter property, we still need to set the value decl
                            // for the function parameter
                            if (valDecl) {
                                isParameterOptional = TypeScript.hasFlag(valDecl.flags, TypeScript.PullElementFlags.Optional);

                                valDecl.setSymbol(parameterSymbol, this.semanticInfoChain);
                                parameterSymbol.addDeclaration(valDecl);
                            }
                        } else {
                            isParameterOptional = TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Optional);

                            parameterSymbol.addDeclaration(decl);
                            decl.setSymbol(parameterSymbol, this.semanticInfoChain);
                        }

                        parameterSymbol.isOptional = isParameterOptional;
                    }

                    signatureSymbol.addParameter(parameterSymbol, parameterSymbol.isOptional);

                    if (signatureSymbol.isDefinition()) {
                        funcType.addEnclosedNonMember(parameterSymbol);
                    }
                }
            }
        };

        // function declarations
        PullSymbolBinder.prototype.bindFunctionDeclarationToPullSymbol = function (functionDeclaration) {
            var declKind = functionDeclaration.kind;
            var declFlags = functionDeclaration.flags;
            var funcDeclAST = this.semanticInfoChain.getASTForDecl(functionDeclaration);

            var isExported = (declFlags & 1 /* Exported */) !== 0;

            var funcName = functionDeclaration.name;

            // 1. Test for existing decl - if it exists, use its symbol
            // 2. If no other decl exists, create a new symbol and use that one
            var isSignature = (declFlags & TypeScript.PullElementFlags.Signature) !== 0;

            var parent = this.getParent(functionDeclaration, true);

            var parentDecl = functionDeclaration.getParentDecl();
            var parentHadSymbol = false;

            // PULLREVIEW: On a re-bind, there's no need to search far-and-wide: just look in the parent's member list
            var functionSymbol = null;
            var functionTypeSymbol = null;

            functionSymbol = this.getExistingSymbol(functionDeclaration, TypeScript.PullElementKind.SomeValue, parent);

            if (functionSymbol) {
                // SPEC: Nov 18
                // When merging a non-ambient function or class declaration and a non-ambient internal module declaration,
                // the function or class declaration must be located prior to the internal module declaration in the same source file.
                // => when any of components is ambient - order doesn't matter
                // Duplicate is acceptable if it is another signature (not a duplicate implementation), or an ambient fundule
                if (functionSymbol.kind === TypeScript.PullElementKind.Function) {
                    // normal fundule - we are allowed to add overloads
                    var acceptableRedeclaration = isSignature || functionSymbol.allDeclsHaveFlag(TypeScript.PullElementFlags.Signature);
                    if (!acceptableRedeclaration) {
                        this.semanticInfoChain.addDiagnosticFromAST(funcDeclAST.identifier, TypeScript.DiagnosticCode.Duplicate_function_implementation);
                    }
                } else {
                    // check if this is ambient fundule?
                    var isCurrentDeclAmbient = TypeScript.hasFlag(functionDeclaration.flags, TypeScript.PullElementFlags.Ambient);
                    var acceptableRedeclaration = TypeScript.ArrayUtilities.all(functionSymbol.getDeclarations(), function (decl) {
                        // allowed elements for ambient fundules
                        // - signatures
                        // - initialized modules that can be ambient or not depending on whether current decl is ambient
                        var isInitializedModuleOrAmbientDecl = TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.InitializedModule) && (isCurrentDeclAmbient || TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Ambient));
                        var isSignature = TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Signature);
                        return isInitializedModuleOrAmbientDecl || isSignature;
                    });

                    if (!acceptableRedeclaration) {
                        this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(funcDeclAST.identifier, functionDeclaration.getDisplayName());
                        functionSymbol.type = this.semanticInfoChain.getResolver().getNewErrorTypeSymbol(funcName);
                    }
                }
            }

            if (functionSymbol) {
                functionTypeSymbol = functionSymbol.type;
                parentHadSymbol = true;
            }

            if (!functionSymbol) {
                // PULLTODO: Make sure that we properly flag signature decl types when collecting decls
                functionSymbol = new TypeScript.PullSymbol(funcName, TypeScript.PullElementKind.Function, this.semanticInfoChain);
            }

            if (!functionTypeSymbol) {
                functionTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.FunctionType, this.semanticInfoChain);
                functionSymbol.type = functionTypeSymbol;
                functionTypeSymbol.setFunctionSymbol(functionSymbol);
            }

            functionDeclaration.setSymbol(functionSymbol, this.semanticInfoChain);
            functionSymbol.addDeclaration(functionDeclaration);
            functionTypeSymbol.addDeclaration(functionDeclaration);

            this.semanticInfoChain.setSymbolForAST(funcDeclAST.identifier, functionSymbol);
            this.semanticInfoChain.setSymbolForAST(funcDeclAST, functionSymbol);

            if (parent && !parentHadSymbol) {
                if (isExported) {
                    parent.addMember(functionSymbol);
                } else {
                    parent.addEnclosedNonMember(functionSymbol);
                }
            }

            var signature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.CallSignature, this.semanticInfoChain, !isSignature);

            signature.addDeclaration(functionDeclaration);
            functionDeclaration.setSignatureSymbol(signature, this.semanticInfoChain);

            if (TypeScript.lastParameterIsRest(funcDeclAST.callSignature.parameterList.parameters)) {
                signature.hasVarArgs = true;
            }

            var funcDecl = this.semanticInfoChain.getASTForDecl(functionDeclaration);
            this.bindParameterSymbols(funcDecl, funcDecl.callSignature.parameterList.parameters, functionTypeSymbol, signature);

            var typeParameters = functionDeclaration.getTypeParameters();
            var typeParameter;

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameter = signature.findTypeParameter(typeParameters[i].name);

                if (!typeParameter) {
                    typeParameter = new TypeScript.PullTypeParameterSymbol(typeParameters[i].name, this.semanticInfoChain);

                    signature.addTypeParameter(typeParameter);
                } else {
                    var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameter.getDeclarations()[0]);
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameter.name]);
                }

                typeParameter.addDeclaration(typeParameters[i]);
                typeParameters[i].setSymbol(typeParameter, this.semanticInfoChain);
            }

            // add the implicit call member for this function type
            functionTypeSymbol.appendCallSignature(signature);
        };

        PullSymbolBinder.prototype.bindFunctionExpressionToPullSymbol = function (functionExpressionDeclaration) {
            var declKind = functionExpressionDeclaration.kind;
            var declFlags = functionExpressionDeclaration.flags;
            var ast = this.semanticInfoChain.getASTForDecl(functionExpressionDeclaration);

            var parameters = ast.kind() === 219 /* SimpleArrowFunctionExpression */ ? [ast.parameter] : TypeScript.ASTHelpers.getParameterList(ast).parameters;
            var funcExpAST = ast;

            // 1. Test for existing decl - if it exists, use its symbol
            // 2. If no other decl exists, create a new symbol and use that one
            var functionName = declKind === TypeScript.PullElementKind.FunctionExpression ? functionExpressionDeclaration.getFunctionExpressionName() : functionExpressionDeclaration.name;
            var functionSymbol = new TypeScript.PullSymbol(functionName, declKind, this.semanticInfoChain);
            var functionTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.FunctionType, this.semanticInfoChain);
            functionTypeSymbol.setFunctionSymbol(functionSymbol);

            functionSymbol.type = functionTypeSymbol;

            functionExpressionDeclaration.setSymbol(functionSymbol, this.semanticInfoChain);
            functionSymbol.addDeclaration(functionExpressionDeclaration);
            functionTypeSymbol.addDeclaration(functionExpressionDeclaration);

            var name = funcExpAST.kind() === 222 /* FunctionExpression */ ? funcExpAST.identifier : funcExpAST.kind() === 241 /* FunctionPropertyAssignment */ ? funcExpAST.propertyName : null;
            if (name) {
                this.semanticInfoChain.setSymbolForAST(name, functionSymbol);
            }

            this.semanticInfoChain.setSymbolForAST(funcExpAST, functionSymbol);

            var signature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.CallSignature, this.semanticInfoChain, true);

            if (TypeScript.lastParameterIsRest(parameters)) {
                signature.hasVarArgs = true;
            }

            var typeParameters = functionExpressionDeclaration.getTypeParameters();
            var typeParameter;

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameter = signature.findTypeParameter(typeParameters[i].name);

                if (!typeParameter) {
                    typeParameter = new TypeScript.PullTypeParameterSymbol(typeParameters[i].name, this.semanticInfoChain);

                    signature.addTypeParameter(typeParameter);
                } else {
                    var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameter.getDeclarations()[0]);
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameter.getName()]);
                }

                typeParameter.addDeclaration(typeParameters[i]);
                typeParameters[i].setSymbol(typeParameter, this.semanticInfoChain);
            }

            signature.addDeclaration(functionExpressionDeclaration);
            functionExpressionDeclaration.setSignatureSymbol(signature, this.semanticInfoChain);

            this.bindParameterSymbols(funcExpAST, parameters, functionTypeSymbol, signature);

            // add the implicit call member for this function type
            functionTypeSymbol.appendCallSignature(signature);
        };

        PullSymbolBinder.prototype.bindFunctionTypeDeclarationToPullSymbol = function (functionTypeDeclaration) {
            var declKind = functionTypeDeclaration.kind;
            var declFlags = functionTypeDeclaration.flags;
            var funcTypeAST = this.semanticInfoChain.getASTForDecl(functionTypeDeclaration);

            // 1. Test for existing decl - if it exists, use its symbol
            // 2. If no other decl exists, create a new symbol and use that one
            var functionTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.FunctionType, this.semanticInfoChain);

            functionTypeDeclaration.setSymbol(functionTypeSymbol, this.semanticInfoChain);
            functionTypeSymbol.addDeclaration(functionTypeDeclaration);
            this.semanticInfoChain.setSymbolForAST(funcTypeAST, functionTypeSymbol);

            var isSignature = (declFlags & TypeScript.PullElementFlags.Signature) !== 0;
            var signature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.CallSignature, this.semanticInfoChain, !isSignature);

            if (TypeScript.lastParameterIsRest(funcTypeAST.parameterList.parameters)) {
                signature.hasVarArgs = true;
            }

            var typeParameters = functionTypeDeclaration.getTypeParameters();
            var typeParameter;

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameter = signature.findTypeParameter(typeParameters[i].name);

                if (!typeParameter) {
                    typeParameter = new TypeScript.PullTypeParameterSymbol(typeParameters[i].name, this.semanticInfoChain);

                    signature.addTypeParameter(typeParameter);
                } else {
                    var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameter.getDeclarations()[0]);
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameter.name]);
                }

                typeParameter.addDeclaration(typeParameters[i]);
                typeParameters[i].setSymbol(typeParameter, this.semanticInfoChain);
            }

            signature.addDeclaration(functionTypeDeclaration);
            functionTypeDeclaration.setSignatureSymbol(signature, this.semanticInfoChain);

            this.bindParameterSymbols(funcTypeAST, funcTypeAST.parameterList.parameters, functionTypeSymbol, signature);

            // add the implicit call member for this function type
            functionTypeSymbol.appendCallSignature(signature);
        };

        // method declarations
        PullSymbolBinder.prototype.bindMethodDeclarationToPullSymbol = function (methodDeclaration) {
            var declKind = methodDeclaration.kind;
            var declFlags = methodDeclaration.flags;
            var methodAST = this.semanticInfoChain.getASTForDecl(methodDeclaration);

            var isPrivate = (declFlags & TypeScript.PullElementFlags.Private) !== 0;
            var isStatic = (declFlags & TypeScript.PullElementFlags.Static) !== 0;
            var isOptional = (declFlags & TypeScript.PullElementFlags.Optional) !== 0;

            var methodName = methodDeclaration.name;

            var isSignature = (declFlags & TypeScript.PullElementFlags.Signature) !== 0;

            var parent = this.getParent(methodDeclaration, true);
            var parentHadSymbol = false;

            var methodSymbol = null;
            var methodTypeSymbol = null;

            if (parent.isClass() && isStatic) {
                parent = parent.getConstructorMethod().type;
            }

            methodSymbol = parent.findMember(methodName, false);

            if (methodSymbol && (methodSymbol.kind !== TypeScript.PullElementKind.Method || (!isSignature && !methodSymbol.allDeclsHaveFlag(TypeScript.PullElementFlags.Signature)))) {
                if (methodSymbol.kind === TypeScript.PullElementKind.Method) {
                    this.semanticInfoChain.addDiagnosticFromAST(methodAST, TypeScript.DiagnosticCode.Duplicate_function_implementation);
                } else {
                    this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(methodAST, methodDeclaration.getDisplayName());
                }
                methodSymbol = null;
            }

            if (methodSymbol) {
                methodTypeSymbol = methodSymbol.type;
                parentHadSymbol = true;
            }

            if (!methodSymbol) {
                // PULLTODO: Make sure that we properly flag signature decl types when collecting decls
                methodSymbol = new TypeScript.PullSymbol(methodName, TypeScript.PullElementKind.Method, this.semanticInfoChain);
            }

            if (!methodTypeSymbol) {
                methodTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.FunctionType, this.semanticInfoChain);
                methodSymbol.type = methodTypeSymbol;
                methodTypeSymbol.setFunctionSymbol(methodSymbol);
            }

            methodDeclaration.setSymbol(methodSymbol, this.semanticInfoChain);
            methodSymbol.addDeclaration(methodDeclaration);
            methodTypeSymbol.addDeclaration(methodDeclaration);

            var nameAST = methodAST.kind() === 135 /* MemberFunctionDeclaration */ ? methodAST.propertyName : methodAST.propertyName;

            TypeScript.Debug.assert(nameAST);

            this.semanticInfoChain.setSymbolForAST(nameAST, methodSymbol);
            this.semanticInfoChain.setSymbolForAST(methodAST, methodSymbol);

            if (isOptional) {
                methodSymbol.isOptional = true;
            }

            if (!parentHadSymbol) {
                parent.addMember(methodSymbol);
            }

            var sigKind = TypeScript.PullElementKind.CallSignature;

            var signature = new TypeScript.PullSignatureSymbol(sigKind, this.semanticInfoChain, !isSignature);

            var parameterList = TypeScript.ASTHelpers.getParameterList(methodAST);
            if (TypeScript.lastParameterIsRest(parameterList.parameters)) {
                signature.hasVarArgs = true;
            }

            var typeParameters = methodDeclaration.getTypeParameters();
            var typeParameter;
            var typeParameterName;
            var typeParameterAST;

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameterName = typeParameters[i].name;
                typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameters[i]);

                typeParameter = signature.findTypeParameter(typeParameterName);

                if (!typeParameter) {
                    typeParameter = new TypeScript.PullTypeParameterSymbol(typeParameterName, this.semanticInfoChain);
                    signature.addTypeParameter(typeParameter);
                } else {
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameter.getName()]);
                }

                typeParameter.addDeclaration(typeParameters[i]);
                typeParameters[i].setSymbol(typeParameter, this.semanticInfoChain);
            }

            signature.addDeclaration(methodDeclaration);
            methodDeclaration.setSignatureSymbol(signature, this.semanticInfoChain);

            var funcDecl = this.semanticInfoChain.getASTForDecl(methodDeclaration);
            this.bindParameterSymbols(funcDecl, TypeScript.ASTHelpers.getParameterList(funcDecl).parameters, methodTypeSymbol, signature);

            // add the implicit call member for this function type
            var signatureIndex = this.getIndexForInsertingSignatureAtEndOfEnclosingDeclInSignatureList(signature, methodTypeSymbol.getOwnCallSignatures());
            methodTypeSymbol.insertCallSignatureAtIndex(signature, signatureIndex);
        };

        PullSymbolBinder.prototype.bindStaticPrototypePropertyOfClass = function (classAST, classTypeSymbol, constructorTypeSymbol) {
            var prototypeStr = "prototype";

            var prototypeSymbol = constructorTypeSymbol.findMember(prototypeStr, false);
            if (prototypeSymbol && !prototypeSymbol.getIsSynthesized()) {
                // Report duplicate symbol error on existing prototype symbol since class has explicit prototype symbol
                // This kind of scenario can happen with augmented module and class with module member named prototype
                this.semanticInfoChain.addDiagnostic(this.semanticInfoChain.diagnosticFromDecl(prototypeSymbol.getDeclarations()[0], TypeScript.DiagnosticCode.Duplicate_identifier_0, [prototypeSymbol.getDisplayName()]));
            }

            // Add synthetic prototype decl and symbol
            if (!prototypeSymbol || !prototypeSymbol.getIsSynthesized()) {
                var prototypeDecl = new TypeScript.PullSynthesizedDecl(prototypeStr, prototypeStr, TypeScript.PullElementKind.Property, TypeScript.PullElementFlags.Public | TypeScript.PullElementFlags.Static, constructorTypeSymbol.getDeclarations()[0]);

                prototypeSymbol = new TypeScript.PullSymbol(prototypeStr, TypeScript.PullElementKind.Property, this.semanticInfoChain);
                prototypeSymbol.setIsSynthesized();
                prototypeSymbol.addDeclaration(prototypeDecl);
                prototypeSymbol.type = classTypeSymbol;
                constructorTypeSymbol.addMember(prototypeSymbol);

                if (prototypeSymbol.type && prototypeSymbol.type.isGeneric()) {
                    var resolver = this.semanticInfoChain.getResolver();
                    prototypeSymbol.type = resolver.instantiateTypeToAny(prototypeSymbol.type, new TypeScript.PullTypeResolutionContext(resolver));
                }
                prototypeSymbol.setResolved();
            }
        };

        // class constructor declarations
        PullSymbolBinder.prototype.bindConstructorDeclarationToPullSymbol = function (constructorDeclaration) {
            var declKind = constructorDeclaration.kind;
            var declFlags = constructorDeclaration.flags;
            var constructorAST = this.semanticInfoChain.getASTForDecl(constructorDeclaration);

            var constructorName = constructorDeclaration.name;

            var isSignature = (declFlags & TypeScript.PullElementFlags.Signature) !== 0;

            var parent = this.getParent(constructorDeclaration, true);

            var parentHadSymbol = false;

            var constructorSymbol = parent.getConstructorMethod();
            var constructorTypeSymbol = null;

            if (constructorSymbol && (constructorSymbol.kind !== TypeScript.PullElementKind.ConstructorMethod || (!isSignature && constructorSymbol.type && constructorSymbol.type.hasOwnConstructSignatures()))) {
                var hasDefinitionSignature = false;
                var constructorSigs = constructorSymbol.type.getOwnDeclaredConstructSignatures();

                for (var i = 0; i < constructorSigs.length; i++) {
                    if (!constructorSigs[i].anyDeclHasFlag(TypeScript.PullElementFlags.Signature)) {
                        hasDefinitionSignature = true;
                        break;
                    }
                }

                if (hasDefinitionSignature) {
                    this.semanticInfoChain.addDiagnosticFromAST(constructorAST, TypeScript.DiagnosticCode.Multiple_constructor_implementations_are_not_allowed);

                    constructorSymbol = null;
                }
            }

            if (constructorSymbol) {
                constructorTypeSymbol = constructorSymbol.type;
            } else {
                constructorSymbol = new TypeScript.PullSymbol(constructorName, TypeScript.PullElementKind.ConstructorMethod, this.semanticInfoChain);
                constructorTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.ConstructorType, this.semanticInfoChain);
            }

            // Even if we're reusing the symbol, it would have been cleared by the call to invalidate above
            parent.setConstructorMethod(constructorSymbol);
            constructorSymbol.type = constructorTypeSymbol;

            constructorDeclaration.setSymbol(constructorSymbol, this.semanticInfoChain);
            constructorSymbol.addDeclaration(constructorDeclaration);
            constructorTypeSymbol.addDeclaration(constructorDeclaration);
            constructorSymbol.setIsSynthesized(false);
            this.semanticInfoChain.setSymbolForAST(constructorAST, constructorSymbol);

            // add a call signature to the constructor method, and a construct signature to the parent class type
            var constructSignature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.ConstructSignature, this.semanticInfoChain, !isSignature);
            constructSignature.returnType = parent;
            constructSignature.addTypeParametersFromReturnType();

            constructSignature.addDeclaration(constructorDeclaration);
            constructorDeclaration.setSignatureSymbol(constructSignature, this.semanticInfoChain);

            this.bindParameterSymbols(constructorAST, constructorAST.callSignature.parameterList.parameters, constructorTypeSymbol, constructSignature);

            if (TypeScript.lastParameterIsRest(constructorAST.callSignature.parameterList.parameters)) {
                constructSignature.hasVarArgs = true;
            }

            constructorTypeSymbol.appendConstructSignature(constructSignature);
        };

        PullSymbolBinder.prototype.bindConstructSignatureDeclarationToPullSymbol = function (constructSignatureDeclaration) {
            var parent = this.getParent(constructSignatureDeclaration, true);
            var constructorAST = this.semanticInfoChain.getASTForDecl(constructSignatureDeclaration);

            var constructSignature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.ConstructSignature, this.semanticInfoChain);

            if (TypeScript.lastParameterIsRest(constructorAST.callSignature.parameterList.parameters)) {
                constructSignature.hasVarArgs = true;
            }

            var typeParameters = constructSignatureDeclaration.getTypeParameters();
            var typeParameter;

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameter = constructSignature.findTypeParameter(typeParameters[i].name);

                if (!typeParameter) {
                    typeParameter = new TypeScript.PullTypeParameterSymbol(typeParameters[i].name, this.semanticInfoChain);

                    constructSignature.addTypeParameter(typeParameter);
                } else {
                    var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameter.getDeclarations()[0]);
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameter.getName()]);
                }

                typeParameter.addDeclaration(typeParameters[i]);
                typeParameters[i].setSymbol(typeParameter, this.semanticInfoChain);
            }

            constructSignature.addDeclaration(constructSignatureDeclaration);
            constructSignatureDeclaration.setSignatureSymbol(constructSignature, this.semanticInfoChain);

            var funcDecl = this.semanticInfoChain.getASTForDecl(constructSignatureDeclaration);
            this.bindParameterSymbols(funcDecl, TypeScript.ASTHelpers.getParameterList(funcDecl).parameters, null, constructSignature);

            this.semanticInfoChain.setSymbolForAST(this.semanticInfoChain.getASTForDecl(constructSignatureDeclaration), constructSignature);

            var signatureIndex = this.getIndexForInsertingSignatureAtEndOfEnclosingDeclInSignatureList(constructSignature, parent.getOwnDeclaredConstructSignatures());
            parent.insertConstructSignatureAtIndex(constructSignature, signatureIndex);
        };

        PullSymbolBinder.prototype.bindCallSignatureDeclarationToPullSymbol = function (callSignatureDeclaration) {
            var parent = this.getParent(callSignatureDeclaration, true);
            var callSignatureAST = this.semanticInfoChain.getASTForDecl(callSignatureDeclaration);

            var callSignature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.CallSignature, this.semanticInfoChain);

            if (TypeScript.lastParameterIsRest(callSignatureAST.parameterList.parameters)) {
                callSignature.hasVarArgs = true;
            }

            var typeParameters = callSignatureDeclaration.getTypeParameters();
            var typeParameter;

            for (var i = 0; i < typeParameters.length; i++) {
                typeParameter = callSignature.findTypeParameter(typeParameters[i].name);

                if (!typeParameter) {
                    typeParameter = new TypeScript.PullTypeParameterSymbol(typeParameters[i].name, this.semanticInfoChain);

                    callSignature.addTypeParameter(typeParameter);
                } else {
                    var typeParameterAST = this.semanticInfoChain.getASTForDecl(typeParameter.getDeclarations()[0]);
                    this.semanticInfoChain.addDiagnosticFromAST(typeParameterAST, TypeScript.DiagnosticCode.Duplicate_identifier_0, [typeParameter.getName()]);
                }

                typeParameter.addDeclaration(typeParameters[i]);
                typeParameters[i].setSymbol(typeParameter, this.semanticInfoChain);
            }

            callSignature.addDeclaration(callSignatureDeclaration);
            callSignatureDeclaration.setSignatureSymbol(callSignature, this.semanticInfoChain);

            var funcDecl = this.semanticInfoChain.getASTForDecl(callSignatureDeclaration);
            this.bindParameterSymbols(funcDecl, funcDecl.parameterList.parameters, null, callSignature);

            this.semanticInfoChain.setSymbolForAST(this.semanticInfoChain.getASTForDecl(callSignatureDeclaration), callSignature);

            var signatureIndex = this.getIndexForInsertingSignatureAtEndOfEnclosingDeclInSignatureList(callSignature, parent.getOwnCallSignatures());
            parent.insertCallSignatureAtIndex(callSignature, signatureIndex);
        };

        PullSymbolBinder.prototype.bindIndexSignatureDeclarationToPullSymbol = function (indexSignatureDeclaration) {
            var indexSignature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.IndexSignature, this.semanticInfoChain);

            indexSignature.addDeclaration(indexSignatureDeclaration);
            indexSignatureDeclaration.setSignatureSymbol(indexSignature, this.semanticInfoChain);

            var funcDecl = this.semanticInfoChain.getASTForDecl(indexSignatureDeclaration);
            this.bindParameterSymbols(funcDecl, funcDecl.parameters, null, indexSignature);

            this.semanticInfoChain.setSymbolForAST(this.semanticInfoChain.getASTForDecl(indexSignatureDeclaration), indexSignature);

            var parent = this.getParent(indexSignatureDeclaration);
            parent.addIndexSignature(indexSignature);
            indexSignature.setContainer(parent);
        };

        // getters and setters
        PullSymbolBinder.prototype.bindGetAccessorDeclarationToPullSymbol = function (getAccessorDeclaration) {
            var declKind = getAccessorDeclaration.kind;
            var declFlags = getAccessorDeclaration.flags;
            var funcDeclAST = this.semanticInfoChain.getASTForDecl(getAccessorDeclaration);

            var isExported = (declFlags & 1 /* Exported */) !== 0;

            var funcName = getAccessorDeclaration.name;

            var isSignature = (declFlags & TypeScript.PullElementFlags.Signature) !== 0;
            var isStatic = false;

            if (TypeScript.hasFlag(declFlags, TypeScript.PullElementFlags.Static)) {
                isStatic = true;
            }

            var parent = this.getParent(getAccessorDeclaration, true);
            var parentHadSymbol = false;

            var accessorSymbol = null;
            var getterSymbol = null;
            var getterTypeSymbol = null;

            if (isStatic) {
                parent = parent.getConstructorMethod().type;
            }

            accessorSymbol = parent.findMember(funcName, false);

            if (accessorSymbol) {
                if (!accessorSymbol.isAccessor()) {
                    this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(funcDeclAST.propertyName, getAccessorDeclaration.getDisplayName());
                    accessorSymbol = null;
                } else {
                    getterSymbol = accessorSymbol.getGetter();

                    if (getterSymbol) {
                        this.semanticInfoChain.addDiagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Getter_0_already_declared, [getAccessorDeclaration.getDisplayName()]);
                        accessorSymbol = null;
                        getterSymbol = null;
                    }
                }
            }

            if (accessorSymbol) {
                parentHadSymbol = true;
            }

            // we have an accessor we can use...
            if (accessorSymbol && getterSymbol) {
                getterTypeSymbol = getterSymbol.type;
            }

            if (!accessorSymbol) {
                accessorSymbol = new TypeScript.PullAccessorSymbol(funcName, this.semanticInfoChain);
            }

            if (!getterSymbol) {
                getterSymbol = new TypeScript.PullSymbol(funcName, TypeScript.PullElementKind.Function, this.semanticInfoChain);
                getterTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.FunctionType, this.semanticInfoChain);
                getterTypeSymbol.setFunctionSymbol(getterSymbol);

                getterSymbol.type = getterTypeSymbol;

                accessorSymbol.setGetter(getterSymbol);
            }

            getAccessorDeclaration.setSymbol(accessorSymbol, this.semanticInfoChain);
            accessorSymbol.addDeclaration(getAccessorDeclaration);
            getterSymbol.addDeclaration(getAccessorDeclaration);

            // Note that the name ISyntaxElement binds to the full accessor symbol, whereas the declaration ISyntaxElement
            // binds to just the getter symbol. This is because when the resolver resolves an
            // accessor declaration ISyntaxElement, it just expects the getter/setter symbol. But when
            // the language service looks up the name of an accessor, it should treat it as a
            // property and display it to the user as such.
            var nameAST = funcDeclAST.propertyName;
            this.semanticInfoChain.setSymbolForAST(nameAST, accessorSymbol);
            this.semanticInfoChain.setSymbolForAST(funcDeclAST, getterSymbol);

            if (!parentHadSymbol) {
                parent.addMember(accessorSymbol);
            }

            var signature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.CallSignature, this.semanticInfoChain, !isSignature);

            signature.addDeclaration(getAccessorDeclaration);
            getAccessorDeclaration.setSignatureSymbol(signature, this.semanticInfoChain);

            this.bindParameterSymbols(funcDeclAST, funcDeclAST.callSignature.parameterList.parameters, getterTypeSymbol, signature);

            // add the implicit call member for this function type
            getterTypeSymbol.appendCallSignature(signature);
        };

        PullSymbolBinder.prototype.bindSetAccessorDeclarationToPullSymbol = function (setAccessorDeclaration) {
            var declKind = setAccessorDeclaration.kind;
            var declFlags = setAccessorDeclaration.flags;
            var funcDeclAST = this.semanticInfoChain.getASTForDecl(setAccessorDeclaration);

            var isExported = (declFlags & 1 /* Exported */) !== 0;

            var funcName = setAccessorDeclaration.name;

            var isSignature = (declFlags & TypeScript.PullElementFlags.Signature) !== 0;
            var isStatic = false;

            if (TypeScript.hasFlag(declFlags, TypeScript.PullElementFlags.Static)) {
                isStatic = true;
            }

            var parent = this.getParent(setAccessorDeclaration, true);
            var parentHadSymbol = false;

            var accessorSymbol = null;
            var setterSymbol = null;
            var setterTypeSymbol = null;

            if (isStatic) {
                parent = parent.getConstructorMethod().type;
            }

            accessorSymbol = parent.findMember(funcName, false);

            if (accessorSymbol) {
                if (!accessorSymbol.isAccessor()) {
                    this.semanticInfoChain.addDuplicateIdentifierDiagnosticFromAST(funcDeclAST.propertyName, setAccessorDeclaration.getDisplayName());
                    accessorSymbol = null;
                } else {
                    setterSymbol = accessorSymbol.getSetter();

                    if (setterSymbol) {
                        this.semanticInfoChain.addDiagnosticFromAST(funcDeclAST, TypeScript.DiagnosticCode.Setter_0_already_declared, [setAccessorDeclaration.getDisplayName()]);
                        accessorSymbol = null;
                        setterSymbol = null;
                    }
                }
            }

            if (accessorSymbol) {
                parentHadSymbol = true;

                // we have an accessor we can use...
                if (setterSymbol) {
                    setterTypeSymbol = setterSymbol.type;
                }
            }

            if (!accessorSymbol) {
                // PULLTODO: Make sure that we properly flag signature decl types when collecting decls
                accessorSymbol = new TypeScript.PullAccessorSymbol(funcName, this.semanticInfoChain);
            }

            if (!setterSymbol) {
                setterSymbol = new TypeScript.PullSymbol(funcName, TypeScript.PullElementKind.Function, this.semanticInfoChain);
                setterTypeSymbol = new TypeScript.PullTypeSymbol("", TypeScript.PullElementKind.FunctionType, this.semanticInfoChain);
                setterTypeSymbol.setFunctionSymbol(setterSymbol);

                setterSymbol.type = setterTypeSymbol;

                accessorSymbol.setSetter(setterSymbol);
            }

            setAccessorDeclaration.setSymbol(accessorSymbol, this.semanticInfoChain);
            accessorSymbol.addDeclaration(setAccessorDeclaration);
            setterSymbol.addDeclaration(setAccessorDeclaration);

            // Note that the name ISyntaxElement binds to the full accessor symbol, whereas the declaration ISyntaxElement
            // binds to just the setter symbol. This is because when the resolver resolves an
            // accessor declaration ISyntaxElement, it just expects the getter/setter symbol. But when
            // the language service looks up the name of an accessor, it should treat it as a
            // property and display it to the user as such.
            var nameAST = funcDeclAST.propertyName;
            this.semanticInfoChain.setSymbolForAST(nameAST, accessorSymbol);
            this.semanticInfoChain.setSymbolForAST(funcDeclAST, setterSymbol);

            if (!parentHadSymbol) {
                parent.addMember(accessorSymbol);
            }

            var signature = new TypeScript.PullSignatureSymbol(TypeScript.PullElementKind.CallSignature, this.semanticInfoChain, !isSignature);

            signature.addDeclaration(setAccessorDeclaration);
            setAccessorDeclaration.setSignatureSymbol(signature, this.semanticInfoChain);

            // PULLTODO: setter should not have a parameters
            this.bindParameterSymbols(funcDeclAST, funcDeclAST.callSignature.parameterList.parameters, setterTypeSymbol, signature);

            // add the implicit call member for this function type
            setterTypeSymbol.appendCallSignature(signature);
        };

        PullSymbolBinder.prototype.getDeclsToBind = function (decl) {
            var decls;
            switch (decl.kind) {
                case TypeScript.PullElementKind.Enum:
                case TypeScript.PullElementKind.DynamicModule:
                case TypeScript.PullElementKind.Container:
                case TypeScript.PullElementKind.Interface:
                    decls = this.findDeclsInContext(decl, decl.kind, true);
                    break;

                case TypeScript.PullElementKind.Variable:
                case TypeScript.PullElementKind.Function:
                case TypeScript.PullElementKind.Method:
                case TypeScript.PullElementKind.ConstructorMethod:
                    decls = this.findDeclsInContext(decl, decl.kind, false);
                    break;

                default:
                    decls = [decl];
            }
            TypeScript.Debug.assert(decls && decls.length > 0);
            TypeScript.Debug.assert(TypeScript.ArrayUtilities.contains(decls, decl));
            return decls;
        };

        PullSymbolBinder.prototype.shouldBindDeclaration = function (decl) {
            return !decl.hasBeenBound(this.semanticInfoChain) && this.declsBeingBound.indexOf(decl.declID) < 0;
        };

        // binding
        PullSymbolBinder.prototype.bindDeclToPullSymbol = function (decl) {
            if (this.shouldBindDeclaration(decl)) {
                // The decl does not have a symbol attached to it and
                // its not already being bound
                this.bindAllDeclsToPullSymbol(decl);
            }
        };

        PullSymbolBinder.prototype.bindAllDeclsToPullSymbol = function (askedDecl) {
            var allDecls = this.getDeclsToBind(askedDecl);
            for (var i = 0; i < allDecls.length; i++) {
                var decl = allDecls[i];

                // This check is necessary for two reasons
                // 1. This decl could be actually something we dont care to bind other decls corresponding to it
                //    and so it was already bound without binding other decls with same name corresponding to it (e.g parameter)
                // 2. This was bound as part of some recursion
                //    eg:
                //      module A {
                //          var o;
                //      }
                //      enum A {
                //          /*quickInfoHere*/c
                //      }
                //      module A {
                //          var p;
                //      }
                //     As part of binding the member declaration, we would bind enum and hence end up binding all value decls
                //     which are instance vars from module declaration. As part of it, we would want to bind corresponding
                //     module declaration which in turn would try to bind all the var declarations
                if (this.shouldBindDeclaration(decl)) {
                    this.bindSingleDeclToPullSymbol(decl);
                }
            }
        };

        PullSymbolBinder.prototype.bindSingleDeclToPullSymbol = function (decl) {
            // Add it to the list in case we revisit it during binding
            this.declsBeingBound.push(decl.declID);

            switch (decl.kind) {
                case TypeScript.PullElementKind.Script:
                    var childDecls = decl.getChildDecls();
                    for (var i = 0; i < childDecls.length; i++) {
                        this.bindDeclToPullSymbol(childDecls[i]);
                    }
                    break;

                case TypeScript.PullElementKind.Enum:
                    this.bindEnumDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.DynamicModule:
                case TypeScript.PullElementKind.Container:
                    this.bindModuleDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.Interface:
                    this.bindInterfaceDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.Class:
                    this.bindClassDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.Function:
                    this.bindFunctionDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.Variable:
                    this.bindVariableDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.CatchVariable:
                    this.bindCatchVariableToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.EnumMember:
                    this.bindEnumMemberDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.Property:
                    this.bindPropertyDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.Method:
                    this.bindMethodDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.ConstructorMethod:
                    this.bindConstructorDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.CallSignature:
                    this.bindCallSignatureDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.ConstructSignature:
                    this.bindConstructSignatureDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.IndexSignature:
                    this.bindIndexSignatureDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.GetAccessor:
                    this.bindGetAccessorDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.SetAccessor:
                    this.bindSetAccessorDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.ObjectType:
                    this.bindObjectTypeDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.FunctionType:
                    this.bindFunctionTypeDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.ConstructorType:
                    this.bindConstructorTypeDeclarationToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.FunctionExpression:
                    this.bindFunctionExpressionToPullSymbol(decl);
                    break;

                case TypeScript.PullElementKind.TypeAlias:
                    this.bindImportDeclaration(decl);
                    break;

                case TypeScript.PullElementKind.Parameter:
                case TypeScript.PullElementKind.TypeParameter:
                    // parameters are bound by their enclosing function or type.  Ensure that that
                    // decl is bound.
                    decl.getParentDecl().getSymbol(this.semanticInfoChain);
                    break;

                case TypeScript.PullElementKind.CatchBlock:
                case TypeScript.PullElementKind.WithBlock:
                    break;
            }

            // Rremove the decl from the list
            TypeScript.Debug.assert(TypeScript.ArrayUtilities.last(this.declsBeingBound) === decl.declID);
            this.declsBeingBound.pop();
        };
        return PullSymbolBinder;
    })();
    TypeScript.PullSymbolBinder = PullSymbolBinder;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (PullHelpers) {
        // This helps in case we would like to make sure we have type while we are resolving/infering types for it
        // without infering back to any because we incorrectly detected recursive resolution of function
        function resolveDeclaredSymbolToUseType(symbol) {
            if (symbol.isSignature()) {
                if (!symbol.returnType) {
                    symbol._resolveDeclaredSymbol();
                }
            } else if (!symbol.type) {
                symbol._resolveDeclaredSymbol();
            }
        }
        PullHelpers.resolveDeclaredSymbolToUseType = resolveDeclaredSymbolToUseType;

        function getSignatureForFuncDecl(functionDecl, semanticInfoChain) {
            var funcDecl = functionDecl.ast();
            var funcSymbol = functionDecl.getSymbol(semanticInfoChain);

            if (!funcSymbol) {
                funcSymbol = functionDecl.getSignatureSymbol(semanticInfoChain);
            }

            var functionSignature = null;
            var typeSymbolWithAllSignatures = null;
            if (funcSymbol.isSignature()) {
                functionSignature = funcSymbol;
                var parent = functionDecl.getParentDecl();
                typeSymbolWithAllSignatures = parent.getSymbol(semanticInfoChain).type;
            } else {
                functionSignature = functionDecl.getSignatureSymbol(semanticInfoChain);
                typeSymbolWithAllSignatures = funcSymbol.type;
            }
            var signatures;

            if (funcDecl.kind() === 137 /* ConstructorDeclaration */ || functionDecl.kind === TypeScript.PullElementKind.ConstructSignature) {
                signatures = typeSymbolWithAllSignatures.getConstructSignatures();
            } else if (functionDecl.kind === TypeScript.PullElementKind.IndexSignature) {
                signatures = typeSymbolWithAllSignatures.getIndexSignatures();
            } else {
                signatures = typeSymbolWithAllSignatures.getCallSignatures();
            }

            return {
                signature: functionSignature,
                allSignatures: signatures
            };
        }
        PullHelpers.getSignatureForFuncDecl = getSignatureForFuncDecl;

        function getAccessorSymbol(getterOrSetter, semanticInfoChain) {
            var functionDecl = semanticInfoChain.getDeclForAST(getterOrSetter);
            var getterOrSetterSymbol = functionDecl.getSymbol(semanticInfoChain);

            return getterOrSetterSymbol;
        }
        PullHelpers.getAccessorSymbol = getAccessorSymbol;

        function getGetterAndSetterFunction(funcDecl, semanticInfoChain) {
            var accessorSymbol = PullHelpers.getAccessorSymbol(funcDecl, semanticInfoChain);
            var result = {
                getter: null,
                setter: null
            };
            var getter = accessorSymbol.getGetter();
            if (getter) {
                var getterDecl = getter.getDeclarations()[0];
                result.getter = semanticInfoChain.getASTForDecl(getterDecl);
            }
            var setter = accessorSymbol.getSetter();
            if (setter) {
                var setterDecl = setter.getDeclarations()[0];
                result.setter = semanticInfoChain.getASTForDecl(setterDecl);
            }

            return result;
        }
        PullHelpers.getGetterAndSetterFunction = getGetterAndSetterFunction;

        function symbolIsEnum(source) {
            return source && (source.kind & (TypeScript.PullElementKind.Enum | TypeScript.PullElementKind.EnumMember)) !== 0;
        }
        PullHelpers.symbolIsEnum = symbolIsEnum;

        function symbolIsModule(symbol) {
            return symbol && (symbol.kind === TypeScript.PullElementKind.Container || isOneDeclarationOfKind(symbol, TypeScript.PullElementKind.Container));
        }
        PullHelpers.symbolIsModule = symbolIsModule;

        function isOneDeclarationOfKind(symbol, kind) {
            var decls = symbol.getDeclarations();
            for (var i = 0; i < decls.length; i++) {
                if (decls[i].kind === kind) {
                    return true;
                }
            }

            return false;
        }

        function isInStaticMemberContext(ast, semanticInfoChain) {
            var memberDeclAST = TypeScript.ASTHelpers.getEnclosingMemberDeclaration(ast);

            if (!memberDeclAST) {
                return false;
            }

            var decl = semanticInfoChain.getDeclForAST(memberDeclAST);

            return decl && TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Static);
        }
        PullHelpers.isInStaticMemberContext = isInStaticMemberContext;

        function isNameNumeric(name) {
            // Coerce the name to a number, and then use isFinite to make sure it is not Infinity or NaN
            return isFinite(+name);
        }
        PullHelpers.isNameNumeric = isNameNumeric;

        function typeSymbolsAreIdentical(a, b) {
            // initialized types are omitted, since the type reference points back to the generic type
            // declaration.  (E.g., the referencedTypeSymbol of 'Foo<number>' would be 'Foo<T>'
            if (a.isTypeReference() && !a.getIsSpecialized()) {
                a = a.referencedTypeSymbol;
            }

            if (b.isTypeReference() && !b.getIsSpecialized()) {
                b = b.referencedTypeSymbol;
            }

            return a === b;
        }
        PullHelpers.typeSymbolsAreIdentical = typeSymbolsAreIdentical;

        function getRootType(type) {
            var rootType = type.getRootSymbol();

            while (true) {
                if (type === rootType) {
                    return type;
                }

                type = rootType;
                rootType = type.getRootSymbol();
            }
        }
        PullHelpers.getRootType = getRootType;

        function isSymbolLocal(symbol) {
            var container = symbol.getContainer();
            if (container) {
                var containerKind = container.kind;
                if (containerKind & (TypeScript.PullElementKind.SomeFunction | TypeScript.PullElementKind.FunctionType)) {
                    return true;
                }

                if (containerKind === TypeScript.PullElementKind.ConstructorType && !symbol.anyDeclHasFlag(TypeScript.PullElementFlags.Static | 1 /* Exported */)) {
                    // container kind can be ConstructorType when
                    // - symbol represents static member of the class or exported value in the clodule
                    // - symbol represents local varable in the constructor
                    // 'IsSymbolLocal' should return true only for the second category
                    return true;
                }
            }

            return false;
        }
        PullHelpers.isSymbolLocal = isSymbolLocal;

        function isExportedSymbolInClodule(symbol) {
            var container = symbol.getContainer();
            return container && container.kind === TypeScript.PullElementKind.ConstructorType && symbolIsModule(container) && symbol.anyDeclHasFlag(1 /* Exported */);
        }
        PullHelpers.isExportedSymbolInClodule = isExportedSymbolInClodule;

        function isSymbolDeclaredInScopeChain(symbol, scopeSymbol) {
            TypeScript.Debug.assert(symbol);
            var symbolDeclarationScope = symbol.getContainer();

            while (scopeSymbol) {
                // symbol is declared in same as scope symbol
                if (scopeSymbol === symbolDeclarationScope) {
                    return true;
                }

                // look in the outer scope of scopeSymbol
                scopeSymbol = scopeSymbol.getContainer();
            }

            if (scopeSymbol === null && symbolDeclarationScope === null) {
                // Both are global scopes.
                return true;
            }

            return false;
        }
        PullHelpers.isSymbolDeclaredInScopeChain = isSymbolDeclaredInScopeChain;

        

        // Walks the signature
        function walkSignatureSymbol(signatureSymbol, walker) {
            var continueWalk = true;
            var parameters = signatureSymbol.parameters;
            if (parameters) {
                for (var i = 0; continueWalk && i < parameters.length; i++) {
                    continueWalk = walker.signatureParameterWalk(parameters[i]);
                }
            }

            if (continueWalk) {
                continueWalk = walker.signatureReturnTypeWalk(signatureSymbol.returnType);
            }

            return continueWalk;
        }

        // Walk the type symbol structure
        function walkPullTypeSymbolStructure(typeSymbol, walker) {
            var continueWalk = true;

            // Members
            var members = typeSymbol.getMembers();
            for (var i = 0; continueWalk && i < members.length; i++) {
                continueWalk = walker.memberSymbolWalk(members[i]);
            }

            if (continueWalk) {
                // Call signatures
                var callSigantures = typeSymbol.getCallSignatures();
                for (var i = 0; continueWalk && i < callSigantures.length; i++) {
                    continueWalk = walker.callSignatureWalk(callSigantures[i]);
                    if (continueWalk) {
                        continueWalk = walkSignatureSymbol(callSigantures[i], walker);
                    }
                }
            }

            if (continueWalk) {
                // Construct signatures
                var constructSignatures = typeSymbol.getConstructSignatures();
                for (var i = 0; continueWalk && i < constructSignatures.length; i++) {
                    continueWalk = walker.constructSignatureWalk(constructSignatures[i]);
                    if (continueWalk) {
                        continueWalk = walkSignatureSymbol(constructSignatures[i], walker);
                    }
                }
            }

            if (continueWalk) {
                // Index signatures
                var indexSignatures = typeSymbol.getIndexSignatures();
                for (var i = 0; continueWalk && i < indexSignatures.length; i++) {
                    continueWalk = walker.indexSignatureWalk(indexSignatures[i]);
                    if (continueWalk) {
                        continueWalk = walkSignatureSymbol(indexSignatures[i], walker);
                    }
                }
            }
        }
        PullHelpers.walkPullTypeSymbolStructure = walkPullTypeSymbolStructure;

        // Helper class to walk the other decls
        var OtherPullDeclsWalker = (function () {
            function OtherPullDeclsWalker() {
                // The below walk just gives example of the usage of walk:
                // This is list of decls that are currently binding other decl.
                // We maintain this so that we dont keep binding other decls in the stack.
                // eg. if we have this:
                // module a{            // decl1
                // }
                // module a {           // decl2
                // }
                // module a {           // decl3
                // }
                // module a {           // decl4
                // }
                // If we do not keep track of these decls we would end up binding decl4 on stack when binding decl1, decl2, decl3 as below:
                // After binding decl1, we would go and try to bind other decls of 'a'
                // as part of it we would try to bind decl1, since its already bound we proceed to decl2
                // After binding decl2, we go bind other decls of 'a' and find that decl1 and decl2 are already bound
                // So as we bind decl3, and then go and try to bind other decls of 'a' which ends us up in binding decl4.
                // Thus the stack would be proportional to decls for given particular symbol.
                //
                // To avoid this before binding other symbols we always check if the list of decls contains
                // the decl whose other decls we are already binding and if yes we skip the binding other decls
                // In the above eg. when we start binding other decls of 'a' after binding decl1, we go bind decl2
                // but when binding other decls of decl2, we find that it contains decl1, which is already binding its other decls
                // hence we dont do other decl binding and return and do same process for rest of the decls, thus ending up
                // binding only current decl if we are binding that symbol as part of binding other decls
                this.currentlyWalkingOtherDecls = [];
            }
            OtherPullDeclsWalker.prototype.walkOtherPullDecls = function (currentDecl, otherDecls, callBack) {
                if (otherDecls) {
                    var isAlreadyWalkingOtherDecl = TypeScript.ArrayUtilities.any(this.currentlyWalkingOtherDecls, function (inWalkingOtherDecl) {
                        return TypeScript.ArrayUtilities.contains(otherDecls, inWalkingOtherDecl);
                    });

                    // If we are already binding other decls for this
                    if (!isAlreadyWalkingOtherDecl) {
                        this.currentlyWalkingOtherDecls.push(currentDecl);
                        for (var i = 0; i < otherDecls.length; i++) {
                            if (otherDecls[i] !== currentDecl) {
                                callBack(otherDecls[i]);
                            }
                        }
                        var currentlyWalkingOtherDeclsDecl = this.currentlyWalkingOtherDecls.pop();
                        TypeScript.Debug.assert(currentlyWalkingOtherDeclsDecl == currentDecl);
                    }
                }
            };
            return OtherPullDeclsWalker;
        })();
        PullHelpers.OtherPullDeclsWalker = OtherPullDeclsWalker;
    })(TypeScript.PullHelpers || (TypeScript.PullHelpers = {}));
    var PullHelpers = TypeScript.PullHelpers;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='..\references.ts' />
var TypeScript;
(function (TypeScript) {
    var WrapsTypeParameterCache = (function () {
        function WrapsTypeParameterCache() {
            this._wrapsTypeParameterCache = TypeScript.BitVector.getBitVector(true);
        }
        // 0 indicates that it does not wrap type parameter
        // undefined indicates that the info wasn't available from cache
        // rest indicates the valid type parameter id
        //
        // The obvious way to answer the question, "Does this type wrap any type parameter
        // from a given map?" is via a boolean. However, using a boolean would make the
        // cache less effective. So we instead return the ID of SOME type parameter that is
        // both in the typeParameterArgumentMap and is set to true in the cache. If all
        // type parameters in the map are set to false in the cache, we return 0. And if
        // neither of those apply, we need more information, so we return undefined.
        //
        // For example, consider a type or signature that wraps type
        // parameters with ID's [1, 5, 6]. We are asked if it wraps some type parameter from
        // the map [2, 4, 6]. Of course it does, because it wraps 6. If we cached true
        // for map [2, 4, 6], this would not help us if we were later asked if it wraps
        // something from [1, 3, 6], since it is not the same map that we were asked about
        // before. However, by caching the 6, we are implicitly caching true for ANY map
        // that contains a 6.
        //
        // On the negative side, if we find that nothing is wrapped from [2, 3, 4], we should
        // cache false for each type parameter (2, 3, and 4). This way if we are later asked
        // about [3, 4], we know to return false.
        //
        // Another way to think about this is that if we wrap some type parameter, then
        // we have only learned that we wrap ONE type parameter. If we do not wrap any
        // type parameter, we have learned that for ALL type parameters in the map.
        WrapsTypeParameterCache.prototype.getWrapsTypeParameter = function (typeParameterArgumentMap) {
            // Find result from cache
            var someTypeParameterWasMissingFromCache = false;
            for (var typeParameterID in typeParameterArgumentMap) {
                if (typeParameterArgumentMap.hasOwnProperty(typeParameterID)) {
                    var cachedValue = this._wrapsTypeParameterCache.valueAt(typeParameterID);
                    if (cachedValue) {
                        // Cached value indicates that the type parameter is wrapped
                        return typeParameterID;
                    }
                    someTypeParameterWasMissingFromCache = someTypeParameterWasMissingFromCache || cachedValue === undefined;
                }
            }

            // If everything was cached, then this type doesnt wrap the type parameter
            if (!someTypeParameterWasMissingFromCache) {
                return 0;
            }

            return undefined;
        };

        WrapsTypeParameterCache.prototype.setWrapsTypeParameter = function (typeParameterArgumentMap, wrappingTypeParameterID) {
            if (wrappingTypeParameterID) {
                // wrappingTypeParameterID is the known type parameter that is wrapped
                // We dont know about other type parameters present in the map and hence we cant set their values
                this._wrapsTypeParameterCache.setValueAt(wrappingTypeParameterID, true);
            } else {
                for (var typeParameterID in typeParameterArgumentMap) {
                    if (typeParameterArgumentMap.hasOwnProperty(typeParameterID)) {
                        this._wrapsTypeParameterCache.setValueAt(typeParameterID, false);
                    }
                }
            }
        };
        return WrapsTypeParameterCache;
    })();
    TypeScript.WrapsTypeParameterCache = WrapsTypeParameterCache;

    (function (PullInstantiationHelpers) {
        // This class helps in creating the type substitution map
        // But it creates another copy only if the type substitution map is changing
        // helping in not modifying entried in the existing map
        var MutableTypeParameterSubstitutionMap = (function () {
            function MutableTypeParameterSubstitutionMap(typeParameterSubstitutionMap) {
                this.typeParameterSubstitutionMap = typeParameterSubstitutionMap;
                this.createdDuplicateTypeSubstitutionMap = false;
            }
            MutableTypeParameterSubstitutionMap.prototype.ensureCopyOfUnderlyingMap = function () {
                if (!this.createdDuplicateTypeSubstitutionMap) {
                    var passedInTypeArgumentMap = this.typeParameterSubstitutionMap;
                    this.typeParameterSubstitutionMap = [];
                    for (var typeParameterID in passedInTypeArgumentMap) {
                        if (passedInTypeArgumentMap.hasOwnProperty(typeParameterID)) {
                            this.typeParameterSubstitutionMap[typeParameterID] = passedInTypeArgumentMap[typeParameterID];
                        }
                    }
                    this.createdDuplicateTypeSubstitutionMap = true;
                }
            };
            return MutableTypeParameterSubstitutionMap;
        })();
        PullInstantiationHelpers.MutableTypeParameterSubstitutionMap = MutableTypeParameterSubstitutionMap;

        // Instantiate the type arguments
        // This instantiates all the type parameters the symbol can reference and the type argument in the end
        // will contain the final instantiated version for each typeparameter
        // eg. if the type is already specialized, we need to create a new type substitution map that represents
        // the mapping of type arguments we've just received to type arguments as previously passed through
        // If we have below sample
        //interface IList<T> {
        //    owner: IList<IList<T>>;
        //}
        //class List<U> implements IList<U> {
        //    owner: IList<IList<U>>;
        //}
        //class List2<V> extends List<V> {
        //    owner: List2<List2<V>>;
        //}
        // When instantiating List<V> with U = V and trying to get owner property we would have the map that
        // says U = V, but when creating the IList<V> we want to updates its type substitution maps to say T = V because
        // IList<T>  would now be instantiated with V
        function instantiateTypeArgument(resolver, symbol, mutableTypeParameterMap) {
            if (symbol.getIsSpecialized()) {
                // Get the type substitution map from the signature and update our type substitution map
                var rootTypeArgumentMap = symbol.getTypeParameterSubstitutionMap();
                var newTypeArgumentMap = [];
                var allowedTypeParameters = symbol.getAllowedToReferenceTypeParameters();
                for (var i = 0; i < allowedTypeParameters.length; i++) {
                    var typeParameterID = allowedTypeParameters[i].pullSymbolID;
                    var typeArg = rootTypeArgumentMap[typeParameterID];
                    if (typeArg) {
                        newTypeArgumentMap[typeParameterID] = resolver.instantiateType(typeArg, mutableTypeParameterMap.typeParameterSubstitutionMap);
                    }
                }

                for (var i = 0; i < allowedTypeParameters.length; i++) {
                    var typeParameterID = allowedTypeParameters[i].pullSymbolID;
                    if (newTypeArgumentMap[typeParameterID] && mutableTypeParameterMap.typeParameterSubstitutionMap[typeParameterID] != newTypeArgumentMap[typeParameterID]) {
                        mutableTypeParameterMap.ensureCopyOfUnderlyingMap();
                        mutableTypeParameterMap.typeParameterSubstitutionMap[typeParameterID] = newTypeArgumentMap[typeParameterID];
                    }
                }
            }
        }
        PullInstantiationHelpers.instantiateTypeArgument = instantiateTypeArgument;

        // Removes any entries that this instantiable symbol cannot reference
        // eg. In any type, typeparameter map should only contain information about the allowed to reference type parameters
        // so remove unnecessary entries that are outside these scope, eg. from above sample we need to remove entry U = V
        // and keep only T = V
        function cleanUpTypeParameterSubstitutionMap(symbol, mutableTypeParameterSubstitutionMap) {
            var allowedToReferenceTypeParameters = symbol.getAllowedToReferenceTypeParameters();
            for (var typeParameterID in mutableTypeParameterSubstitutionMap.typeParameterSubstitutionMap) {
                if (mutableTypeParameterSubstitutionMap.typeParameterSubstitutionMap.hasOwnProperty(typeParameterID)) {
                    if (!TypeScript.ArrayUtilities.any(allowedToReferenceTypeParameters, function (typeParameter) {
                        return typeParameter.pullSymbolID == typeParameterID;
                    })) {
                        mutableTypeParameterSubstitutionMap.ensureCopyOfUnderlyingMap();
                        delete mutableTypeParameterSubstitutionMap.typeParameterSubstitutionMap[typeParameterID];
                    }
                }
            }
        }
        PullInstantiationHelpers.cleanUpTypeParameterSubstitutionMap = cleanUpTypeParameterSubstitutionMap;

        // This method get the allowed to reference type parameter in any decl
        // eg. in below code
        // interface IList<T> {
        //     owner: /*Any type here can only refere to type parameter T*/;
        //     map<U>(a: /*any type parameter here can only refere to U and T*/
        // }
        function getAllowedToReferenceTypeParametersFromDecl(decl, semanticInfoChain) {
            var allowedToReferenceTypeParameters = [];

            var allowedToUseDeclTypeParameters = false;
            var getTypeParametersFromParentDecl = false;

            switch (decl.kind) {
                case TypeScript.PullElementKind.Method:
                    if (TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Static)) {
                        // Static method/property cannot use type parameters from parent
                        allowedToUseDeclTypeParameters = true;
                        break;
                    }

                case TypeScript.PullElementKind.FunctionType:
                case TypeScript.PullElementKind.ConstructorType:
                case TypeScript.PullElementKind.ConstructSignature:
                case TypeScript.PullElementKind.CallSignature:
                case TypeScript.PullElementKind.FunctionExpression:
                case TypeScript.PullElementKind.Function:
                    allowedToUseDeclTypeParameters = true;
                    getTypeParametersFromParentDecl = true;
                    break;

                case TypeScript.PullElementKind.Property:
                    if (TypeScript.hasFlag(decl.flags, TypeScript.PullElementFlags.Static)) {
                        break;
                    }

                case TypeScript.PullElementKind.Parameter:
                case TypeScript.PullElementKind.GetAccessor:
                case TypeScript.PullElementKind.SetAccessor:
                case TypeScript.PullElementKind.ConstructorMethod:
                case TypeScript.PullElementKind.IndexSignature:
                case TypeScript.PullElementKind.ObjectType:
                case TypeScript.PullElementKind.ObjectLiteral:
                case TypeScript.PullElementKind.TypeParameter:
                    getTypeParametersFromParentDecl = true;
                    break;

                case TypeScript.PullElementKind.Class:
                case TypeScript.PullElementKind.Interface:
                    allowedToUseDeclTypeParameters = true;
                    break;
            }

            if (getTypeParametersFromParentDecl) {
                allowedToReferenceTypeParameters = allowedToReferenceTypeParameters.concat(getAllowedToReferenceTypeParametersFromDecl(decl.getParentDecl(), semanticInfoChain));
            }

            if (allowedToUseDeclTypeParameters) {
                var typeParameterDecls = decl.getTypeParameters();
                for (var i = 0; i < typeParameterDecls.length; i++) {
                    allowedToReferenceTypeParameters.push(typeParameterDecls[i].getSymbol(semanticInfoChain));
                }
            }

            return allowedToReferenceTypeParameters;
        }
        PullInstantiationHelpers.getAllowedToReferenceTypeParametersFromDecl = getAllowedToReferenceTypeParametersFromDecl;

        function createTypeParameterSubstitutionMap(typeParameters, typeArguments) {
            return updateTypeParameterSubstitutionMap(typeParameters, typeArguments, {});
        }
        PullInstantiationHelpers.createTypeParameterSubstitutionMap = createTypeParameterSubstitutionMap;

        function updateTypeParameterSubstitutionMap(typeParameters, typeArguments, typeParameterSubstitutionMap) {
            for (var i = 0; i < typeParameters.length; i++) {
                // The reason we call getRootSymbol below is to handle the case where a signature
                // has a type parameter constrained to an outer type parameter. Because signatures
                // are instantiated from the root signature, the map needs to be in terms of the root
                // type parameter. For example,
                // interface I<T> {
                //     foo<U extends T>(u: U): U;
                // }
                // var i: I<string>;
                // var f = i.foo(""); // f should be string
                //
                // When we instantiate T to string, we create a new U, but instantiations of the
                // signature must be against the root U.
                // Note that when this type of situation does not apply, getRootSymbol is the
                // identity function.
                typeParameterSubstitutionMap[typeParameters[i].getRootSymbol().pullSymbolID] = typeArguments[i];
            }
            return typeParameterSubstitutionMap;
        }
        PullInstantiationHelpers.updateTypeParameterSubstitutionMap = updateTypeParameterSubstitutionMap;

        function updateMutableTypeParameterSubstitutionMap(typeParameters, typeArguments, mutableMap) {
            for (var i = 0; i < typeParameters.length; i++) {
                // See comment in updateTypeParameterArgumentMap for why we use getRootSymbol
                var typeParameterId = typeParameters[i].getRootSymbol().pullSymbolID;
                if (mutableMap.typeParameterSubstitutionMap[typeParameterId] !== typeArguments[i]) {
                    mutableMap.ensureCopyOfUnderlyingMap();
                    mutableMap.typeParameterSubstitutionMap[typeParameterId] = typeArguments[i];
                }
            }
        }
        PullInstantiationHelpers.updateMutableTypeParameterSubstitutionMap = updateMutableTypeParameterSubstitutionMap;

        function twoTypesAreInstantiationsOfSameNamedGenericType(type1, type2) {
            var type1IsGeneric = type1.isGeneric() && type1.getTypeArguments() !== null;
            var type2IsGeneric = type2.isGeneric() && type2.getTypeArguments() !== null;

            if (type1IsGeneric && type2IsGeneric) {
                var type1Root = TypeScript.PullHelpers.getRootType(type1);
                var type2Root = TypeScript.PullHelpers.getRootType(type2);
                return type1Root === type2Root;
            }

            return false;
        }
        PullInstantiationHelpers.twoTypesAreInstantiationsOfSameNamedGenericType = twoTypesAreInstantiationsOfSameNamedGenericType;
    })(TypeScript.PullInstantiationHelpers || (TypeScript.PullInstantiationHelpers = {}));
    var PullInstantiationHelpers = TypeScript.PullInstantiationHelpers;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
///<reference path="..\typescript.ts" />
var TypeScript;
(function (TypeScript) {
    (function (GenerativeTypeClassification) {
        GenerativeTypeClassification[GenerativeTypeClassification["Unknown"] = 0] = "Unknown";
        GenerativeTypeClassification[GenerativeTypeClassification["Open"] = 1] = "Open";
        GenerativeTypeClassification[GenerativeTypeClassification["Closed"] = 2] = "Closed";
        GenerativeTypeClassification[GenerativeTypeClassification["InfinitelyExpanding"] = 3] = "InfinitelyExpanding";
    })(TypeScript.GenerativeTypeClassification || (TypeScript.GenerativeTypeClassification = {}));
    var GenerativeTypeClassification = TypeScript.GenerativeTypeClassification;

    // Type references and instantiated type references
    var TypeReferenceSymbol = (function (_super) {
        __extends(TypeReferenceSymbol, _super);
        // use the root symbol to model the actual type
        // do not call this directly!
        function TypeReferenceSymbol(referencedTypeSymbol) {
            _super.call(this, referencedTypeSymbol.name, referencedTypeSymbol.kind, referencedTypeSymbol.semanticInfoChain);
            this.referencedTypeSymbol = referencedTypeSymbol;
            this.isResolved = true;

            TypeScript.Debug.assert(referencedTypeSymbol !== null, "Type root symbol may not be null");

            this.setRootSymbol(referencedTypeSymbol);

            this.typeReference = this;
        }
        TypeReferenceSymbol.createTypeReference = function (type) {
            if (type.isTypeReference()) {
                return type;
            }

            var typeReference = type.typeReference;

            if (!typeReference) {
                typeReference = new TypeReferenceSymbol(type);
                type.typeReference = typeReference;
            }

            return typeReference;
        };

        TypeReferenceSymbol.prototype.isTypeReference = function () {
            return true;
        };

        TypeReferenceSymbol.prototype.setResolved = function () {
        };

        // do nothing on invalidate
        TypeReferenceSymbol.prototype.setUnresolved = function () {
        };
        TypeReferenceSymbol.prototype.invalidate = function () {
        };

        TypeReferenceSymbol.prototype.ensureReferencedTypeIsResolved = function () {
            this._getResolver().resolveDeclaredSymbol(this.referencedTypeSymbol);
        };

        TypeReferenceSymbol.prototype.getReferencedTypeSymbol = function () {
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol;
        };

        TypeReferenceSymbol.prototype._getResolver = function () {
            return this.referencedTypeSymbol._getResolver();
        };

        // type symbol shims
        TypeReferenceSymbol.prototype.hasMembers = function () {
            // no need to resolve first - members are collected during binding
            return this.referencedTypeSymbol.hasMembers();
        };

        TypeReferenceSymbol.prototype.setAssociatedContainerType = function (type) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": setAssociatedContainerType");
        };

        TypeReferenceSymbol.prototype.getAssociatedContainerType = function () {
            return this.referencedTypeSymbol.getAssociatedContainerType();
        };

        TypeReferenceSymbol.prototype.getFunctionSymbol = function () {
            // necessary because the function symbol may be set during type resolution to
            // facilitate doc comments
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.getFunctionSymbol();
        };
        TypeReferenceSymbol.prototype.setFunctionSymbol = function (symbol) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": setFunctionSymbol");
        };

        TypeReferenceSymbol.prototype.addContainedNonMember = function (nonMember) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addContainedNonMember");
        };
        TypeReferenceSymbol.prototype.findContainedNonMemberContainer = function (containerName, kind) {
            if (typeof kind === "undefined") { kind = 0 /* None */; }
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.findContainedNonMemberContainer(containerName, kind);
        };

        TypeReferenceSymbol.prototype.addMember = function (memberSymbol) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addMember");
        };
        TypeReferenceSymbol.prototype.addEnclosedMemberType = function (enclosedType) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addEnclosedMemberType");
        };
        TypeReferenceSymbol.prototype.addEnclosedMemberContainer = function (enclosedContainer) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addEnclosedMemberContainer");
        };
        TypeReferenceSymbol.prototype.addEnclosedNonMember = function (enclosedNonMember) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addEnclosedNonMember");
        };
        TypeReferenceSymbol.prototype.addEnclosedNonMemberType = function (enclosedNonMemberType) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addEnclosedNonMemberType");
        };
        TypeReferenceSymbol.prototype.addEnclosedNonMemberContainer = function (enclosedNonMemberContainer) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addEnclosedNonMemberContainer");
        };
        TypeReferenceSymbol.prototype.addTypeParameter = function (typeParameter) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addTypeParameter");
        };
        TypeReferenceSymbol.prototype.addConstructorTypeParameter = function (typeParameter) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addConstructorTypeParameter");
        };

        TypeReferenceSymbol.prototype.findContainedNonMember = function (name) {
            // need to ensure the referenced type is resolved so we can find the non-member
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.findContainedNonMember(name);
        };

        TypeReferenceSymbol.prototype.findContainedNonMemberType = function (typeName, kind) {
            if (typeof kind === "undefined") { kind = 0 /* None */; }
            // similar to the above, need to ensure that the type is resolved so we can introspect any
            // contained types
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.findContainedNonMemberType(typeName, kind);
        };

        TypeReferenceSymbol.prototype.getMembers = function () {
            // need to resolve the referenced types to get the members
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.getMembers();
        };

        TypeReferenceSymbol.prototype.setHasDefaultConstructor = function (hasOne) {
            if (typeof hasOne === "undefined") { hasOne = true; }
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ":setHasDefaultConstructor");
        };
        TypeReferenceSymbol.prototype.getHasDefaultConstructor = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getHasDefaultConstructor();
        };
        TypeReferenceSymbol.prototype.getConstructorMethod = function () {
            // need to resolve so we don't accidentally substitute in a default constructor
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getConstructorMethod();
        };
        TypeReferenceSymbol.prototype.setConstructorMethod = function (constructorMethod) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": setConstructorMethod");
        };
        TypeReferenceSymbol.prototype.getTypeParameters = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getTypeParameters();
        };

        TypeReferenceSymbol.prototype.isGeneric = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.isGeneric();
        };

        TypeReferenceSymbol.prototype.addSpecialization = function (specializedVersionOfThisType, substitutingTypes) {
            //Debug.fail("Reference symbol " + this.pullSymbolIDString + ": addSpecialization");
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.addSpecialization(specializedVersionOfThisType, substitutingTypes);
        };
        TypeReferenceSymbol.prototype.getSpecialization = function (substitutingTypes) {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getSpecialization(substitutingTypes);
        };
        TypeReferenceSymbol.prototype.getKnownSpecializations = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getKnownSpecializations();
        };
        TypeReferenceSymbol.prototype.getTypeArguments = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getTypeArguments();
        };
        TypeReferenceSymbol.prototype.getTypeArgumentsOrTypeParameters = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getTypeArgumentsOrTypeParameters();
        };

        TypeReferenceSymbol.prototype.appendCallSignature = function (callSignature) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": appendCallSignature");
        };
        TypeReferenceSymbol.prototype.insertCallSignatureAtIndex = function (callSignature, index) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": insertCallSignatureAtIndex");
        };
        TypeReferenceSymbol.prototype.appendConstructSignature = function (callSignature) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": appendConstructSignature");
        };
        TypeReferenceSymbol.prototype.insertConstructSignatureAtIndex = function (callSignature, index) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": insertConstructSignatureAtIndex");
        };
        TypeReferenceSymbol.prototype.addIndexSignature = function (indexSignature) {
            TypeScript.Debug.fail("Reference symbol " + this.pullSymbolID + ": addIndexSignature");
        };

        TypeReferenceSymbol.prototype.hasOwnCallSignatures = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.hasOwnCallSignatures();
        };
        TypeReferenceSymbol.prototype.getCallSignatures = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getCallSignatures();
        };
        TypeReferenceSymbol.prototype.hasOwnConstructSignatures = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.hasOwnConstructSignatures();
        };
        TypeReferenceSymbol.prototype.getConstructSignatures = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getConstructSignatures();
        };
        TypeReferenceSymbol.prototype.hasOwnIndexSignatures = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.hasOwnIndexSignatures();
        };
        TypeReferenceSymbol.prototype.getIndexSignatures = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getIndexSignatures();
        };

        TypeReferenceSymbol.prototype.addImplementedType = function (implementedType) {
            this.referencedTypeSymbol.addImplementedType(implementedType);
        };
        TypeReferenceSymbol.prototype.getImplementedTypes = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getImplementedTypes();
        };
        TypeReferenceSymbol.prototype.addExtendedType = function (extendedType) {
            this.referencedTypeSymbol.addExtendedType(extendedType);
        };
        TypeReferenceSymbol.prototype.getExtendedTypes = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getExtendedTypes();
        };
        TypeReferenceSymbol.prototype.addTypeThatExtendsThisType = function (type) {
            this.referencedTypeSymbol.addTypeThatExtendsThisType(type);
        };
        TypeReferenceSymbol.prototype.getTypesThatExtendThisType = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getTypesThatExtendThisType();
        };
        TypeReferenceSymbol.prototype.addTypeThatExplicitlyImplementsThisType = function (type) {
            this.referencedTypeSymbol.addTypeThatExplicitlyImplementsThisType(type);
        };
        TypeReferenceSymbol.prototype.getTypesThatExplicitlyImplementThisType = function () {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.getTypesThatExplicitlyImplementThisType();
        };

        TypeReferenceSymbol.prototype.isValidBaseKind = function (baseType, isExtendedType) {
            this.ensureReferencedTypeIsResolved();
            return this.referencedTypeSymbol.isValidBaseKind(baseType, isExtendedType);
        };

        TypeReferenceSymbol.prototype.findMember = function (name, lookInParent) {
            if (typeof lookInParent === "undefined") { lookInParent = true; }
            // ensure that the type is resolved before looking for members
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.findMember(name, lookInParent);
        };
        TypeReferenceSymbol.prototype.findNestedType = function (name, kind) {
            if (typeof kind === "undefined") { kind = 0 /* None */; }
            // ensure that the type is resolved before looking for nested types
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.findNestedType(name, kind);
        };
        TypeReferenceSymbol.prototype.findNestedContainer = function (name, kind) {
            if (typeof kind === "undefined") { kind = 0 /* None */; }
            // ensure that the type is resolved before looking for nested containers
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.findNestedContainer(name, kind);
        };
        TypeReferenceSymbol.prototype.getAllMembers = function (searchDeclKind, memberVisiblity) {
            // ensure that the type is resolved before trying to collect all members
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.getAllMembers(searchDeclKind, memberVisiblity);
        };

        TypeReferenceSymbol.prototype.findTypeParameter = function (name) {
            // ensure that the type is resolved before trying to look up a type parameter
            this.ensureReferencedTypeIsResolved();

            return this.referencedTypeSymbol.findTypeParameter(name);
        };

        /*
        public getNamePartForFullName(): string {
        return this.referencedTypeSymbol.getNamePartForFullName();
        }
        public getScopedName(scopeSymbol?: PullSymbol, useConstraintInName?: boolean): string {
        return this.referencedTypeSymbol.getScopedName(scopeSymbol, useConstraintInName);
        }
        public isNamedTypeSymbol(): boolean {
        return this.referencedTypeSymbol.isNamedTypeSymbol();
        }
        
        public toString(scopeSymbol?: PullSymbol, useConstraintInName?: boolean): string {
        return this.referencedTypeSymbol.toString(scopeSymbol, useConstraintInName);
        }
        
        public getScopedNameEx(scopeSymbol?: PullSymbol, useConstraintInName?: boolean, getPrettyTypeName?: boolean, getTypeParamMarkerInfo?: boolean): MemberName {
        return this.referencedTypeSymbol.getScopedNameEx(scopeSymbol, useConstraintInName, getPrettyTypeName, getTypeParamMarkerInfo);
        }
        */
        TypeReferenceSymbol.prototype.hasOnlyOverloadCallSignatures = function () {
            // no need to resolve the referenced type - only computed during printing
            return this.referencedTypeSymbol.hasOnlyOverloadCallSignatures();
        };
        return TypeReferenceSymbol;
    })(TypeScript.PullTypeSymbol);
    TypeScript.TypeReferenceSymbol = TypeReferenceSymbol;

    TypeScript.nSpecializationsCreated = 0;
    TypeScript.nSpecializedSignaturesCreated = 0;
    TypeScript.nSpecializedTypeParameterCreated = 0;

    var InstantiatedTypeReferenceSymbol = (function (_super) {
        __extends(InstantiatedTypeReferenceSymbol, _super);
        function InstantiatedTypeReferenceSymbol(referencedTypeSymbol, _typeParameterSubstitutionMap, isInstanceReferenceType) {
            _super.call(this, referencedTypeSymbol);
            this.referencedTypeSymbol = referencedTypeSymbol;
            this._typeParameterSubstitutionMap = _typeParameterSubstitutionMap;
            this.isInstanceReferenceType = isInstanceReferenceType;
            this._instantiatedMembers = null;
            this._allInstantiatedMemberNameCache = null;
            this._instantiatedMemberNameCache = TypeScript.createIntrinsicsObject();
            this._instantiatedCallSignatures = null;
            this._instantiatedConstructSignatures = null;
            this._instantiatedIndexSignatures = null;
            this._typeArgumentReferences = undefined;
            this._instantiatedConstructorMethod = null;
            this._instantiatedAssociatedContainerType = null;
            this._isArray = undefined;
            this._generativeTypeClassification = [];

            TypeScript.nSpecializationsCreated++;
        }
        InstantiatedTypeReferenceSymbol.prototype.getIsSpecialized = function () {
            return !this.isInstanceReferenceType;
        };

        InstantiatedTypeReferenceSymbol.prototype.getGenerativeTypeClassification = function (enclosingType) {
            // Generative type classification is available only on named type symbols
            if (!this.isNamedTypeSymbol()) {
                return 0 /* Unknown */;
            }

            var generativeTypeClassification = this._generativeTypeClassification[enclosingType.pullSymbolID] || 0 /* Unknown */;
            if (generativeTypeClassification === 0 /* Unknown */) {
                // With respect to the enclosing type, is this type reference open, closed or
                // infinitely expanding?
                // Create a type parameter map for figuring out if the typeParameter wraps
                var typeParameters = enclosingType.getTypeParameters();
                var enclosingTypeParameterMap = [];
                for (var i = 0; i < typeParameters.length; i++) {
                    enclosingTypeParameterMap[typeParameters[i].pullSymbolID] = typeParameters[i];
                }

                var typeArguments = this.getTypeArguments();
                for (var i = 0; i < typeArguments.length; i++) {
                    // Spec section 3.8.7 Recursive Types:
                    // - A type reference without type arguments or with type arguments that do not reference
                    //      any of G's type parameters is classified as a closed type reference.
                    // - A type reference that references any of G's type parameters in a type argument is
                    //      classified as an open type reference.
                    if (typeArguments[i].wrapsSomeTypeParameter(enclosingTypeParameterMap, true)) {
                        // This type wraps type parameter of the enclosing type so it is at least open
                        generativeTypeClassification = 1 /* Open */;
                        break;
                    }
                }

                // If the type reference is determined to be atleast open, determine if it is infinitely expanding
                if (generativeTypeClassification === 1 /* Open */) {
                    if (this.wrapsSomeTypeParameterIntoInfinitelyExpandingTypeReference(enclosingType)) {
                        generativeTypeClassification = 3 /* InfinitelyExpanding */;
                    }
                } else {
                    // This type doesnot wrap any type parameter from the enclosing type so it is closed
                    generativeTypeClassification = 2 /* Closed */;
                }

                this._generativeTypeClassification[enclosingType.pullSymbolID] = generativeTypeClassification;
            }

            return generativeTypeClassification;
        };

        // shims
        InstantiatedTypeReferenceSymbol.prototype.isArrayNamedTypeReference = function () {
            if (this._isArray === undefined) {
                this._isArray = this.getRootSymbol().isArrayNamedTypeReference() || (this.getRootSymbol() === this._getResolver().getArrayNamedType());
            }
            return this._isArray;
        };

        InstantiatedTypeReferenceSymbol.prototype.getElementType = function () {
            if (!this.isArrayNamedTypeReference()) {
                return null;
            }

            var typeArguments = this.getTypeArguments();
            return typeArguments ? typeArguments[0] : null;
        };

        InstantiatedTypeReferenceSymbol.prototype.getReferencedTypeSymbol = function () {
            this.ensureReferencedTypeIsResolved();

            if (this.getIsSpecialized()) {
                return this;
            }

            return this.referencedTypeSymbol;
        };

        // The typeParameterSubstitutionMap parameter represents a mapping of PUllSymbolID strings of type parameters to type argument symbols
        // The instantiateFunctionTypeParameters parameter is set to true when a signature is being specialized at a call site, or if its
        // type parameters need to otherwise be specialized (say, during a type relationship check)
        InstantiatedTypeReferenceSymbol.create = function (resolver, type, typeParameterSubstitutionMap) {
            TypeScript.Debug.assert(resolver);

            // check for an existing instantiation
            // If the type substitution map is going to change, we need to create copy so that
            // we dont polute the map entry passed in by the caller.
            // (eg. when getting the member type using enclosing types type substitution map)
            var mutableTypeParameterMap = new TypeScript.PullInstantiationHelpers.MutableTypeParameterSubstitutionMap(typeParameterSubstitutionMap);

            // if the type is already specialized, we need to create a new type substitution map that represents
            // the mapping of type arguments we've just received to type arguments as previously passed through
            // If we have below sample
            //interface IList<T> {
            //    owner: IList<IList<T>>;
            //}
            //class List<U> implements IList<U> {
            //    owner: IList<IList<U>>;
            //}
            //class List2<V> extends List<V> {
            //    owner: List2<List2<V>>;
            //}
            // When instantiating List<V> with U = V and trying to get owner property we would have the map that
            // says U = V, but when creating the IList<V> we want to updates its type substitution maps to say T = V because
            // IList<T>  would now be instantiated with V
            TypeScript.PullInstantiationHelpers.instantiateTypeArgument(resolver, type, mutableTypeParameterMap);

            // Lookup in cache if this specialization already exists
            var rootType = type.getRootSymbol();
            var instantiation = rootType.getSpecialization(mutableTypeParameterMap.typeParameterSubstitutionMap);
            if (instantiation) {
                return instantiation;
            }

            // In any type, typeparameter map should only contain information about the allowed to reference type parameters
            // so remove unnecessary entries that are outside these scope, eg. from above sample we need to remove entry U = V
            // and keep only T = V
            TypeScript.PullInstantiationHelpers.cleanUpTypeParameterSubstitutionMap(type, mutableTypeParameterMap);
            typeParameterSubstitutionMap = mutableTypeParameterMap.typeParameterSubstitutionMap;

            // If the reference is made to itself (e.g., referring to Array<T> within the declaration of Array<T>,
            // We want to special-case the reference so later calls to getMember, etc., will delegate directly
            // to the referenced declaration type, and not force any additional instantiation
            var isInstanceReferenceType = (type.kind & TypeScript.PullElementKind.SomeInstantiatableType) != 0;
            var resolvedTypeParameterArgumentMap = typeParameterSubstitutionMap;
            if (isInstanceReferenceType) {
                var typeParameters = rootType.getTypeParameters();
                for (var i = 0; i < typeParameters.length; i++) {
                    if (!TypeScript.PullHelpers.typeSymbolsAreIdentical(typeParameters[i], typeParameterSubstitutionMap[typeParameters[i].pullSymbolID])) {
                        isInstanceReferenceType = false;
                        break;
                    }
                }

                if (isInstanceReferenceType) {
                    typeParameterSubstitutionMap = [];
                }
            }

            // Create the type using type substitution map
            instantiation = new InstantiatedTypeReferenceSymbol(rootType, typeParameterSubstitutionMap, isInstanceReferenceType);

            // Store in the cache
            rootType.addSpecialization(instantiation, resolvedTypeParameterArgumentMap);

            return instantiation;
        };

        InstantiatedTypeReferenceSymbol.prototype.isGeneric = function () {
            return this.getRootSymbol().isGeneric();
        };

        InstantiatedTypeReferenceSymbol.prototype.getTypeParameterSubstitutionMap = function () {
            return this._typeParameterSubstitutionMap;
        };

        InstantiatedTypeReferenceSymbol.prototype.getTypeArguments = function () {
            if (this.isInstanceReferenceType) {
                return this.getTypeParameters();
            }

            if (this._typeArgumentReferences === undefined) {
                var typeParameters = this.referencedTypeSymbol.getTypeParameters();

                if (typeParameters.length) {
                    var typeArgument = null;
                    var typeArguments = [];

                    for (var i = 0; i < typeParameters.length; i++) {
                        typeArgument = this._typeParameterSubstitutionMap[typeParameters[i].pullSymbolID];

                        if (!typeArgument) {
                            TypeScript.Debug.fail("type argument count mismatch");
                        }

                        if (typeArgument) {
                            typeArguments[typeArguments.length] = typeArgument;
                        }
                    }

                    this._typeArgumentReferences = typeArguments;
                } else {
                    this._typeArgumentReferences = null;
                }
            }

            return this._typeArgumentReferences;
        };

        InstantiatedTypeReferenceSymbol.prototype.getTypeArgumentsOrTypeParameters = function () {
            return this.getTypeArguments();
        };

        InstantiatedTypeReferenceSymbol.prototype.populateInstantiatedMemberFromReferencedMember = function (referencedMember) {
            var instantiatedMember;
            TypeScript.PullHelpers.resolveDeclaredSymbolToUseType(referencedMember);

            // if the member does not require further specialization, re-use the referenced symbol
            if (!referencedMember.type.wrapsSomeTypeParameter(this._typeParameterSubstitutionMap)) {
                instantiatedMember = referencedMember;
            } else {
                instantiatedMember = new TypeScript.PullSymbol(referencedMember.name, referencedMember.kind, referencedMember.semanticInfoChain);
                instantiatedMember.setRootSymbol(referencedMember);
                instantiatedMember.type = this._getResolver().instantiateType(referencedMember.type, this._typeParameterSubstitutionMap);
                instantiatedMember.isOptional = referencedMember.isOptional;
            }
            this._instantiatedMemberNameCache[instantiatedMember.name] = instantiatedMember;
        };

        //
        // lazily evaluated members
        //
        InstantiatedTypeReferenceSymbol.prototype.getMembers = function () {
            // need to resolve the referenced types to get the members
            this.ensureReferencedTypeIsResolved();

            if (this.isInstanceReferenceType) {
                return this.referencedTypeSymbol.getMembers();
            }

            // for each of the referenced type's members, need to properly instantiate their
            // type references
            if (!this._instantiatedMembers) {
                var referencedMembers = this.referencedTypeSymbol.getMembers();
                var referencedMember = null;
                var instantiatedMember = null;

                this._instantiatedMembers = [];

                for (var i = 0; i < referencedMembers.length; i++) {
                    referencedMember = referencedMembers[i];

                    this._getResolver().resolveDeclaredSymbol(referencedMember);

                    if (!this._instantiatedMemberNameCache[referencedMember.name]) {
                        this.populateInstantiatedMemberFromReferencedMember(referencedMember);
                    }

                    this._instantiatedMembers[this._instantiatedMembers.length] = this._instantiatedMemberNameCache[referencedMember.name];
                }
            }

            return this._instantiatedMembers;
        };

        InstantiatedTypeReferenceSymbol.prototype.findMember = function (name, lookInParent) {
            if (typeof lookInParent === "undefined") { lookInParent = true; }
            // ensure that the type is resolved before looking for members
            this.ensureReferencedTypeIsResolved();

            if (this.isInstanceReferenceType) {
                return this.referencedTypeSymbol.findMember(name, lookInParent);
            }

            // if the member exists on the referenced type, need to ensure that it's
            // instantiated
            var memberSymbol = this._instantiatedMemberNameCache[name];

            if (!memberSymbol) {
                var referencedMemberSymbol = this.referencedTypeSymbol.findMember(name, lookInParent);

                if (referencedMemberSymbol) {
                    this.populateInstantiatedMemberFromReferencedMember(referencedMemberSymbol);
                    memberSymbol = this._instantiatedMemberNameCache[name];
                } else {
                    memberSymbol = null;
                }
            }

            return memberSymbol;
        };

        // May need to cache based on search kind / visibility combinations
        InstantiatedTypeReferenceSymbol.prototype.getAllMembers = function (searchDeclKind, memberVisiblity) {
            // ensure that the type is resolved before trying to collect all members
            this.ensureReferencedTypeIsResolved();

            if (this.isInstanceReferenceType) {
                return this.referencedTypeSymbol.getAllMembers(searchDeclKind, memberVisiblity);
            }

            var requestedMembers = [];
            var allReferencedMembers = this.referencedTypeSymbol.getAllMembers(searchDeclKind, memberVisiblity);

            if (!this._allInstantiatedMemberNameCache) {
                this._allInstantiatedMemberNameCache = TypeScript.createIntrinsicsObject();

                // first, seed with this type's members
                var members = this.getMembers();

                for (var i = 0; i < members.length; i++) {
                    this._allInstantiatedMemberNameCache[members[i].name] = members[i];
                }
            }

            // next, for add any symbols belonging to the parent type, if necessary
            var referencedMember = null;
            var requestedMember = null;

            for (var i = 0; i < allReferencedMembers.length; i++) {
                referencedMember = allReferencedMembers[i];

                this._getResolver().resolveDeclaredSymbol(referencedMember);

                if (this._allInstantiatedMemberNameCache[referencedMember.name]) {
                    requestedMembers[requestedMembers.length] = this._allInstantiatedMemberNameCache[referencedMember.name];
                } else {
                    if (!referencedMember.type.wrapsSomeTypeParameter(this._typeParameterSubstitutionMap)) {
                        this._allInstantiatedMemberNameCache[referencedMember.name] = referencedMember;
                        requestedMembers[requestedMembers.length] = referencedMember;
                    } else {
                        requestedMember = new TypeScript.PullSymbol(referencedMember.name, referencedMember.kind, referencedMember.semanticInfoChain);
                        requestedMember.setRootSymbol(referencedMember);

                        requestedMember.type = this._getResolver().instantiateType(referencedMember.type, this._typeParameterSubstitutionMap);
                        requestedMember.isOptional = referencedMember.isOptional;

                        this._allInstantiatedMemberNameCache[requestedMember.name] = requestedMember;
                        requestedMembers[requestedMembers.length] = requestedMember;
                    }
                }
            }

            return requestedMembers;
        };

        InstantiatedTypeReferenceSymbol.prototype.getConstructorMethod = function () {
            if (this.isInstanceReferenceType) {
                return this.referencedTypeSymbol.getConstructorMethod();
            }

            if (!this._instantiatedConstructorMethod) {
                var referencedConstructorMethod = this.referencedTypeSymbol.getConstructorMethod();
                this._instantiatedConstructorMethod = new TypeScript.PullSymbol(referencedConstructorMethod.name, referencedConstructorMethod.kind, referencedConstructorMethod.semanticInfoChain);
                this._instantiatedConstructorMethod.setRootSymbol(referencedConstructorMethod);
                this._instantiatedConstructorMethod.setResolved();

                this._instantiatedConstructorMethod.type = InstantiatedTypeReferenceSymbol.create(this._getResolver(), referencedConstructorMethod.type, this._typeParameterSubstitutionMap);
            }

            return this._instantiatedConstructorMethod;
        };

        InstantiatedTypeReferenceSymbol.prototype.getAssociatedContainerType = function () {
            if (!this.isInstanceReferenceType) {
                return this.referencedTypeSymbol.getAssociatedContainerType();
            }

            if (!this._instantiatedAssociatedContainerType) {
                var referencedAssociatedContainerType = this.referencedTypeSymbol.getAssociatedContainerType();

                if (referencedAssociatedContainerType) {
                    this._instantiatedAssociatedContainerType = InstantiatedTypeReferenceSymbol.create(this._getResolver(), referencedAssociatedContainerType, this._typeParameterSubstitutionMap);
                }
            }

            return this._instantiatedAssociatedContainerType;
        };

        InstantiatedTypeReferenceSymbol.prototype.getCallSignatures = function () {
            this.ensureReferencedTypeIsResolved();

            if (this.isInstanceReferenceType) {
                return this.referencedTypeSymbol.getCallSignatures();
            }

            if (this._instantiatedCallSignatures) {
                return this._instantiatedCallSignatures;
            }

            var referencedCallSignatures = this.referencedTypeSymbol.getCallSignatures();
            this._instantiatedCallSignatures = [];

            for (var i = 0; i < referencedCallSignatures.length; i++) {
                var referencedSignature = referencedCallSignatures[i];
                this._getResolver().resolveDeclaredSymbol(referencedSignature);

                if (!referencedSignature.wrapsSomeTypeParameter(this._typeParameterSubstitutionMap)) {
                    this._instantiatedCallSignatures[this._instantiatedCallSignatures.length] = referencedSignature;
                } else {
                    var signatureTypeParameterSubstitutionMap = this.augmentSignatureSubstitutionMapWithSynthesizedTypeParameters(referencedSignature);
                    this._instantiatedCallSignatures[this._instantiatedCallSignatures.length] = this._getResolver().getOrCreateSignatureWithSubstitution(referencedSignature, signatureTypeParameterSubstitutionMap);
                    this._instantiatedCallSignatures[this._instantiatedCallSignatures.length - 1].functionType = this;
                }
            }

            return this._instantiatedCallSignatures;
        };

        InstantiatedTypeReferenceSymbol.prototype.getConstructSignatures = function () {
            this.ensureReferencedTypeIsResolved();

            if (this.isInstanceReferenceType) {
                return this.referencedTypeSymbol.getConstructSignatures();
            }

            if (this._instantiatedConstructSignatures) {
                return this._instantiatedConstructSignatures;
            }

            var referencedConstructSignatures = this.referencedTypeSymbol.getConstructSignatures();
            this._instantiatedConstructSignatures = [];

            for (var i = 0; i < referencedConstructSignatures.length; i++) {
                var referencedSignature = referencedConstructSignatures[i];
                this._getResolver().resolveDeclaredSymbol(referencedSignature);

                if (!referencedSignature.wrapsSomeTypeParameter(this._typeParameterSubstitutionMap)) {
                    this._instantiatedConstructSignatures[this._instantiatedConstructSignatures.length] = referencedSignature;
                } else {
                    // Construct signatures only get new type parameters if they are not from
                    // class constructors. Otherwise, they must share the type parameters with
                    // the class itself, which means a generic base class reference would actually
                    // instantiate the base constructor with the type arguments of the base class
                    // reference.
                    if (this.isConstructor()) {
                        var signatureTypeParameterArgumentMap = this._typeParameterSubstitutionMap;
                        this._instantiatedConstructSignatures[this._instantiatedConstructSignatures.length] = this._getResolver().instantiateSignature(referencedSignature, signatureTypeParameterArgumentMap);
                    } else {
                        var signatureTypeParameterArgumentMap = this.augmentSignatureSubstitutionMapWithSynthesizedTypeParameters(referencedSignature);
                        this._instantiatedConstructSignatures[this._instantiatedConstructSignatures.length] = this._getResolver().getOrCreateSignatureWithSubstitution(referencedSignature, signatureTypeParameterArgumentMap);
                    }
                    this._instantiatedConstructSignatures[this._instantiatedConstructSignatures.length - 1].functionType = this;
                }
            }

            return this._instantiatedConstructSignatures;
        };

        // This method takes a map of all substitutions that are in scope outside the signature.
        // The output is the composition of that map with all the new substitutions that result
        // from generating new type parameters to replace the root type parameters. Here is an
        // example of what this means:
        //
        // interface Foo<T> {
        //     method<U>(func: (t: T) => U): Foo<U>
        // }
        //
        // Suppose we are inside the reference Foo<U>. The map coming in (this._typeParameterSubstitutionMap)
        // might be [T -> U]. If we just left the signature alone, and performed this substitution, we would
        // get method<U>(func: (t: U) => U): Foo<U>, which is wrong because the U that came in needn't be
        // the same as the new U. So we have to generate a U' that is distinct from U, and then update the
        // map accordingly.
        InstantiatedTypeReferenceSymbol.prototype.augmentSignatureSubstitutionMapWithSynthesizedTypeParameters = function (referencedSignature) {
            if (referencedSignature.isGeneric()) {
                // Collect the signature's root type parameters, and for each one, create a new
                // type parameter with the same name. In the above example, getTypeParameters
                // should return an array of U, and newOwnTypeParameters should be an array
                // of U' (a fresh type parameter). Note also that U' keeps track of U as its
                // root type parameter. We assert in order to be sure that all keys in the map
                // are IDs of root type parameters (all of our substitution maps are against the root
                // signature).
                var signaturesOwnTypeParameters = referencedSignature.getTypeParameters();
                var newOwnTypeParameters = new Array(signaturesOwnTypeParameters.length);
                for (var i = 0; i < signaturesOwnTypeParameters.length; i++) {
                    var ownRootTypeParameter = signaturesOwnTypeParameters[i];

                    // Asserts that ownRootTypeParameter is in fact a root type parameter.
                    // This is necessary as all substitution maps are internally based on
                    // root type parameters.
                    TypeScript.Debug.assert(ownRootTypeParameter.getRootSymbol() === ownRootTypeParameter);
                    newOwnTypeParameters[i] = new SynthesizedTypeParameterSymbol(ownRootTypeParameter, this._typeParameterSubstitutionMap);
                }

                // We make a copy of this._typeParameterSubstitutionMap that accounts for this new type
                // parameter. In the above example, we copy the map [T -> U], and we output the map
                // [T -> U, U -> U']. Similarly, if we instantiated the same signature inside
                // Foo<U'>, we would get the map [T -> U', U -> U'']. Note that this only works
                // because we do not do recursive lookups in the map when substituting. In other words,
                // we do not use the transitive closure of the map (doing so would cause us to substitute
                // U' for T in the first example, which would be incorrect).
                // See PullInstantiationHelpers.instantiateTypeArgument.
                var signaturesOwnTypeArgumentMap = new TypeScript.PullInstantiationHelpers.MutableTypeParameterSubstitutionMap(this._typeParameterSubstitutionMap);
                for (var i = 0; i < signaturesOwnTypeParameters.length; i++) {
                    signaturesOwnTypeArgumentMap.ensureCopyOfUnderlyingMap();
                    signaturesOwnTypeArgumentMap.typeParameterSubstitutionMap[signaturesOwnTypeParameters[i].pullSymbolID] = newOwnTypeParameters[i];
                }
                return signaturesOwnTypeArgumentMap.typeParameterSubstitutionMap;
            } else {
                return this._typeParameterSubstitutionMap;
            }
        };

        InstantiatedTypeReferenceSymbol.prototype.getIndexSignatures = function () {
            this.ensureReferencedTypeIsResolved();

            if (this.isInstanceReferenceType) {
                return this.referencedTypeSymbol.getIndexSignatures();
            }

            if (this._instantiatedIndexSignatures) {
                return this._instantiatedIndexSignatures;
            }

            var referencedIndexSignatures = this.referencedTypeSymbol.getIndexSignatures();
            this._instantiatedIndexSignatures = [];

            for (var i = 0; i < referencedIndexSignatures.length; i++) {
                this._getResolver().resolveDeclaredSymbol(referencedIndexSignatures[i]);

                if (!referencedIndexSignatures[i].wrapsSomeTypeParameter(this._typeParameterSubstitutionMap)) {
                    this._instantiatedIndexSignatures[this._instantiatedIndexSignatures.length] = referencedIndexSignatures[i];
                } else {
                    this._instantiatedIndexSignatures[this._instantiatedIndexSignatures.length] = this._getResolver().getOrCreateSignatureWithSubstitution(referencedIndexSignatures[i], this._typeParameterSubstitutionMap);
                    this._instantiatedIndexSignatures[this._instantiatedIndexSignatures.length - 1].functionType = this;
                }
            }

            return this._instantiatedIndexSignatures;
        };
        return InstantiatedTypeReferenceSymbol;
    })(TypeReferenceSymbol);
    TypeScript.InstantiatedTypeReferenceSymbol = InstantiatedTypeReferenceSymbol;

    // The following two classes are very similar. They are both variants of signatures with type
    // parameter substitution maps. The only difference is the InstantiatedSignatureSymbol appears
    // to have no type parameters, whereas the SignatureSymbolWithSubstitution does have type
    // parameters.
    // A signature can reference type parameters and have associated substitutions for those
    // type parameters. Consider the following:
    //
    // interface Foo<T> {
    //     bar<S>(x: T, y: S): Foo<S>; // bar itself is PullSignatureSymbol - it is the root symbol
    //                                 // Foo<S> has SignatureSymbolWithSubstitution with map [T -> S, S -> S'] (case 3 below)
    // }
    //
    // var a: Foo<string>;           // Member bar of Foo<S> has a SignatureSymbolWithSubstitution with map [T -> string] (case 1 below)
    // var b = a.bar<number>("", 0); // call to a.bar produces an InstantiatedSignatureSymbol with map [T -> string, S -> number] (case 2 below)
    //
    // There are 3 reasons a signature may have substitutions for referenced type parameters:
    // 1. There are surrounding type parameter substitutions that need to be applied inside the
    //    signature. For example, in Foo<string>, the parameter x should be of type string.
    //    The substitution map here is [T -> string]
    // 2. The signature is instantiated with type arguments. For example, in the above call to
    //    bar<number>("", 0) on Foo<string>, you'd get an InstantiatedSignatureSymbol
    //    bar(x: string, y: number): Foo<number>, which has map [T -> string, S -> number];
    // 3. We needed to synthesize a new type parameter for the signature (for the reason why,
    //    see the comment on SynthesizedTypeParameter). In this case, inside Foo<S>, bar would have
    //    the signature <S'>(x: S, y: S'): Foo<S'>. This is NOT an instantiated signature, but
    //    just a SignatureSymbolWithSubstitution. The map here is [T -> S, S -> S'].
    //
    // This distinction does not exist for types because the only way to substitute in a type
    // is to instantiate it. That's because types cannot be declared in a context where type
    // parameters are in scope.
    //
    // Note that InstantiatedSignatureSymbol could extend SignatureSymbolWithSubstitution,
    // but that would make the inheritance chain longer. These classes are small enough
    // that we have duplicated most of their logic, and they both just extend PullSignatureSymbol.
    var InstantiatedSignatureSymbol = (function (_super) {
        __extends(InstantiatedSignatureSymbol, _super);
        function InstantiatedSignatureSymbol(rootSignature, _typeParameterSubstitutionMap) {
            _super.call(this, rootSignature.kind, rootSignature.semanticInfoChain, rootSignature.isDefinition());
            this._typeParameterSubstitutionMap = _typeParameterSubstitutionMap;
            this.setRootSymbol(rootSignature);
            TypeScript.nSpecializedSignaturesCreated++;

            // Store in the cache
            rootSignature.addSpecialization(this, _typeParameterSubstitutionMap);
        }
        InstantiatedSignatureSymbol.prototype.getTypeParameterSubstitutionMap = function () {
            return this._typeParameterSubstitutionMap;
        };

        InstantiatedSignatureSymbol.prototype.getIsSpecialized = function () {
            return true;
        };

        InstantiatedSignatureSymbol.prototype.getIsInstantiated = function () {
            return true;
        };

        InstantiatedSignatureSymbol.prototype._getResolver = function () {
            return this.getRootSymbol()._getResolver();
        };

        InstantiatedSignatureSymbol.prototype.getTypeParameters = function () {
            return TypeScript.sentinelEmptyArray;
        };

        InstantiatedSignatureSymbol.prototype.getAllowedToReferenceTypeParameters = function () {
            var rootSymbol = this.getRootSymbol();
            return rootSymbol.getAllowedToReferenceTypeParameters();
        };
        return InstantiatedSignatureSymbol;
    })(TypeScript.PullSignatureSymbol);
    TypeScript.InstantiatedSignatureSymbol = InstantiatedSignatureSymbol;

    // Copied example from above InstantiatedSignatureSymbol for convenience. See the explanation above
    // for the exact difference between InstantiatedSignatureSymbol and SignatureSymbolWithSubstitution.
    //
    // interface Foo<T> {
    //     bar<S>(x: T, y: S): Foo<S>; // bar itself is PullSignatureSymbol - it is the root symbol
    //                                 // Foo<S> has SignatureSymbolWithSubstitution with map [T -> S, S -> S']
    // }
    //
    // var a: Foo<string>;           // Member bar of Foo<S> has a SignatureSymbolWithSubstitution with map [T -> string]
    // var b = a.bar<number>("", 0); // call to a.bar produces an InstantiatedSignatureSymbol with map [T -> string, S -> number]
    var SignatureSymbolWithSubstitution = (function (_super) {
        __extends(SignatureSymbolWithSubstitution, _super);
        function SignatureSymbolWithSubstitution(rootSignature, _typeParameterSubstitutionMap) {
            _super.call(this, rootSignature.kind, rootSignature.semanticInfoChain, rootSignature.isDefinition());
            this._typeParameterSubstitutionMap = _typeParameterSubstitutionMap;
            this.setRootSymbol(rootSignature);
            TypeScript.nSpecializedSignaturesCreated++;

            // Store in the cache
            rootSignature.addSpecialization(this, _typeParameterSubstitutionMap);
        }
        SignatureSymbolWithSubstitution.prototype.getTypeParameterSubstitutionMap = function () {
            return this._typeParameterSubstitutionMap;
        };

        SignatureSymbolWithSubstitution.prototype.getIsSpecialized = function () {
            return true;
        };

        SignatureSymbolWithSubstitution.prototype._getResolver = function () {
            return this.getRootSymbol()._getResolver();
        };

        SignatureSymbolWithSubstitution.prototype.getTypeParameters = function () {
            if (!this._typeParameters) {
                var rootSymbol = this.getRootSymbol();
                var rootTypeParameters = rootSymbol.getTypeParameters();

                if (rootTypeParameters.length) {
                    this._typeParameters = [];
                    for (var i = 0; i < rootTypeParameters.length; i++) {
                        // Sometimes, one of the root symbol's type parameters is itself a surrounding type argument
                        // For example
                        // interface Foo<T> {
                        //     boo<S>(x: T, y: S): Foo<S>;
                        // }
                        // In the inner instantiation of Foo<S>, the surrounding T will actually be an S.
                        // Unless we substitute this inner S with an S', the types of x and y will appear
                        // to be the same.
                        // If typeParameterSubstitution does not exist, that means we did not generate
                        // new type parameters (this happens when no surrounding type parameters are
                        // referenced in the signature). In this case, we can just use the root type
                        // parameters of the signature.
                        // If typeParameterSubstitution does exist, it means we have synthesized new
                        // type parameters for this signature, and we should return them instead of
                        // the root type parameters.
                        var typeParameterSubstitution = this._typeParameterSubstitutionMap[rootTypeParameters[i].pullSymbolID];
                        this._typeParameters[this._typeParameters.length] = typeParameterSubstitution || rootTypeParameters[i];
                    }
                } else {
                    this._typeParameters = TypeScript.sentinelEmptyArray;
                }
            }

            return this._typeParameters;
        };

        SignatureSymbolWithSubstitution.prototype.getAllowedToReferenceTypeParameters = function () {
            var rootSymbol = this.getRootSymbol();
            return rootSymbol.getAllowedToReferenceTypeParameters();
        };
        return SignatureSymbolWithSubstitution;
    })(TypeScript.PullSignatureSymbol);
    TypeScript.SignatureSymbolWithSubstitution = SignatureSymbolWithSubstitution;

    // Sometimes, one of the root symbol's type parameters is itself a surrounding type argument
    // For example
    // interface Foo<T> {
    //     boo<S>(x: T, y: S): Foo<S>;
    // }
    // In the inner instantiation of Foo<S>, the surrounding T will actually be an S.
    // Unless we substitute this inner S with an S', the types of x and y will appear
    // to be the same. PullSynthesizedTypeParameterSymbol is the S' in this example.
    var SynthesizedTypeParameterSymbol = (function (_super) {
        __extends(SynthesizedTypeParameterSymbol, _super);
        // We specifically do not set a root symbol here. Root symbols are only for instantiation.
        // This is distinct from instantiation.
        function SynthesizedTypeParameterSymbol(originalTypeParameter, _typeParameterSubstitutionMapForConstraint) {
            _super.call(this, originalTypeParameter.name, originalTypeParameter.semanticInfoChain);
            this.originalTypeParameter = originalTypeParameter;
            this._typeParameterSubstitutionMapForConstraint = _typeParameterSubstitutionMapForConstraint;
            var originalTypeParameterDeclarations = originalTypeParameter.getDeclarations();
            for (var i = 0; i < originalTypeParameterDeclarations.length; i++) {
                this.addDeclaration(originalTypeParameterDeclarations[i]);
            }
        }
        SynthesizedTypeParameterSymbol.prototype._getResolver = function () {
            return this.originalTypeParameter._getResolver();
        };

        SynthesizedTypeParameterSymbol.prototype.getConstraint = function () {
            var constraint = _super.prototype.getConstraint.call(this);
            if (!constraint) {
                var originalConstraint = this.originalTypeParameter.getConstraint();
                if (originalConstraint) {
                    constraint = this._getResolver().instantiateType(originalConstraint, this._typeParameterSubstitutionMapForConstraint);
                    this.setConstraint(constraint);
                }
            }
            return constraint;
        };
        return SynthesizedTypeParameterSymbol;
    })(TypeScript.PullTypeParameterSymbol);
    TypeScript.SynthesizedTypeParameterSymbol = SynthesizedTypeParameterSymbol;
})(TypeScript || (TypeScript = {}));
///<reference path='resources\references.ts' />
///<reference path='core\references.ts' />
///<reference path='text\references.ts' />
///<reference path='syntax\references.ts' />
///<reference path='diagnostics.ts' />
///<reference path='document.ts' />
///<reference path='flags.ts' />
///<reference path='hashTable.ts' />
///<reference path='ast.ts' />
///<reference path='astHelpers.ts' />
///<reference path='astWalker.ts' />
///<reference path='base64.ts' />
///<reference path='sourceMapping.ts' />
///<reference path='emitter.ts' />
///<reference path='types.ts' />
///<reference path='pathUtils.ts' />
///<reference path='referenceResolution.ts' />
///<reference path='precompile.ts' />
///<reference path='referenceResolver.ts' />
///<reference path='declarationEmitter.ts' />
///<reference path='bloomFilter.ts' />
///<reference path='identifierWalker.ts' />
///<reference path='settings.ts' />
///<reference path='typecheck\pullFlags.ts' />
///<reference path='typecheck\pullDecls.ts' />
///<reference path='typecheck\pullSymbols.ts' />
///<reference path='typecheck\pullTypeEnclosingTypeWalker.ts' />
///<reference path='typecheck\pullTypeResolutionContext.ts' />
///<reference path='typecheck\pullTypeResolution.ts' />
///<reference path='typecheck\pullSemanticInfo.ts' />
///<reference path='typecheck\pullDeclCollection.ts' />
///<reference path='typecheck\pullSymbolBinder.ts' />
///<reference path='typecheck\pullHelpers.ts' />
///<reference path='typecheck\pullInstantiationHelpers.ts' />
///<reference path='typecheck\pullTypeInstantiation.ts' />
///<reference path='typescript.ts' />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
if (Error)
    Error.stackTraceLimit = 1000;

var TypeScript;
(function (TypeScript) {
    TypeScript.fileResolutionTime = 0;
    TypeScript.fileResolutionIOTime = 0;
    TypeScript.fileResolutionScanImportsTime = 0;
    TypeScript.fileResolutionImportFileSearchTime = 0;
    TypeScript.fileResolutionGetDefaultLibraryTime = 0;
    TypeScript.sourceCharactersCompiled = 0;
    TypeScript.syntaxTreeParseTime = 0;
    TypeScript.typeCheckTime = 0;
    TypeScript.createDeclarationsTime = 0;

    TypeScript.compilerResolvePathTime = 0;
    TypeScript.compilerDirectoryNameTime = 0;
    TypeScript.compilerDirectoryExistsTime = 0;
    TypeScript.compilerFileExistsTime = 0;

    TypeScript.emitTime = 0;
    TypeScript.emitWriteFileTime = 0;

    TypeScript.declarationEmitTime = 0;
    TypeScript.declarationEmitIsExternallyVisibleTime = 0;
    TypeScript.declarationEmitTypeSignatureTime = 0;
    TypeScript.declarationEmitGetBoundDeclTypeTime = 0;
    TypeScript.declarationEmitIsOverloadedCallSignatureTime = 0;
    TypeScript.declarationEmitFunctionDeclarationGetSymbolTime = 0;
    TypeScript.declarationEmitGetBaseTypeTime = 0;
    TypeScript.declarationEmitGetAccessorFunctionTime = 0;
    TypeScript.declarationEmitGetTypeParameterSymbolTime = 0;
    TypeScript.declarationEmitGetImportDeclarationSymbolTime = 0;

    TypeScript.ioHostResolvePathTime = 0;
    TypeScript.ioHostDirectoryNameTime = 0;
    TypeScript.ioHostCreateDirectoryStructureTime = 0;
    TypeScript.ioHostWriteFileTime = 0;

    (function (EmitOutputResult) {
        EmitOutputResult[EmitOutputResult["Succeeded"] = 0] = "Succeeded";
        EmitOutputResult[EmitOutputResult["FailedBecauseOfSyntaxErrors"] = 1] = "FailedBecauseOfSyntaxErrors";
        EmitOutputResult[EmitOutputResult["FailedBecauseOfCompilerOptionsErrors"] = 2] = "FailedBecauseOfCompilerOptionsErrors";
        EmitOutputResult[EmitOutputResult["FailedToGenerateDeclarationsBecauseOfSemanticErrors"] = 3] = "FailedToGenerateDeclarationsBecauseOfSemanticErrors";
    })(TypeScript.EmitOutputResult || (TypeScript.EmitOutputResult = {}));
    var EmitOutputResult = TypeScript.EmitOutputResult;

    var EmitOutput = (function () {
        function EmitOutput(emitOutputResult) {
            if (typeof emitOutputResult === "undefined") { emitOutputResult = 0 /* Succeeded */; }
            this.outputFiles = [];
            this.emitOutputResult = emitOutputResult;
        }
        return EmitOutput;
    })();
    TypeScript.EmitOutput = EmitOutput;

    (function (OutputFileType) {
        OutputFileType[OutputFileType["JavaScript"] = 0] = "JavaScript";
        OutputFileType[OutputFileType["SourceMap"] = 1] = "SourceMap";
        OutputFileType[OutputFileType["Declaration"] = 2] = "Declaration";
    })(TypeScript.OutputFileType || (TypeScript.OutputFileType = {}));
    var OutputFileType = TypeScript.OutputFileType;

    var OutputFile = (function () {
        function OutputFile(name, writeByteOrderMark, text, fileType, sourceMapEntries) {
            if (typeof sourceMapEntries === "undefined") { sourceMapEntries = []; }
            this.name = name;
            this.writeByteOrderMark = writeByteOrderMark;
            this.text = text;
            this.fileType = fileType;
            this.sourceMapEntries = sourceMapEntries;
        }
        return OutputFile;
    })();
    TypeScript.OutputFile = OutputFile;

    // Represents the results of the last "pull" on the compiler when using the streaming
    // 'compile' method.  The compile result for a single pull can have diagnostics (if
    // something went wrong), and/or OutputFiles that need to get written.
    var CompileResult = (function () {
        function CompileResult() {
            this.diagnostics = [];
            this.outputFiles = [];
        }
        CompileResult.fromDiagnostics = function (diagnostics) {
            var result = new CompileResult();
            result.diagnostics = diagnostics;
            return result;
        };

        CompileResult.fromOutputFiles = function (outputFiles) {
            var result = new CompileResult();
            result.outputFiles = outputFiles;
            return result;
        };
        return CompileResult;
    })();
    TypeScript.CompileResult = CompileResult;

    var OperationCanceledException = (function () {
        function OperationCanceledException() {
        }
        return OperationCanceledException;
    })();
    TypeScript.OperationCanceledException = OperationCanceledException;

    var CancellationToken = (function () {
        function CancellationToken(cancellationToken) {
            this.cancellationToken = cancellationToken;
        }
        CancellationToken.prototype.isCancellationRequested = function () {
            return this.cancellationToken && this.cancellationToken.isCancellationRequested();
        };

        CancellationToken.prototype.throwIfCancellationRequested = function () {
            if (this.isCancellationRequested()) {
                throw new OperationCanceledException();
            }
        };
        CancellationToken.None = new CancellationToken(null);
        return CancellationToken;
    })();
    TypeScript.CancellationToken = CancellationToken;

    var DocumentRegistryEntry = (function () {
        function DocumentRegistryEntry(document) {
            this.document = document;
            this.refCount = 0;
            this.owners = [];
        }
        return DocumentRegistryEntry;
    })();

    var NonCachingDocumentRegistry = (function () {
        function NonCachingDocumentRegistry() {
        }
        NonCachingDocumentRegistry.prototype.acquireDocument = function (fileName, compilationSettings, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles) {
            if (typeof referencedFiles === "undefined") { referencedFiles = []; }
            return TypeScript.Document.create(compilationSettings, fileName, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles);
        };

        NonCachingDocumentRegistry.prototype.updateDocument = function (document, fileName, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange) {
            return document.update(scriptSnapshot, version, isOpen, textChangeRange);
        };

        NonCachingDocumentRegistry.prototype.releaseDocument = function (fileName, compilationSettings) {
            // no op since this class doesn't cache anything
        };
        NonCachingDocumentRegistry.Instance = new NonCachingDocumentRegistry();
        return NonCachingDocumentRegistry;
    })();
    TypeScript.NonCachingDocumentRegistry = NonCachingDocumentRegistry;

    var DocumentRegistry = (function () {
        function DocumentRegistry() {
            this.buckets = {};
        }
        DocumentRegistry.prototype.getKeyFromCompilationSettings = function (settings) {
            return "_" + settings.propagateEnumConstants().toString() + "|" + settings.allowAutomaticSemicolonInsertion().toString() + "|" + TypeScript.LanguageVersion[settings.codeGenTarget()];
        };

        DocumentRegistry.prototype.getBucketForCompilationSettings = function (settings, createIfMissing) {
            var key = this.getKeyFromCompilationSettings(settings);
            var bucket = this.buckets[key];
            if (!bucket && createIfMissing) {
                this.buckets[key] = bucket = new TypeScript.StringHashTable();
            }
            return bucket;
        };

        DocumentRegistry.prototype.reportStats = function () {
            var _this = this;
            var bucketInfoArray = Object.keys(this.buckets).filter(function (name) {
                return name && name.charAt(0) === '_';
            }).map(function (name) {
                var entries = _this.buckets[name];
                var documents = entries.getAllKeys().map(function (name) {
                    var entry = entries.lookup(name);
                    return {
                        name: name,
                        refCount: entry.refCount,
                        references: entry.owners.slice(0)
                    };
                });
                documents.sort(function (x, y) {
                    return y.refCount - x.refCount;
                });
                return { bucket: name, documents: documents };
            });
            return JSON.stringify(bucketInfoArray, null, 2);
        };

        DocumentRegistry.prototype.acquireDocument = function (fileName, compilationSettings, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles) {
            if (typeof referencedFiles === "undefined") { referencedFiles = []; }
            var bucket = this.getBucketForCompilationSettings(compilationSettings, true);
            var entry = bucket.lookup(fileName);
            if (!entry) {
                var document = TypeScript.Document.create(compilationSettings, fileName, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles);

                entry = new DocumentRegistryEntry(document);
                bucket.add(fileName, entry);
            }
            entry.refCount++;

            return entry.document;
        };

        DocumentRegistry.prototype.updateDocument = function (document, fileName, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange) {
            var bucket = this.getBucketForCompilationSettings(compilationSettings, false);
            TypeScript.Debug.assert(bucket);
            var entry = bucket.lookup(fileName);
            TypeScript.Debug.assert(entry);

            if (entry.document.isOpen === isOpen && entry.document.version === version) {
                return entry.document;
            }

            entry.document = entry.document.update(scriptSnapshot, version, isOpen, textChangeRange);
            return entry.document;
        };

        DocumentRegistry.prototype.releaseDocument = function (fileName, compilationSettings) {
            var bucket = this.getBucketForCompilationSettings(compilationSettings, false);
            TypeScript.Debug.assert(bucket);

            var entry = bucket.lookup(fileName);
            entry.refCount--;

            TypeScript.Debug.assert(entry.refCount >= 0);
            if (entry.refCount === 0) {
                bucket.remove(fileName);
            }
        };
        return DocumentRegistry;
    })();
    TypeScript.DocumentRegistry = DocumentRegistry;

    var TypeScriptCompiler = (function () {
        function TypeScriptCompiler(logger, _settings) {
            if (typeof logger === "undefined") { logger = new TypeScript.NullLogger(); }
            if (typeof _settings === "undefined") { _settings = TypeScript.ImmutableCompilationSettings.defaultSettings(); }
            this.logger = logger;
            this._settings = _settings;
            this.semanticInfoChain = null;
            this.semanticInfoChain = new TypeScript.SemanticInfoChain(this, logger);
        }
        TypeScriptCompiler.prototype.getSemanticInfoChain = function () {
            return this.semanticInfoChain;
        };

        TypeScriptCompiler.prototype.compilationSettings = function () {
            return this._settings;
        };

        TypeScriptCompiler.prototype.setCompilationSettings = function (newSettings) {
            var oldSettings = this._settings;
            this._settings = newSettings;

            if (!compareDataObjects(oldSettings, newSettings)) {
                // If our options have changed at all, we have to consider any cached semantic
                // data we have invalid.
                this.semanticInfoChain.invalidate(oldSettings, newSettings);
            }
        };

        TypeScriptCompiler.prototype.getDocument = function (fileName) {
            fileName = TypeScript.switchToForwardSlashes(fileName);
            return this.semanticInfoChain.getDocument(fileName);
        };

        TypeScriptCompiler.prototype.cleanupSemanticCache = function () {
            this.semanticInfoChain.invalidate();
        };

        TypeScriptCompiler.prototype.addOrUpdateFile = function (document) {
            // TODO: TypeScript.sourceCharactersCompiled += document. scriptSnapshot.getLength();
            // Note: the semantic info chain will recognize that this is a replacement of an
            // existing script, and will handle it appropriately.
            this.semanticInfoChain.addDocument(document);
        };

        TypeScriptCompiler.prototype.addFile = function (fileName, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles) {
            if (typeof referencedFiles === "undefined") { referencedFiles = []; }
            fileName = TypeScript.switchToForwardSlashes(fileName);
            var document = TypeScript.Document.create(this.compilationSettings(), fileName, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles);
            this.addOrUpdateFile(document);
        };

        TypeScriptCompiler.prototype.updateFile = function (fileName, scriptSnapshot, version, isOpen, textChangeRange) {
            fileName = TypeScript.switchToForwardSlashes(fileName);

            var document = this.getDocument(fileName);
            var updatedDocument = document.update(scriptSnapshot, version, isOpen, textChangeRange);

            // Note: the semantic info chain will recognize that this is a replacement of an
            // existing script, and will handle it appropriately.
            this.addOrUpdateFile(updatedDocument);
        };

        TypeScriptCompiler.prototype.removeFile = function (fileName) {
            fileName = TypeScript.switchToForwardSlashes(fileName);
            this.semanticInfoChain.removeDocument(fileName);
        };

        TypeScriptCompiler.prototype.mapOutputFileName = function (document, emitOptions, extensionChanger) {
            if (document.emitToOwnOutputFile()) {
                var updatedFileName = document.fileName;
                if (emitOptions.outputDirectory() !== "") {
                    // Replace the common directory path with the option specified
                    updatedFileName = document.fileName.replace(emitOptions.commonDirectoryPath(), "");
                    updatedFileName = emitOptions.outputDirectory() + updatedFileName;
                }
                return extensionChanger(updatedFileName, false);
            } else {
                return extensionChanger(emitOptions.sharedOutputFile(), true);
            }
        };

        TypeScriptCompiler.prototype.writeByteOrderMarkForDocument = function (document) {
            // Set this to 'true' if you want to know why the compiler emitted a document with a
            // byte order mark.
            var printReason = false;

            // If module its always emitted in its own file
            if (document.emitToOwnOutputFile()) {
                var result = document.byteOrderMark !== 0 /* None */;
                if (printReason) {
                    TypeScript.Environment.standardOut.WriteLine("Emitting byte order mark because of: " + document.fileName);
                }
                return result;
            } else {
                var fileNames = this.fileNames();

                var result = false;
                for (var i = 0, n = fileNames.length; i < n; i++) {
                    var document = this.getDocument(fileNames[i]);

                    if (document.syntaxTree().isExternalModule()) {
                        continue;
                    }

                    if (document.byteOrderMark !== 0 /* None */) {
                        if (printReason) {
                            TypeScript.Environment.standardOut.WriteLine("Emitting byte order mark because of: " + document.fileName);
                            result = true;
                        } else {
                            return true;
                        }
                    }
                }

                return result;
            }
        };

        TypeScriptCompiler.mapToDTSFileName = function (fileName, wholeFileNameReplaced) {
            return TypeScript.getDeclareFilePath(fileName);
        };

        TypeScriptCompiler.prototype._shouldEmit = function (document) {
            // If its already a declare file or is resident or does not contain body
            return !document.isDeclareFile();
        };

        TypeScriptCompiler.prototype._shouldEmitDeclarations = function (document) {
            if (!this.compilationSettings().generateDeclarationFiles()) {
                return false;
            }

            return this._shouldEmit(document);
        };

        // Does the actual work of emittin the declarations from the provided document into the
        // provided emitter.  If no emitter is provided a new one is created.
        TypeScriptCompiler.prototype.emitDocumentDeclarationsWorker = function (document, emitOptions, declarationEmitter) {
            var sourceUnit = document.sourceUnit();
            TypeScript.Debug.assert(this._shouldEmitDeclarations(document));

            if (declarationEmitter) {
                declarationEmitter.document = document;
            } else {
                var declareFileName = this.mapOutputFileName(document, emitOptions, TypeScriptCompiler.mapToDTSFileName);
                declarationEmitter = new TypeScript.DeclarationEmitter(declareFileName, document, this, emitOptions, this.semanticInfoChain);
            }

            declarationEmitter.emitDeclarations(sourceUnit);
            return declarationEmitter;
        };

        TypeScriptCompiler.prototype._emitDocumentDeclarations = function (document, emitOptions, onSingleFileEmitComplete, sharedEmitter) {
            var start = new Date().getTime();
            if (this._shouldEmitDeclarations(document)) {
                if (document.emitToOwnOutputFile()) {
                    var singleEmitter = this.emitDocumentDeclarationsWorker(document, emitOptions);
                    if (singleEmitter) {
                        onSingleFileEmitComplete(singleEmitter.getOutputFile());
                    }
                } else {
                    // Create or reuse file
                    sharedEmitter = this.emitDocumentDeclarationsWorker(document, emitOptions, sharedEmitter);
                }
            }

            TypeScript.declarationEmitTime += new Date().getTime() - start;
            return sharedEmitter;
        };

        // Will not throw exceptions.
        TypeScriptCompiler.prototype.emitAllDeclarations = function (resolvePath) {
            var emitOutput = new EmitOutput();

            var emitOptions = new TypeScript.EmitOptions(this, resolvePath);
            if (emitOptions.diagnostic()) {
                emitOutput.emitOutputResult = 2 /* FailedBecauseOfCompilerOptionsErrors */;
                return emitOutput;
            }

            var sharedEmitter = null;
            var fileNames = this.fileNames();

            for (var i = 0, n = fileNames.length; i < n; i++) {
                var fileName = fileNames[i];

                var document = this.getDocument(fileNames[i]);

                sharedEmitter = this._emitDocumentDeclarations(document, emitOptions, function (file) {
                    return emitOutput.outputFiles.push(file);
                }, sharedEmitter);
            }

            if (sharedEmitter) {
                emitOutput.outputFiles.push(sharedEmitter.getOutputFile());
            }

            return emitOutput;
        };

        // Will not throw exceptions.
        TypeScriptCompiler.prototype.emitDeclarations = function (fileName, resolvePath) {
            fileName = TypeScript.switchToForwardSlashes(fileName);
            var emitOutput = new EmitOutput();

            var emitOptions = new TypeScript.EmitOptions(this, resolvePath);
            if (emitOptions.diagnostic()) {
                emitOutput.emitOutputResult = 2 /* FailedBecauseOfCompilerOptionsErrors */;
                return emitOutput;
            }

            var document = this.getDocument(fileName);

            // Emitting module or multiple files, always goes to single file
            if (document.emitToOwnOutputFile()) {
                this._emitDocumentDeclarations(document, emitOptions, function (file) {
                    return emitOutput.outputFiles.push(file);
                }, null);
                return emitOutput;
            } else {
                return this.emitAllDeclarations(resolvePath);
            }
        };

        TypeScriptCompiler.prototype.canEmitDeclarations = function (fileName) {
            fileName = TypeScript.switchToForwardSlashes(fileName);
            var document = this.getDocument(fileName);
            return this._shouldEmitDeclarations(document);
        };

        TypeScriptCompiler.mapToFileNameExtension = function (extension, fileName, wholeFileNameReplaced) {
            if (wholeFileNameReplaced) {
                // The complete output is redirected in this file so do not change extension
                return fileName;
            } else {
                // Change the extension of the file
                var splitFname = fileName.split(".");
                splitFname.pop();
                return splitFname.join(".") + extension;
            }
        };

        TypeScriptCompiler.mapToJSFileName = function (fileName, wholeFileNameReplaced) {
            return TypeScriptCompiler.mapToFileNameExtension(".js", fileName, wholeFileNameReplaced);
        };

        // Caller is responsible for closing the returned emitter.
        // May throw exceptions.
        TypeScriptCompiler.prototype.emitDocumentWorker = function (document, emitOptions, emitter) {
            var sourceUnit = document.sourceUnit();
            TypeScript.Debug.assert(this._shouldEmit(document));

            var typeScriptFileName = document.fileName;
            if (!emitter) {
                var javaScriptFileName = this.mapOutputFileName(document, emitOptions, TypeScriptCompiler.mapToJSFileName);
                var outFile = new TypeScript.TextWriter(javaScriptFileName, this.writeByteOrderMarkForDocument(document), 0 /* JavaScript */);

                emitter = new TypeScript.Emitter(javaScriptFileName, outFile, emitOptions, this.semanticInfoChain);

                if (this.compilationSettings().mapSourceFiles()) {
                    // We always create map files next to the jsFiles
                    var sourceMapFile = new TypeScript.TextWriter(javaScriptFileName + TypeScript.SourceMapper.MapFileExtension, false, 1 /* SourceMap */);
                    emitter.createSourceMapper(document, javaScriptFileName, outFile, sourceMapFile, emitOptions.resolvePath);
                }
            } else if (this.compilationSettings().mapSourceFiles()) {
                // Already emitting into js file, update the mapper for new source info
                emitter.setSourceMapperNewSourceFile(document);
            }

            // Set location info
            emitter.setDocument(document);
            emitter.emitJavascript(sourceUnit, false);

            return emitter;
        };

        // Private.  only for use by compiler or CompilerIterator
        TypeScriptCompiler.prototype._emitDocument = function (document, emitOptions, onSingleFileEmitComplete, sharedEmitter) {
            var start = new Date().getTime();

            // Emitting module or multiple files, always goes to single file
            if (this._shouldEmit(document)) {
                if (document.emitToOwnOutputFile()) {
                    // We're outputting to mulitple files.  We don't want to reuse an emitter in that case.
                    var singleEmitter = this.emitDocumentWorker(document, emitOptions);
                    if (singleEmitter) {
                        onSingleFileEmitComplete(singleEmitter.getOutputFiles());
                    }
                } else {
                    // We're not outputting to multiple files.  Keep using the same emitter and don't
                    // close until below.
                    sharedEmitter = this.emitDocumentWorker(document, emitOptions, sharedEmitter);
                }
            }

            TypeScript.emitTime += new Date().getTime() - start;
            return sharedEmitter;
        };

        // Will not throw exceptions.
        TypeScriptCompiler.prototype.emitAll = function (resolvePath) {
            var emitOutput = new EmitOutput();

            var emitOptions = new TypeScript.EmitOptions(this, resolvePath);
            if (emitOptions.diagnostic()) {
                emitOutput.emitOutputResult = 2 /* FailedBecauseOfCompilerOptionsErrors */;
                return emitOutput;
            }

            var fileNames = this.fileNames();
            var sharedEmitter = null;

            for (var i = 0, n = fileNames.length; i < n; i++) {
                var fileName = fileNames[i];

                var document = this.getDocument(fileName);

                sharedEmitter = this._emitDocument(document, emitOptions, function (files) {
                    return emitOutput.outputFiles.push.apply(emitOutput.outputFiles, files);
                }, sharedEmitter);
            }

            if (sharedEmitter) {
                emitOutput.outputFiles.push.apply(emitOutput.outputFiles, sharedEmitter.getOutputFiles());
            }

            return emitOutput;
        };

        // Emit single file if outputMany is specified, else emit all
        // Will not throw exceptions.
        TypeScriptCompiler.prototype.emit = function (fileName, resolvePath) {
            fileName = TypeScript.switchToForwardSlashes(fileName);
            var emitOutput = new EmitOutput();

            var emitOptions = new TypeScript.EmitOptions(this, resolvePath);
            if (emitOptions.diagnostic()) {
                emitOutput.emitOutputResult = 2 /* FailedBecauseOfCompilerOptionsErrors */;
                return emitOutput;
            }

            var document = this.getDocument(fileName);

            // Emitting module or multiple files, always goes to single file
            if (document.emitToOwnOutputFile()) {
                this._emitDocument(document, emitOptions, function (files) {
                    return emitOutput.outputFiles.push.apply(emitOutput.outputFiles, files);
                }, null);
                return emitOutput;
            } else {
                // In output Single file mode, emit everything
                return this.emitAll(resolvePath);
            }
        };

        // Returns an iterator that will stream compilation results from this compiler.  Syntactic
        // diagnostics will be returned first, then semantic diagnostics, then emit results, then
        // declaration emit results.
        //
        // The continueOnDiagnostics flag governs whether or not iteration follows the batch compiler
        // logic and doesn't perform further analysis once diagnostics are produced.  For example,
        // in batch compilation nothing is done if there are any syntactic diagnostics.  Clients
        // can override this if they still want to procede in those cases.
        TypeScriptCompiler.prototype.compile = function (resolvePath, continueOnDiagnostics) {
            if (typeof continueOnDiagnostics === "undefined") { continueOnDiagnostics = false; }
            return new CompilerIterator(this, resolvePath, continueOnDiagnostics);
        };

        //
        // Pull typecheck infrastructure
        //
        TypeScriptCompiler.prototype.getSyntacticDiagnostics = function (fileName) {
            fileName = TypeScript.switchToForwardSlashes(fileName);
            return this.getDocument(fileName).diagnostics();
        };

        /** Used for diagnostics in tests */
        TypeScriptCompiler.prototype.getSyntaxTree = function (fileName) {
            return this.getDocument(fileName).syntaxTree();
        };

        TypeScriptCompiler.prototype.getSourceUnit = function (fileName) {
            return this.getDocument(fileName).sourceUnit();
        };

        TypeScriptCompiler.prototype.getSemanticDiagnostics = function (fileName) {
            fileName = TypeScript.switchToForwardSlashes(fileName);

            var document = this.getDocument(fileName);

            var startTime = (new Date()).getTime();
            TypeScript.PullTypeResolver.typeCheck(this.compilationSettings(), this.semanticInfoChain, document);
            var endTime = (new Date()).getTime();

            TypeScript.typeCheckTime += endTime - startTime;

            var errors = this.semanticInfoChain.getDiagnostics(fileName);

            errors = TypeScript.ArrayUtilities.distinct(errors, TypeScript.Diagnostic.equals);
            errors.sort(function (d1, d2) {
                if (d1.fileName() < d2.fileName()) {
                    return -1;
                } else if (d1.fileName() > d2.fileName()) {
                    return 1;
                }

                if (d1.start() < d2.start()) {
                    return -1;
                } else if (d1.start() > d2.start()) {
                    return 1;
                }

                // For multiple errors reported on the same file at the same position.
                var code1 = TypeScript.diagnosticInformationMap[d1.diagnosticKey()].code;
                var code2 = TypeScript.diagnosticInformationMap[d2.diagnosticKey()].code;
                if (code1 < code2) {
                    return -1;
                } else if (code1 > code2) {
                    return 1;
                }

                return 0;
            });

            return errors;
        };

        TypeScriptCompiler.prototype.getCompilerOptionsDiagnostics = function (resolvePath) {
            var emitOptions = new TypeScript.EmitOptions(this, resolvePath);
            var emitDiagnostic = emitOptions.diagnostic();
            if (emitDiagnostic) {
                return [emitDiagnostic];
            }
            return TypeScript.sentinelEmptyArray;
        };

        TypeScriptCompiler.prototype.resolveAllFiles = function () {
            var fileNames = this.fileNames();
            for (var i = 0, n = fileNames.length; i < n; i++) {
                this.getSemanticDiagnostics(fileNames[i]);
            }
        };

        TypeScriptCompiler.prototype.getSymbolOfDeclaration = function (decl) {
            if (!decl) {
                return null;
            }

            var resolver = this.semanticInfoChain.getResolver();
            var ast = this.semanticInfoChain.getASTForDecl(decl);
            if (!ast) {
                return null;
            }

            var enclosingDecl = resolver.getEnclosingDecl(decl);
            if (ast.kind() === 139 /* GetAccessor */ || ast.kind() === 140 /* SetAccessor */) {
                return this.getSymbolOfDeclaration(enclosingDecl);
            }

            return resolver.resolveAST(ast, false, new TypeScript.PullTypeResolutionContext(resolver));
        };

        TypeScriptCompiler.prototype.extractResolutionContextFromAST = function (resolver, ast, document, propagateContextualTypes) {
            var scriptName = document.fileName;

            var enclosingDecl = null;
            var enclosingDeclAST = null;
            var inContextuallyTypedAssignment = false;
            var inWithBlock = false;

            var resolutionContext = new TypeScript.PullTypeResolutionContext(resolver);

            if (!ast) {
                return null;
            }

            var path = this.getASTPath(ast);

            for (var i = 0, n = path.length; i < n; i++) {
                var current = path[i];

                switch (current.kind()) {
                    case 222 /* FunctionExpression */:
                    case 219 /* SimpleArrowFunctionExpression */:
                    case 218 /* ParenthesizedArrowFunctionExpression */:
                        if (propagateContextualTypes) {
                            resolver.resolveAST(current, true, resolutionContext);
                        }
                        break;

                    case 136 /* MemberVariableDeclaration */:
                        var memberVariable = current;
                        inContextuallyTypedAssignment = memberVariable.variableDeclarator.typeAnnotation !== null;

                        this.extractResolutionContextForVariable(inContextuallyTypedAssignment, propagateContextualTypes, resolver, resolutionContext, enclosingDecl, memberVariable, memberVariable.variableDeclarator.equalsValueClause);
                        break;

                    case 225 /* VariableDeclarator */:
                        var variableDeclarator = current;
                        inContextuallyTypedAssignment = variableDeclarator.typeAnnotation !== null;

                        this.extractResolutionContextForVariable(inContextuallyTypedAssignment, propagateContextualTypes, resolver, resolutionContext, enclosingDecl, variableDeclarator, variableDeclarator.equalsValueClause);
                        break;

                    case 213 /* InvocationExpression */:
                    case 216 /* ObjectCreationExpression */:
                        if (propagateContextualTypes) {
                            var isNew = current.kind() === 216 /* ObjectCreationExpression */;
                            var callExpression = current;
                            var contextualType = null;

                            // Check if we are in an argumnt for a call, propagate the contextual typing
                            if ((i + 2 < n) && callExpression.argumentList === path[i + 1] && callExpression.argumentList.arguments === path[i + 2]) {
                                var callResolutionResults = new TypeScript.PullAdditionalCallResolutionData();
                                if (isNew) {
                                    resolver.resolveObjectCreationExpression(callExpression, resolutionContext, callResolutionResults);
                                } else {
                                    resolver.resolveInvocationExpression(callExpression, resolutionContext, callResolutionResults);
                                }

                                // Find the index in the arguments list
                                if (callResolutionResults.actualParametersContextTypeSymbols) {
                                    var argExpression = path[i + 3];
                                    if (argExpression) {
                                        for (var j = 0, m = callExpression.argumentList.arguments.length; j < m; j++) {
                                            if (callExpression.argumentList.arguments[j] === argExpression) {
                                                var callContextualType = callResolutionResults.actualParametersContextTypeSymbols[j];
                                                if (callContextualType) {
                                                    contextualType = callContextualType;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                            } else {
                                // Just resolve the call expression
                                if (isNew) {
                                    resolver.resolveObjectCreationExpression(callExpression, resolutionContext);
                                } else {
                                    resolver.resolveInvocationExpression(callExpression, resolutionContext);
                                }
                            }

                            resolutionContext.pushNewContextualType(contextualType);
                        }

                        break;

                    case 214 /* ArrayLiteralExpression */:
                        if (propagateContextualTypes) {
                            // Propagate the child element type
                            var contextualType = null;
                            var currentContextualType = resolutionContext.getContextualType();
                            if (currentContextualType && currentContextualType.isArrayNamedTypeReference()) {
                                contextualType = currentContextualType.getElementType();
                            }

                            resolutionContext.pushNewContextualType(contextualType);
                        }

                        break;

                    case 215 /* ObjectLiteralExpression */:
                        if (propagateContextualTypes) {
                            var objectLiteralExpression = current;
                            var objectLiteralResolutionContext = new TypeScript.PullAdditionalObjectLiteralResolutionData();
                            resolver.resolveObjectLiteralExpression(objectLiteralExpression, inContextuallyTypedAssignment, resolutionContext, objectLiteralResolutionContext);

                            // find the member in the path
                            var memeberAST = (path[i + 1] && path[i + 1].kind() === 2 /* SeparatedList */) ? path[i + 2] : path[i + 1];
                            if (memeberAST) {
                                // Propagate the member contextual type
                                var contextualType = null;
                                var memberDecls = objectLiteralExpression.propertyAssignments;
                                if (memberDecls && objectLiteralResolutionContext.membersContextTypeSymbols) {
                                    for (var j = 0, m = memberDecls.length; j < m; j++) {
                                        if (memberDecls[j] === memeberAST) {
                                            var memberContextualType = objectLiteralResolutionContext.membersContextTypeSymbols[j];
                                            if (memberContextualType) {
                                                contextualType = memberContextualType;
                                                break;
                                            }
                                        }
                                    }
                                }

                                resolutionContext.pushNewContextualType(contextualType);
                            }
                        }

                        break;

                    case 174 /* AssignmentExpression */:
                        if (propagateContextualTypes) {
                            var assignmentExpression = current;
                            var contextualType = null;

                            if (path[i + 1] && path[i + 1] === assignmentExpression.right) {
                                // propagate the left hand side type as a contextual type
                                var leftType = resolver.resolveAST(assignmentExpression.left, inContextuallyTypedAssignment, resolutionContext).type;
                                if (leftType) {
                                    inContextuallyTypedAssignment = true;
                                    contextualType = leftType;
                                }
                            }

                            resolutionContext.pushNewContextualType(contextualType);
                        }

                        break;

                    case 220 /* CastExpression */:
                        var castExpression = current;
                        if (!(i + 1 < n && path[i + 1] === castExpression.type)) {
                            // We are outside the cast term
                            if (propagateContextualTypes) {
                                var contextualType = null;
                                var typeSymbol = resolver.resolveAST(castExpression, inContextuallyTypedAssignment, resolutionContext).type;

                                // Set the context type
                                if (typeSymbol) {
                                    inContextuallyTypedAssignment = true;
                                    contextualType = typeSymbol;
                                }

                                resolutionContext.pushNewContextualType(contextualType);
                            }
                        }

                        break;

                    case 150 /* ReturnStatement */:
                        if (propagateContextualTypes) {
                            var returnStatement = current;
                            var contextualType = null;

                            if (enclosingDecl && (enclosingDecl.kind & TypeScript.PullElementKind.SomeFunction)) {
                                var typeAnnotation = TypeScript.ASTHelpers.getType(enclosingDeclAST);
                                if (typeAnnotation) {
                                    // The containing function has a type annotation, propagate it as the contextual type
                                    var returnTypeSymbol = resolver.resolveTypeReference(typeAnnotation, resolutionContext);
                                    if (returnTypeSymbol) {
                                        inContextuallyTypedAssignment = true;
                                        contextualType = returnTypeSymbol;
                                    }
                                } else {
                                    // No type annotation, check if there is a contextual type enforced on the function, and propagate that
                                    var currentContextualType = resolutionContext.getContextualType();
                                    if (currentContextualType && currentContextualType.isFunction()) {
                                        var contextualSignatures = currentContextualType.kind == TypeScript.PullElementKind.ConstructorType ? currentContextualType.getConstructSignatures() : currentContextualType.getCallSignatures();
                                        var currentContextualTypeSignatureSymbol = contextualSignatures[0];
                                        var currentContextualTypeReturnTypeSymbol = currentContextualTypeSignatureSymbol.returnType;
                                        if (currentContextualTypeReturnTypeSymbol) {
                                            inContextuallyTypedAssignment = true;
                                            contextualType = currentContextualTypeReturnTypeSymbol;
                                        }
                                    }
                                }
                            }

                            resolutionContext.pushNewContextualType(contextualType);
                        }

                        break;

                    case 122 /* ObjectType */:
                        // ObjectType are just like Object Literals are bound when needed, ensure we have a decl, by forcing it to be
                        // resolved before descending into it.
                        if (propagateContextualTypes && TypeScript.isTypesOnlyLocation(current)) {
                            resolver.resolveAST(current, false, resolutionContext);
                        }

                        break;

                    case 163 /* WithStatement */:
                        inWithBlock = true;
                        break;

                    case 146 /* Block */:
                        inContextuallyTypedAssignment = false;
                        break;
                }

                // Record enclosing Decl
                var decl = this.semanticInfoChain.getDeclForAST(current);
                if (decl) {
                    enclosingDecl = decl;
                    enclosingDeclAST = current;
                }
            }

            // if the found ISyntaxElement is a named, we want to check for previous dotted expressions,
            // since those will give us the right typing
            if (ast && ast.parent && ast.kind() === 11 /* IdentifierName */) {
                if (ast.parent.kind() === 212 /* MemberAccessExpression */) {
                    if (ast.parent.name === ast) {
                        ast = ast.parent;
                    }
                } else if (ast.parent.kind() === 121 /* QualifiedName */) {
                    if (ast.parent.right === ast) {
                        ast = ast.parent;
                    }
                }
            }

            return {
                ast: ast,
                enclosingDecl: enclosingDecl,
                resolutionContext: resolutionContext,
                inContextuallyTypedAssignment: inContextuallyTypedAssignment,
                inWithBlock: inWithBlock
            };
        };

        TypeScriptCompiler.prototype.extractResolutionContextForVariable = function (inContextuallyTypedAssignment, propagateContextualTypes, resolver, resolutionContext, enclosingDecl, assigningAST, init) {
            if (inContextuallyTypedAssignment) {
                if (propagateContextualTypes) {
                    resolver.resolveAST(assigningAST, false, resolutionContext);
                    var varSymbol = this.semanticInfoChain.getSymbolForAST(assigningAST);

                    var contextualType = null;
                    if (varSymbol && inContextuallyTypedAssignment) {
                        contextualType = varSymbol.type;
                    }

                    resolutionContext.pushNewContextualType(contextualType);

                    if (init) {
                        resolver.resolveAST(init, inContextuallyTypedAssignment, resolutionContext);
                    }
                }
            }
        };

        TypeScriptCompiler.prototype.getASTPath = function (ast) {
            var result = [];

            while (ast) {
                result.unshift(ast);
                ast = ast.parent;
            }

            return result;
        };

        TypeScriptCompiler.prototype.pullGetSymbolInformationFromAST = function (ast, document) {
            var resolver = this.semanticInfoChain.getResolver();
            var context = this.extractResolutionContextFromAST(resolver, ast, document, true);
            if (!context || context.inWithBlock) {
                return null;
            }

            ast = context.ast;
            var symbol = resolver.resolveAST(ast, context.inContextuallyTypedAssignment, context.resolutionContext);

            if (!symbol) {
                TypeScript.Debug.assert(ast.kind() === 120 /* SourceUnit */, "No symbol was found for ast and ast was not source unit. Ast Kind: " + TypeScript.SyntaxKind[ast.kind()]);
                return null;
            }

            if (symbol.isTypeReference()) {
                symbol = symbol.getReferencedTypeSymbol();
            }

            var aliasSymbol = this.semanticInfoChain.getAliasSymbolForAST(ast);

            return {
                symbol: symbol,
                aliasSymbol: aliasSymbol,
                ast: ast,
                enclosingScopeSymbol: this.getSymbolOfDeclaration(context.enclosingDecl)
            };
        };

        TypeScriptCompiler.prototype.pullGetCallInformationFromAST = function (ast, document) {
            // ISyntaxElement has to be a call expression
            if (ast.kind() !== 213 /* InvocationExpression */ && ast.kind() !== 216 /* ObjectCreationExpression */) {
                return null;
            }

            var isNew = ast.kind() === 216 /* ObjectCreationExpression */;

            var resolver = this.semanticInfoChain.getResolver();
            var context = this.extractResolutionContextFromAST(resolver, ast, document, true);
            if (!context || context.inWithBlock) {
                return null;
            }

            var callResolutionResults = new TypeScript.PullAdditionalCallResolutionData();

            if (isNew) {
                resolver.resolveObjectCreationExpression(ast, context.resolutionContext, callResolutionResults);
            } else {
                resolver.resolveInvocationExpression(ast, context.resolutionContext, callResolutionResults);
            }

            return {
                targetSymbol: callResolutionResults.targetSymbol,
                resolvedSignatures: callResolutionResults.resolvedSignatures,
                candidateSignature: callResolutionResults.candidateSignature,
                ast: ast,
                enclosingScopeSymbol: this.getSymbolOfDeclaration(context.enclosingDecl),
                isConstructorCall: isNew
            };
        };

        TypeScriptCompiler.prototype.pullGetVisibleMemberSymbolsFromAST = function (ast, document) {
            var resolver = this.semanticInfoChain.getResolver();
            var context = this.extractResolutionContextFromAST(resolver, ast, document, true);
            if (!context || context.inWithBlock) {
                return null;
            }

            var symbols = resolver.getVisibleMembersFromExpression(ast, context.enclosingDecl, context.resolutionContext);
            if (!symbols) {
                return null;
            }

            return {
                symbols: symbols,
                enclosingScopeSymbol: this.getSymbolOfDeclaration(context.enclosingDecl)
            };
        };

        TypeScriptCompiler.prototype.pullGetVisibleDeclsFromAST = function (ast, document) {
            var resolver = this.semanticInfoChain.getResolver();
            var context = this.extractResolutionContextFromAST(resolver, ast, document, false);
            if (!context || context.inWithBlock) {
                return null;
            }

            return resolver.getVisibleDecls(context.enclosingDecl);
        };

        TypeScriptCompiler.prototype.pullGetContextualMembersFromAST = function (ast, document) {
            // Input has to be an object literal
            if (ast.kind() !== 215 /* ObjectLiteralExpression */) {
                return null;
            }

            var resolver = this.semanticInfoChain.getResolver();
            var context = this.extractResolutionContextFromAST(resolver, ast, document, true);
            if (!context || context.inWithBlock) {
                return null;
            }

            var members = resolver.getVisibleContextSymbols(context.enclosingDecl, context.resolutionContext);

            return {
                symbols: members,
                enclosingScopeSymbol: this.getSymbolOfDeclaration(context.enclosingDecl)
            };
        };

        TypeScriptCompiler.prototype.pullGetDeclInformation = function (decl, ast, document) {
            var resolver = this.semanticInfoChain.getResolver();

            // Note: we not only need to resolve down to the path the ast is at, but we also need to
            // resolve the path to where the decl is at.  This is because, currently, some decls
            // can't fin their symbols unless they are first resolved.  For example, a property of
            // an object literal must be resolved before its symbol can be retrieved.
            var context = this.extractResolutionContextFromAST(resolver, ast, document, true);
            if (!context || context.inWithBlock) {
                return null;
            }

            var astForDecl = decl.ast();
            if (!astForDecl) {
                return null;
            }

            var astForDeclContext = this.extractResolutionContextFromAST(resolver, astForDecl, this.getDocument(TypeScript.syntaxTree(astForDecl).fileName()), true);
            if (!astForDeclContext) {
                return null;
            }

            var symbol = decl.getSymbol(this.semanticInfoChain);
            resolver.resolveDeclaredSymbol(symbol, context.resolutionContext);
            symbol.setUnresolved();

            return {
                symbol: symbol,
                aliasSymbol: null,
                ast: ast,
                enclosingScopeSymbol: this.getSymbolOfDeclaration(context.enclosingDecl)
            };
        };

        TypeScriptCompiler.prototype.topLevelDeclaration = function (fileName) {
            return this.semanticInfoChain.topLevelDecl(fileName);
        };

        TypeScriptCompiler.prototype.getDeclForAST = function (ast) {
            return this.semanticInfoChain.getDeclForAST(ast);
        };

        TypeScriptCompiler.prototype.fileNames = function () {
            return this.semanticInfoChain.fileNames();
        };

        TypeScriptCompiler.prototype.topLevelDecl = function (fileName) {
            return this.semanticInfoChain.topLevelDecl(fileName);
        };

        TypeScriptCompiler.getLocationText = function (location, resolvePath) {
            return resolvePath(location.fileName()) + "(" + (location.line() + 1) + "," + (location.character() + 1) + ")";
        };

        TypeScriptCompiler.getFullDiagnosticText = function (diagnostic, resolvePath) {
            var result = "";
            if (diagnostic.fileName()) {
                result += this.getLocationText(diagnostic, resolvePath) + ": ";
            }

            result += diagnostic.message();

            var additionalLocations = diagnostic.additionalLocations();
            if (additionalLocations.length > 0) {
                result += " " + TypeScript.getLocalizedText(TypeScript.DiagnosticCode.Additional_locations, null) + TypeScript.Environment.newLine;

                for (var i = 0, n = additionalLocations.length; i < n; i++) {
                    result += "\t" + this.getLocationText(additionalLocations[i], resolvePath) + TypeScript.Environment.newLine;
                }
            } else {
                result += TypeScript.Environment.newLine;
            }

            return result;
        };
        return TypeScriptCompiler;
    })();
    TypeScript.TypeScriptCompiler = TypeScriptCompiler;

    var CompilerPhase;
    (function (CompilerPhase) {
        CompilerPhase[CompilerPhase["Syntax"] = 0] = "Syntax";
        CompilerPhase[CompilerPhase["Semantics"] = 1] = "Semantics";
        CompilerPhase[CompilerPhase["EmitOptionsValidation"] = 2] = "EmitOptionsValidation";
        CompilerPhase[CompilerPhase["Emit"] = 3] = "Emit";
        CompilerPhase[CompilerPhase["DeclarationEmit"] = 4] = "DeclarationEmit";
    })(CompilerPhase || (CompilerPhase = {}));

    var CompilerIterator = (function () {
        function CompilerIterator(compiler, resolvePath, continueOnDiagnostics, startingPhase) {
            if (typeof startingPhase === "undefined") { startingPhase = 0 /* Syntax */; }
            this.compiler = compiler;
            this.resolvePath = resolvePath;
            this.continueOnDiagnostics = continueOnDiagnostics;
            this.index = -1;
            this.fileNames = null;
            this._current = null;
            this._emitOptions = null;
            this._sharedEmitter = null;
            this._sharedDeclarationEmitter = null;
            this.hadSyntacticDiagnostics = false;
            this.hadSemanticDiagnostics = false;
            this.hadEmitDiagnostics = false;
            this.fileNames = compiler.fileNames();
            this.compilerPhase = startingPhase;
        }
        CompilerIterator.prototype.current = function () {
            return this._current;
        };

        CompilerIterator.prototype.moveNext = function () {
            this._current = null;

            while (this.moveNextInternal()) {
                if (this._current) {
                    return true;
                }
            }

            return false;
        };

        CompilerIterator.prototype.moveNextInternal = function () {
            this.index++;

            while (this.shouldMoveToNextPhase()) {
                this.index = 0;
                this.compilerPhase++;
            }

            if (this.compilerPhase > 4 /* DeclarationEmit */) {
                // We're totally done.
                return false;
            }

            switch (this.compilerPhase) {
                case 0 /* Syntax */:
                    return this.moveNextSyntaxPhase();
                case 1 /* Semantics */:
                    return this.moveNextSemanticsPhase();
                case 2 /* EmitOptionsValidation */:
                    return this.moveNextEmitOptionsValidationPhase();
                case 3 /* Emit */:
                    return this.moveNextEmitPhase();
                case 4 /* DeclarationEmit */:
                    return this.moveNextDeclarationEmitPhase();
            }
        };

        CompilerIterator.prototype.shouldMoveToNextPhase = function () {
            switch (this.compilerPhase) {
                case 2 /* EmitOptionsValidation */:
                    // Only one step in emit validation.  We're done once we do that step.
                    return this.index === 1;

                case 0 /* Syntax */:
                case 1 /* Semantics */:
                    // Each of these phases are done when we've processed the last file.
                    return this.index === this.fileNames.length;

                case 3 /* Emit */:
                case 4 /* DeclarationEmit */:
                    // Emitting is done when we get 'one' past the end of hte file list.  This is
                    // because we use that step to collect the results from the shared emitter.
                    return this.index === (this.fileNames.length + 1);
            }

            return false;
        };

        CompilerIterator.prototype.moveNextSyntaxPhase = function () {
            TypeScript.Debug.assert(this.index >= 0 && this.index < this.fileNames.length);
            var fileName = this.fileNames[this.index];

            var diagnostics = this.compiler.getSyntacticDiagnostics(fileName);
            if (diagnostics.length) {
                if (!this.continueOnDiagnostics) {
                    this.hadSyntacticDiagnostics = true;
                }

                this._current = CompileResult.fromDiagnostics(diagnostics);
            }

            return true;
        };

        CompilerIterator.prototype.moveNextSemanticsPhase = function () {
            // Don't move forward if there were syntax diagnostics.
            if (this.hadSyntacticDiagnostics) {
                return false;
            }

            TypeScript.Debug.assert(this.index >= 0 && this.index < this.fileNames.length);
            var fileName = this.fileNames[this.index];
            var diagnostics = this.compiler.getSemanticDiagnostics(fileName);
            if (diagnostics.length) {
                if (!this.continueOnDiagnostics) {
                    this.hadSemanticDiagnostics = true;
                }

                this._current = CompileResult.fromDiagnostics(diagnostics);
            }

            return true;
        };

        CompilerIterator.prototype.moveNextEmitOptionsValidationPhase = function () {
            TypeScript.Debug.assert(!this.hadSyntacticDiagnostics);

            if (!this._emitOptions) {
                this._emitOptions = new TypeScript.EmitOptions(this.compiler, this.resolvePath);
            }

            if (this._emitOptions.diagnostic()) {
                if (!this.continueOnDiagnostics) {
                    this.hadEmitDiagnostics = true;
                }

                this._current = CompileResult.fromDiagnostics([this._emitOptions.diagnostic()]);
            }

            return true;
        };

        CompilerIterator.prototype.moveNextEmitPhase = function () {
            var _this = this;
            TypeScript.Debug.assert(!this.hadSyntacticDiagnostics);
            TypeScript.Debug.assert(this._emitOptions);

            if (this.hadEmitDiagnostics) {
                return false;
            }

            TypeScript.Debug.assert(this.index >= 0 && this.index <= this.fileNames.length);
            if (this.index < this.fileNames.length) {
                var fileName = this.fileNames[this.index];
                var document = this.compiler.getDocument(fileName);

                // Try to emit this single document.  It will either get emitted to its own file
                // (in which case we'll have our call back triggered), or it will get added to the
                // shared emitter (and we'll take care of it after all the files are done.
                this._sharedEmitter = this.compiler._emitDocument(document, this._emitOptions, function (outputFiles) {
                    _this._current = CompileResult.fromOutputFiles(outputFiles);
                }, this._sharedEmitter);
                return true;
            }

            // If we've moved past all the files, and we have a multi-input->single-output
            // emitter set up.  Then add the outputs of that emitter to the results.
            if (this.index === this.fileNames.length && this._sharedEmitter) {
                // Collect shared emit result.
                this._current = CompileResult.fromOutputFiles(this._sharedEmitter.getOutputFiles());
            }

            return true;
        };

        CompilerIterator.prototype.moveNextDeclarationEmitPhase = function () {
            var _this = this;
            TypeScript.Debug.assert(!this.hadSyntacticDiagnostics);
            TypeScript.Debug.assert(!this.hadEmitDiagnostics);
            if (this.hadSemanticDiagnostics) {
                return false;
            }

            if (!this.compiler.compilationSettings().generateDeclarationFiles()) {
                return false;
            }

            TypeScript.Debug.assert(this.index >= 0 && this.index <= this.fileNames.length);
            if (this.index < this.fileNames.length) {
                var fileName = this.fileNames[this.index];
                var document = this.compiler.getDocument(fileName);

                this._sharedDeclarationEmitter = this.compiler._emitDocumentDeclarations(document, this._emitOptions, function (file) {
                    _this._current = CompileResult.fromOutputFiles([file]);
                }, this._sharedDeclarationEmitter);
                return true;
            }

            // If we've moved past all the files, and we have a multi-input->single-output
            // emitter set up.  Then add the outputs of that emitter to the results.
            if (this.index === this.fileNames.length && this._sharedDeclarationEmitter) {
                this._current = CompileResult.fromOutputFiles([this._sharedDeclarationEmitter.getOutputFile()]);
            }

            return true;
        };
        return CompilerIterator;
    })();

    function compareDataObjects(dst, src) {
        for (var e in dst) {
            if (typeof dst[e] === "object") {
                if (!compareDataObjects(dst[e], src[e]))
                    return false;
            } else if (typeof dst[e] !== "function") {
                if (dst[e] !== src[e])
                    return false;
            }
        }
        return true;
    }
    TypeScript.compareDataObjects = compareDataObjects;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
/*----------------- ThirdPartyNotices -------------------------------------------------------
This file is based on or incorporates material from the projects listed below
(collectively "Third Party Code"). Microsoft is not the original author of the
Third Party Code. The original copyright notice and the license, under which
Microsoft received such Third Party Code, are set forth below. Such license and
notices are provided for informational purposes only. Microsoft licenses the Third
Party Code to you under the terms of the Apache 2.0 License.
--
Array filter Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter
Array forEach Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
Array indexOf Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
Array map Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
Array Reduce Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/Reduce
Array some Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/some
String Trim Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/Trim
Date now Compatibility Method,
Available at https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date/now
Copyright (c) 2007 - 2012 Mozilla Developer Network and individual contributors
Licensed by Microsoft 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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR
CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions and
limitations under the License.
--
Original License provided for Informational Purposes Only
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------- End of ThirdPartyNotices --------------------------------------------------- */
// Compatibility with non ES5 compliant engines
if (!String.prototype.trim) {
    String.prototype.trim = function () {
        return this.replace(/^\s+|\s+$/g, '');
    };
}

// Compatibility with non ES5 compliant engines
if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement, fromIndex) {
        "use strict";
        if (this == null) {
            throw new TypeError();
        }
        var t = Object(this);
        var len = t.length >>> 0;
        if (len === 0) {
            return -1;
        }
        var n = 0;
        if (arguments.length > 0) {
            n = Number(arguments[1]);
            if (n != n) {
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        if (n >= len) {
            return -1;
        }
        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
        for (; k < len; k++) {
            if (k in t && t[k] === searchElement) {
                return k;
            }
        }
        return -1;
    };
}

if (!Array.prototype.filter) {
    Array.prototype.filter = function (fun, thisp) {
        "use strict";

        if (this == null)
            throw new TypeError();

        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun != "function")
            throw new TypeError();

        var res = [];
        for (var i = 0; i < len; i++) {
            if (i in t) {
                var val = t[i];
                if (fun.call(thisp, val, i, t))
                    res.push(val);
            }
        }

        return res;
    };
}

// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {
    Array.prototype.map = function (callback, thisArg) {
        var T = undefined, A, k;

        if (this == null) {
            throw new TypeError(" this is null or not defined");
        }

        // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
        var O = Object(this);

        // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
        // 3. Let len be ToUint32(lenValue).
        var len = O.length >>> 0;

        // 4. If IsCallable(callback) is false, throw a TypeError exception.
        // See: http://es5.github.com/#x9.11
        if ({}.toString.call(callback) != "[object Function]") {
            throw new TypeError(callback + " is not a function");
        }

        // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
        if (thisArg) {
            T = thisArg;
        }

        // 6. Let A be a new array created as if by the expression new Array(len) where Array is
        // the standard built-in constructor with that name and len is the value of len.
        A = new Array(len);

        // 7. Let k be 0
        k = 0;

        while (k < len) {
            var kValue, mappedValue;

            // a. Let Pk be ToString(k).
            //   This is implicit for LHS operands of the in operator
            // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
            //   This step can be combined with c
            // c. If kPresent is true, then
            if (k in O) {
                // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
                kValue = O[k];

                // ii. Let mappedValue be the result of calling the Call internal method of callback
                // with T as the this value and argument list containing kValue, k, and O.
                mappedValue = callback.call(T, kValue, k, O);

                // iii. Call the DefineOwnProperty internal method of A with arguments
                // Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
                // and false.
                // In browsers that support Object.defineProperty, use the following:
                // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
                // For best browser support, use the following:
                A[k] = mappedValue;
            }

            // d. Increase k by 1.
            k++;
        }

        // 9. return A
        return A;
    };
}

if (!Array.prototype.reduce) {
    Array.prototype.reduce = function reduce(accumulator) {
        if (this === null || this === undefined)
            throw new TypeError("Object is null or undefined");
        var i = 0, l = this.length >> 0, curr;

        if (typeof accumulator !== "function")
            throw new TypeError("First argument is not callable");

        if (arguments.length < 2) {
            if (l === 0)
                throw new TypeError("Array length is 0 and no second argument");
            curr = this[0];
            i = 1; // start accumulating at the second element
        } else
            curr = arguments[1];

        while (i < l) {
            if (i in this)
                curr = accumulator.call(undefined, curr, this[i], i, this);
            ++i;
        }

        return curr;
    };
}

// Compatibility with non ES5 compliant engines
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.com/#x15.4.4.18
if (!Array.prototype.forEach) {
    Array.prototype.forEach = function (callback, thisArg) {
        var T, k;

        if (this == null) {
            throw new TypeError(" this is null or not defined");
        }

        // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
        var O = Object(this);

        // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
        // 3. Let len be ToUint32(lenValue).
        var len = O.length >>> 0;

        // 4. If IsCallable(callback) is false, throw a TypeError exception.
        // See: http://es5.github.com/#x9.11
        if ({}.toString.call(callback) != "[object Function]") {
            throw new TypeError(callback + " is not a function");
        }

        // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
        if (thisArg) {
            T = thisArg;
        } else {
            T = undefined; // added to stop definite assignment error
        }

        // 6. Let k be 0
        k = 0;

        while (k < len) {
            var kValue;

            // a. Let Pk be ToString(k).
            //   This is implicit for LHS operands of the in operator
            // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
            //   This step can be combined with c
            // c. If kPresent is true, then
            if (k in O) {
                // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
                kValue = O[k];

                // ii. Call the Call internal method of callback with T as the this value and
                // argument list containing kValue, k, and O.
                callback.call(T, kValue, k, O);
            }

            // d. Increase k by 1.
            k++;
        }
        // 8. return undefined
    };
}

// Compatibility with non ES5 compliant engines
if (!Date.now) {
    Date.now = function () {
        return (new Date()).getTime();
    };
}

// Compatibility with non ES5 compliant engines
// Production steps of ECMA-262, Edition 5.1, 15.4.4.17
if (!Array.prototype.some) {
    Array.prototype.some = function (fun /*, thisp */ ) {
        "use strict";

        if (this == null)
            throw new TypeError();

        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun != "function")
            throw new TypeError();

        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            var idx = i.toString();
            if (idx in t && fun.call(thisp, t[i], i, t))
                return true;
        }

        return false;
    };
}
///<reference path="references.ts" />
var TypeScript;
(function (TypeScript) {
    (function (IncrementalParser) {
        // Parser source used in incremental scenarios. This parser source wraps an old tree, text
        // change and new text, and uses all three to provide nodes and tokens to the parser.  In
        // general, nodes from the old tree are returned as long as they do not intersect with the text
        // change.  Then, once the text change is reached, tokens from the old tree are returned as
        // long as they do not intersect with the text change.  Then, the text that is actually changed
        // will be scanned using a normal scanner.  Then, once the new text is scanned, the source will
        // attempt to sync back up with nodes or tokens that started where the new tokens end. Once it
        // can do that, then all subsequent data will come from the original tree.
        //
        // This allows for an enormous amount of tree reuse in common scenarios.  Situations that
        // prevent this level of reuse include substantially destructive operations like introducing
        // "/*" without a "*/" nearby to terminate the comment.
        function createParserSource(oldSyntaxTree, textChangeRange, text) {
            var fileName = oldSyntaxTree.fileName();
            var languageVersion = oldSyntaxTree.languageVersion();

            // The underlying source that we will use to scan tokens from any new text, or any tokens
            // from the old tree that we decide we can't use for any reason.  We will also continue
            // scanning tokens from this source until we've decided that we're resynchronized and can
            // read in subsequent data from the old tree.
            //
            // This parser source also keeps track of the absolute position in the text that we're in,
            // and any token diagnostics produced.  That way we dont' have to track that ourselves.
            var _scannerParserSource;

            // The range of text in the *original* text that was changed, and the new length of it after
            // the change.
            var _changeRange;

            // Cached value of _changeRange.newSpan().  Cached for performance.
            var _changeRangeNewSpan;

            // This number represents how our position in the old tree relates to the position we're
            // pointing at in the new text.  If it is 0 then our positions are in sync and we can read
            // nodes or tokens from the old tree.  If it is non-zero, then our positions are not in
            // sync and we cannot use nodes or tokens from the old tree.
            //
            // Now, changeDelta could be negative or positive.  Negative means 'the position we're at
            // in the original tree is behind the position we're at in the text'.  In this case we
            // keep throwing out old nodes or tokens (and thus move forward in the original tree) until
            // changeDelta becomes 0 again or positive.  If it becomes 0 then we are resynched and can
            // read nodes or tokesn from the tree.
            //
            // If changeDelta is positive, that means the current node or token we're pointing at in
            // the old tree is at a further ahead position than the position we're pointing at in the
            // new text.  In this case we have no choice but to scan tokens from teh new text.  We will
            // continue to do so until, again, changeDelta becomes 0 and we've resynced, or change delta
            // becomes negative and we need to skip nodes or tokes in the original tree.
            var _changeDelta = 0;

            // The cursor we use to navigate through and retrieve nodes and tokens from the old tree.
            var _oldSourceUnitCursor = getSyntaxCursor();
            var oldSourceUnit = oldSyntaxTree.sourceUnit();

            var _outstandingRewindPointCount = 0;

            // Start the cursor pointing at the first element in the source unit (if it exists).
            if (oldSourceUnit.moduleElements.length > 0) {
                _oldSourceUnitCursor.pushElement(TypeScript.childAt(oldSourceUnit.moduleElements, 0), 0);
            }

            // In general supporting multiple individual edits is just not that important.  So we
            // just collapse this all down to a single range to make the code here easier.  The only
            // time this could be problematic would be if the user made a ton of discontinuous edits.
            // For example, doing a column select on a *large* section of a code.  If this is a
            // problem, we can always update this code to handle multiple changes.
            _changeRange = extendToAffectedRange(textChangeRange, oldSourceUnit);
            _changeRangeNewSpan = _changeRange.newSpan();

            // The old tree's length, plus whatever length change was caused by the edit
            // Had better equal the new text's length!
            if (TypeScript.Debug.shouldAssert(2 /* Aggressive */)) {
                TypeScript.Debug.assert((TypeScript.fullWidth(oldSourceUnit) - _changeRange.span().length() + _changeRange.newLength()) === text.length());
            }

            // Set up a scanner so that we can scan tokens out of the new text.
            _scannerParserSource = TypeScript.Scanner.createParserSource(oldSyntaxTree.fileName(), text, oldSyntaxTree.languageVersion());

            function release() {
                _scannerParserSource.release();
                _scannerParserSource = null;
                _oldSourceUnitCursor = null;
                _outstandingRewindPointCount = 0;
            }

            function extendToAffectedRange(changeRange, sourceUnit) {
                // Consider the following code:
                //      void foo() { /; }
                //
                // If the text changes with an insertion of / just before the semicolon then we end up with:
                //      void foo() { //; }
                //
                // If we were to just use the changeRange a is, then we would not rescan the { token
                // (as it does not intersect the actual original change range).  Because an edit may
                // change the token touching it, we actually need to look back *at least* one token so
                // that the prior token sees that change.
                //
                // Note: i believe (outside of regex tokens) max lookahead is just one token for
                // TypeScript.  However, if this turns out to be wrong, we may have to increase how much
                // futher we look back.
                //
                // Note: lookahead handling for regex characters is handled specially in during
                // incremental parsing, and does not need to be handled here.
                var maxLookahead = 1;

                var start = changeRange.span().start();

                for (var i = 0; start > 0 && i <= maxLookahead; i++) {
                    var token = TypeScript.findToken(sourceUnit, start);

                    // Debug.assert(token.kind !== SyntaxKind.None);
                    // Debug.assert(token.kind() === SyntaxKind.EndOfFileToken || token.fullWidth() > 0);
                    var position = token.fullStart();

                    start = Math.max(0, position - 1);
                }

                var finalSpan = TypeScript.TextSpan.fromBounds(start, changeRange.span().end());
                var finalLength = changeRange.newLength() + (changeRange.span().start() - start);

                return new TypeScript.TextChangeRange(finalSpan, finalLength);
            }

            function absolutePosition() {
                return _scannerParserSource.absolutePosition();
            }

            function tokenDiagnostics() {
                return _scannerParserSource.tokenDiagnostics();
            }

            function getRewindPoint() {
                // Get a rewind point for our new text reader and for our old source unit cursor.
                var rewindPoint = _scannerParserSource.getRewindPoint();

                // Clone our cursor.  That way we can restore to that point if hte parser needs to rewind.
                var oldSourceUnitCursorClone = cloneSyntaxCursor(_oldSourceUnitCursor);

                // Store where we were when the rewind point was created.
                rewindPoint.changeDelta = _changeDelta;
                rewindPoint.changeRange = _changeRange;
                rewindPoint.oldSourceUnitCursor = _oldSourceUnitCursor;

                _oldSourceUnitCursor = oldSourceUnitCursorClone;

                // Debug.assert(rewindPoint.pinCount === _oldSourceUnitCursor.pinCount());
                _outstandingRewindPointCount++;
                return rewindPoint;
            }

            function rewind(rewindPoint) {
                // Restore our state to the values when the rewind point was created.
                _changeRange = rewindPoint.changeRange;
                _changeDelta = rewindPoint.changeDelta;

                // Reset the cursor to what it was when we got the rewind point.  Make sure to return
                // our existing cursor to the pool so it can be reused.
                returnSyntaxCursor(_oldSourceUnitCursor);
                _oldSourceUnitCursor = rewindPoint.oldSourceUnitCursor;

                // Null out the cursor that the rewind point points to.  This way we don't try
                // to return it in 'releaseRewindPoint'.
                rewindPoint.oldSourceUnitCursor = null;

                _scannerParserSource.rewind(rewindPoint);
            }

            function releaseRewindPoint(rewindPoint) {
                if (rewindPoint.oldSourceUnitCursor !== null) {
                    returnSyntaxCursor(rewindPoint.oldSourceUnitCursor);
                }

                _scannerParserSource.releaseRewindPoint(rewindPoint);
                _outstandingRewindPointCount--;
                TypeScript.Debug.assert(_outstandingRewindPointCount >= 0);
            }

            function isPinned() {
                return _outstandingRewindPointCount > 0;
            }

            function canReadFromOldSourceUnit() {
                // If we're currently pinned, then do not want to touch the cursor.  Here's why.  First,
                // recall that we're 'pinned' when we're speculatively parsing.  So say we were to allow
                // returning old nodes/tokens while speculatively parsing. Then, the parser might start
                // mutating the nodes and tokens we returned (i.e. by setting their parents).   Then,
                // when we rewound, those nodes and tokens would still have those updated parents.
                // Parents which we just decided we did *not* want to parse (hence why we rewound).  For
                // Example, say we have something like:
                //
                //          var v = f<a,b,c>e;  // note: this is not generic.
                //
                // When incrementally parsing, we will need to speculatively parse to determine if the
                // above is generic.  This will cause us to reuse the "a, b, c" tokens, and set their
                // parent to a new type argument list.  A type argument list we will then throw away once
                // we decide that it isn't actually generic.  We will have now 'broken' the original tree.
                //
                // As such, the rule is simple.  We only return nodes/tokens from teh original tree if
                // we know the parser will accept and consume them and never rewind back before them.
                if (isPinned()) {
                    return false;
                }

                // If our current absolute position is in the middle of the changed range in the new text
                // then we definitely can't read from the old source unit right now.
                if (_changeRange !== null && _changeRangeNewSpan.intersectsWithPosition(absolutePosition())) {
                    return false;
                }

                // First, try to sync up with the new text if we're behind.
                syncCursorToNewTextIfBehind();

                // Now, if we're synced up *and* we're not currently pinned in the new text scanner,
                // then we can read a node from the cursor.  If we're pinned in the scanner then we
                // can't read a node from the cursor because we will mess up the pinned scanner when
                // we try to move it forward past this node.
                return _changeDelta === 0 && !_oldSourceUnitCursor.isFinished();
            }

            function updateTokens(nodeOrToken) {
                // If we got a node or token, and we're past the range of edited text, then walk its
                // constituent tokens, making sure all their positions are correct.  We don't need to
                // do this for the tokens before the edited range (since their positions couldn't have
                // been affected by the edit), and we don't need to do this for the tokens in the
                // edited range, as their positions will be correct when the underlying parser source
                // creates them.
                var position = absolutePosition();
                var tokenWasMoved = isPastChangeRange() && TypeScript.fullStart(nodeOrToken) !== position;

                if (tokenWasMoved) {
                    setTokenFullStartWalker.position = position;

                    TypeScript.visitNodeOrToken(setTokenFullStartWalker, nodeOrToken);
                }
            }

            function currentNode() {
                if (canReadFromOldSourceUnit()) {
                    // Try to read a node.  If we can't then our caller will call back in and just try
                    // to get a token.
                    var node = tryGetNodeFromOldSourceUnit();
                    if (node !== null) {
                        // Make sure the positions for the tokens in this node are correct.
                        updateTokens(node);
                        return node;
                    }
                }

                // Either we were ahead of the old text, or we were pinned.  No node can be read here.
                return null;
            }

            function currentToken() {
                if (canReadFromOldSourceUnit()) {
                    var token = tryGetTokenFromOldSourceUnit();
                    if (token !== null) {
                        // Make sure the token's position/text is correct.
                        updateTokens(token);
                        return token;
                    }
                }

                // Either we couldn't read from the old source unit, or we weren't able to successfully
                // get a token from it.  In this case we need to read a token from the underlying text.
                return _scannerParserSource.currentToken();
            }

            function currentContextualToken() {
                // Just delegate to the underlying source to handle
                return _scannerParserSource.currentContextualToken();
            }

            function syncCursorToNewTextIfBehind() {
                while (true) {
                    if (_oldSourceUnitCursor.isFinished()) {
                        break;
                    }

                    if (_changeDelta >= 0) {
                        break;
                    }

                    // We're behind in the original tree.  Throw out a node or token in an attempt to
                    // catch up to the position we're at in the new text.
                    var currentNodeOrToken = _oldSourceUnitCursor.currentNodeOrToken();

                    // If we're pointing at a node, and that node's width is less than our delta,
                    // then we can just skip that node.  Otherwise, if we're pointing at a node
                    // whose width is greater than the delta, then crumble it and try again.
                    // Otherwise, we must be pointing at a token.  Just skip it and try again.
                    if (TypeScript.isNode(currentNodeOrToken) && (TypeScript.fullWidth(currentNodeOrToken) > Math.abs(_changeDelta))) {
                        // We were pointing at a node whose width was more than changeDelta.  Crumble the
                        // node and try again.  Note: we haven't changed changeDelta.  So the callers loop
                        // will just repeat this until we get to a node or token that we can skip over.
                        _oldSourceUnitCursor.moveToFirstChild();
                    } else {
                        _oldSourceUnitCursor.moveToNextSibling();

                        // Get our change delta closer to 0 as we skip past this item.
                        _changeDelta += TypeScript.fullWidth(currentNodeOrToken);
                        // If this was a node, then our changeDelta is 0 or negative.  If this was a
                        // token, then we could still be negative (and we have to read another token),
                        // we could be zero (we're done), or we could be positive (we've moved ahead
                        // of the new text).  Only if we're negative will we continue looping.
                    }
                }
                // At this point, we must be either:
                //   a) done with the cursor
                //   b) (ideally) caught up to the new text position.
                //   c) ahead of the new text position.
                // In case 'b' we can try to reuse a node from teh old tree.
                // Debug.assert(_oldSourceUnitCursor.isFinished() || _changeDelta >= 0);
            }

            function intersectsWithChangeRangeSpanInOriginalText(start, length) {
                return !isPastChangeRange() && _changeRange.span().intersectsWith(start, length);
            }

            function tryGetNodeFromOldSourceUnit() {
                while (true) {
                    var node = _oldSourceUnitCursor.currentNode();
                    if (node === null) {
                        // Couldn't even read a node, nothing to return.
                        return null;
                    }

                    if (!intersectsWithChangeRangeSpanInOriginalText(absolutePosition(), TypeScript.fullWidth(node))) {
                        // Didn't intersect with the change range.
                        var isIncrementallyUnusuable = TypeScript.isIncrementallyUnusable(node);
                        if (!isIncrementallyUnusuable) {
                            // Didn't contain anything that would make it unusable.  Awesome.  This is
                            // a node we can reuse.
                            return node;
                        }
                    }

                    // We couldn't use currentNode. Try to move to its first child (in case that's a
                    // node).  If it is we can try using that.  Otherwise we'll just bail out in the
                    // next iteration of the loop.
                    _oldSourceUnitCursor.moveToFirstChild();
                }
            }

            function canReuseTokenFromOldSourceUnit(position, token) {
                // A token is safe to return if:
                //  a) it does not intersect the changed text.
                //  b) it does not contain skipped text.
                //  c) it is not zero width.
                //  d) it is not a contextual parser token.
                //
                // NOTE: It is safe to get a token regardless of what our strict context was/is.  That's
                // because the strict context doesn't change what tokens are scanned, only how the
                // parser reacts to them.
                //
                // NOTE: we don't mark a keyword that was converted to an identifier as 'incrementally
                // unusable.  This is because we don't want to mark it's containing parent node as
                // unusable.  i.e. if i have this:  "public Foo(string: Type) { }", then that *entire* node
                // is reusuable even though "string" was converted to an identifier.  However, we still
                // need to make sure that if that the parser asks for a *token* we don't return it.
                // Converted identifiers can't ever be created by the scanner, and as such, should not
                // be returned by this source.
                if (token !== null) {
                    if (!intersectsWithChangeRangeSpanInOriginalText(position, token.fullWidth())) {
                        // Didn't intersect with the change range.
                        if (!token.isIncrementallyUnusable() && !TypeScript.Scanner.isContextualToken(token)) {
                            // Didn't contain anything that would make it unusable.  Awesome.  This is
                            // a token we can reuse.
                            return true;
                        }
                    }
                }

                return false;
            }

            function tryGetTokenFromOldSourceUnit() {
                // Debug.assert(canReadFromOldSourceUnit());
                // get the current token that the cursor is pointing at.
                var token = _oldSourceUnitCursor.currentToken();

                return canReuseTokenFromOldSourceUnit(absolutePosition(), token) ? token : null;
            }

            function peekToken(n) {
                if (canReadFromOldSourceUnit()) {
                    var token = tryPeekTokenFromOldSourceUnit(n);
                    if (token !== null) {
                        return token;
                    }
                }

                // Couldn't peek this far in the old tree.  Get the token from the new text.
                return _scannerParserSource.peekToken(n);
            }

            function tryPeekTokenFromOldSourceUnit(n) {
                // Debug.assert(canReadFromOldSourceUnit());
                // clone the existing cursor so we can move it forward and then restore ourselves back
                // to where we started from.
                var cursorClone = cloneSyntaxCursor(_oldSourceUnitCursor);

                var token = tryPeekTokenFromOldSourceUnitWorker(n);

                returnSyntaxCursor(_oldSourceUnitCursor);
                _oldSourceUnitCursor = cursorClone;

                return token;
            }

            function tryPeekTokenFromOldSourceUnitWorker(n) {
                // In order to peek the 'nth' token we need all the tokens up to that point.  That way
                // we know we know position that the nth token is at.  The position is necessary so
                // that we can test if this token (or any that precede it cross the change range).
                var currentPosition = absolutePosition();

                // First, make sure the cursor is pointing at a token.
                _oldSourceUnitCursor.moveToFirstToken();

                for (var i = 0; i < n; i++) {
                    var interimToken = _oldSourceUnitCursor.currentToken();

                    if (!canReuseTokenFromOldSourceUnit(currentPosition, interimToken)) {
                        return null;
                    }

                    currentPosition += interimToken.fullWidth();
                    _oldSourceUnitCursor.moveToNextSibling();
                }

                var token = _oldSourceUnitCursor.currentToken();
                return canReuseTokenFromOldSourceUnit(currentPosition, token) ? token : null;
            }

            function consumeNode(node) {
                // A node could have only come from the old source unit cursor.  Update it and our
                // current state.
                // Debug.assert(_changeDelta === 0);
                // Debug.assert(currentNode() === node);
                _oldSourceUnitCursor.moveToNextSibling();

                // Update the underlying source with where it should now be currently pointin.
                var _absolutePosition = absolutePosition() + TypeScript.fullWidth(node);
                _scannerParserSource.resetToPosition(_absolutePosition);
                // Debug.assert(previousToken !== null);
                // Debug.assert(previousToken.width() > 0);
                //if (!isPastChangeRange()) {
                //    // If we still have a change range, then this node must have ended before the
                //    // change range starts.  Thus, we don't need to call 'skipPastChanges'.
                //    Debug.assert(absolutePosition() < _changeRange.span().start());
                //}
            }

            function consumeToken(currentToken) {
                // This token may have come from the old source unit, or from the new text.  Handle
                // both accordingly.
                if (_oldSourceUnitCursor.currentToken() === currentToken) {
                    // The token came from the old source unit.  So our tree and text must be in sync.
                    // Debug.assert(_changeDelta === 0);
                    // Move the cursor past this token.
                    _oldSourceUnitCursor.moveToNextSibling();

                    // Debug.assert(!_normalParserSource.isPinned());
                    // Update the underlying source with where it should now be currently pointing. We
                    // don't need to do this when the token came from the new text as the source will
                    // automatically be placed in the right position.
                    var _absolutePosition = absolutePosition() + currentToken.fullWidth();
                    _scannerParserSource.resetToPosition(_absolutePosition);
                    // Debug.assert(previousToken !== null);
                    // Debug.assert(previousToken.width() > 0);
                    //if (!isPastChangeRange()) {
                    //    // If we still have a change range, then this token must have ended before the
                    //    // change range starts.  Thus, we don't need to call 'skipPastChanges'.
                    //    Debug.assert(absolutePosition() < _changeRange.span().start());
                    //}
                } else {
                    // the token came from the new text.  That means the normal source moved forward,
                    // while the syntax cursor stayed in the same place.  Thus our delta moves even
                    // further back.
                    _changeDelta -= currentToken.fullWidth();

                    // Move our underlying source forward.
                    _scannerParserSource.consumeToken(currentToken);

                    // Because we read a token from the new text, we may have moved ourselves past the
                    // change range.  If we did, then we may also have to update our change delta to
                    // compensate for the length change between the old and new text.
                    if (!isPastChangeRange()) {
                        // var changeEndInNewText = _changeRange.span().start() + _changeRange.newLength();
                        if (absolutePosition() >= _changeRangeNewSpan.end()) {
                            _changeDelta += _changeRange.newLength() - _changeRange.span().length();

                            // Once we're past the change range, we no longer need it.  Null it out.
                            // From now on we can check if we're past the change range just by seeing
                            // if this is null.
                            _changeRange = null;
                        }
                    }
                }
            }

            function isPastChangeRange() {
                return _changeRange === null;
            }

            return {
                text: text,
                fileName: fileName,
                languageVersion: languageVersion,
                currentNode: currentNode,
                currentToken: currentToken,
                currentContextualToken: currentContextualToken,
                peekToken: peekToken,
                consumeNode: consumeNode,
                consumeToken: consumeToken,
                getRewindPoint: getRewindPoint,
                rewind: rewind,
                releaseRewindPoint: releaseRewindPoint,
                tokenDiagnostics: tokenDiagnostics,
                release: release
            };
        }

        function createSyntaxCursorPiece(element, indexInParent) {
            return { element: element, indexInParent: indexInParent };
        }

        // Pool syntax cursors so we don't churn too much memory when we need temporary cursors.
        // i.e. when we're speculatively parsing, we can cheaply get a pooled cursor and then
        // return it when we no longer need it.
        var syntaxCursorPool = [];
        var syntaxCursorPoolCount = 0;

        function returnSyntaxCursor(cursor) {
            // Make sure the cursor isn't holding onto any syntax elements.  We don't want to leak
            // them when we return the cursor to the pool.
            cursor.clean();

            syntaxCursorPool[syntaxCursorPoolCount] = cursor;
            syntaxCursorPoolCount++;
        }

        function getSyntaxCursor() {
            // Get an existing cursor from the pool if we have one.  Or create a new one if we don't.
            var cursor = syntaxCursorPoolCount > 0 ? syntaxCursorPool[syntaxCursorPoolCount - 1] : createSyntaxCursor();

            if (syntaxCursorPoolCount > 0) {
                // If we reused an existing cursor, take it out of the pool so no one else uses it.
                syntaxCursorPoolCount--;
                syntaxCursorPool[syntaxCursorPoolCount] = null;
            }

            return cursor;
        }

        function cloneSyntaxCursor(cursor) {
            var newCursor = getSyntaxCursor();

            // Make the new cursor a *deep* copy of the cursor passed in.  This ensures each cursor can
            // be moved without affecting the other.
            newCursor.deepCopyFrom(cursor);

            return newCursor;
        }

        function createSyntaxCursor() {
            // Our list of path pieces.  The piece pointed to by 'currentPieceIndex' must be a node or
            // token.  However, pieces earlier than that may point to list nodes.
            //
            // For perf we reuse pieces as much as possible.  i.e. instead of popping items off the
            // list, we just will change currentPieceIndex so we can reuse that piece later.
            var pieces = [];
            var currentPieceIndex = -1;

            // Cleans up this cursor so that it doesn't have any references to actual syntax nodes.
            // This sould be done before returning the cursor to the pool so that the Parser module
            // doesn't unnecessarily keep old syntax trees alive.
            function clean() {
                for (var i = 0, n = pieces.length; i < n; i++) {
                    var piece = pieces[i];

                    if (piece.element === null) {
                        break;
                    }

                    piece.element = null;
                    piece.indexInParent = -1;
                }

                currentPieceIndex = -1;
            }

            // Makes this cursor into a deep copy of the cursor passed in.
            function deepCopyFrom(other) {
                for (var i = 0, n = other.pieces.length; i < n; i++) {
                    var piece = other.pieces[i];

                    if (piece.element === null) {
                        break;
                    }

                    pushElement(piece.element, piece.indexInParent);
                }
                // Debug.assert(currentPieceIndex === other.currentPieceIndex);
            }

            function isFinished() {
                return currentPieceIndex < 0;
            }

            function currentNodeOrToken() {
                if (isFinished()) {
                    return null;
                }

                var result = pieces[currentPieceIndex].element;

                // The current element must always be a node or a token.
                // Debug.assert(result !== null);
                // Debug.assert(result.isNode() || result.isToken());
                return result;
            }

            function currentNode() {
                var element = currentNodeOrToken();
                return TypeScript.isNode(element) ? element : null;
            }

            function moveToFirstChild() {
                var nodeOrToken = currentNodeOrToken();
                if (nodeOrToken === null) {
                    return;
                }

                if (TypeScript.isToken(nodeOrToken)) {
                    // If we're already on a token, there's nothing to do.
                    return;
                }

                for (var i = 0, n = TypeScript.childCount(nodeOrToken); i < n; i++) {
                    var child = TypeScript.childAt(nodeOrToken, i);
                    if (child !== null && !TypeScript.isShared(child)) {
                        // Great, we found a real child.  Push that.
                        pushElement(child, i);

                        // If it was a list, make sure we're pointing at its first element.  We know we
                        // must have one because this is a non-shared list.
                        moveToFirstChildIfList();
                        return;
                    }
                }

                // This element must have been an empty node.  Moving to its 'first child' is equivalent to just
                // moving to the next sibling.
                // Debug.assert(fullWidth(nodeOrToken) === 0);
                moveToNextSibling();
            }

            function moveToNextSibling() {
                while (!isFinished()) {
                    // first look to our parent and see if it has a sibling of us that we can move to.
                    var currentPiece = pieces[currentPieceIndex];
                    var parent = currentPiece.element.parent;

                    for (var i = currentPiece.indexInParent + 1, n = TypeScript.childCount(parent); i < n; i++) {
                        var sibling = TypeScript.childAt(parent, i);

                        if (sibling !== null && !TypeScript.isShared(sibling)) {
                            // We found a good sibling that we can move to.  Just reuse our existing piece
                            // so we don't have to push/pop.
                            currentPiece.element = sibling;
                            currentPiece.indexInParent = i;

                            // The sibling might have been a list.  Move to it's first child.  it must have
                            // one since this was a non-shared element.
                            moveToFirstChildIfList();
                            return;
                        }
                    }

                    // Didn't have a sibling for this element.  Go up to our parent and get its sibling.
                    // Clear the data from the old piece.  We don't want to keep any elements around
                    // unintentionally.
                    currentPiece.element = null;
                    currentPiece.indexInParent = -1;

                    // Point at the parent.  if we move past the top of the path, then we're finished.
                    currentPieceIndex--;
                }
            }

            function moveToFirstChildIfList() {
                var element = pieces[currentPieceIndex].element;

                if (TypeScript.isList(element) || TypeScript.isSeparatedList(element)) {
                    // We cannot ever get an empty list in our piece path.  Empty lists are 'shared' and
                    // we make sure to filter that out before pushing any children.
                    // Debug.assert(childCount(element) > 0);
                    pushElement(TypeScript.childAt(element, 0), 0);
                }
            }

            function pushElement(element, indexInParent) {
                // Debug.assert(element !== null);
                // Debug.assert(indexInParent >= 0);
                currentPieceIndex++;

                // Reuse an existing piece if we have one.  Otherwise, push a new piece to our list.
                if (currentPieceIndex === pieces.length) {
                    pieces.push(createSyntaxCursorPiece(element, indexInParent));
                } else {
                    var piece = pieces[currentPieceIndex];
                    piece.element = element;
                    piece.indexInParent = indexInParent;
                }
            }

            function moveToFirstToken() {
                while (!isFinished()) {
                    var element = pieces[currentPieceIndex].element;
                    if (TypeScript.isNode(element)) {
                        moveToFirstChild();
                        continue;
                    }

                    // Debug.assert(isToken(element));
                    return;
                }
            }

            function currentToken() {
                moveToFirstToken();

                var element = currentNodeOrToken();

                // Debug.assert(element === null || element.isToken());
                return element === null ? null : element;
            }

            return {
                pieces: pieces,
                clean: clean,
                isFinished: isFinished,
                moveToFirstChild: moveToFirstChild,
                moveToFirstToken: moveToFirstToken,
                moveToNextSibling: moveToNextSibling,
                currentNodeOrToken: currentNodeOrToken,
                currentNode: currentNode,
                currentToken: currentToken,
                pushElement: pushElement,
                deepCopyFrom: deepCopyFrom
            };
        }

        // A simple walker we use to hit all the tokens of a node and update their positions when they
        // are reused in a different location because of an incremental parse.
        var SetTokenFullStartWalker = (function (_super) {
            __extends(SetTokenFullStartWalker, _super);
            function SetTokenFullStartWalker() {
                _super.apply(this, arguments);
            }
            SetTokenFullStartWalker.prototype.visitToken = function (token) {
                var position = this.position;
                token.setFullStart(position);

                this.position = position + token.fullWidth();
            };
            return SetTokenFullStartWalker;
        })(TypeScript.SyntaxWalker);

        var setTokenFullStartWalker = new SetTokenFullStartWalker();

        function parse(oldSyntaxTree, textChangeRange, newText) {
            TypeScript.Debug.assert(oldSyntaxTree.isConcrete(), "Can only incrementally parse a concrete syntax tree.");
            if (textChangeRange.isUnchanged()) {
                return oldSyntaxTree;
            }

            return TypeScript.Parser.parseSource(createParserSource(oldSyntaxTree, textChangeRange, newText), oldSyntaxTree.isDeclaration());
        }
        IncrementalParser.parse = parse;
    })(TypeScript.IncrementalParser || (TypeScript.IncrementalParser = {}));
    var IncrementalParser = TypeScript.IncrementalParser;
})(TypeScript || (TypeScript = {}));
///<reference path="references.ts" />
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        // Inject support for incremental parsing to the core compiler Document class.
        TypeScript.Document.incrementalParse = TypeScript.IncrementalParser.parse;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    function isSeparatedListTypeScriptSpecific(list) {
        for (var i = 0, n = TypeScript.childCount(list); i < n; i++) {
            if (isTypeScriptSpecific(TypeScript.childAt(list, i))) {
                return true;
            }
        }

        return false;
    }

    function isListTypeScriptSpecific(list) {
        for (var i = 0, n = list.length; i < n; i++) {
            if (isTypeScriptSpecific(list[i])) {
                return true;
            }
        }

        return false;
    }

    function isTypeScriptSpecific(element) {
        if (element === null) {
            return false;
        }
        if (TypeScript.isToken(element)) {
            return false;
        }
        if (TypeScript.isList(element)) {
            return isListTypeScriptSpecific(element);
        }
        if (TypeScript.isSeparatedList(element)) {
            return isSeparatedListTypeScriptSpecific(element);
        }

        switch (element.kind()) {
            case 121 /* QualifiedName */:
            case 122 /* ObjectType */:
            case 123 /* FunctionType */:
            case 124 /* ArrayType */:
            case 125 /* ConstructorType */:
            case 126 /* GenericType */:
            case 127 /* TypeQuery */:
            case 128 /* InterfaceDeclaration */:
            case 130 /* ModuleDeclaration */:
            case 131 /* ClassDeclaration */:
            case 132 /* EnumDeclaration */:
            case 133 /* ImportDeclaration */:
            case 134 /* ExportAssignment */:
            case 135 /* MemberFunctionDeclaration */:
            case 136 /* MemberVariableDeclaration */:
            case 137 /* ConstructorDeclaration */:
            case 138 /* IndexMemberDeclaration */:
            case 140 /* SetAccessor */:
            case 141 /* PropertySignature */:
            case 143 /* ConstructSignature */:
            case 144 /* IndexSignature */:
            case 218 /* ParenthesizedArrowFunctionExpression */:
            case 219 /* SimpleArrowFunctionExpression */:
            case 220 /* CastExpression */:
            case 228 /* TypeArgumentList */:
            case 229 /* TypeParameterList */:
            case 230 /* ExtendsHeritageClause */:
            case 231 /* ImplementsHeritageClause */:
            case 238 /* TypeParameter */:
            case 239 /* Constraint */:
            case 244 /* TypeAnnotation */:
            case 245 /* ExternalModuleReference */:
            case 246 /* ModuleNameModuleReference */:
                return true;
            case 152 /* BreakStatement */:
            case 153 /* ContinueStatement */:
            case 156 /* EmptyStatement */:
            case 162 /* DebuggerStatement */:
            case 223 /* OmittedExpression */:
                return false;
            case 120 /* SourceUnit */:
                return isSourceUnitTypeScriptSpecific(element);
            case 129 /* FunctionDeclaration */:
                return isFunctionDeclarationTypeScriptSpecific(element);
            case 139 /* GetAccessor */:
                return isGetAccessorTypeScriptSpecific(element);
            case 142 /* CallSignature */:
                return isCallSignatureTypeScriptSpecific(element);
            case 145 /* MethodSignature */:
                return isMethodSignatureTypeScriptSpecific(element);
            case 146 /* Block */:
                return isBlockTypeScriptSpecific(element);
            case 147 /* IfStatement */:
                return isIfStatementTypeScriptSpecific(element);
            case 148 /* VariableStatement */:
                return isVariableStatementTypeScriptSpecific(element);
            case 149 /* ExpressionStatement */:
                return isExpressionStatementTypeScriptSpecific(element);
            case 150 /* ReturnStatement */:
                return isReturnStatementTypeScriptSpecific(element);
            case 151 /* SwitchStatement */:
                return isSwitchStatementTypeScriptSpecific(element);
            case 154 /* ForStatement */:
                return isForStatementTypeScriptSpecific(element);
            case 155 /* ForInStatement */:
                return isForInStatementTypeScriptSpecific(element);
            case 157 /* ThrowStatement */:
                return isThrowStatementTypeScriptSpecific(element);
            case 158 /* WhileStatement */:
                return isWhileStatementTypeScriptSpecific(element);
            case 159 /* TryStatement */:
                return isTryStatementTypeScriptSpecific(element);
            case 160 /* LabeledStatement */:
                return isLabeledStatementTypeScriptSpecific(element);
            case 161 /* DoStatement */:
                return isDoStatementTypeScriptSpecific(element);
            case 163 /* WithStatement */:
                return isWithStatementTypeScriptSpecific(element);
            case 168 /* PreIncrementExpression */:
            case 169 /* PreDecrementExpression */:
            case 164 /* PlusExpression */:
            case 165 /* NegateExpression */:
            case 166 /* BitwiseNotExpression */:
            case 167 /* LogicalNotExpression */:
                return isPrefixUnaryExpressionTypeScriptSpecific(element);
            case 170 /* DeleteExpression */:
                return isDeleteExpressionTypeScriptSpecific(element);
            case 171 /* TypeOfExpression */:
                return isTypeOfExpressionTypeScriptSpecific(element);
            case 172 /* VoidExpression */:
                return isVoidExpressionTypeScriptSpecific(element);
            case 186 /* ConditionalExpression */:
                return isConditionalExpressionTypeScriptSpecific(element);
            case 205 /* MultiplyExpression */:
            case 206 /* DivideExpression */:
            case 207 /* ModuloExpression */:
            case 208 /* AddExpression */:
            case 209 /* SubtractExpression */:
            case 202 /* LeftShiftExpression */:
            case 203 /* SignedRightShiftExpression */:
            case 204 /* UnsignedRightShiftExpression */:
            case 196 /* LessThanExpression */:
            case 197 /* GreaterThanExpression */:
            case 198 /* LessThanOrEqualExpression */:
            case 199 /* GreaterThanOrEqualExpression */:
            case 200 /* InstanceOfExpression */:
            case 201 /* InExpression */:
            case 192 /* EqualsWithTypeConversionExpression */:
            case 193 /* NotEqualsWithTypeConversionExpression */:
            case 194 /* EqualsExpression */:
            case 195 /* NotEqualsExpression */:
            case 191 /* BitwiseAndExpression */:
            case 190 /* BitwiseExclusiveOrExpression */:
            case 189 /* BitwiseOrExpression */:
            case 188 /* LogicalAndExpression */:
            case 187 /* LogicalOrExpression */:
            case 182 /* OrAssignmentExpression */:
            case 180 /* AndAssignmentExpression */:
            case 181 /* ExclusiveOrAssignmentExpression */:
            case 183 /* LeftShiftAssignmentExpression */:
            case 184 /* SignedRightShiftAssignmentExpression */:
            case 185 /* UnsignedRightShiftAssignmentExpression */:
            case 175 /* AddAssignmentExpression */:
            case 176 /* SubtractAssignmentExpression */:
            case 177 /* MultiplyAssignmentExpression */:
            case 178 /* DivideAssignmentExpression */:
            case 179 /* ModuloAssignmentExpression */:
            case 174 /* AssignmentExpression */:
            case 173 /* CommaExpression */:
                return isBinaryExpressionTypeScriptSpecific(element);
            case 210 /* PostIncrementExpression */:
            case 211 /* PostDecrementExpression */:
                return isPostfixUnaryExpressionTypeScriptSpecific(element);
            case 212 /* MemberAccessExpression */:
                return isMemberAccessExpressionTypeScriptSpecific(element);
            case 213 /* InvocationExpression */:
                return isInvocationExpressionTypeScriptSpecific(element);
            case 214 /* ArrayLiteralExpression */:
                return isArrayLiteralExpressionTypeScriptSpecific(element);
            case 215 /* ObjectLiteralExpression */:
                return isObjectLiteralExpressionTypeScriptSpecific(element);
            case 216 /* ObjectCreationExpression */:
                return isObjectCreationExpressionTypeScriptSpecific(element);
            case 217 /* ParenthesizedExpression */:
                return isParenthesizedExpressionTypeScriptSpecific(element);
            case 221 /* ElementAccessExpression */:
                return isElementAccessExpressionTypeScriptSpecific(element);
            case 222 /* FunctionExpression */:
                return isFunctionExpressionTypeScriptSpecific(element);
            case 224 /* VariableDeclaration */:
                return isVariableDeclarationTypeScriptSpecific(element);
            case 225 /* VariableDeclarator */:
                return isVariableDeclaratorTypeScriptSpecific(element);
            case 226 /* ArgumentList */:
                return isArgumentListTypeScriptSpecific(element);
            case 227 /* ParameterList */:
                return isParameterListTypeScriptSpecific(element);
            case 232 /* EqualsValueClause */:
                return isEqualsValueClauseTypeScriptSpecific(element);
            case 233 /* CaseSwitchClause */:
                return isCaseSwitchClauseTypeScriptSpecific(element);
            case 234 /* DefaultSwitchClause */:
                return isDefaultSwitchClauseTypeScriptSpecific(element);
            case 235 /* ElseClause */:
                return isElseClauseTypeScriptSpecific(element);
            case 236 /* CatchClause */:
                return isCatchClauseTypeScriptSpecific(element);
            case 237 /* FinallyClause */:
                return isFinallyClauseTypeScriptSpecific(element);
            case 240 /* SimplePropertyAssignment */:
                return isSimplePropertyAssignmentTypeScriptSpecific(element);
            case 241 /* FunctionPropertyAssignment */:
                return isFunctionPropertyAssignmentTypeScriptSpecific(element);
            case 242 /* Parameter */:
                return isParameterTypeScriptSpecific(element);
            case 243 /* EnumElement */:
                return isEnumElementTypeScriptSpecific(element);
        }
    }
    TypeScript.isTypeScriptSpecific = isTypeScriptSpecific;

    function isSourceUnitTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.moduleElements);
    }

    function isFunctionDeclarationTypeScriptSpecific(node) {
        return node.modifiers.length > 0 || isTypeScriptSpecific(node.callSignature) || isTypeScriptSpecific(node.block);
    }

    function isGetAccessorTypeScriptSpecific(node) {
        return node.modifiers.length > 0 || isTypeScriptSpecific(node.callSignature) || isTypeScriptSpecific(node.block);
    }

    function isCallSignatureTypeScriptSpecific(node) {
        return node.typeParameterList !== null || isTypeScriptSpecific(node.parameterList) || node.typeAnnotation !== null;
    }

    function isMethodSignatureTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.callSignature);
    }

    function isBlockTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.statements);
    }

    function isIfStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.condition) || isTypeScriptSpecific(node.statement) || isTypeScriptSpecific(node.elseClause);
    }

    function isVariableStatementTypeScriptSpecific(node) {
        return node.modifiers.length > 0 || isTypeScriptSpecific(node.variableDeclaration);
    }

    function isExpressionStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isReturnStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isSwitchStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression) || isTypeScriptSpecific(node.switchClauses);
    }

    function isForStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.variableDeclaration) || isTypeScriptSpecific(node.initializer) || isTypeScriptSpecific(node.condition) || isTypeScriptSpecific(node.incrementor) || isTypeScriptSpecific(node.statement);
    }

    function isForInStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.variableDeclaration) || isTypeScriptSpecific(node.left) || isTypeScriptSpecific(node.expression) || isTypeScriptSpecific(node.statement);
    }

    function isThrowStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isWhileStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.condition) || isTypeScriptSpecific(node.statement);
    }

    function isTryStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.block) || isTypeScriptSpecific(node.catchClause) || isTypeScriptSpecific(node.finallyClause);
    }

    function isLabeledStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.statement);
    }

    function isDoStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.statement) || isTypeScriptSpecific(node.condition);
    }

    function isWithStatementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.condition) || isTypeScriptSpecific(node.statement);
    }

    function isPrefixUnaryExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.operand);
    }

    function isDeleteExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isTypeOfExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isVoidExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isConditionalExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.condition) || isTypeScriptSpecific(node.whenTrue) || isTypeScriptSpecific(node.whenFalse);
    }

    function isBinaryExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.left) || isTypeScriptSpecific(node.right);
    }

    function isPostfixUnaryExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.operand);
    }

    function isMemberAccessExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isInvocationExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression) || isTypeScriptSpecific(node.argumentList);
    }

    function isArrayLiteralExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expressions);
    }

    function isObjectLiteralExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.propertyAssignments);
    }

    function isObjectCreationExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression) || isTypeScriptSpecific(node.argumentList);
    }

    function isParenthesizedExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isElementAccessExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression) || isTypeScriptSpecific(node.argumentExpression);
    }

    function isFunctionExpressionTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.callSignature) || isTypeScriptSpecific(node.block);
    }

    function isVariableDeclarationTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.variableDeclarators);
    }

    function isVariableDeclaratorTypeScriptSpecific(node) {
        return node.typeAnnotation !== null || isTypeScriptSpecific(node.equalsValueClause);
    }

    function isArgumentListTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.typeArgumentList) || isTypeScriptSpecific(node.arguments);
    }

    function isParameterListTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.parameters);
    }

    function isEqualsValueClauseTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.value);
    }

    function isCaseSwitchClauseTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression) || isTypeScriptSpecific(node.statements);
    }

    function isDefaultSwitchClauseTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.statements);
    }

    function isElseClauseTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.statement);
    }

    function isCatchClauseTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.typeAnnotation) || isTypeScriptSpecific(node.block);
    }

    function isFinallyClauseTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.block);
    }

    function isSimplePropertyAssignmentTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.expression);
    }

    function isFunctionPropertyAssignmentTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.callSignature) || isTypeScriptSpecific(node.block);
    }

    function isParameterTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.modifiers) || node.typeAnnotation !== null || node.equalsValueClause !== null;
    }

    function isEnumElementTypeScriptSpecific(node) {
        return isTypeScriptSpecific(node.equalsValueClause);
    }
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        (function (EndOfLineState) {
            EndOfLineState[EndOfLineState["Start"] = 0] = "Start";
            EndOfLineState[EndOfLineState["InMultiLineCommentTrivia"] = 1] = "InMultiLineCommentTrivia";
            EndOfLineState[EndOfLineState["InSingleQuoteStringLiteral"] = 2] = "InSingleQuoteStringLiteral";
            EndOfLineState[EndOfLineState["InDoubleQuoteStringLiteral"] = 3] = "InDoubleQuoteStringLiteral";
        })(Services.EndOfLineState || (Services.EndOfLineState = {}));
        var EndOfLineState = Services.EndOfLineState;

        (function (TokenClass) {
            TokenClass[TokenClass["Punctuation"] = 0] = "Punctuation";
            TokenClass[TokenClass["Keyword"] = 1] = "Keyword";
            TokenClass[TokenClass["Operator"] = 2] = "Operator";
            TokenClass[TokenClass["Comment"] = 3] = "Comment";
            TokenClass[TokenClass["Whitespace"] = 4] = "Whitespace";
            TokenClass[TokenClass["Identifier"] = 5] = "Identifier";
            TokenClass[TokenClass["NumberLiteral"] = 6] = "NumberLiteral";
            TokenClass[TokenClass["StringLiteral"] = 7] = "StringLiteral";
            TokenClass[TokenClass["RegExpLiteral"] = 8] = "RegExpLiteral";
        })(Services.TokenClass || (Services.TokenClass = {}));
        var TokenClass = Services.TokenClass;

        var noRegexTable = [];
        noRegexTable[11 /* IdentifierName */] = true;
        noRegexTable[14 /* StringLiteral */] = true;
        noRegexTable[13 /* NumericLiteral */] = true;
        noRegexTable[12 /* RegularExpressionLiteral */] = true;
        noRegexTable[35 /* ThisKeyword */] = true;
        noRegexTable[93 /* PlusPlusToken */] = true;
        noRegexTable[94 /* MinusMinusToken */] = true;
        noRegexTable[73 /* CloseParenToken */] = true;
        noRegexTable[75 /* CloseBracketToken */] = true;
        noRegexTable[71 /* CloseBraceToken */] = true;
        noRegexTable[37 /* TrueKeyword */] = true;
        noRegexTable[24 /* FalseKeyword */] = true;

        var Classifier = (function () {
            function Classifier(host) {
                var _this = this;
                this.host = host;
                this.lastDiagnosticKey = null;
                this.reportDiagnostic = function (position, fullWidth, key, args) {
                    _this.lastDiagnosticKey = key;
                };
            }
            /// COLORIZATION
            Classifier.prototype.getClassificationsForLine = function (text, lexState) {
                var offset = 0;
                if (lexState !== 0 /* Start */) {
                    // If we're in a string literal, then prepend: "\
                    // (and a newline).  That way when we lex we'll think we're still in a string literal.
                    //
                    // If we're in a multiline comment, then prepend: /*
                    // (and a newline).  That way when we lex we'll think we're still in a multiline comment.
                    if (lexState === 3 /* InDoubleQuoteStringLiteral */) {
                        text = '"\\\n' + text;
                    } else if (lexState === 2 /* InSingleQuoteStringLiteral */) {
                        text = "'\\\n" + text;
                    } else if (lexState === 1 /* InMultiLineCommentTrivia */) {
                        text = "/*\n" + text;
                    }

                    offset = 3;
                }

                var result = new ClassificationResult();
                var simpleText = TypeScript.SimpleText.fromString(text);
                this.scanner = TypeScript.Scanner.createScanner(1 /* EcmaScript5 */, simpleText, this.reportDiagnostic);

                var lastTokenKind = 0 /* None */;
                var token = null;
                do {
                    this.lastDiagnosticKey = null;

                    token = this.scanner.scan(!noRegexTable[lastTokenKind]);
                    lastTokenKind = token.kind();

                    this.processToken(text, simpleText, offset, token, result);
                } while(token.kind() !== 10 /* EndOfFileToken */);

                this.lastDiagnosticKey = null;
                return result;
            };

            Classifier.prototype.processToken = function (text, simpleText, offset, token, result) {
                this.processTriviaList(text, offset, token.leadingTrivia(simpleText), result);
                this.addResult(text, offset, result, TypeScript.width(token), token.kind());
                this.processTriviaList(text, offset, token.trailingTrivia(simpleText), result);

                if (TypeScript.fullEnd(token) >= text.length) {
                    // We're at the end.
                    if (this.lastDiagnosticKey === TypeScript.DiagnosticCode.AsteriskSlash_expected) {
                        result.finalLexState = 1 /* InMultiLineCommentTrivia */;
                        return;
                    }

                    if (token.kind() === 14 /* StringLiteral */) {
                        var tokenText = token.text();
                        if (tokenText.length > 0 && tokenText.charCodeAt(tokenText.length - 1) === 92 /* backslash */) {
                            var quoteChar = tokenText.charCodeAt(0);
                            result.finalLexState = quoteChar === 34 /* doubleQuote */ ? 3 /* InDoubleQuoteStringLiteral */ : 2 /* InSingleQuoteStringLiteral */;
                            return;
                        }
                    }
                }
            };

            Classifier.prototype.processTriviaList = function (text, offset, triviaList, result) {
                for (var i = 0, n = triviaList.count(); i < n; i++) {
                    var trivia = triviaList.syntaxTriviaAt(i);
                    this.addResult(text, offset, result, trivia.fullWidth(), trivia.kind());
                }
            };

            Classifier.prototype.addResult = function (text, offset, result, length, kind) {
                if (length > 0) {
                    // If this is the first classification we're adding to the list, then remove any
                    // offset we have if we were continuing a construct from the previous line.
                    if (result.entries.length === 0) {
                        length -= offset;
                    }

                    result.entries.push(new ClassificationInfo(length, this.classFromKind(kind)));
                }
            };

            Classifier.prototype.classFromKind = function (kind) {
                if (TypeScript.SyntaxFacts.isAnyKeyword(kind)) {
                    return 1 /* Keyword */;
                } else if (TypeScript.SyntaxFacts.isBinaryExpressionOperatorToken(kind) || TypeScript.SyntaxFacts.isPrefixUnaryExpressionOperatorToken(kind)) {
                    return 2 /* Operator */;
                } else if (TypeScript.SyntaxFacts.isAnyPunctuation(kind)) {
                    return 0 /* Punctuation */;
                }

                switch (kind) {
                    case 4 /* WhitespaceTrivia */:
                        return 4 /* Whitespace */;
                    case 6 /* MultiLineCommentTrivia */:
                    case 7 /* SingleLineCommentTrivia */:
                        return 3 /* Comment */;
                    case 13 /* NumericLiteral */:
                        return 6 /* NumberLiteral */;
                    case 14 /* StringLiteral */:
                        return 7 /* StringLiteral */;
                    case 12 /* RegularExpressionLiteral */:
                        return 8 /* RegExpLiteral */;
                    case 11 /* IdentifierName */:
                    default:
                        return 5 /* Identifier */;
                }
            };
            return Classifier;
        })();
        Services.Classifier = Classifier;

        var ClassificationResult = (function () {
            function ClassificationResult() {
                this.finalLexState = 0 /* Start */;
                this.entries = [];
            }
            return ClassificationResult;
        })();
        Services.ClassificationResult = ClassificationResult;

        var ClassificationInfo = (function () {
            function ClassificationInfo(length, classification) {
                this.length = length;
                this.classification = classification;
            }
            return ClassificationInfo;
        })();
        Services.ClassificationInfo = ClassificationInfo;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    ///<reference path='diagnosticServices.ts' />
    (function (Services) {
        

        

        function logInternalError(logger, err) {
            logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message);
        }
        Services.logInternalError = logInternalError;

        var ReferenceEntry = (function () {
            function ReferenceEntry(fileName, minChar, limChar, isWriteAccess) {
                this.fileName = "";
                this.minChar = -1;
                this.limChar = -1;
                this.isWriteAccess = false;
                this.fileName = fileName;
                this.minChar = minChar;
                this.limChar = limChar;
                this.isWriteAccess = isWriteAccess;
            }
            return ReferenceEntry;
        })();
        Services.ReferenceEntry = ReferenceEntry;

        var NavigateToItem = (function () {
            function NavigateToItem() {
                this.name = "";
                this.kind = "";
                this.kindModifiers = "";
                this.matchKind = "";
                this.fileName = "";
                this.minChar = -1;
                this.limChar = -1;
                this.additionalSpans = null;
                this.containerName = "";
                this.containerKind = "";
            }
            return NavigateToItem;
        })();
        Services.NavigateToItem = NavigateToItem;

        var TextEdit = (function () {
            function TextEdit(minChar, limChar, text) {
                this.minChar = minChar;
                this.limChar = limChar;
                this.text = text;
            }
            TextEdit.createInsert = function (pos, text) {
                return new TextEdit(pos, pos, text);
            };
            TextEdit.createDelete = function (minChar, limChar) {
                return new TextEdit(minChar, limChar, "");
            };
            TextEdit.createReplace = function (minChar, limChar, text) {
                return new TextEdit(minChar, limChar, text);
            };
            return TextEdit;
        })();
        Services.TextEdit = TextEdit;

        var EditorOptions = (function () {
            function EditorOptions() {
                this.IndentSize = 4;
                this.TabSize = 4;
                this.NewLineCharacter = "\r\n";
                this.ConvertTabsToSpaces = true;
            }
            EditorOptions.clone = function (objectToClone) {
                var editorOptions = new EditorOptions();
                editorOptions.IndentSize = objectToClone.IndentSize;
                editorOptions.TabSize = objectToClone.TabSize;
                editorOptions.NewLineCharacter = objectToClone.NewLineCharacter;
                editorOptions.ConvertTabsToSpaces = objectToClone.ConvertTabsToSpaces;
                return editorOptions;
            };
            return EditorOptions;
        })();
        Services.EditorOptions = EditorOptions;

        var FormatCodeOptions = (function (_super) {
            __extends(FormatCodeOptions, _super);
            function FormatCodeOptions() {
                _super.apply(this, arguments);
                this.InsertSpaceAfterCommaDelimiter = true;
                this.InsertSpaceAfterSemicolonInForStatements = true;
                this.InsertSpaceBeforeAndAfterBinaryOperators = true;
                this.InsertSpaceAfterKeywordsInControlFlowStatements = true;
                this.InsertSpaceAfterFunctionKeywordForAnonymousFunctions = false;
                this.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis = false;
                this.PlaceOpenBraceOnNewLineForFunctions = false;
                this.PlaceOpenBraceOnNewLineForControlBlocks = false;
            }
            FormatCodeOptions.clone = function (objectToClone) {
                var formatCodeOptions = EditorOptions.clone(objectToClone);
                formatCodeOptions.InsertSpaceAfterCommaDelimiter = objectToClone.InsertSpaceAfterCommaDelimiter;
                formatCodeOptions.InsertSpaceAfterSemicolonInForStatements = objectToClone.InsertSpaceAfterSemicolonInForStatements;
                formatCodeOptions.InsertSpaceBeforeAndAfterBinaryOperators = objectToClone.InsertSpaceBeforeAndAfterBinaryOperators;
                formatCodeOptions.InsertSpaceAfterKeywordsInControlFlowStatements = objectToClone.InsertSpaceAfterKeywordsInControlFlowStatements;
                formatCodeOptions.InsertSpaceAfterFunctionKeywordForAnonymousFunctions = objectToClone.InsertSpaceAfterFunctionKeywordForAnonymousFunctions;
                formatCodeOptions.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis = objectToClone.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis;
                formatCodeOptions.PlaceOpenBraceOnNewLineForFunctions = objectToClone.PlaceOpenBraceOnNewLineForFunctions;
                formatCodeOptions.PlaceOpenBraceOnNewLineForControlBlocks = objectToClone.PlaceOpenBraceOnNewLineForControlBlocks;
                return formatCodeOptions;
            };
            return FormatCodeOptions;
        })(EditorOptions);
        Services.FormatCodeOptions = FormatCodeOptions;

        var DefinitionInfo = (function () {
            function DefinitionInfo(fileName, minChar, limChar, kind, name, containerKind, containerName) {
                this.fileName = fileName;
                this.minChar = minChar;
                this.limChar = limChar;
                this.kind = kind;
                this.name = name;
                this.containerKind = containerKind;
                this.containerName = containerName;
            }
            return DefinitionInfo;
        })();
        Services.DefinitionInfo = DefinitionInfo;

        var TypeInfo = (function () {
            function TypeInfo(memberName, docComment, fullSymbolName, kind, minChar, limChar) {
                this.memberName = memberName;
                this.docComment = docComment;
                this.fullSymbolName = fullSymbolName;
                this.kind = kind;
                this.minChar = minChar;
                this.limChar = limChar;
            }
            return TypeInfo;
        })();
        Services.TypeInfo = TypeInfo;

        var SpanInfo = (function () {
            function SpanInfo(minChar, limChar, text) {
                if (typeof text === "undefined") { text = null; }
                this.minChar = minChar;
                this.limChar = limChar;
                this.text = text;
            }
            return SpanInfo;
        })();
        Services.SpanInfo = SpanInfo;

        var SignatureInfo = (function () {
            function SignatureInfo() {
                this.formal = [];
            }
            return SignatureInfo;
        })();
        Services.SignatureInfo = SignatureInfo;

        var FormalSignatureItemInfo = (function () {
            function FormalSignatureItemInfo() {
                this.typeParameters = [];
                this.parameters = [];
            }
            return FormalSignatureItemInfo;
        })();
        Services.FormalSignatureItemInfo = FormalSignatureItemInfo;

        var FormalTypeParameterInfo = (function () {
            function FormalTypeParameterInfo() {
            }
            return FormalTypeParameterInfo;
        })();
        Services.FormalTypeParameterInfo = FormalTypeParameterInfo;

        var FormalParameterInfo = (function () {
            function FormalParameterInfo() {
            }
            return FormalParameterInfo;
        })();
        Services.FormalParameterInfo = FormalParameterInfo;

        var ActualSignatureInfo = (function () {
            function ActualSignatureInfo() {
            }
            return ActualSignatureInfo;
        })();
        Services.ActualSignatureInfo = ActualSignatureInfo;

        var CompletionInfo = (function () {
            function CompletionInfo() {
                this.maybeInaccurate = false;
                this.isMemberCompletion = false;
                this.entries = [];
            }
            return CompletionInfo;
        })();
        Services.CompletionInfo = CompletionInfo;

        var ScriptElementKind = (function () {
            function ScriptElementKind() {
            }
            ScriptElementKind.unknown = "";

            // predefined type (void) or keyword (class)
            ScriptElementKind.keyword = "keyword";

            // top level script node
            ScriptElementKind.scriptElement = "script";

            // module foo {}
            ScriptElementKind.moduleElement = "module";

            // class X {}
            ScriptElementKind.classElement = "class";

            // interface Y {}
            ScriptElementKind.interfaceElement = "interface";

            // enum E
            ScriptElementKind.enumElement = "enum";

            // Inside module and script only
            // var v = ..
            ScriptElementKind.variableElement = "var";

            // Inside function
            ScriptElementKind.localVariableElement = "local var";

            // Inside module and script only
            // function f() { }
            ScriptElementKind.functionElement = "function";

            // Inside function
            ScriptElementKind.localFunctionElement = "local function";

            // class X { [public|private]* foo() {} }
            ScriptElementKind.memberFunctionElement = "method";

            // class X { [public|private]* [get|set] foo:number; }
            ScriptElementKind.memberGetAccessorElement = "getter";
            ScriptElementKind.memberSetAccessorElement = "setter";

            // class X { [public|private]* foo:number; }
            // interface Y { foo:number; }
            ScriptElementKind.memberVariableElement = "property";

            // class X { constructor() { } }
            ScriptElementKind.constructorImplementationElement = "constructor";

            // interface Y { ():number; }
            ScriptElementKind.callSignatureElement = "call";

            // interface Y { []:number; }
            ScriptElementKind.indexSignatureElement = "index";

            // interface Y { new():Y; }
            ScriptElementKind.constructSignatureElement = "construct";

            // function foo(*Y*: string)
            ScriptElementKind.parameterElement = "parameter";

            ScriptElementKind.typeParameterElement = "type parameter";

            ScriptElementKind.primitiveType = "primitive type";
            return ScriptElementKind;
        })();
        Services.ScriptElementKind = ScriptElementKind;

        var ScriptElementKindModifier = (function () {
            function ScriptElementKindModifier() {
            }
            ScriptElementKindModifier.none = "";
            ScriptElementKindModifier.publicMemberModifier = "public";
            ScriptElementKindModifier.privateMemberModifier = "private";
            ScriptElementKindModifier.exportedModifier = "export";
            ScriptElementKindModifier.ambientModifier = "declare";
            ScriptElementKindModifier.staticModifier = "static";
            return ScriptElementKindModifier;
        })();
        Services.ScriptElementKindModifier = ScriptElementKindModifier;

        var MatchKind = (function () {
            function MatchKind() {
            }
            MatchKind.none = null;
            MatchKind.exact = "exact";
            MatchKind.subString = "substring";
            MatchKind.prefix = "prefix";
            return MatchKind;
        })();
        Services.MatchKind = MatchKind;

        var DiagnosticCategory = (function () {
            function DiagnosticCategory() {
            }
            DiagnosticCategory.none = "";
            DiagnosticCategory.error = "error";
            DiagnosticCategory.warning = "warning";
            DiagnosticCategory.message = "message";
            return DiagnosticCategory;
        })();
        Services.DiagnosticCategory = DiagnosticCategory;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var TextSnapshot = (function () {
                function TextSnapshot(snapshot) {
                    this.snapshot = snapshot;
                    this.lines = [];
                }
                TextSnapshot.prototype.getText = function (span) {
                    return this.snapshot.substr(span.start(), span.length());
                };

                TextSnapshot.prototype.getLineNumberFromPosition = function (position) {
                    return this.snapshot.lineMap().getLineNumberFromPosition(position);
                };

                TextSnapshot.prototype.getLineFromPosition = function (position) {
                    var lineNumber = this.getLineNumberFromPosition(position);
                    return this.getLineFromLineNumber(lineNumber);
                };

                TextSnapshot.prototype.getLineFromLineNumber = function (lineNumber) {
                    var line = this.lines[lineNumber];
                    if (line === undefined) {
                        line = this.getLineFromLineNumberWorker(lineNumber);
                        this.lines[lineNumber] = line;
                    }
                    return line;
                };

                TextSnapshot.prototype.getLineFromLineNumberWorker = function (lineNumber) {
                    var lineMap = this.snapshot.lineMap().lineStarts();
                    var lineMapIndex = lineNumber;
                    if (lineMapIndex < 0 || lineMapIndex >= lineMap.length)
                        throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Invalid_line_number_0, [lineMapIndex]));
                    var start = lineMap[lineMapIndex];

                    var end;
                    var endIncludingLineBreak;
                    var lineBreak = "";
                    if (lineMapIndex == lineMap.length) {
                        end = endIncludingLineBreak = this.snapshot.length();
                    } else {
                        endIncludingLineBreak = (lineMapIndex >= lineMap.length - 1 ? this.snapshot.length() : lineMap[lineMapIndex + 1]);
                        for (var p = endIncludingLineBreak - 1; p >= start; p--) {
                            var c = this.snapshot.substr(p, 1);

                            //TODO: Other ones?
                            if (c != "\r" && c != "\n") {
                                break;
                            }
                        }
                        end = p + 1;
                        lineBreak = this.snapshot.substr(end, endIncludingLineBreak - end);
                    }
                    var result = new Formatting.TextSnapshotLine(this, lineNumber, start, end, lineBreak);
                    return result;
                };
                return TextSnapshot;
            })();
            Formatting.TextSnapshot = TextSnapshot;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var TextSnapshotLine = (function () {
                function TextSnapshotLine(_snapshot, _lineNumber, _start, _end, _lineBreak) {
                    this._snapshot = _snapshot;
                    this._lineNumber = _lineNumber;
                    this._start = _start;
                    this._end = _end;
                    this._lineBreak = _lineBreak;
                }
                TextSnapshotLine.prototype.snapshot = function () {
                    return this._snapshot;
                };

                TextSnapshotLine.prototype.start = function () {
                    return new Formatting.SnapshotPoint(this._snapshot, this._start);
                };

                TextSnapshotLine.prototype.startPosition = function () {
                    return this._start;
                };

                TextSnapshotLine.prototype.end = function () {
                    return new Formatting.SnapshotPoint(this._snapshot, this._end);
                };

                TextSnapshotLine.prototype.endPosition = function () {
                    return this._end;
                };

                TextSnapshotLine.prototype.endIncludingLineBreak = function () {
                    return new Formatting.SnapshotPoint(this._snapshot, this._end + this._lineBreak.length);
                };

                TextSnapshotLine.prototype.endIncludingLineBreakPosition = function () {
                    return this._end + this._lineBreak.length;
                };

                TextSnapshotLine.prototype.length = function () {
                    return this._end - this._start;
                };

                TextSnapshotLine.prototype.lineNumber = function () {
                    return this._lineNumber;
                };

                TextSnapshotLine.prototype.getText = function () {
                    return this._snapshot.getText(TypeScript.TextSpan.fromBounds(this._start, this._end));
                };
                return TextSnapshotLine;
            })();
            Formatting.TextSnapshotLine = TextSnapshotLine;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var SnapshotPoint = (function () {
                function SnapshotPoint(snapshot, position) {
                    this.snapshot = snapshot;
                    this.position = position;
                }
                SnapshotPoint.prototype.getContainingLine = function () {
                    return this.snapshot.getLineFromPosition(this.position);
                };
                SnapshotPoint.prototype.add = function (offset) {
                    return new SnapshotPoint(this.snapshot, this.position + offset);
                };
                return SnapshotPoint;
            })();
            Formatting.SnapshotPoint = SnapshotPoint;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        /// <reference path="formatting.ts"/>
        (function (Formatting) {
            var FormattingContext = (function () {
                function FormattingContext(snapshot, formattingRequestKind) {
                    this.snapshot = snapshot;
                    this.formattingRequestKind = formattingRequestKind;
                    this.currentTokenSpan = null;
                    this.nextTokenSpan = null;
                    this.contextNode = null;
                    this.currentTokenParent = null;
                    this.nextTokenParent = null;
                    this.contextNodeAllOnSameLine = null;
                    this.nextNodeAllOnSameLine = null;
                    this.tokensAreOnSameLine = null;
                    this.contextNodeBlockIsOnOneLine = null;
                    this.nextNodeBlockIsOnOneLine = null;
                    TypeScript.Debug.assert(this.snapshot != null, "snapshot is null");
                }
                FormattingContext.prototype.updateContext = function (currentTokenSpan, currentTokenParent, nextTokenSpan, nextTokenParent, commonParent) {
                    TypeScript.Debug.assert(currentTokenSpan != null, "currentTokenSpan is null");
                    TypeScript.Debug.assert(currentTokenParent != null, "currentTokenParent is null");
                    TypeScript.Debug.assert(nextTokenSpan != null, "nextTokenSpan is null");
                    TypeScript.Debug.assert(nextTokenParent != null, "nextTokenParent is null");
                    TypeScript.Debug.assert(commonParent != null, "commonParent is null");

                    this.currentTokenSpan = currentTokenSpan;
                    this.currentTokenParent = currentTokenParent;
                    this.nextTokenSpan = nextTokenSpan;
                    this.nextTokenParent = nextTokenParent;
                    this.contextNode = commonParent;

                    this.contextNodeAllOnSameLine = null;
                    this.nextNodeAllOnSameLine = null;
                    this.tokensAreOnSameLine = null;
                    this.contextNodeBlockIsOnOneLine = null;
                    this.nextNodeBlockIsOnOneLine = null;
                };

                FormattingContext.prototype.ContextNodeAllOnSameLine = function () {
                    if (this.contextNodeAllOnSameLine === null) {
                        this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode);
                    }

                    return this.contextNodeAllOnSameLine;
                };

                FormattingContext.prototype.NextNodeAllOnSameLine = function () {
                    if (this.nextNodeAllOnSameLine === null) {
                        this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent);
                    }

                    return this.nextNodeAllOnSameLine;
                };

                FormattingContext.prototype.TokensAreOnSameLine = function () {
                    if (this.tokensAreOnSameLine === null) {
                        var startLine = this.snapshot.getLineNumberFromPosition(this.currentTokenSpan.start());
                        var endLine = this.snapshot.getLineNumberFromPosition(this.nextTokenSpan.start());

                        this.tokensAreOnSameLine = (startLine == endLine);
                    }

                    return this.tokensAreOnSameLine;
                };

                FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () {
                    if (this.contextNodeBlockIsOnOneLine === null) {
                        this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode);
                    }

                    return this.contextNodeBlockIsOnOneLine;
                };

                FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () {
                    if (this.nextNodeBlockIsOnOneLine === null) {
                        this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent);
                    }

                    return this.nextNodeBlockIsOnOneLine;
                };

                FormattingContext.prototype.NodeIsOnOneLine = function (node) {
                    var startLine = this.snapshot.getLineNumberFromPosition(node.start());
                    var endLine = this.snapshot.getLineNumberFromPosition(node.end());

                    return startLine == endLine;
                };

                // Now we know we have a block (or a fake block represented by some other kind of node with an open and close brace as children).
                // IMPORTANT!!! This relies on the invariant that IsBlockContext must return true ONLY for nodes with open and close braces as immediate children
                FormattingContext.prototype.BlockIsOnOneLine = function (node) {
                    var block = node.node();

                    // Now check if they are on the same line
                    return this.snapshot.getLineNumberFromPosition(TypeScript.end(block.openBraceToken)) === this.snapshot.getLineNumberFromPosition(TypeScript.start(block.closeBraceToken));
                };
                return FormattingContext;
            })();
            Formatting.FormattingContext = FormattingContext;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        /// <reference path="formatting.ts"/>
        (function (Formatting) {
            var FormattingManager = (function () {
                function FormattingManager(syntaxTree, snapshot, rulesProvider, editorOptions) {
                    this.syntaxTree = syntaxTree;
                    this.snapshot = snapshot;
                    this.rulesProvider = rulesProvider;
                    //
                    // TODO: convert to use FormattingOptions instead of EditorOptions
                    this.options = new TypeScript.FormattingOptions(!editorOptions.ConvertTabsToSpaces, editorOptions.TabSize, editorOptions.IndentSize, editorOptions.NewLineCharacter);
                }
                FormattingManager.prototype.formatSelection = function (minChar, limChar) {
                    var span = TypeScript.TextSpan.fromBounds(minChar, limChar);
                    return this.formatSpan(span, 1 /* FormatSelection */);
                };

                FormattingManager.prototype.formatDocument = function (minChar, limChar) {
                    var span = TypeScript.TextSpan.fromBounds(minChar, limChar);
                    return this.formatSpan(span, 0 /* FormatDocument */);
                };

                FormattingManager.prototype.formatOnPaste = function (minChar, limChar) {
                    var span = TypeScript.TextSpan.fromBounds(minChar, limChar);
                    return this.formatSpan(span, 5 /* FormatOnPaste */);
                };

                FormattingManager.prototype.formatOnSemicolon = function (caretPosition) {
                    var sourceUnit = this.syntaxTree.sourceUnit();
                    var semicolonPositionedToken = TypeScript.findToken(sourceUnit, caretPosition - 1);

                    if (semicolonPositionedToken.kind() === 78 /* SemicolonToken */) {
                        // Find the outer most parent that this semicolon terminates
                        var current = semicolonPositionedToken;
                        while (current.parent !== null && TypeScript.end(current.parent) === TypeScript.end(semicolonPositionedToken) && current.parent.kind() !== 1 /* List */) {
                            current = current.parent;
                        }

                        // Compute the span
                        var span = new TypeScript.TextSpan(TypeScript.fullStart(current), TypeScript.fullWidth(current));

                        // Format the span
                        return this.formatSpan(span, 3 /* FormatOnSemicolon */);
                    }

                    return [];
                };

                FormattingManager.prototype.formatOnClosingCurlyBrace = function (caretPosition) {
                    var sourceUnit = this.syntaxTree.sourceUnit();
                    var closeBracePositionedToken = TypeScript.findToken(sourceUnit, caretPosition - 1);

                    if (closeBracePositionedToken.kind() === 71 /* CloseBraceToken */) {
                        // Find the outer most parent that this closing brace terminates
                        var current = closeBracePositionedToken;
                        while (current.parent !== null && TypeScript.end(current.parent) === TypeScript.end(closeBracePositionedToken) && current.parent.kind() !== 1 /* List */) {
                            current = current.parent;
                        }

                        // Compute the span
                        var span = new TypeScript.TextSpan(TypeScript.fullStart(current), TypeScript.fullWidth(current));

                        // Format the span
                        return this.formatSpan(span, 4 /* FormatOnClosingCurlyBrace */);
                    }

                    return [];
                };

                FormattingManager.prototype.formatOnEnter = function (caretPosition) {
                    var lineNumber = this.snapshot.getLineNumberFromPosition(caretPosition);

                    if (lineNumber > 0) {
                        // Format both lines
                        var prevLine = this.snapshot.getLineFromLineNumber(lineNumber - 1);
                        var currentLine = this.snapshot.getLineFromLineNumber(lineNumber);
                        var span = TypeScript.TextSpan.fromBounds(prevLine.startPosition(), currentLine.endPosition());

                        // Format the span
                        return this.formatSpan(span, 2 /* FormatOnEnter */);
                    }

                    return [];
                };

                FormattingManager.prototype.formatSpan = function (span, formattingRequestKind) {
                    // Always format from the beginning of the line
                    var startLine = this.snapshot.getLineFromPosition(span.start());
                    span = TypeScript.TextSpan.fromBounds(startLine.startPosition(), span.end());

                    var result = [];

                    var formattingEdits = Formatting.Formatter.getEdits(span, this.syntaxTree.sourceUnit(), this.options, true, this.snapshot, this.rulesProvider, formattingRequestKind);

                    //
                    // TODO: Change the ILanguageService interface to return TextEditInfo (with start, and length) instead of TextEdit (with minChar and limChar)
                    formattingEdits.forEach(function (item) {
                        var edit = new TypeScript.Services.TextEdit(item.position, item.position + item.length, item.replaceWith);
                        result.push(edit);
                    });

                    return result;
                };
                return FormattingManager;
            })();
            Formatting.FormattingManager = FormattingManager;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        /// <reference path="formatting.ts"/>
        (function (Formatting) {
            (function (FormattingRequestKind) {
                FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument";
                FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection";
                FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter";
                FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon";
                FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 4] = "FormatOnClosingCurlyBrace";
                FormattingRequestKind[FormattingRequestKind["FormatOnPaste"] = 5] = "FormatOnPaste";
            })(Formatting.FormattingRequestKind || (Formatting.FormattingRequestKind = {}));
            var FormattingRequestKind = Formatting.FormattingRequestKind;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var Rule = (function () {
                function Rule(Descriptor, Operation, Flag) {
                    if (typeof Flag === "undefined") { Flag = 0 /* None */; }
                    this.Descriptor = Descriptor;
                    this.Operation = Operation;
                    this.Flag = Flag;
                }
                Rule.prototype.toString = function () {
                    return "[desc=" + this.Descriptor + "," + "operation=" + this.Operation + "," + "flag=" + this.Flag + "]";
                };
                return Rule;
            })();
            Formatting.Rule = Rule;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            (function (RuleAction) {
                RuleAction[RuleAction["Ignore"] = 0] = "Ignore";
                RuleAction[RuleAction["Space"] = 1] = "Space";
                RuleAction[RuleAction["NewLine"] = 2] = "NewLine";
                RuleAction[RuleAction["Delete"] = 3] = "Delete";
            })(Formatting.RuleAction || (Formatting.RuleAction = {}));
            var RuleAction = Formatting.RuleAction;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var RuleDescriptor = (function () {
                function RuleDescriptor(LeftTokenRange, RightTokenRange) {
                    this.LeftTokenRange = LeftTokenRange;
                    this.RightTokenRange = RightTokenRange;
                }
                RuleDescriptor.prototype.toString = function () {
                    return "[leftRange=" + this.LeftTokenRange + "," + "rightRange=" + this.RightTokenRange + "]";
                };

                RuleDescriptor.create1 = function (left, right) {
                    return RuleDescriptor.create4(Formatting.Shared.TokenRange.FromToken(left), Formatting.Shared.TokenRange.FromToken(right));
                };

                RuleDescriptor.create2 = function (left, right) {
                    return RuleDescriptor.create4(left, Formatting.Shared.TokenRange.FromToken(right));
                };

                RuleDescriptor.create3 = function (left, right) {
                    return RuleDescriptor.create4(Formatting.Shared.TokenRange.FromToken(left), right);
                };

                RuleDescriptor.create4 = function (left, right) {
                    return new RuleDescriptor(left, right);
                };
                return RuleDescriptor;
            })();
            Formatting.RuleDescriptor = RuleDescriptor;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            (function (RuleFlags) {
                RuleFlags[RuleFlags["None"] = 0] = "None";
                RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines";
            })(Formatting.RuleFlags || (Formatting.RuleFlags = {}));
            var RuleFlags = Formatting.RuleFlags;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var RuleOperation = (function () {
                function RuleOperation() {
                    this.Context = null;
                    this.Action = null;
                }
                RuleOperation.prototype.toString = function () {
                    return "[context=" + this.Context + "," + "action=" + this.Action + "]";
                };

                RuleOperation.create1 = function (action) {
                    return RuleOperation.create2(Formatting.RuleOperationContext.Any, action);
                };

                RuleOperation.create2 = function (context, action) {
                    var result = new RuleOperation();
                    result.Context = context;
                    result.Action = action;
                    return result;
                };
                return RuleOperation;
            })();
            Formatting.RuleOperation = RuleOperation;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var RuleOperationContext = (function () {
                function RuleOperationContext() {
                    var funcs = [];
                    for (var _i = 0; _i < (arguments.length - 0); _i++) {
                        funcs[_i] = arguments[_i + 0];
                    }
                    this.customContextChecks = funcs;
                }
                RuleOperationContext.prototype.IsAny = function () {
                     {
                        return this == RuleOperationContext.Any;
                    }
                };

                RuleOperationContext.prototype.InContext = function (context) {
                    if (this.IsAny()) {
                        return true;
                    }

                    for (var i = 0, len = this.customContextChecks.length; i < len; i++) {
                        if (!this.customContextChecks[i](context)) {
                            return false;
                        }
                    }
                    return true;
                };
                RuleOperationContext.Any = new RuleOperationContext();
                return RuleOperationContext;
            })();
            Formatting.RuleOperationContext = RuleOperationContext;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var Rules = (function () {
                function Rules() {
                    ///
                    /// Common Rules
                    ///
                    // Leave comments alone
                    this.IgnoreBeforeComment = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.Any, Formatting.Shared.TokenRange.Comments), Formatting.RuleOperation.create1(0 /* Ignore */));
                    this.IgnoreAfterLineComment = new Formatting.Rule(Formatting.RuleDescriptor.create3(7 /* SingleLineCommentTrivia */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create1(0 /* Ignore */));

                    // Space after keyword but not before ; or : or ?
                    this.NoSpaceBeforeSemicolon = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 78 /* SemicolonToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceBeforeColon = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 106 /* ColonToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 3 /* Delete */));
                    this.NoSpaceBeforeQMark = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 105 /* QuestionToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 3 /* Delete */));
                    this.SpaceAfterColon = new Formatting.Rule(Formatting.RuleDescriptor.create3(106 /* ColonToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterQMark = new Formatting.Rule(Formatting.RuleDescriptor.create3(105 /* QuestionToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterSemicolon = new Formatting.Rule(Formatting.RuleDescriptor.create3(78 /* SemicolonToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));

                    // Space after }.
                    this.SpaceAfterCloseBrace = new Formatting.Rule(Formatting.RuleDescriptor.create3(71 /* CloseBraceToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsAfterCodeBlockContext), 1 /* Space */));

                    // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied
                    this.SpaceBetweenCloseBraceAndElse = new Formatting.Rule(Formatting.RuleDescriptor.create1(71 /* CloseBraceToken */, 23 /* ElseKeyword */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));
                    this.SpaceBetweenCloseBraceAndWhile = new Formatting.Rule(Formatting.RuleDescriptor.create1(71 /* CloseBraceToken */, 42 /* WhileKeyword */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));
                    this.NoSpaceAfterCloseBrace = new Formatting.Rule(Formatting.RuleDescriptor.create3(71 /* CloseBraceToken */, Formatting.Shared.TokenRange.FromTokens([73 /* CloseParenToken */, 75 /* CloseBracketToken */, 79 /* CommaToken */, 78 /* SemicolonToken */])), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    // No space for indexer and dot
                    this.NoSpaceBeforeDot = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 76 /* DotToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceAfterDot = new Formatting.Rule(Formatting.RuleDescriptor.create3(76 /* DotToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceBeforeOpenBracket = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 74 /* OpenBracketToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceAfterOpenBracket = new Formatting.Rule(Formatting.RuleDescriptor.create3(74 /* OpenBracketToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceBeforeCloseBracket = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 75 /* CloseBracketToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceAfterCloseBracket = new Formatting.Rule(Formatting.RuleDescriptor.create3(75 /* CloseBracketToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    // Place a space before open brace in a function declaration
                    this.FunctionOpenBraceLeftTokenRange = Formatting.Shared.TokenRange.AnyIncludingMultilineComments;
                    this.SpaceBeforeOpenBraceInFunction = new Formatting.Rule(Formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 70 /* OpenBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 1 /* Space */), 1 /* CanDeleteNewLines */);

                    // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc)
                    this.TypeScriptOpenBraceLeftTokenRange = Formatting.Shared.TokenRange.FromTokens([11 /* IdentifierName */, 6 /* MultiLineCommentTrivia */]);
                    this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new Formatting.Rule(Formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 70 /* OpenBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 1 /* Space */), 1 /* CanDeleteNewLines */);

                    // Place a space before open brace in a control flow construct
                    this.ControlOpenBraceLeftTokenRange = Formatting.Shared.TokenRange.FromTokens([73 /* CloseParenToken */, 6 /* MultiLineCommentTrivia */, 22 /* DoKeyword */, 38 /* TryKeyword */, 25 /* FinallyKeyword */, 23 /* ElseKeyword */]);
                    this.SpaceBeforeOpenBraceInControl = new Formatting.Rule(Formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 70 /* OpenBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 1 /* Space */), 1 /* CanDeleteNewLines */);

                    // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
                    this.SpaceAfterOpenBrace = new Formatting.Rule(Formatting.RuleDescriptor.create3(70 /* OpenBraceToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 1 /* Space */));
                    this.SpaceBeforeCloseBrace = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 71 /* CloseBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 1 /* Space */));
                    this.NoSpaceBetweenEmptyBraceBrackets = new Formatting.Rule(Formatting.RuleDescriptor.create1(70 /* OpenBraceToken */, 71 /* CloseBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectContext), 3 /* Delete */));

                    // Insert new line after { and before } in multi-line contexts.
                    this.NewLineAfterOpenBraceInBlockContext = new Formatting.Rule(Formatting.RuleDescriptor.create3(70 /* OpenBraceToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 2 /* NewLine */));

                    // For functions and control block place } on a new line    [multi-line rule]
                    this.NewLineBeforeCloseBraceInBlockContext = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.AnyIncludingMultilineComments, 71 /* CloseBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 2 /* NewLine */));

                    // Special handling of unary operators.
                    // Prefix operators generally shouldn't have a space between
                    // them and their target unary expression.
                    this.NoSpaceAfterUnaryPrefixOperator = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.UnaryPrefixOperators, Formatting.Shared.TokenRange.UnaryPrefixExpressions), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 3 /* Delete */));
                    this.NoSpaceAfterUnaryPreincrementOperator = new Formatting.Rule(Formatting.RuleDescriptor.create3(93 /* PlusPlusToken */, Formatting.Shared.TokenRange.UnaryPreincrementExpressions), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceAfterUnaryPredecrementOperator = new Formatting.Rule(Formatting.RuleDescriptor.create3(94 /* MinusMinusToken */, Formatting.Shared.TokenRange.UnaryPredecrementExpressions), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceBeforeUnaryPostincrementOperator = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.UnaryPostincrementExpressions, 93 /* PlusPlusToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceBeforeUnaryPostdecrementOperator = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.UnaryPostdecrementExpressions, 94 /* MinusMinusToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    // More unary operator special-casing.
                    // DevDiv 181814:  Be careful when removing leading whitespace
                    // around unary operators.  Examples:
                    //      1 - -2  --X-->  1--2
                    //      a + ++b --X-->  a+++b
                    this.SpaceAfterPostincrementWhenFollowedByAdd = new Formatting.Rule(Formatting.RuleDescriptor.create1(93 /* PlusPlusToken */, 89 /* PlusToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterAddWhenFollowedByUnaryPlus = new Formatting.Rule(Formatting.RuleDescriptor.create1(89 /* PlusToken */, 89 /* PlusToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterAddWhenFollowedByPreincrement = new Formatting.Rule(Formatting.RuleDescriptor.create1(89 /* PlusToken */, 93 /* PlusPlusToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterPostdecrementWhenFollowedBySubtract = new Formatting.Rule(Formatting.RuleDescriptor.create1(94 /* MinusMinusToken */, 90 /* MinusToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new Formatting.Rule(Formatting.RuleDescriptor.create1(90 /* MinusToken */, 90 /* MinusToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterSubtractWhenFollowedByPredecrement = new Formatting.Rule(Formatting.RuleDescriptor.create1(90 /* MinusToken */, 94 /* MinusMinusToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));

                    this.NoSpaceBeforeComma = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 79 /* CommaToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    this.SpaceAfterCertainKeywords = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.FromTokens([40 /* VarKeyword */, 36 /* ThrowKeyword */, 31 /* NewKeyword */, 21 /* DeleteKeyword */, 33 /* ReturnKeyword */, 39 /* TypeOfKeyword */]), Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));
                    this.NoSpaceBeforeOpenParenInFuncCall = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 72 /* OpenParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionCallOrNewContext), 3 /* Delete */));
                    this.SpaceAfterFunctionInFuncDecl = new Formatting.Rule(Formatting.RuleDescriptor.create3(27 /* FunctionKeyword */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 1 /* Space */));
                    this.NoSpaceBeforeOpenParenInFuncDecl = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 72 /* OpenParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionDeclContext), 3 /* Delete */));
                    this.SpaceAfterVoidOperator = new Formatting.Rule(Formatting.RuleDescriptor.create3(41 /* VoidKeyword */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsVoidOpContext), 1 /* Space */));

                    this.NoSpaceBetweenReturnAndSemicolon = new Formatting.Rule(Formatting.RuleDescriptor.create1(33 /* ReturnKeyword */, 78 /* SemicolonToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    // Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
                    // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
                    this.SpaceBetweenStatements = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.FromTokens([73 /* CloseParenToken */, 22 /* DoKeyword */, 23 /* ElseKeyword */, 16 /* CaseKeyword */]), Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotForContext), 1 /* Space */));

                    // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter.
                    this.SpaceAfterTryFinally = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.FromTokens([38 /* TryKeyword */, 25 /* FinallyKeyword */]), 70 /* OpenBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));

                    //      get x() {}
                    //      set x(val) {}
                    this.SpaceAfterGetSetInMember = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.FromTokens([64 /* GetKeyword */, 68 /* SetKeyword */]), 11 /* IdentifierName */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 1 /* Space */));

                    // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options.
                    this.SpaceBeforeBinaryKeywordOperator = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.Any, Formatting.Shared.TokenRange.BinaryKeywordOperators), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterBinaryKeywordOperator = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.BinaryKeywordOperators, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));

                    // TypeScript-specific higher priority rules
                    // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses
                    this.NoSpaceAfterConstructor = new Formatting.Rule(Formatting.RuleDescriptor.create1(62 /* ConstructorKeyword */, 72 /* OpenParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    // Use of module as a function call. e.g.: import m2 = module("m2");
                    this.NoSpaceAfterModuleImport = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.FromTokens([65 /* ModuleKeyword */, 66 /* RequireKeyword */]), 72 /* OpenParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    // Add a space around certain TypeScript keywords
                    this.SpaceAfterCertainTypeScriptKeywords = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.FromTokens([44 /* ClassKeyword */, 63 /* DeclareKeyword */, 46 /* EnumKeyword */, 47 /* ExportKeyword */, 48 /* ExtendsKeyword */, 64 /* GetKeyword */, 51 /* ImplementsKeyword */, 49 /* ImportKeyword */, 52 /* InterfaceKeyword */, 65 /* ModuleKeyword */, 55 /* PrivateKeyword */, 57 /* PublicKeyword */, 68 /* SetKeyword */, 58 /* StaticKeyword */]), Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));
                    this.SpaceBeforeCertainTypeScriptKeywords = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.Any, Formatting.Shared.TokenRange.FromTokens([48 /* ExtendsKeyword */, 51 /* ImplementsKeyword */])), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));

                    // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" {
                    this.SpaceAfterModuleName = new Formatting.Rule(Formatting.RuleDescriptor.create1(14 /* StringLiteral */, 70 /* OpenBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsModuleDeclContext), 1 /* Space */));

                    // Lambda expressions
                    this.SpaceAfterArrow = new Formatting.Rule(Formatting.RuleDescriptor.create3(85 /* EqualsGreaterThanToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));

                    // Optional parameters and var args
                    this.NoSpaceAfterEllipsis = new Formatting.Rule(Formatting.RuleDescriptor.create1(77 /* DotDotDotToken */, 11 /* IdentifierName */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceAfterOptionalParameters = new Formatting.Rule(Formatting.RuleDescriptor.create3(105 /* QuestionToken */, Formatting.Shared.TokenRange.FromTokens([73 /* CloseParenToken */, 79 /* CommaToken */])), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 3 /* Delete */));

                    // generics
                    this.NoSpaceBeforeOpenAngularBracket = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.TypeNames, 80 /* LessThanToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 3 /* Delete */));
                    this.NoSpaceBetweenCloseParenAndAngularBracket = new Formatting.Rule(Formatting.RuleDescriptor.create1(73 /* CloseParenToken */, 80 /* LessThanToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 3 /* Delete */));
                    this.NoSpaceAfterOpenAngularBracket = new Formatting.Rule(Formatting.RuleDescriptor.create3(80 /* LessThanToken */, Formatting.Shared.TokenRange.TypeNames), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 3 /* Delete */));
                    this.NoSpaceBeforeCloseAngularBracket = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 81 /* GreaterThanToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 3 /* Delete */));
                    this.NoSpaceAfterCloseAngularBracket = new Formatting.Rule(Formatting.RuleDescriptor.create3(81 /* GreaterThanToken */, Formatting.Shared.TokenRange.FromTokens([72 /* OpenParenToken */, 74 /* OpenBracketToken */, 81 /* GreaterThanToken */, 79 /* CommaToken */])), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 3 /* Delete */));

                    // Remove spaces in empty interface literals. e.g.: x: {}
                    this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new Formatting.Rule(Formatting.RuleDescriptor.create1(70 /* OpenBraceToken */, 71 /* CloseBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectTypeContext), 3 /* Delete */));

                    // These rules are higher in priority than user-configurable rules.
                    this.HighPriorityCommonRules = [
                        this.IgnoreBeforeComment, this.IgnoreAfterLineComment,
                        this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQMark, this.SpaceAfterQMark,
                        this.NoSpaceBeforeDot, this.NoSpaceAfterDot,
                        this.NoSpaceAfterUnaryPrefixOperator,
                        this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator,
                        this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator,
                        this.SpaceAfterPostincrementWhenFollowedByAdd,
                        this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement,
                        this.SpaceAfterPostdecrementWhenFollowedBySubtract,
                        this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement,
                        this.NoSpaceAfterCloseBrace,
                        this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NewLineBeforeCloseBraceInBlockContext,
                        this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets,
                        this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember,
                        this.NoSpaceBetweenReturnAndSemicolon,
                        this.SpaceAfterCertainKeywords,
                        this.NoSpaceBeforeOpenParenInFuncCall,
                        this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator,
                        this.SpaceAfterVoidOperator,
                        this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport,
                        this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords,
                        this.SpaceAfterModuleName,
                        this.SpaceAfterArrow,
                        this.NoSpaceAfterEllipsis,
                        this.NoSpaceAfterOptionalParameters,
                        this.NoSpaceBetweenEmptyInterfaceBraceBrackets,
                        this.NoSpaceBeforeOpenAngularBracket,
                        this.NoSpaceBetweenCloseParenAndAngularBracket,
                        this.NoSpaceAfterOpenAngularBracket,
                        this.NoSpaceBeforeCloseAngularBracket,
                        this.NoSpaceAfterCloseAngularBracket
                    ];

                    // These rules are lower in priority than user-configurable rules.
                    this.LowPriorityCommonRules = [
                        this.NoSpaceBeforeSemicolon,
                        this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock,
                        this.NoSpaceBeforeComma,
                        this.NoSpaceBeforeOpenBracket, this.NoSpaceAfterOpenBracket,
                        this.NoSpaceBeforeCloseBracket, this.NoSpaceAfterCloseBracket,
                        this.SpaceAfterSemicolon,
                        this.NoSpaceBeforeOpenParenInFuncDecl,
                        this.SpaceBetweenStatements, this.SpaceAfterTryFinally
                    ];

                    ///
                    /// Rules controlled by user options
                    ///
                    // Insert space after comma delimiter
                    this.SpaceAfterComma = new Formatting.Rule(Formatting.RuleDescriptor.create3(79 /* CommaToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));
                    this.NoSpaceAfterComma = new Formatting.Rule(Formatting.RuleDescriptor.create3(79 /* CommaToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    // Insert space before and after binary operators
                    this.SpaceBeforeBinaryOperator = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.Any, Formatting.Shared.TokenRange.BinaryOperators), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));
                    this.SpaceAfterBinaryOperator = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.BinaryOperators, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 1 /* Space */));
                    this.NoSpaceBeforeBinaryOperator = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.Any, Formatting.Shared.TokenRange.BinaryOperators), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 3 /* Delete */));
                    this.NoSpaceAfterBinaryOperator = new Formatting.Rule(Formatting.RuleDescriptor.create4(Formatting.Shared.TokenRange.BinaryOperators, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 3 /* Delete */));

                    // Insert space after keywords in control flow statements
                    this.SpaceAfterKeywordInControl = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Keywords, 72 /* OpenParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsControlDeclContext), 1 /* Space */));
                    this.NoSpaceAfterKeywordInControl = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Keywords, 72 /* OpenParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsControlDeclContext), 3 /* Delete */));

                    // Open Brace braces after function
                    //TypeScript: Function can have return types, which can be made of tons of different token kinds
                    this.NewLineBeforeOpenBraceInFunction = new Formatting.Rule(Formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 70 /* OpenBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), 2 /* NewLine */), 1 /* CanDeleteNewLines */);

                    // Open Brace braces after TypeScript module/class/interface
                    this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new Formatting.Rule(Formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 70 /* OpenBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), 2 /* NewLine */), 1 /* CanDeleteNewLines */);

                    // Open Brace braces after control block
                    this.NewLineBeforeOpenBraceInControl = new Formatting.Rule(Formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 70 /* OpenBraceToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), 2 /* NewLine */), 1 /* CanDeleteNewLines */);

                    // Insert space after semicolon in for statement
                    this.SpaceAfterSemicolonInFor = new Formatting.Rule(Formatting.RuleDescriptor.create3(78 /* SemicolonToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), 1 /* Space */));
                    this.NoSpaceAfterSemicolonInFor = new Formatting.Rule(Formatting.RuleDescriptor.create3(78 /* SemicolonToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), 3 /* Delete */));

                    // Insert space after opening and before closing nonempty parenthesis
                    this.SpaceAfterOpenParen = new Formatting.Rule(Formatting.RuleDescriptor.create3(72 /* OpenParenToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));
                    this.SpaceBeforeCloseParen = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 73 /* CloseParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 1 /* Space */));
                    this.NoSpaceBetweenParens = new Formatting.Rule(Formatting.RuleDescriptor.create1(72 /* OpenParenToken */, 73 /* CloseParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceAfterOpenParen = new Formatting.Rule(Formatting.RuleDescriptor.create3(72 /* OpenParenToken */, Formatting.Shared.TokenRange.Any), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));
                    this.NoSpaceBeforeCloseParen = new Formatting.Rule(Formatting.RuleDescriptor.create2(Formatting.Shared.TokenRange.Any, 73 /* CloseParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 3 /* Delete */));

                    // Insert space after function keyword for anonymous functions
                    this.SpaceAfterAnonymousFunctionKeyword = new Formatting.Rule(Formatting.RuleDescriptor.create1(27 /* FunctionKeyword */, 72 /* OpenParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 1 /* Space */));
                    this.NoSpaceAfterAnonymousFunctionKeyword = new Formatting.Rule(Formatting.RuleDescriptor.create1(27 /* FunctionKeyword */, 72 /* OpenParenToken */), Formatting.RuleOperation.create2(new Formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 3 /* Delete */));
                }
                Rules.prototype.getRuleName = function (rule) {
                    var o = this;
                    for (var name in o) {
                        if (o[name] === rule) {
                            return name;
                        }
                    }
                    throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Unknown_rule, null));
                };

                ///
                /// Contexts
                ///
                Rules.IsForContext = function (context) {
                    return context.contextNode.kind() === 154 /* ForStatement */;
                };

                Rules.IsNotForContext = function (context) {
                    return !Rules.IsForContext(context);
                };

                Rules.IsBinaryOpContext = function (context) {
                    switch (context.contextNode.kind()) {
                        case 174 /* AssignmentExpression */:
                        case 175 /* AddAssignmentExpression */:
                        case 176 /* SubtractAssignmentExpression */:
                        case 177 /* MultiplyAssignmentExpression */:
                        case 178 /* DivideAssignmentExpression */:
                        case 179 /* ModuloAssignmentExpression */:
                        case 180 /* AndAssignmentExpression */:
                        case 181 /* ExclusiveOrAssignmentExpression */:
                        case 182 /* OrAssignmentExpression */:
                        case 183 /* LeftShiftAssignmentExpression */:
                        case 184 /* SignedRightShiftAssignmentExpression */:
                        case 185 /* UnsignedRightShiftAssignmentExpression */:
                        case 186 /* ConditionalExpression */:
                        case 187 /* LogicalOrExpression */:
                        case 188 /* LogicalAndExpression */:
                        case 189 /* BitwiseOrExpression */:
                        case 190 /* BitwiseExclusiveOrExpression */:
                        case 191 /* BitwiseAndExpression */:
                        case 192 /* EqualsWithTypeConversionExpression */:
                        case 193 /* NotEqualsWithTypeConversionExpression */:
                        case 194 /* EqualsExpression */:
                        case 195 /* NotEqualsExpression */:
                        case 196 /* LessThanExpression */:
                        case 197 /* GreaterThanExpression */:
                        case 198 /* LessThanOrEqualExpression */:
                        case 199 /* GreaterThanOrEqualExpression */:
                        case 200 /* InstanceOfExpression */:
                        case 201 /* InExpression */:
                        case 202 /* LeftShiftExpression */:
                        case 203 /* SignedRightShiftExpression */:
                        case 204 /* UnsignedRightShiftExpression */:
                        case 205 /* MultiplyExpression */:
                        case 206 /* DivideExpression */:
                        case 207 /* ModuloExpression */:
                        case 208 /* AddExpression */:
                        case 209 /* SubtractExpression */:
                            return true;

                        case 133 /* ImportDeclaration */:

                        case 225 /* VariableDeclarator */:
                        case 232 /* EqualsValueClause */:
                            return context.currentTokenSpan.kind === 107 /* EqualsToken */ || context.nextTokenSpan.kind === 107 /* EqualsToken */;

                        case 155 /* ForInStatement */:
                            return context.currentTokenSpan.kind === 29 /* InKeyword */ || context.nextTokenSpan.kind === 29 /* InKeyword */;
                    }
                    return false;
                };

                Rules.IsNotBinaryOpContext = function (context) {
                    return !Rules.IsBinaryOpContext(context);
                };

                Rules.IsSameLineTokenOrBeforeMultilineBlockContext = function (context) {
                    //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction.
                    ////
                    //// Ex:
                    //// if (1)     { ....
                    ////      * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context
                    ////
                    //// Ex:
                    //// if (1)
                    //// { ... }
                    ////      * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we don't format.
                    ////
                    //// Ex:
                    //// if (1)
                    //// { ...
                    //// }
                    ////      * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we format.
                    return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context);
                };

                // This check is done before an open brace in a control construct, a function, or a typescript block declaration
                Rules.IsBeforeMultilineBlockContext = function (context) {
                    return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine());
                };

                Rules.IsMultilineBlockContext = function (context) {
                    return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
                };

                Rules.IsSingleLineBlockContext = function (context) {
                    return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
                };

                Rules.IsBlockContext = function (context) {
                    return Rules.NodeIsBlockContext(context.contextNode);
                };

                Rules.IsBeforeBlockContext = function (context) {
                    return Rules.NodeIsBlockContext(context.nextTokenParent);
                };

                // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children
                Rules.NodeIsBlockContext = function (node) {
                    if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) {
                        // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc).
                        return true;
                    }

                    switch (node.kind()) {
                        case 146 /* Block */:
                        case 151 /* SwitchStatement */:
                        case 215 /* ObjectLiteralExpression */:
                            return true;
                    }

                    return false;
                };

                Rules.IsFunctionDeclContext = function (context) {
                    switch (context.contextNode.kind()) {
                        case 129 /* FunctionDeclaration */:
                        case 135 /* MemberFunctionDeclaration */:
                        case 139 /* GetAccessor */:
                        case 140 /* SetAccessor */:
                        case 145 /* MethodSignature */:
                        case 142 /* CallSignature */:
                        case 222 /* FunctionExpression */:
                        case 137 /* ConstructorDeclaration */:
                        case 219 /* SimpleArrowFunctionExpression */:
                        case 218 /* ParenthesizedArrowFunctionExpression */:
                        case 128 /* InterfaceDeclaration */:
                            return true;
                    }

                    return false;
                };

                Rules.IsTypeScriptDeclWithBlockContext = function (context) {
                    return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode);
                };

                Rules.NodeIsTypeScriptDeclWithBlockContext = function (node) {
                    switch (node.kind()) {
                        case 131 /* ClassDeclaration */:
                        case 132 /* EnumDeclaration */:
                        case 122 /* ObjectType */:
                        case 130 /* ModuleDeclaration */:
                            return true;
                    }

                    return false;
                };

                Rules.IsAfterCodeBlockContext = function (context) {
                    switch (context.currentTokenParent.kind()) {
                        case 131 /* ClassDeclaration */:
                        case 130 /* ModuleDeclaration */:
                        case 132 /* EnumDeclaration */:
                        case 146 /* Block */:
                        case 151 /* SwitchStatement */:
                            return true;
                    }
                    return false;
                };

                Rules.IsControlDeclContext = function (context) {
                    switch (context.contextNode.kind()) {
                        case 147 /* IfStatement */:
                        case 151 /* SwitchStatement */:
                        case 154 /* ForStatement */:
                        case 155 /* ForInStatement */:
                        case 158 /* WhileStatement */:
                        case 159 /* TryStatement */:
                        case 161 /* DoStatement */:
                        case 163 /* WithStatement */:
                        case 235 /* ElseClause */:
                        case 236 /* CatchClause */:
                        case 237 /* FinallyClause */:
                            return true;

                        default:
                            return false;
                    }
                };

                Rules.IsObjectContext = function (context) {
                    return context.contextNode.kind() === 215 /* ObjectLiteralExpression */;
                };

                Rules.IsFunctionCallContext = function (context) {
                    return context.contextNode.kind() === 213 /* InvocationExpression */;
                };

                Rules.IsNewContext = function (context) {
                    return context.contextNode.kind() === 216 /* ObjectCreationExpression */;
                };

                Rules.IsFunctionCallOrNewContext = function (context) {
                    return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context);
                };

                Rules.IsSameLineTokenContext = function (context) {
                    return context.TokensAreOnSameLine();
                };

                Rules.IsNotFormatOnEnter = function (context) {
                    return context.formattingRequestKind != 2 /* FormatOnEnter */;
                };

                Rules.IsModuleDeclContext = function (context) {
                    return context.contextNode.kind() === 130 /* ModuleDeclaration */;
                };

                Rules.IsObjectTypeContext = function (context) {
                    return context.contextNode.kind() === 122 /* ObjectType */ && context.contextNode.parent().kind() !== 128 /* InterfaceDeclaration */;
                };

                Rules.IsTypeArgumentOrParameter = function (tokenKind, parentKind) {
                    return ((tokenKind === 80 /* LessThanToken */ || tokenKind === 81 /* GreaterThanToken */) && (parentKind === 229 /* TypeParameterList */ || parentKind === 228 /* TypeArgumentList */));
                };

                Rules.IsTypeArgumentOrParameterContext = function (context) {
                    return Rules.IsTypeArgumentOrParameter(context.currentTokenSpan.kind, context.currentTokenParent.kind()) || Rules.IsTypeArgumentOrParameter(context.nextTokenSpan.kind, context.nextTokenParent.kind());
                };

                Rules.IsVoidOpContext = function (context) {
                    return context.currentTokenSpan.kind === 41 /* VoidKeyword */ && context.currentTokenParent.kind() === 172 /* VoidExpression */;
                };
                return Rules;
            })();
            Formatting.Rules = Rules;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var RulesMap = (function () {
                function RulesMap() {
                    this.map = [];
                    this.mapRowLength = 0;
                }
                RulesMap.create = function (rules) {
                    var result = new RulesMap();
                    result.Initialize(rules);
                    return result;
                };

                RulesMap.prototype.Initialize = function (rules) {
                    this.mapRowLength = TypeScript.SyntaxKind.LastToken + 1;
                    this.map = new Array(this.mapRowLength * this.mapRowLength); //new Array<RulesBucket>(this.mapRowLength * this.mapRowLength);

                    // This array is used only during construction of the rulesbucket in the map
                    var rulesBucketConstructionStateList = new Array(this.map.length);

                    this.FillRules(rules, rulesBucketConstructionStateList);
                    return this.map;
                };

                RulesMap.prototype.FillRules = function (rules, rulesBucketConstructionStateList) {
                    var _this = this;
                    rules.forEach(function (rule) {
                        _this.FillRule(rule, rulesBucketConstructionStateList);
                    });
                };

                RulesMap.prototype.GetRuleBucketIndex = function (row, column) {
                    var rulesBucketIndex = (row * this.mapRowLength) + column;

                    //Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array.");
                    return rulesBucketIndex;
                };

                RulesMap.prototype.FillRule = function (rule, rulesBucketConstructionStateList) {
                    var _this = this;
                    var specificRule = rule.Descriptor.LeftTokenRange != Formatting.Shared.TokenRange.Any && rule.Descriptor.RightTokenRange != Formatting.Shared.TokenRange.Any;

                    rule.Descriptor.LeftTokenRange.GetTokens().forEach(function (left) {
                        rule.Descriptor.RightTokenRange.GetTokens().forEach(function (right) {
                            var rulesBucketIndex = _this.GetRuleBucketIndex(left, right);

                            var rulesBucket = _this.map[rulesBucketIndex];
                            if (rulesBucket == undefined) {
                                rulesBucket = _this.map[rulesBucketIndex] = new RulesBucket();
                            }

                            rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex);
                        });
                    });
                };

                RulesMap.prototype.GetRule = function (context) {
                    var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind);
                    var bucket = this.map[bucketIndex];
                    if (bucket != null) {
                        for (var i = 0, len = bucket.Rules().length; i < len; i++) {
                            var rule = bucket.Rules()[i];
                            if (rule.Operation.Context.InContext(context))
                                return rule;
                        }
                    }
                    return null;
                };
                return RulesMap;
            })();
            Formatting.RulesMap = RulesMap;

            var MaskBitSize = 5;
            var Mask = 0x1f;

            (function (RulesPosition) {
                RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific";
                RulesPosition[RulesPosition["IgnoreRulesAny"] = MaskBitSize * 1] = "IgnoreRulesAny";
                RulesPosition[RulesPosition["ContextRulesSpecific"] = MaskBitSize * 2] = "ContextRulesSpecific";
                RulesPosition[RulesPosition["ContextRulesAny"] = MaskBitSize * 3] = "ContextRulesAny";
                RulesPosition[RulesPosition["NoContextRulesSpecific"] = MaskBitSize * 4] = "NoContextRulesSpecific";
                RulesPosition[RulesPosition["NoContextRulesAny"] = MaskBitSize * 5] = "NoContextRulesAny";
            })(Formatting.RulesPosition || (Formatting.RulesPosition = {}));
            var RulesPosition = Formatting.RulesPosition;

            var RulesBucketConstructionState = (function () {
                function RulesBucketConstructionState() {
                    //// The Rules list contains all the inserted rules into a rulebucket in the following order:
                    ////    1- Ignore rules with specific token combination
                    ////    2- Ignore rules with any token combination
                    ////    3- Context rules with specific token combination
                    ////    4- Context rules with any token combination
                    ////    5- Non-context rules with specific token combination
                    ////    6- Non-context rules with any token combination
                    ////
                    //// The member rulesInsertionIndexBitmap is used to describe the number of rules
                    //// in each sub-bucket (above) hence can be used to know the index of where to insert
                    //// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits.
                    ////
                    //// Example:
                    //// In order to insert a rule to the end of sub-bucket (3), we get the index by adding
                    //// the values in the bitmap segments 3rd, 2nd, and 1st.
                    this.rulesInsertionIndexBitmap = 0;
                }
                RulesBucketConstructionState.prototype.GetInsertionIndex = function (maskPosition) {
                    var index = 0;

                    var pos = 0;
                    var indexBitmap = this.rulesInsertionIndexBitmap;

                    while (pos <= maskPosition) {
                        index += (indexBitmap & Mask);
                        indexBitmap >>= MaskBitSize;
                        pos += MaskBitSize;
                    }

                    return index;
                };

                RulesBucketConstructionState.prototype.IncreaseInsertionIndex = function (maskPosition) {
                    var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask;
                    value++;
                    TypeScript.Debug.assert((value & Mask) == value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");

                    var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition);
                    temp |= value << maskPosition;

                    this.rulesInsertionIndexBitmap = temp;
                };
                return RulesBucketConstructionState;
            })();
            Formatting.RulesBucketConstructionState = RulesBucketConstructionState;

            var RulesBucket = (function () {
                function RulesBucket() {
                    this.rules = [];
                }
                RulesBucket.prototype.Rules = function () {
                    return this.rules;
                };

                RulesBucket.prototype.AddRule = function (rule, specificTokens, constructionState, rulesBucketIndex) {
                    var position;

                    if (rule.Operation.Action == 0 /* Ignore */) {
                        position = specificTokens ? 0 /* IgnoreRulesSpecific */ : RulesPosition.IgnoreRulesAny;
                    } else if (!rule.Operation.Context.IsAny()) {
                        position = specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny;
                    } else {
                        position = specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny;
                    }

                    var state = constructionState[rulesBucketIndex];
                    if (state === undefined) {
                        state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState();
                    }
                    var index = state.GetInsertionIndex(position);
                    this.rules.splice(index, 0, rule);
                    state.IncreaseInsertionIndex(position);
                };
                return RulesBucket;
            })();
            Formatting.RulesBucket = RulesBucket;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        /// <reference path="formatting.ts"/>
        (function (Formatting) {
            var RulesProvider = (function () {
                function RulesProvider(logger) {
                    this.logger = logger;
                    this.globalRules = new Formatting.Rules();
                }
                RulesProvider.prototype.getRuleName = function (rule) {
                    return this.globalRules.getRuleName(rule);
                };

                RulesProvider.prototype.getRuleByName = function (name) {
                    return this.globalRules[name];
                };

                RulesProvider.prototype.getRulesMap = function () {
                    return this.rulesMap;
                };

                RulesProvider.prototype.ensureUpToDate = function (options) {
                    var _this = this;
                    if (this.options == null || !TypeScript.compareDataObjects(this.options, options)) {
                        var activeRules = TypeScript.timeFunction(this.logger, "RulesProvider: createActiveRules()", function () {
                            return _this.createActiveRules(options);
                        });
                        var rulesMap = TypeScript.timeFunction(this.logger, "RulesProvider: RulesMap.create()", function () {
                            return Formatting.RulesMap.create(activeRules);
                        });

                        this.activeRules = activeRules;
                        this.rulesMap = rulesMap;
                        this.options = TypeScript.Services.FormatCodeOptions.clone(options);
                    }
                };

                RulesProvider.prototype.createActiveRules = function (options) {
                    var rules = this.globalRules.HighPriorityCommonRules.slice(0);

                    if (options.InsertSpaceAfterCommaDelimiter) {
                        rules.push(this.globalRules.SpaceAfterComma);
                    } else {
                        rules.push(this.globalRules.NoSpaceAfterComma);
                    }

                    if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) {
                        rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword);
                    } else {
                        rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword);
                    }

                    if (options.InsertSpaceAfterKeywordsInControlFlowStatements) {
                        rules.push(this.globalRules.SpaceAfterKeywordInControl);
                    } else {
                        rules.push(this.globalRules.NoSpaceAfterKeywordInControl);
                    }

                    if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
                        rules.push(this.globalRules.SpaceAfterOpenParen);
                        rules.push(this.globalRules.SpaceBeforeCloseParen);
                        rules.push(this.globalRules.NoSpaceBetweenParens);
                    } else {
                        rules.push(this.globalRules.NoSpaceAfterOpenParen);
                        rules.push(this.globalRules.NoSpaceBeforeCloseParen);
                        rules.push(this.globalRules.NoSpaceBetweenParens);
                    }

                    if (options.InsertSpaceAfterSemicolonInForStatements) {
                        rules.push(this.globalRules.SpaceAfterSemicolonInFor);
                    } else {
                        rules.push(this.globalRules.NoSpaceAfterSemicolonInFor);
                    }

                    if (options.InsertSpaceBeforeAndAfterBinaryOperators) {
                        rules.push(this.globalRules.SpaceBeforeBinaryOperator);
                        rules.push(this.globalRules.SpaceAfterBinaryOperator);
                    } else {
                        rules.push(this.globalRules.NoSpaceBeforeBinaryOperator);
                        rules.push(this.globalRules.NoSpaceAfterBinaryOperator);
                    }

                    if (options.PlaceOpenBraceOnNewLineForControlBlocks) {
                        rules.push(this.globalRules.NewLineBeforeOpenBraceInControl);
                    }

                    if (options.PlaceOpenBraceOnNewLineForFunctions) {
                        rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction);
                        rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock);
                    }

                    rules = rules.concat(this.globalRules.LowPriorityCommonRules);

                    return rules;
                };
                return RulesProvider;
            })();
            Formatting.RulesProvider = RulesProvider;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var TextEditInfo = (function () {
                function TextEditInfo(position, length, replaceWith) {
                    this.position = position;
                    this.length = length;
                    this.replaceWith = replaceWith;
                }
                TextEditInfo.prototype.toString = function () {
                    return "[ position: " + this.position + ", length: " + this.length + ", replaceWith: '" + this.replaceWith + "' ]";
                };
                return TextEditInfo;
            })();
            Formatting.TextEditInfo = TextEditInfo;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            (function (Shared) {
                var TokenRangeAccess = (function () {
                    function TokenRangeAccess(from, to, except) {
                        this.tokens = [];
                        for (var token = from; token <= to; token++) {
                            if (except.indexOf(token) < 0) {
                                this.tokens.push(token);
                            }
                        }
                    }
                    TokenRangeAccess.prototype.GetTokens = function () {
                        return this.tokens;
                    };

                    TokenRangeAccess.prototype.Contains = function (token) {
                        return this.tokens.indexOf(token) >= 0;
                    };

                    TokenRangeAccess.prototype.toString = function () {
                        return "[tokenRangeStart=" + TypeScript.SyntaxKind[this.tokens[0]] + "," + "tokenRangeEnd=" + TypeScript.SyntaxKind[this.tokens[this.tokens.length - 1]] + "]";
                    };
                    return TokenRangeAccess;
                })();
                Shared.TokenRangeAccess = TokenRangeAccess;

                var TokenValuesAccess = (function () {
                    function TokenValuesAccess(tks) {
                        this.tokens = tks && tks.length ? tks : [];
                    }
                    TokenValuesAccess.prototype.GetTokens = function () {
                        return this.tokens;
                    };

                    TokenValuesAccess.prototype.Contains = function (token) {
                        return this.tokens.indexOf(token) >= 0;
                    };
                    return TokenValuesAccess;
                })();
                Shared.TokenValuesAccess = TokenValuesAccess;

                var TokenSingleValueAccess = (function () {
                    function TokenSingleValueAccess(token) {
                        this.token = token;
                    }
                    TokenSingleValueAccess.prototype.GetTokens = function () {
                        return [this.token];
                    };

                    TokenSingleValueAccess.prototype.Contains = function (tokenValue) {
                        return tokenValue == this.token;
                    };

                    TokenSingleValueAccess.prototype.toString = function () {
                        return "[singleTokenKind=" + TypeScript.SyntaxKind[this.token] + "]";
                    };
                    return TokenSingleValueAccess;
                })();
                Shared.TokenSingleValueAccess = TokenSingleValueAccess;

                var TokenAllAccess = (function () {
                    function TokenAllAccess() {
                    }
                    TokenAllAccess.prototype.GetTokens = function () {
                        var result = [];
                        for (var token = TypeScript.SyntaxKind.FirstToken; token <= TypeScript.SyntaxKind.LastToken; token++) {
                            result.push(token);
                        }
                        return result;
                    };

                    TokenAllAccess.prototype.Contains = function (tokenValue) {
                        return true;
                    };

                    TokenAllAccess.prototype.toString = function () {
                        return "[allTokens]";
                    };
                    return TokenAllAccess;
                })();
                Shared.TokenAllAccess = TokenAllAccess;

                var TokenRange = (function () {
                    function TokenRange(tokenAccess) {
                        this.tokenAccess = tokenAccess;
                    }
                    TokenRange.FromToken = function (token) {
                        return new TokenRange(new TokenSingleValueAccess(token));
                    };

                    TokenRange.FromTokens = function (tokens) {
                        return new TokenRange(new TokenValuesAccess(tokens));
                    };

                    TokenRange.FromRange = function (f, to, except) {
                        if (typeof except === "undefined") { except = []; }
                        return new TokenRange(new TokenRangeAccess(f, to, except));
                    };

                    TokenRange.AllTokens = function () {
                        return new TokenRange(new TokenAllAccess());
                    };

                    TokenRange.prototype.GetTokens = function () {
                        return this.tokenAccess.GetTokens();
                    };

                    TokenRange.prototype.Contains = function (token) {
                        return this.tokenAccess.Contains(token);
                    };

                    TokenRange.prototype.toString = function () {
                        return this.tokenAccess.toString();
                    };

                    TokenRange.Any = TokenRange.AllTokens();
                    TokenRange.AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([6 /* MultiLineCommentTrivia */]));
                    TokenRange.Keywords = TokenRange.FromRange(TypeScript.SyntaxKind.FirstKeyword, TypeScript.SyntaxKind.LastKeyword);
                    TokenRange.Operators = TokenRange.FromRange(78 /* SemicolonToken */, 119 /* SlashEqualsToken */);
                    TokenRange.BinaryOperators = TokenRange.FromRange(80 /* LessThanToken */, 119 /* SlashEqualsToken */);
                    TokenRange.BinaryKeywordOperators = TokenRange.FromTokens([29 /* InKeyword */, 30 /* InstanceOfKeyword */]);
                    TokenRange.ReservedKeywords = TokenRange.FromRange(TypeScript.SyntaxKind.FirstFutureReservedStrictKeyword, TypeScript.SyntaxKind.LastFutureReservedStrictKeyword);
                    TokenRange.UnaryPrefixOperators = TokenRange.FromTokens([93 /* PlusPlusToken */, 94 /* MinusMinusToken */, 102 /* TildeToken */, 101 /* ExclamationToken */]);
                    TokenRange.UnaryPrefixExpressions = TokenRange.FromTokens([13 /* NumericLiteral */, 11 /* IdentifierName */, 72 /* OpenParenToken */, 74 /* OpenBracketToken */, 70 /* OpenBraceToken */, 35 /* ThisKeyword */, 31 /* NewKeyword */]);
                    TokenRange.UnaryPreincrementExpressions = TokenRange.FromTokens([11 /* IdentifierName */, 72 /* OpenParenToken */, 35 /* ThisKeyword */, 31 /* NewKeyword */]);
                    TokenRange.UnaryPostincrementExpressions = TokenRange.FromTokens([11 /* IdentifierName */, 73 /* CloseParenToken */, 75 /* CloseBracketToken */, 31 /* NewKeyword */]);
                    TokenRange.UnaryPredecrementExpressions = TokenRange.FromTokens([11 /* IdentifierName */, 72 /* OpenParenToken */, 35 /* ThisKeyword */, 31 /* NewKeyword */]);
                    TokenRange.UnaryPostdecrementExpressions = TokenRange.FromTokens([11 /* IdentifierName */, 73 /* CloseParenToken */, 75 /* CloseBracketToken */, 31 /* NewKeyword */]);
                    TokenRange.Comments = TokenRange.FromTokens([7 /* SingleLineCommentTrivia */, 6 /* MultiLineCommentTrivia */]);
                    TokenRange.TypeNames = TokenRange.FromTokens([11 /* IdentifierName */, 67 /* NumberKeyword */, 69 /* StringKeyword */, 61 /* BooleanKeyword */, 41 /* VoidKeyword */, 60 /* AnyKeyword */]);
                    return TokenRange;
                })();
                Shared.TokenRange = TokenRange;
            })(Formatting.Shared || (Formatting.Shared = {}));
            var Shared = Formatting.Shared;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var TokenSpan = (function (_super) {
                __extends(TokenSpan, _super);
                function TokenSpan(kind, start, length) {
                    _super.call(this, start, length);
                    this.kind = kind;
                }
                return TokenSpan;
            })(TypeScript.TextSpan);
            Formatting.TokenSpan = TokenSpan;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var IndentationNodeContext = (function () {
                function IndentationNodeContext(parent, node, fullStart, indentationAmount, childIndentationAmountDelta) {
                    this.update(parent, node, fullStart, indentationAmount, childIndentationAmountDelta);
                }
                IndentationNodeContext.prototype.parent = function () {
                    return this._parent;
                };

                IndentationNodeContext.prototype.node = function () {
                    return this._node;
                };

                IndentationNodeContext.prototype.fullStart = function () {
                    return this._fullStart;
                };

                IndentationNodeContext.prototype.fullWidth = function () {
                    return TypeScript.fullWidth(this._node);
                };

                IndentationNodeContext.prototype.start = function () {
                    return this._fullStart + TypeScript.leadingTriviaWidth(this._node);
                };

                IndentationNodeContext.prototype.end = function () {
                    return this._fullStart + TypeScript.leadingTriviaWidth(this._node) + TypeScript.width(this._node);
                };

                IndentationNodeContext.prototype.indentationAmount = function () {
                    return this._indentationAmount;
                };

                IndentationNodeContext.prototype.childIndentationAmountDelta = function () {
                    return this._childIndentationAmountDelta;
                };

                IndentationNodeContext.prototype.depth = function () {
                    return this._depth;
                };

                IndentationNodeContext.prototype.kind = function () {
                    return this._node.kind();
                };

                IndentationNodeContext.prototype.hasSkippedOrMissingTokenChild = function () {
                    if (this._hasSkippedOrMissingTokenChild === null) {
                        this._hasSkippedOrMissingTokenChild = TypeScript.Syntax.nodeHasSkippedOrMissingTokens(this._node);
                    }
                    return this._hasSkippedOrMissingTokenChild;
                };

                IndentationNodeContext.prototype.clone = function (pool) {
                    var parent = null;
                    if (this._parent) {
                        parent = this._parent.clone(pool);
                    }
                    return pool.getNode(parent, this._node, this._fullStart, this._indentationAmount, this._childIndentationAmountDelta);
                };

                IndentationNodeContext.prototype.update = function (parent, node, fullStart, indentationAmount, childIndentationAmountDelta) {
                    this._parent = parent;
                    this._node = node;
                    this._fullStart = fullStart;
                    this._indentationAmount = indentationAmount;
                    this._childIndentationAmountDelta = childIndentationAmountDelta;
                    this._hasSkippedOrMissingTokenChild = null;

                    if (parent) {
                        this._depth = parent.depth() + 1;
                    } else {
                        this._depth = 0;
                    }
                };
                return IndentationNodeContext;
            })();
            Formatting.IndentationNodeContext = IndentationNodeContext;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var IndentationNodeContextPool = (function () {
                function IndentationNodeContextPool() {
                    this.nodes = [];
                }
                IndentationNodeContextPool.prototype.getNode = function (parent, node, fullStart, indentationLevel, childIndentationLevelDelta) {
                    if (this.nodes.length > 0) {
                        var cachedNode = this.nodes.pop();
                        cachedNode.update(parent, node, fullStart, indentationLevel, childIndentationLevelDelta);
                        return cachedNode;
                    }

                    return new Formatting.IndentationNodeContext(parent, node, fullStart, indentationLevel, childIndentationLevelDelta);
                };

                IndentationNodeContextPool.prototype.releaseNode = function (node, recursive) {
                    if (typeof recursive === "undefined") { recursive = false; }
                    this.nodes.push(node);

                    if (recursive) {
                        var parent = node.parent();
                        if (parent) {
                            this.releaseNode(parent, recursive);
                        }
                    }
                };
                return IndentationNodeContextPool;
            })();
            Formatting.IndentationNodeContextPool = IndentationNodeContextPool;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var IndentationTrackingWalker = (function (_super) {
                __extends(IndentationTrackingWalker, _super);
                function IndentationTrackingWalker(textSpan, sourceUnit, snapshot, indentFirstToken, options) {
                    _super.call(this);
                    this.options = options;
                    this._position = 0;
                    this._parent = null;

                    // Create a pool object to manage context nodes while walking the tree
                    this._indentationNodeContextPool = new Formatting.IndentationNodeContextPool();

                    this._textSpan = textSpan;
                    this._text = sourceUnit.syntaxTree.text;
                    this._snapshot = snapshot;
                    this._parent = this._indentationNodeContextPool.getNode(null, sourceUnit, 0, 0, 0);

                    // Is the first token in the span at the start of a new line.
                    this._lastTriviaWasNewLine = indentFirstToken;
                }
                IndentationTrackingWalker.prototype.position = function () {
                    return this._position;
                };

                IndentationTrackingWalker.prototype.parent = function () {
                    return this._parent;
                };

                IndentationTrackingWalker.prototype.textSpan = function () {
                    return this._textSpan;
                };

                IndentationTrackingWalker.prototype.snapshot = function () {
                    return this._snapshot;
                };

                IndentationTrackingWalker.prototype.indentationNodeContextPool = function () {
                    return this._indentationNodeContextPool;
                };

                IndentationTrackingWalker.prototype.forceIndentNextToken = function (tokenStart) {
                    this._lastTriviaWasNewLine = true;
                    this.forceRecomputeIndentationOfParent(tokenStart, true);
                };

                IndentationTrackingWalker.prototype.forceSkipIndentingNextToken = function (tokenStart) {
                    this._lastTriviaWasNewLine = false;
                    this.forceRecomputeIndentationOfParent(tokenStart, false);
                };

                IndentationTrackingWalker.prototype.indentToken = function (token, indentationAmount, commentIndentationAmount) {
                    throw TypeScript.Errors.abstract();
                };

                IndentationTrackingWalker.prototype.visitTokenInSpan = function (token) {
                    if (this._lastTriviaWasNewLine) {
                        // Compute the indentation level at the current token
                        var indentationAmount = this.getTokenIndentationAmount(token);
                        var commentIndentationAmount = this.getCommentIndentationAmount(token);

                        // Process the token
                        this.indentToken(token, indentationAmount, commentIndentationAmount);
                    }
                };

                IndentationTrackingWalker.prototype.visitToken = function (token) {
                    var tokenSpan = new TypeScript.TextSpan(this._position, token.fullWidth());

                    if (tokenSpan.intersectsWithTextSpan(this._textSpan)) {
                        this.visitTokenInSpan(token);

                        // Only track new lines on tokens within the range. Make sure to check that the last trivia is a newline, and not just one of the trivia
                        var trivia = token.trailingTrivia();
                        this._lastTriviaWasNewLine = trivia.hasNewLine() && trivia.syntaxTriviaAt(trivia.count() - 1).kind() == 5 /* NewLineTrivia */;
                    }

                    // Update the position
                    this._position += token.fullWidth();
                };

                IndentationTrackingWalker.prototype.visitNode = function (node) {
                    var nodeSpan = new TypeScript.TextSpan(this._position, TypeScript.fullWidth(node));

                    if (nodeSpan.intersectsWithTextSpan(this._textSpan)) {
                        // Update indentation level
                        var indentation = this.getNodeIndentation(node);

                        // Update the parent
                        var currentParent = this._parent;
                        this._parent = this._indentationNodeContextPool.getNode(currentParent, node, this._position, indentation.indentationAmount, indentation.indentationAmountDelta);

                        // Visit node
                        TypeScript.visitNodeOrToken(this, node);

                        // Reset state
                        this._indentationNodeContextPool.releaseNode(this._parent);
                        this._parent = currentParent;
                    } else {
                        // We're skipping the node, so update our position accordingly.
                        this._position += TypeScript.fullWidth(node);
                    }
                };

                IndentationTrackingWalker.prototype.getTokenIndentationAmount = function (token) {
                    // If this is the first token of a node, it should follow the node indentation and not the child indentation;
                    // (e.g.class in a class declaration or module in module declariotion).
                    // Open and close braces should follow the indentation of thier parent as well(e.g.
                    // class {
                    // }
                    // Also in a do-while statement, the while should be indented like the parent.
                    if (TypeScript.firstToken(this._parent.node()) === token || token.kind() === 70 /* OpenBraceToken */ || token.kind() === 71 /* CloseBraceToken */ || token.kind() === 74 /* OpenBracketToken */ || token.kind() === 75 /* CloseBracketToken */ || (token.kind() === 42 /* WhileKeyword */ && this._parent.node().kind() == 161 /* DoStatement */)) {
                        return this._parent.indentationAmount();
                    }

                    return (this._parent.indentationAmount() + this._parent.childIndentationAmountDelta());
                };

                IndentationTrackingWalker.prototype.getCommentIndentationAmount = function (token) {
                    // If this is token terminating an indentation scope, leading comments should be indented to follow the children
                    // indentation level and not the node
                    if (token.kind() === 71 /* CloseBraceToken */ || token.kind() === 75 /* CloseBracketToken */) {
                        return (this._parent.indentationAmount() + this._parent.childIndentationAmountDelta());
                    }
                    return this._parent.indentationAmount();
                };

                IndentationTrackingWalker.prototype.getNodeIndentation = function (node, newLineInsertedByFormatting) {
                    var parent = this._parent;

                    // We need to get the parent's indentation, which could be one of 2 things. If first token of the parent is in the span, use the parent's computed indentation.
                    // If the parent was outside the span, use the actual indentation of the parent.
                    var parentIndentationAmount;
                    if (this._textSpan.containsPosition(parent.start())) {
                        parentIndentationAmount = parent.indentationAmount();
                    } else {
                        if (parent.kind() === 146 /* Block */ && !this.shouldIndentBlockInParent(this._parent.parent())) {
                            // Blocks preserve the indentation of their containing node (unless they're a
                            // standalone block in a list).  i.e. if you have:
                            //
                            //  function foo(
                            //      a: number) {
                            //
                            // Then we expect the indentation of the block to be tied to the function, not to
                            // the line that the block is defined on.  If we were to do the latter, then the
                            // indentation would be here:
                            //
                            //  function foo(
                            //      a: number) {
                            //          |
                            //
                            // Instead of:
                            //
                            //  function foo(
                            //      a: number) {
                            //      |
                            parent = this._parent.parent();
                        }

                        var line = this._snapshot.getLineFromPosition(parent.start()).getText();
                        var firstNonWhiteSpacePosition = TypeScript.Indentation.firstNonWhitespacePosition(line);
                        parentIndentationAmount = TypeScript.Indentation.columnForPositionInString(line, firstNonWhiteSpacePosition, this.options);
                    }
                    var parentIndentationAmountDelta = parent.childIndentationAmountDelta();

                    // The indentation level of the node
                    var indentationAmount;

                    // The delta it adds to its children.
                    var indentationAmountDelta;
                    var parentNode = parent.node();

                    switch (node.kind()) {
                        default:
                            // General case
                            // This node should follow the child indentation set by its parent
                            // This node does not introduce any new indentation scope, indent any decendants of this node (tokens or child nodes)
                            // using the same indentation level
                            indentationAmount = (parentIndentationAmount + parentIndentationAmountDelta);
                            indentationAmountDelta = 0;
                            break;

                        case 131 /* ClassDeclaration */:
                        case 130 /* ModuleDeclaration */:
                        case 122 /* ObjectType */:
                        case 132 /* EnumDeclaration */:
                        case 151 /* SwitchStatement */:
                        case 215 /* ObjectLiteralExpression */:
                        case 137 /* ConstructorDeclaration */:
                        case 129 /* FunctionDeclaration */:
                        case 222 /* FunctionExpression */:
                        case 135 /* MemberFunctionDeclaration */:
                        case 139 /* GetAccessor */:
                        case 140 /* SetAccessor */:
                        case 138 /* IndexMemberDeclaration */:
                        case 236 /* CatchClause */:

                        case 214 /* ArrayLiteralExpression */:
                        case 124 /* ArrayType */:
                        case 221 /* ElementAccessExpression */:
                        case 144 /* IndexSignature */:

                        case 154 /* ForStatement */:
                        case 155 /* ForInStatement */:
                        case 158 /* WhileStatement */:
                        case 161 /* DoStatement */:
                        case 163 /* WithStatement */:
                        case 233 /* CaseSwitchClause */:
                        case 234 /* DefaultSwitchClause */:
                        case 150 /* ReturnStatement */:
                        case 157 /* ThrowStatement */:
                        case 219 /* SimpleArrowFunctionExpression */:
                        case 218 /* ParenthesizedArrowFunctionExpression */:
                        case 224 /* VariableDeclaration */:
                        case 134 /* ExportAssignment */:

                        case 213 /* InvocationExpression */:
                        case 216 /* ObjectCreationExpression */:
                        case 142 /* CallSignature */:
                        case 143 /* ConstructSignature */:
                            // These nodes should follow the child indentation set by its parent;
                            // they introduce a new indenation scope; children should be indented at one level deeper
                            indentationAmount = (parentIndentationAmount + parentIndentationAmountDelta);
                            indentationAmountDelta = this.options.indentSpaces;
                            break;

                        case 147 /* IfStatement */:
                            if (parent.kind() === 235 /* ElseClause */ && !TypeScript.SyntaxUtilities.isLastTokenOnLine(parentNode.elseKeyword, this._text)) {
                                // This is an else if statement with the if on the same line as the else, do not indent the if statmement.
                                // Note: Children indentation has already been set by the parent if statement, so no need to increment
                                indentationAmount = parentIndentationAmount;
                            } else {
                                // Otherwise introduce a new indenation scope; children should be indented at one level deeper
                                indentationAmount = (parentIndentationAmount + parentIndentationAmountDelta);
                            }
                            indentationAmountDelta = this.options.indentSpaces;
                            break;

                        case 235 /* ElseClause */:
                            // Else should always follow its parent if statement indentation.
                            // Note: Children indentation has already been set by the parent if statement, so no need to increment
                            indentationAmount = parentIndentationAmount;
                            indentationAmountDelta = this.options.indentSpaces;
                            break;

                        case 146 /* Block */:
                            // Check if the block is a member in a list of statements (if the parent is a source unit, module, or block, or switch clause)
                            if (this.shouldIndentBlockInParent(parent)) {
                                indentationAmount = parentIndentationAmount + parentIndentationAmountDelta;
                            } else {
                                indentationAmount = parentIndentationAmount;
                            }

                            indentationAmountDelta = this.options.indentSpaces;
                            break;
                    }

                    // If the parent happens to start on the same line as this node, then override the current node indenation with that
                    // of the parent. This avoid having to add an extra level of indentation for the children. e.g.:
                    //	return {
                    //	    a:1
                    //	};
                    // instead of:
                    //	return {
                    //	        a:1
                    //	    };
                    // We also need to pass the delta (if it is nonzero) to the children, so that subsequent lines get indented. Essentially, if any node starting on the given line
                    // has a nonzero delta , the resulting delta should be inherited from this node. This is to indent cases like the following:
                    //  return a
                    //      || b;
                    // Lastly, it is possible the node indentation needs to be recomputed because the formatter inserted a newline before its first token.
                    // If this is the case, we know the node no longer starts on the same line as its parent (or at least we shouldn't treat it as such).
                    if (parentNode) {
                        if (!newLineInsertedByFormatting) {
                            var parentStartLine = this._snapshot.getLineNumberFromPosition(parent.start());
                            var currentNodeStartLine = this._snapshot.getLineNumberFromPosition(this._position + TypeScript.leadingTriviaWidth(node));
                            if (parentStartLine === currentNodeStartLine || newLineInsertedByFormatting === false) {
                                indentationAmount = parentIndentationAmount;
                                indentationAmountDelta = Math.min(this.options.indentSpaces, parentIndentationAmountDelta + indentationAmountDelta);
                            }
                        }
                    }

                    return {
                        indentationAmount: indentationAmount,
                        indentationAmountDelta: indentationAmountDelta
                    };
                };

                IndentationTrackingWalker.prototype.shouldIndentBlockInParent = function (parent) {
                    switch (parent.kind()) {
                        case 120 /* SourceUnit */:
                        case 130 /* ModuleDeclaration */:
                        case 146 /* Block */:
                        case 233 /* CaseSwitchClause */:
                        case 234 /* DefaultSwitchClause */:
                            return true;

                        default:
                            return false;
                    }
                };

                IndentationTrackingWalker.prototype.forceRecomputeIndentationOfParent = function (tokenStart, newLineAdded /*as opposed to removed*/ ) {
                    var parent = this._parent;
                    if (parent.fullStart() === tokenStart) {
                        // Temporarily pop the parent before recomputing
                        this._parent = parent.parent();
                        var indentation = this.getNodeIndentation(parent.node(), newLineAdded);
                        parent.update(parent.parent(), parent.node(), parent.fullStart(), indentation.indentationAmount, indentation.indentationAmountDelta);
                        this._parent = parent;
                    }
                };
                return IndentationTrackingWalker;
            })(TypeScript.SyntaxWalker);
            Formatting.IndentationTrackingWalker = IndentationTrackingWalker;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var MultipleTokenIndenter = (function (_super) {
                __extends(MultipleTokenIndenter, _super);
                function MultipleTokenIndenter(textSpan, sourceUnit, snapshot, indentFirstToken, options) {
                    _super.call(this, textSpan, sourceUnit, snapshot, indentFirstToken, options);
                    this._edits = [];
                }
                MultipleTokenIndenter.prototype.indentToken = function (token, indentationAmount, commentIndentationAmount) {
                    // Ignore generated tokens
                    if (token.fullWidth() === 0) {
                        return;
                    }

                    // If we have any skipped tokens as children, do not process this node for indentation or formatting
                    if (this.parent().hasSkippedOrMissingTokenChild()) {
                        return;
                    }

                    // Be strict, and only consider nodes that fall inside the span. This avoids indenting a multiline string
                    // on enter at the end of, as the whole token was not included in the span
                    var tokenSpan = new TypeScript.TextSpan(this.position() + token.leadingTriviaWidth(), TypeScript.width(token));
                    if (!this.textSpan().containsTextSpan(tokenSpan)) {
                        return;
                    }

                    // Compute an indentation string for this token
                    var indentationString = TypeScript.Indentation.indentationString(indentationAmount, this.options);

                    var commentIndentationString = TypeScript.Indentation.indentationString(commentIndentationAmount, this.options);

                    // Record any needed indentation edits
                    this.recordIndentationEditsForToken(token, indentationString, commentIndentationString);
                };

                MultipleTokenIndenter.prototype.edits = function () {
                    return this._edits;
                };

                MultipleTokenIndenter.prototype.recordEdit = function (position, length, replaceWith) {
                    this._edits.push(new Formatting.TextEditInfo(position, length, replaceWith));
                };

                MultipleTokenIndenter.prototype.recordIndentationEditsForToken = function (token, indentationString, commentIndentationString) {
                    var position = this.position();
                    var indentNextTokenOrTrivia = true;
                    var leadingWhiteSpace = "";

                    // Process any leading trivia if any
                    var triviaList = token.leadingTrivia();
                    if (triviaList) {
                        for (var i = 0, length = triviaList.count(); i < length; i++, position += trivia.fullWidth()) {
                            var trivia = triviaList.syntaxTriviaAt(i);

                            // Skip this trivia if it is not in the span
                            if (!this.textSpan().containsTextSpan(new TypeScript.TextSpan(position, trivia.fullWidth()))) {
                                continue;
                            }

                            switch (trivia.kind()) {
                                case 6 /* MultiLineCommentTrivia */:
                                    // We will only indent the first line of the multiline comment if we were planning to indent the next trivia. However,
                                    // subsequent lines will always be indented
                                    this.recordIndentationEditsForMultiLineComment(trivia, position, commentIndentationString, leadingWhiteSpace, !indentNextTokenOrTrivia);
                                    indentNextTokenOrTrivia = false;
                                    leadingWhiteSpace = "";
                                    break;

                                case 7 /* SingleLineCommentTrivia */:
                                case 8 /* SkippedTokenTrivia */:
                                    if (indentNextTokenOrTrivia) {
                                        this.recordIndentationEditsForSingleLineOrSkippedText(trivia, position, commentIndentationString);
                                        indentNextTokenOrTrivia = false;
                                    }
                                    break;

                                case 4 /* WhitespaceTrivia */:
                                    // If the next trivia is a comment, use the comment indentation level instead of the regular indentation level
                                    // If the next trivia is a newline, this whole line is just whitespace, so don't do anything (trimming will take care of it)
                                    var nextTrivia = length > i + 1 && triviaList.syntaxTriviaAt(i + 1);
                                    var whiteSpaceIndentationString = nextTrivia && nextTrivia.isComment() ? commentIndentationString : indentationString;
                                    if (indentNextTokenOrTrivia) {
                                        if (!(nextTrivia && nextTrivia.isNewLine())) {
                                            this.recordIndentationEditsForWhitespace(trivia, position, whiteSpaceIndentationString);
                                        }
                                        indentNextTokenOrTrivia = false;
                                    }
                                    leadingWhiteSpace += trivia.fullText();
                                    break;

                                case 5 /* NewLineTrivia */:
                                    // We hit a newline processing the trivia.  We need to add the indentation to the
                                    // next line as well.  Note: don't bother indenting the newline itself.  This will
                                    // just insert ugly whitespace that most users probably will not want.
                                    indentNextTokenOrTrivia = true;
                                    leadingWhiteSpace = "";
                                    break;

                                default:
                                    throw TypeScript.Errors.invalidOperation();
                            }
                        }
                    }

                    if (token.kind() !== 10 /* EndOfFileToken */ && indentNextTokenOrTrivia) {
                        // If the last trivia item was a new line, or no trivia items were encounterd record the
                        // indentation edit at the token position
                        if (indentationString.length > 0) {
                            this.recordEdit(position, 0, indentationString);
                        }
                    }
                };

                MultipleTokenIndenter.prototype.recordIndentationEditsForSingleLineOrSkippedText = function (trivia, fullStart, indentationString) {
                    // Record the edit
                    if (indentationString.length > 0) {
                        this.recordEdit(fullStart, 0, indentationString);
                    }
                };

                MultipleTokenIndenter.prototype.recordIndentationEditsForWhitespace = function (trivia, fullStart, indentationString) {
                    var text = trivia.fullText();

                    // Check if the current indentation matches the desired indentation or not
                    if (indentationString === text) {
                        return;
                    }

                    // Record the edit
                    this.recordEdit(fullStart, text.length, indentationString);
                };

                MultipleTokenIndenter.prototype.recordIndentationEditsForMultiLineComment = function (trivia, fullStart, indentationString, leadingWhiteSpace, firstLineAlreadyIndented) {
                    // If the multiline comment spans multiple lines, we need to add the right indent amount to
                    // each successive line segment as well.
                    var position = fullStart;
                    var segments = TypeScript.Syntax.splitMultiLineCommentTriviaIntoMultipleLines(trivia);

                    if (segments.length <= 1) {
                        if (!firstLineAlreadyIndented) {
                            // Process the one-line multiline comment just like a single line comment
                            this.recordIndentationEditsForSingleLineOrSkippedText(trivia, fullStart, indentationString);
                        }
                        return;
                    }

                    // Find number of columns in first segment
                    var whiteSpaceColumnsInFirstSegment = TypeScript.Indentation.columnForPositionInString(leadingWhiteSpace, leadingWhiteSpace.length, this.options);

                    var indentationColumns = TypeScript.Indentation.columnForPositionInString(indentationString, indentationString.length, this.options);
                    var startIndex = 0;
                    if (firstLineAlreadyIndented) {
                        startIndex = 1;
                        position += segments[0].length;
                    }
                    for (var i = startIndex; i < segments.length; i++) {
                        var segment = segments[i];
                        this.recordIndentationEditsForSegment(segment, position, indentationColumns, whiteSpaceColumnsInFirstSegment);
                        position += segment.length;
                    }
                };

                MultipleTokenIndenter.prototype.recordIndentationEditsForSegment = function (segment, fullStart, indentationColumns, whiteSpaceColumnsInFirstSegment) {
                    // Indent subsequent lines using a column delta of the actual indentation relative to the first line
                    var firstNonWhitespacePosition = TypeScript.Indentation.firstNonWhitespacePosition(segment);
                    var leadingWhiteSpaceColumns = TypeScript.Indentation.columnForPositionInString(segment, firstNonWhitespacePosition, this.options);
                    var deltaFromFirstSegment = leadingWhiteSpaceColumns - whiteSpaceColumnsInFirstSegment;
                    var finalColumns = indentationColumns + deltaFromFirstSegment;
                    if (finalColumns < 0) {
                        finalColumns = 0;
                    }
                    var indentationString = TypeScript.Indentation.indentationString(finalColumns, this.options);

                    if (firstNonWhitespacePosition < segment.length && TypeScript.CharacterInfo.isLineTerminator(segment.charCodeAt(firstNonWhitespacePosition))) {
                        // If this segment was just a newline, then don't bother indenting it.  That will just
                        // leave the user with an ugly indent in their output that they probably do not want.
                        return;
                    }

                    if (indentationString === segment.substring(0, firstNonWhitespacePosition)) {
                        return;
                    }

                    // Record the edit
                    this.recordEdit(fullStart, firstNonWhitespacePosition, indentationString);
                };
                return MultipleTokenIndenter;
            })(Formatting.IndentationTrackingWalker);
            Formatting.MultipleTokenIndenter = MultipleTokenIndenter;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var SingleTokenIndenter = (function (_super) {
                __extends(SingleTokenIndenter, _super);
                function SingleTokenIndenter(indentationPosition, sourceUnit, snapshot, indentFirstToken, options) {
                    _super.call(this, new TypeScript.TextSpan(indentationPosition, 1), sourceUnit, snapshot, indentFirstToken, options);
                    this.indentationAmount = null;

                    this.indentationPosition = indentationPosition;
                }
                SingleTokenIndenter.getIndentationAmount = function (position, sourceUnit, snapshot, options) {
                    var walker = new SingleTokenIndenter(position, sourceUnit, snapshot, true, options);
                    TypeScript.visitNodeOrToken(walker, sourceUnit);
                    return walker.indentationAmount;
                };

                SingleTokenIndenter.prototype.indentToken = function (token, indentationAmount, commentIndentationAmount) {
                    // Compute an indentation string for this token
                    if (token.fullWidth() === 0 || (this.indentationPosition - this.position() < token.leadingTriviaWidth())) {
                        // The position is in the leading trivia, use comment indentation
                        this.indentationAmount = commentIndentationAmount;
                    } else {
                        this.indentationAmount = indentationAmount;
                    }
                };
                return SingleTokenIndenter;
            })(Formatting.IndentationTrackingWalker);
            Formatting.SingleTokenIndenter = SingleTokenIndenter;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='formatting.ts' />
        (function (Formatting) {
            var Formatter = (function (_super) {
                __extends(Formatter, _super);
                function Formatter(textSpan, sourceUnit, indentFirstToken, options, snapshot, rulesProvider, formattingRequestKind) {
                    _super.call(this, textSpan, sourceUnit, snapshot, indentFirstToken, options);
                    this.previousTokenSpan = null;
                    this.previousTokenParent = null;
                    // TODO: implement it with skipped tokens in Fidelity
                    this.scriptHasErrors = false;

                    this.previousTokenParent = this.parent().clone(this.indentationNodeContextPool());

                    this.rulesProvider = rulesProvider;
                    this.formattingRequestKind = formattingRequestKind;
                    this.formattingContext = new Formatting.FormattingContext(this.snapshot(), this.formattingRequestKind);
                }
                Formatter.getEdits = function (textSpan, sourceUnit, options, indentFirstToken, snapshot, rulesProvider, formattingRequestKind) {
                    var walker = new Formatter(textSpan, sourceUnit, indentFirstToken, options, snapshot, rulesProvider, formattingRequestKind);
                    TypeScript.visitNodeOrToken(walker, sourceUnit);
                    return walker.edits();
                };

                Formatter.prototype.visitTokenInSpan = function (token) {
                    if (token.fullWidth() !== 0) {
                        var tokenSpan = new TypeScript.TextSpan(this.position() + token.leadingTriviaWidth(), TypeScript.width(token));
                        if (this.textSpan().containsTextSpan(tokenSpan)) {
                            this.processToken(token);
                        }
                    }

                    // Call the base class to process the token and indent it if needed
                    _super.prototype.visitTokenInSpan.call(this, token);
                };

                Formatter.prototype.processToken = function (token) {
                    var position = this.position();

                    // Extract any leading comments
                    if (token.leadingTriviaWidth() !== 0) {
                        this.processTrivia(token.leadingTrivia(), position);
                        position += token.leadingTriviaWidth();
                    }

                    // Push the token
                    var currentTokenSpan = new Formatting.TokenSpan(token.kind(), position, TypeScript.width(token));
                    if (!this.parent().hasSkippedOrMissingTokenChild()) {
                        if (this.previousTokenSpan) {
                            // Note that formatPair calls TrimWhitespaceInLineRange in between the 2 tokens
                            this.formatPair(this.previousTokenSpan, this.previousTokenParent, currentTokenSpan, this.parent());
                        } else {
                            // We still want to trim whitespace even if it is the first trivia of the first token. Trim from the beginning of the span to the trivia
                            this.trimWhitespaceInLineRange(this.getLineNumber(this.textSpan()), this.getLineNumber(currentTokenSpan));
                        }
                    }
                    this.previousTokenSpan = currentTokenSpan;
                    if (this.previousTokenParent) {
                        // Make sure to clear the previous parent before assigning a new value to it
                        this.indentationNodeContextPool().releaseNode(this.previousTokenParent, true);
                    }
                    this.previousTokenParent = this.parent().clone(this.indentationNodeContextPool());
                    position += TypeScript.width(token);

                    // Extract any trailing comments
                    if (token.trailingTriviaWidth() !== 0) {
                        this.processTrivia(token.trailingTrivia(), position);
                    }
                };

                Formatter.prototype.processTrivia = function (triviaList, fullStart) {
                    var position = fullStart;

                    for (var i = 0, n = triviaList.count(); i < n; i++) {
                        var trivia = triviaList.syntaxTriviaAt(i);

                        // For a comment, format it like it is a token. For skipped text, eat it up as a token, but skip the formatting
                        if (trivia.isComment() || trivia.isSkippedToken()) {
                            var currentTokenSpan = new Formatting.TokenSpan(trivia.kind(), position, trivia.fullWidth());
                            if (this.textSpan().containsTextSpan(currentTokenSpan)) {
                                if (trivia.isComment() && this.previousTokenSpan) {
                                    // Note that formatPair calls TrimWhitespaceInLineRange in between the 2 tokens
                                    this.formatPair(this.previousTokenSpan, this.previousTokenParent, currentTokenSpan, this.parent());
                                } else {
                                    // We still want to trim whitespace even if it is the first trivia of the first token. Trim from the beginning of the span to the trivia
                                    var startLine = this.getLineNumber(this.previousTokenSpan || this.textSpan());
                                    this.trimWhitespaceInLineRange(startLine, this.getLineNumber(currentTokenSpan));
                                }
                                this.previousTokenSpan = currentTokenSpan;
                                if (this.previousTokenParent) {
                                    // Make sure to clear the previous parent before assigning a new value to it
                                    this.indentationNodeContextPool().releaseNode(this.previousTokenParent, true);
                                }
                                this.previousTokenParent = this.parent().clone(this.indentationNodeContextPool());
                            }
                        }

                        position += trivia.fullWidth();
                    }
                };

                Formatter.prototype.findCommonParents = function (parent1, parent2) {
                    // TODO: disable debug assert message
                    var shallowParent;
                    var shallowParentDepth;
                    var deepParent;
                    var deepParentDepth;

                    if (parent1.depth() < parent2.depth()) {
                        shallowParent = parent1;
                        shallowParentDepth = parent1.depth();
                        deepParent = parent2;
                        deepParentDepth = parent2.depth();
                    } else {
                        shallowParent = parent2;
                        shallowParentDepth = parent2.depth();
                        deepParent = parent1;
                        deepParentDepth = parent1.depth();
                    }

                    TypeScript.Debug.assert(shallowParentDepth >= 0, "Expected shallowParentDepth >= 0");
                    TypeScript.Debug.assert(deepParentDepth >= 0, "Expected deepParentDepth >= 0");
                    TypeScript.Debug.assert(deepParentDepth >= shallowParentDepth, "Expected deepParentDepth >= shallowParentDepth");

                    while (deepParentDepth > shallowParentDepth) {
                        deepParent = deepParent.parent();
                        deepParentDepth--;
                    }

                    TypeScript.Debug.assert(deepParentDepth === shallowParentDepth, "Expected deepParentDepth === shallowParentDepth");

                    while (deepParent.node() && shallowParent.node()) {
                        if (deepParent.node() === shallowParent.node()) {
                            return deepParent;
                        }
                        deepParent = deepParent.parent();
                        shallowParent = shallowParent.parent();
                    }

                    throw TypeScript.Errors.invalidOperation();
                };

                Formatter.prototype.formatPair = function (t1, t1Parent, t2, t2Parent) {
                    var token1Line = this.getLineNumber(t1);
                    var token2Line = this.getLineNumber(t2);

                    // Find common parent
                    var commonParent = this.findCommonParents(t1Parent, t2Parent);

                    // Update the context
                    this.formattingContext.updateContext(t1, t1Parent, t2, t2Parent, commonParent);

                    // Find rules matching the current context
                    var rule = this.rulesProvider.getRulesMap().GetRule(this.formattingContext);

                    if (rule != null) {
                        // Record edits from the rule
                        this.RecordRuleEdits(rule, t1, t2);

                        // Handle the case where the next line is moved to be the end of this line.
                        // In this case we don't indent the next line in the next pass.
                        if ((rule.Operation.Action == 1 /* Space */ || rule.Operation.Action == 3 /* Delete */) && token1Line != token2Line) {
                            this.forceSkipIndentingNextToken(t2.start());
                        }

                        // Handle the case where token2 is moved to the new line.
                        // In this case we indent token2 in the next pass but we set
                        // sameLineIndent flag to notify the indenter that the indentation is within the line.
                        if (rule.Operation.Action == 2 /* NewLine */ && token1Line == token2Line) {
                            this.forceIndentNextToken(t2.start());
                        }
                    }

                    // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
                    if (token1Line != token2Line && (!rule || (rule.Operation.Action != 3 /* Delete */ && rule.Flag != 1 /* CanDeleteNewLines */))) {
                        this.trimWhitespaceInLineRange(token1Line, token2Line, t1);
                    }
                };

                Formatter.prototype.getLineNumber = function (span) {
                    return this.snapshot().getLineNumberFromPosition(span.start());
                };

                Formatter.prototype.trimWhitespaceInLineRange = function (startLine, endLine, token) {
                    for (var lineNumber = startLine; lineNumber < endLine; ++lineNumber) {
                        var line = this.snapshot().getLineFromLineNumber(lineNumber);

                        this.trimWhitespace(line, token);
                    }
                };

                Formatter.prototype.trimWhitespace = function (line, token) {
                    // Don't remove the trailing spaces inside comments (this includes line comments and block comments)
                    if (token && (token.kind == 6 /* MultiLineCommentTrivia */ || token.kind == 7 /* SingleLineCommentTrivia */) && token.start() <= line.endPosition() && token.end() >= line.endPosition())
                        return;

                    var text = line.getText();
                    var index = 0;

                    for (index = text.length - 1; index >= 0; --index) {
                        if (!TypeScript.CharacterInfo.isWhitespace(text.charCodeAt(index))) {
                            break;
                        }
                    }

                    ++index;

                    if (index < text.length) {
                        this.recordEdit(line.startPosition() + index, line.length() - index, "");
                    }
                };

                Formatter.prototype.RecordRuleEdits = function (rule, t1, t2) {
                    if (rule.Operation.Action == 0 /* Ignore */) {
                        return;
                    }

                    var betweenSpan;

                    switch (rule.Operation.Action) {
                        case 3 /* Delete */:
                             {
                                betweenSpan = new TypeScript.TextSpan(t1.end(), t2.start() - t1.end());

                                if (betweenSpan.length() > 0) {
                                    this.recordEdit(betweenSpan.start(), betweenSpan.length(), "");
                                    return;
                                }
                            }
                            break;

                        case 2 /* NewLine */:
                             {
                                if (!(rule.Flag == 1 /* CanDeleteNewLines */ || this.getLineNumber(t1) == this.getLineNumber(t2))) {
                                    return;
                                }

                                betweenSpan = new TypeScript.TextSpan(t1.end(), t2.start() - t1.end());

                                var doEdit = false;
                                var betweenText = this.snapshot().getText(betweenSpan);

                                var lineFeedLoc = betweenText.indexOf(this.options.newLineCharacter);
                                if (lineFeedLoc < 0) {
                                    // no linefeeds, do the edit
                                    doEdit = true;
                                } else {
                                    // We only require one line feed. If there is another one, do the edit
                                    lineFeedLoc = betweenText.indexOf(this.options.newLineCharacter, lineFeedLoc + 1);
                                    if (lineFeedLoc >= 0) {
                                        doEdit = true;
                                    }
                                }

                                if (doEdit) {
                                    this.recordEdit(betweenSpan.start(), betweenSpan.length(), this.options.newLineCharacter);
                                    return;
                                }
                            }
                            break;

                        case 1 /* Space */:
                             {
                                if (!(rule.Flag == 1 /* CanDeleteNewLines */ || this.getLineNumber(t1) == this.getLineNumber(t2))) {
                                    return;
                                }

                                betweenSpan = new TypeScript.TextSpan(t1.end(), t2.start() - t1.end());

                                if (betweenSpan.length() > 1 || this.snapshot().getText(betweenSpan) != " ") {
                                    this.recordEdit(betweenSpan.start(), betweenSpan.length(), " ");
                                    return;
                                }
                            }
                            break;
                    }
                };
                return Formatter;
            })(Formatting.MultipleTokenIndenter);
            Formatting.Formatter = Formatter;
        })(Services.Formatting || (Services.Formatting = {}));
        var Formatting = Services.Formatting;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='..\typescriptServices.ts' />
///<reference path='textSnapshot.ts' />
///<reference path='textSnapshotLine.ts' />
///<reference path='snapshotPoint.ts' />
///<reference path='formattingContext.ts' />
///<reference path='formattingManager.ts' />
///<reference path='formattingRequestKind.ts' />
///<reference path='rule.ts' />
///<reference path='ruleAction.ts' />
///<reference path='ruleDescriptor.ts' />
///<reference path='ruleFlag.ts' />
///<reference path='ruleOperation.ts' />
///<reference path='ruleOperationContext.ts' />
///<reference path='rules.ts' />
///<reference path='rulesMap.ts' />
///<reference path='rulesProvider.ts' />
///<reference path='textEditInfo.ts' />
///<reference path='tokenRange.ts' />
///<reference path='tokenSpan.ts' />
///<reference path='indentationNodeContext.ts' />
///<reference path='indentationNodeContextPool.ts' />
///<reference path='indentationTrackingWalker.ts' />
///<reference path='multipleTokenIndenter.ts' />
///<reference path='singleTokenIndenter.ts' />
///<reference path='formatter.ts' />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='..\compiler\typescript.ts' />
///<reference path='classifier.ts' />
///<reference path='languageService.ts' />
///<reference path='formatting\formatting.ts' />
// Access to "Debug" object
var debugObjectHost = this;

var TypeScript;
(function (TypeScript) {
    (function (Services) {
        var CoreServices = (function () {
            function CoreServices(host) {
                this.host = host;
            }
            CoreServices.prototype.getPreProcessedFileInfo = function (fileName, sourceText) {
                return TypeScript.preProcessFile(fileName, sourceText);
            };

            CoreServices.prototype.getDefaultCompilationSettings = function () {
                // Set "ES5" target by default for language service
                var settings = new TypeScript.CompilationSettings();
                settings.codeGenTarget = 1 /* EcmaScript5 */;
                return settings;
            };

            CoreServices.prototype.dumpMemory = function () {
                if (!debugObjectHost || !debugObjectHost.Debug || !debugObjectHost.Debug.dumpHeap) {
                    throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.This_version_of_the_Javascript_runtime_does_not_support_the_0_function, ['Debug.dumpHeap()']));
                }

                var objects = debugObjectHost.Debug.dumpHeap(2);
                var totalSize = 0;
                for (var i = 0; i < objects.length; i++) {
                    totalSize += objects[i].size;
                }

                return "There are " + objects.length + " object(s) accessible from 'global', for a total of " + totalSize + " byte(s).";
            };

            CoreServices.prototype.getMemoryInfo = function () {
                if (!debugObjectHost || !debugObjectHost.Debug || !debugObjectHost.Debug.getMemoryInfo) {
                    throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.This_version_of_the_Javascript_runtime_does_not_support_the_0_function, ['Debug.getMemoryInfo()']));
                }

                return debugObjectHost.Debug.getMemoryInfo();
            };

            CoreServices.prototype.collectGarbage = function () {
                if (!debugObjectHost || !debugObjectHost.CollectGarbage) {
                    throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.This_version_of_the_Javascript_runtime_does_not_support_the_0_function, ['collectGarbage()']));
                }

                debugObjectHost.CollectGarbage();
            };
            return CoreServices;
        })();
        Services.CoreServices = CoreServices;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        // Information about a specific host file.
        var HostFileInformation = (function () {
            function HostFileInformation(fileName, host, version, isOpen, byteOrderMark) {
                this.fileName = fileName;
                this.host = host;
                this.version = version;
                this.isOpen = isOpen;
                this.byteOrderMark = byteOrderMark;
                this._sourceText = null;
            }
            HostFileInformation.prototype.getScriptSnapshot = function () {
                if (this._sourceText === null) {
                    this._sourceText = this.host.getScriptSnapshot(this.fileName);
                }

                return this._sourceText;
            };
            return HostFileInformation;
        })();

        // Cache host information about scripts. Should be refreshed
        // at each language service public entry point, since we don't know when
        // set of scripts handled by the host changes.
        var HostCache = (function () {
            function HostCache(host) {
                // script id => script index
                this._fileNameToEntry = new TypeScript.StringHashTable();

                var fileNames = host.getScriptFileNames();
                for (var i = 0, n = fileNames.length; i < n; i++) {
                    var fileName = fileNames[i];
                    this._fileNameToEntry.add(TypeScript.switchToForwardSlashes(fileName), new HostFileInformation(fileName, host, host.getScriptVersion(fileName), host.getScriptIsOpen(fileName), host.getScriptByteOrderMark(fileName)));
                }

                var settings = host.getCompilationSettings();
                if (!settings) {
                    // Set "ES5" target by default for language service
                    settings = new TypeScript.CompilationSettings();
                    settings.codeGenTarget = 1 /* EcmaScript5 */;
                }

                this._compilationSettings = TypeScript.ImmutableCompilationSettings.fromCompilationSettings(settings);
            }
            HostCache.prototype.compilationSettings = function () {
                return this._compilationSettings;
            };

            HostCache.prototype.contains = function (fileName) {
                return this._fileNameToEntry.lookup(TypeScript.switchToForwardSlashes(fileName)) !== null;
            };

            HostCache.prototype.getHostFileName = function (fileName) {
                var hostCacheEntry = this._fileNameToEntry.lookup(TypeScript.switchToForwardSlashes(fileName));
                if (hostCacheEntry) {
                    return hostCacheEntry.fileName;
                }
                return fileName;
            };

            HostCache.prototype.getFileNames = function () {
                return this._fileNameToEntry.getAllKeys();
            };

            HostCache.prototype.getVersion = function (fileName) {
                return this._fileNameToEntry.lookup(TypeScript.switchToForwardSlashes(fileName)).version;
            };

            HostCache.prototype.isOpen = function (fileName) {
                return this._fileNameToEntry.lookup(TypeScript.switchToForwardSlashes(fileName)).isOpen;
            };

            HostCache.prototype.getByteOrderMark = function (fileName) {
                return this._fileNameToEntry.lookup(TypeScript.switchToForwardSlashes(fileName)).byteOrderMark;
            };

            HostCache.prototype.getScriptSnapshot = function (fileName) {
                return this._fileNameToEntry.lookup(TypeScript.switchToForwardSlashes(fileName)).getScriptSnapshot();
            };

            HostCache.prototype.getScriptTextChangeRangeSinceVersion = function (fileName, lastKnownVersion) {
                var currentVersion = this.getVersion(fileName);
                if (lastKnownVersion === currentVersion) {
                    return TypeScript.TextChangeRange.unchanged;
                }

                var scriptSnapshot = this.getScriptSnapshot(fileName);
                return scriptSnapshot.getTextChangeRangeSinceVersion(lastKnownVersion);
            };
            return HostCache;
        })();

        var SyntaxTreeCache = (function () {
            function SyntaxTreeCache(_host) {
                this._host = _host;
                // For our syntactic only features, we also keep a cache of the syntax tree for the
                // currently edited file.
                this._currentFileName = "";
                this._currentFileVersion = -1;
                this._currentFileSyntaxTree = null;
                this._currentFileScriptSnapshot = null;
                this._hostCache = new HostCache(_host);
            }
            SyntaxTreeCache.prototype.getCurrentFileSyntaxTree = function (fileName) {
                this._hostCache = new HostCache(this._host);

                var version = this._hostCache.getVersion(fileName);
                var syntaxTree = null;

                if (this._currentFileSyntaxTree === null || this._currentFileName !== fileName) {
                    var scriptSnapshot = this._hostCache.getScriptSnapshot(fileName);
                    syntaxTree = this.createSyntaxTree(fileName, scriptSnapshot);
                } else if (this._currentFileVersion !== version) {
                    var scriptSnapshot = this._hostCache.getScriptSnapshot(fileName);
                    syntaxTree = this.updateSyntaxTree(fileName, scriptSnapshot, this._currentFileSyntaxTree, this._currentFileVersion);
                }

                if (syntaxTree !== null) {
                    // All done, ensure state is up to date
                    this._currentFileScriptSnapshot = scriptSnapshot;
                    this._currentFileVersion = version;
                    this._currentFileName = fileName;
                    this._currentFileSyntaxTree = syntaxTree;
                }

                return this._currentFileSyntaxTree;
            };

            SyntaxTreeCache.prototype.createSyntaxTree = function (fileName, scriptSnapshot) {
                var text = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot);

                // For the purposes of features that use this syntax tree, we can just use the default
                // compilation settings.  The features only use the syntax (and not the diagnostics),
                // and the syntax isn't affected by the compilation settings.
                var syntaxTree = TypeScript.Parser.parse(fileName, text, TypeScript.ImmutableCompilationSettings.defaultSettings().codeGenTarget(), TypeScript.isDTSFile(fileName));

                return syntaxTree;
            };

            SyntaxTreeCache.prototype.updateSyntaxTree = function (fileName, scriptSnapshot, previousSyntaxTree, previousFileVersion) {
                var editRange = this._hostCache.getScriptTextChangeRangeSinceVersion(fileName, previousFileVersion);

                // Debug.assert(newLength >= 0);
                // The host considers the entire buffer changed.  So parse a completely new tree.
                if (editRange === null) {
                    return this.createSyntaxTree(fileName, scriptSnapshot);
                }

                var nextSyntaxTree = TypeScript.IncrementalParser.parse(previousSyntaxTree, editRange, TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot));

                this.ensureInvariants(fileName, editRange, nextSyntaxTree, this._currentFileScriptSnapshot, scriptSnapshot);

                return nextSyntaxTree;
            };

            SyntaxTreeCache.prototype.ensureInvariants = function (fileName, editRange, incrementalTree, oldScriptSnapshot, newScriptSnapshot) {
                // First, verify that the edit range and the script snapshots make sense.
                // If this fires, then the edit range is completely bogus.  Somehow the lengths of the
                // old snapshot, the change range and the new snapshot aren't in sync.  This is very
                // bad.
                var expectedNewLength = oldScriptSnapshot.getLength() - editRange.span().length() + editRange.newLength();
                var actualNewLength = newScriptSnapshot.getLength();

                function provideMoreDebugInfo() {
                    var debugInformation = ["expected length:", expectedNewLength, "and actual length:", actualNewLength, "are not equal\r\n"];

                    var oldSpan = editRange.span();

                    function prettyPrintString(s) {
                        return '"' + s.replace(/\r/g, '\\r').replace(/\n/g, '\\n') + '"';
                    }

                    debugInformation.push('Edit range (old text) (start: ' + oldSpan.start() + ', end: ' + oldSpan.end() + ') \r\n');
                    debugInformation.push('Old text edit range contents: ' + prettyPrintString(oldScriptSnapshot.getText(oldSpan.start(), oldSpan.end())));

                    var newSpan = editRange.newSpan();

                    debugInformation.push('Edit range (new text) (start: ' + newSpan.start() + ', end: ' + newSpan.end() + ') \r\n');
                    debugInformation.push('New text edit range contents: ' + prettyPrintString(newScriptSnapshot.getText(newSpan.start(), newSpan.end())));

                    return debugInformation.join(' ');
                }

                TypeScript.Debug.assert(expectedNewLength === actualNewLength, "Expected length is different from actual!", provideMoreDebugInfo);

                if (TypeScript.Debug.shouldAssert(3 /* VeryAggressive */)) {
                    // If this fires, the text change range is bogus.  It says the change starts at point
                    // 'X', but we can see a text difference *before* that point.
                    var oldPrefixText = oldScriptSnapshot.getText(0, editRange.span().start());
                    var newPrefixText = newScriptSnapshot.getText(0, editRange.span().start());
                    TypeScript.Debug.assert(oldPrefixText === newPrefixText, 'Expected equal prefix texts!');

                    // If this fires, the text change range is bogus.  It says the change goes only up to
                    // point 'X', but we can see a text difference *after* that point.
                    var oldSuffixText = oldScriptSnapshot.getText(editRange.span().end(), oldScriptSnapshot.getLength());
                    var newSuffixText = newScriptSnapshot.getText(editRange.newSpan().end(), newScriptSnapshot.getLength());
                    TypeScript.Debug.assert(oldSuffixText === newSuffixText, 'Expected equal suffix texts!');

                    // Ok, text change range and script snapshots look ok.  Let's verify that our
                    // incremental parsing worked properly.
                    //var normalTree = this.createSyntaxTree(fileName, newScriptSnapshot);
                    //Debug.assert(normalTree.structuralEquals(incrementalTree), 'Expected equal incremental and normal trees');
                    // Ok, the trees looked good.  So at least our incremental parser agrees with the
                    // normal parser.  Now, verify that the incremental tree matches the contents of the
                    // script snapshot.
                    var incrementalTreeText = TypeScript.fullText(incrementalTree.sourceUnit());
                    var actualSnapshotText = newScriptSnapshot.getText(0, newScriptSnapshot.getLength());
                    TypeScript.Debug.assert(incrementalTreeText === actualSnapshotText, 'Expected full texts to be equal');
                }
            };
            return SyntaxTreeCache;
        })();
        Services.SyntaxTreeCache = SyntaxTreeCache;

        var LanguageServiceCompiler = (function () {
            function LanguageServiceCompiler(host, documentRegistry, cancellationToken) {
                this.host = host;
                this.documentRegistry = documentRegistry;
                this.cancellationToken = cancellationToken;
                // The underlying typescript compiler we defer most operations to.
                this.compiler = null;
                // A cache of all the information about the files on the host side.
                this.hostCache = null;
                this.logger = this.host;
            }
            LanguageServiceCompiler.prototype.synchronizeHostData = function () {
                var _this = this;
                TypeScript.timeFunction(this.logger, "synchronizeHostData()", function () {
                    _this.synchronizeHostDataWorker();
                });
            };

            LanguageServiceCompiler.prototype.synchronizeHostDataWorker = function () {
                // Reset the cache at start of every refresh
                this.hostCache = new HostCache(this.host);

                var compilationSettings = this.hostCache.compilationSettings();

                // If we don't have a compiler, then create a new one.
                if (this.compiler === null) {
                    this.compiler = new TypeScript.TypeScriptCompiler(this.logger, compilationSettings);
                }

                var oldSettings = this.compiler.compilationSettings();

                var changesInCompilationSettingsAffectSyntax = oldSettings && compilationSettings && !TypeScript.compareDataObjects(oldSettings, compilationSettings) && TypeScript.settingsChangeAffectsSyntax(oldSettings, compilationSettings);

                // let the compiler know about the current compilation settings.
                this.compiler.setCompilationSettings(compilationSettings);

                // Now, remove any files from the compiler that are no longer in the host.
                var compilerFileNames = this.compiler.fileNames();

                for (var i = 0, n = compilerFileNames.length; i < n; i++) {
                    this.cancellationToken.throwIfCancellationRequested();

                    var fileName = compilerFileNames[i];

                    if (!this.hostCache.contains(fileName) || changesInCompilationSettingsAffectSyntax) {
                        this.compiler.removeFile(fileName);
                        this.documentRegistry.releaseDocument(fileName, oldSettings);
                    }
                }

                // Now, for every file the host knows about, either add the file (if the compiler
                // doesn't know about it.).  Or notify the compiler about any changes (if it does
                // know about it.)
                var hostFileNames = this.hostCache.getFileNames();

                for (var i = 0, n = hostFileNames.length; i < n; i++) {
                    var fileName = hostFileNames[i];

                    var version = this.hostCache.getVersion(fileName);
                    var isOpen = this.hostCache.isOpen(fileName);
                    var scriptSnapshot = this.hostCache.getScriptSnapshot(fileName);

                    var document = this.compiler.getDocument(fileName);
                    if (document) {
                        //
                        // If the document is the same, assume no update
                        //
                        if (document.version === version && document.isOpen === isOpen) {
                            continue;
                        }

                        // Only perform incremental parsing on open files that are being edited.  If a file was
                        // open, but is now closed, we want to reparse entirely so we don't have any tokens that
                        // are holding onto expensive script snapshot instances on the host.  Similarly, if a
                        // file was closed, then we always want to reparse.  This is so our tree doesn't keep
                        // the old buffer alive that represented the file on disk (as the host has moved to a
                        // new text buffer).
                        var textChangeRange = null;
                        if (document.isOpen && isOpen) {
                            textChangeRange = this.hostCache.getScriptTextChangeRangeSinceVersion(fileName, document.version);
                        }

                        document = this.documentRegistry.updateDocument(document, fileName, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange);
                    } else {
                        document = this.documentRegistry.acquireDocument(fileName, compilationSettings, scriptSnapshot, this.hostCache.getByteOrderMark(fileName), version, isOpen, []);
                    }

                    this.compiler.addOrUpdateFile(document);
                }
            };

            // Methods that defer to the host cache to get the result.
            LanguageServiceCompiler.prototype.getScriptSnapshot = function (fileName) {
                this.synchronizeHostData();
                return this.hostCache.getScriptSnapshot(fileName);
            };

            // Methods that does not require updating the host cache information
            LanguageServiceCompiler.prototype.getCachedHostFileName = function (fileName) {
                if (!this.hostCache) {
                    this.synchronizeHostData();
                }

                return this.hostCache.getHostFileName(fileName);
            };

            LanguageServiceCompiler.prototype.getCachedTopLevelDeclaration = function (fileName) {
                if (!this.hostCache) {
                    this.synchronizeHostData();
                }

                return this.compiler.topLevelDeclaration(fileName);
            };

            // Methods that defer to the compiler to get the result.
            LanguageServiceCompiler.prototype.compilationSettings = function () {
                this.synchronizeHostData();
                return this.compiler.compilationSettings();
            };

            LanguageServiceCompiler.prototype.fileNames = function () {
                this.synchronizeHostData();
                return this.compiler.fileNames();
            };

            LanguageServiceCompiler.prototype.cleanupSemanticCache = function () {
                this.compiler.cleanupSemanticCache();
            };

            LanguageServiceCompiler.prototype.getDocument = function (fileName) {
                this.synchronizeHostData();
                return this.compiler.getDocument(fileName);
            };

            LanguageServiceCompiler.prototype.getSemanticInfoChain = function () {
                this.synchronizeHostData();
                return this.compiler.getSemanticInfoChain();
            };

            LanguageServiceCompiler.prototype.getSyntacticDiagnostics = function (fileName) {
                this.synchronizeHostData();
                return this.compiler.getSyntacticDiagnostics(fileName);
            };

            LanguageServiceCompiler.prototype.getSemanticDiagnostics = function (fileName) {
                this.synchronizeHostData();
                return this.compiler.getSemanticDiagnostics(fileName);
            };

            LanguageServiceCompiler.prototype.getCompilerOptionsDiagnostics = function (resolvePath) {
                this.synchronizeHostData();
                return this.compiler.getCompilerOptionsDiagnostics(resolvePath);
            };

            LanguageServiceCompiler.prototype.getSymbolInformationFromAST = function (ast, document) {
                this.synchronizeHostData();
                return this.compiler.pullGetSymbolInformationFromAST(ast, document);
            };

            LanguageServiceCompiler.prototype.getCallInformationFromAST = function (ast, document) {
                this.synchronizeHostData();
                return this.compiler.pullGetCallInformationFromAST(ast, document);
            };

            LanguageServiceCompiler.prototype.getVisibleMemberSymbolsFromAST = function (ast, document) {
                this.synchronizeHostData();
                return this.compiler.pullGetVisibleMemberSymbolsFromAST(ast, document);
            };

            LanguageServiceCompiler.prototype.getVisibleDeclsFromAST = function (ast, document) {
                this.synchronizeHostData();
                return this.compiler.pullGetVisibleDeclsFromAST(ast, document);
            };

            LanguageServiceCompiler.prototype.getContextualMembersFromAST = function (ast, document) {
                this.synchronizeHostData();
                return this.compiler.pullGetContextualMembersFromAST(ast, document);
            };

            LanguageServiceCompiler.prototype.pullGetDeclInformation = function (decl, ast, document) {
                this.synchronizeHostData();
                return this.compiler.pullGetDeclInformation(decl, ast, document);
            };

            LanguageServiceCompiler.prototype.topLevelDeclaration = function (fileName) {
                this.synchronizeHostData();
                return this.compiler.topLevelDeclaration(fileName);
            };

            LanguageServiceCompiler.prototype.getDeclForAST = function (ast) {
                this.synchronizeHostData();
                return this.compiler.getDeclForAST(ast);
            };

            LanguageServiceCompiler.prototype.emit = function (fileName, resolvePath) {
                this.synchronizeHostData();
                return this.compiler.emit(fileName, resolvePath);
            };

            LanguageServiceCompiler.prototype.emitDeclarations = function (fileName, resolvePath) {
                this.synchronizeHostData();
                return this.compiler.emitDeclarations(fileName, resolvePath);
            };

            LanguageServiceCompiler.prototype.canEmitDeclarations = function (fileName) {
                this.synchronizeHostData();
                return this.compiler.canEmitDeclarations(fileName);
            };

            LanguageServiceCompiler.prototype.dispose = function () {
                if (this.compiler) {
                    var fileNames = this.compiler.fileNames();
                    for (var i = 0; i < fileNames.length; ++i) {
                        this.documentRegistry.releaseDocument(fileNames[i], this.compiler.compilationSettings());
                    }
                }
            };
            return LanguageServiceCompiler;
        })();
        Services.LanguageServiceCompiler = LanguageServiceCompiler;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (Indentation) {
        function columnForEndOfTokenAtPosition(syntaxTree, position, options) {
            var token = TypeScript.findToken(syntaxTree.sourceUnit(), position);
            return columnForStartOfTokenAtPosition(syntaxTree, position, options) + TypeScript.width(token);
        }
        Indentation.columnForEndOfTokenAtPosition = columnForEndOfTokenAtPosition;

        function columnForStartOfTokenAtPosition(syntaxTree, position, options) {
            var token = TypeScript.findToken(syntaxTree.sourceUnit(), position);

            // Walk backward from this token until we find the first token in the line.  For each token
            // we see (that is not the first tokem in line), push the entirety of the text into the text
            // array.  Then, for the first token, add its text (without its leading trivia) to the text
            // array.  i.e. if we have:
            //
            //      var foo = a => bar();
            //
            // And we want the column for the start of 'bar', then we'll add the underlinded portions to
            // the text array:
            //
            //      var foo = a => bar();
            //                  _
            //                __
            //              __
            //          ____
            //      ____
            var firstTokenInLine = TypeScript.Syntax.firstTokenInLineContainingPosition(syntaxTree, token.fullStart());
            var leadingTextInReverse = [];

            var current = token;
            while (current !== firstTokenInLine) {
                current = TypeScript.previousToken(current);

                if (current === firstTokenInLine) {
                    // We're at the first token in teh line.
                    // We don't want the leading trivia for this token.  That will be taken care of in
                    // columnForFirstNonWhitespaceCharacterInLine.  So just push the trailing trivia
                    // and then the token text.
                    leadingTextInReverse.push(current.trailingTrivia().fullText());
                    leadingTextInReverse.push(current.text());
                } else {
                    // We're at an intermediate token on the line.  Just push all its text into the array.
                    leadingTextInReverse.push(current.fullText());
                }
            }

            // Now, add all trivia to the start of the line on the first token in the list.
            collectLeadingTriviaTextToStartOfLine(firstTokenInLine, leadingTextInReverse);

            return columnForLeadingTextInReverse(leadingTextInReverse, options);
        }
        Indentation.columnForStartOfTokenAtPosition = columnForStartOfTokenAtPosition;

        function columnForStartOfFirstTokenInLineContainingPosition(syntaxTree, position, options) {
            // Walk backward through the tokens until we find the first one on the line.
            var firstTokenInLine = TypeScript.Syntax.firstTokenInLineContainingPosition(syntaxTree, position);
            var leadingTextInReverse = [];

            // Now, add all trivia to the start of the line on the first token in the list.
            collectLeadingTriviaTextToStartOfLine(firstTokenInLine, leadingTextInReverse);

            return columnForLeadingTextInReverse(leadingTextInReverse, options);
        }
        Indentation.columnForStartOfFirstTokenInLineContainingPosition = columnForStartOfFirstTokenInLineContainingPosition;

        // Collect all the trivia that precedes this token.  Stopping when we hit a newline trivia
        // or a multiline comment that spans multiple lines.  This is meant to be called on the first
        // token in a line.
        function collectLeadingTriviaTextToStartOfLine(firstTokenInLine, leadingTextInReverse) {
            var leadingTrivia = firstTokenInLine.leadingTrivia();

            for (var i = leadingTrivia.count() - 1; i >= 0; i--) {
                var trivia = leadingTrivia.syntaxTriviaAt(i);
                if (trivia.kind() === 5 /* NewLineTrivia */) {
                    break;
                }

                if (trivia.kind() === 6 /* MultiLineCommentTrivia */) {
                    var lineSegments = TypeScript.Syntax.splitMultiLineCommentTriviaIntoMultipleLines(trivia);
                    leadingTextInReverse.push(TypeScript.ArrayUtilities.last(lineSegments));

                    if (lineSegments.length > 0) {
                        break;
                    }
                    // It was only on a single line, so keep on going.
                }

                leadingTextInReverse.push(trivia.fullText());
            }
        }

        function columnForLeadingTextInReverse(leadingTextInReverse, options) {
            var column = 0;

            for (var i = leadingTextInReverse.length - 1; i >= 0; i--) {
                var text = leadingTextInReverse[i];
                column = columnForPositionInStringWorker(text, text.length, column, options);
            }

            return column;
        }

        // Returns the column that this input string ends at (assuming it starts at column 0).
        function columnForPositionInString(input, position, options) {
            return columnForPositionInStringWorker(input, position, 0, options);
        }
        Indentation.columnForPositionInString = columnForPositionInString;

        function columnForPositionInStringWorker(input, position, startColumn, options) {
            var column = startColumn;
            var spacesPerTab = options.spacesPerTab;

            for (var j = 0; j < position; j++) {
                var ch = input.charCodeAt(j);

                if (ch === 9 /* tab */) {
                    column += spacesPerTab - column % spacesPerTab;
                } else {
                    column++;
                }
            }

            return column;
        }

        function indentationString(column, options) {
            var numberOfTabs = 0;
            var numberOfSpaces = Math.max(0, column);

            if (options.useTabs) {
                numberOfTabs = Math.floor(column / options.spacesPerTab);
                numberOfSpaces -= numberOfTabs * options.spacesPerTab;
            }

            return TypeScript.StringUtilities.repeat('\t', numberOfTabs) + TypeScript.StringUtilities.repeat(' ', numberOfSpaces);
        }
        Indentation.indentationString = indentationString;

        function firstNonWhitespacePosition(value) {
            for (var i = 0; i < value.length; i++) {
                var ch = value.charCodeAt(i);
                if (!TypeScript.CharacterInfo.isWhitespace(ch)) {
                    return i;
                }
            }

            return value.length;
        }
        Indentation.firstNonWhitespacePosition = firstNonWhitespacePosition;
    })(TypeScript.Indentation || (TypeScript.Indentation = {}));
    var Indentation = TypeScript.Indentation;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var CompletionHelpers = (function () {
            function CompletionHelpers() {
            }
            CompletionHelpers.getSpan = function (ast) {
                return new TypeScript.TextSpan(TypeScript.start(ast), TypeScript.width(ast));
            };

            CompletionHelpers.symbolDeclarationIntersectsPosition = function (symbol, fileName, position) {
                var decl = symbol.getDeclarations()[0];
                if (decl.fileName() === fileName && this.getSpan(decl.ast()).intersectsWithPosition(position)) {
                    // This is the symbol declaration from the given position in the file
                    return true;
                }

                return false;
            };

            CompletionHelpers.filterContextualMembersList = function (contextualMemberSymbols, existingMembers, fileName, position) {
                if (!existingMembers || !existingMembers.symbols || existingMembers.symbols.length === 0) {
                    return contextualMemberSymbols;
                }

                var existingMemberSymbols = existingMembers.symbols;
                var existingMemberNames = TypeScript.createIntrinsicsObject();
                for (var i = 0, n = existingMemberSymbols.length; i < n; i++) {
                    if (this.symbolDeclarationIntersectsPosition(existingMemberSymbols[i], fileName, position)) {
                        continue;
                    }

                    existingMemberNames[TypeScript.stripStartAndEndQuotes(existingMemberSymbols[i].getDisplayName())] = true;
                }

                var filteredMembers = [];
                for (var j = 0, m = contextualMemberSymbols.length; j < m; j++) {
                    var contextualMemberSymbol = contextualMemberSymbols[j];
                    if (!existingMemberNames[TypeScript.stripStartAndEndQuotes(contextualMemberSymbol.getDisplayName())]) {
                        if (this.symbolDeclarationIntersectsPosition(contextualMemberSymbol, fileName, position)) {
                            continue;
                        }
                        filteredMembers.push(contextualMemberSymbol);
                    }
                }

                return filteredMembers;
            };

            CompletionHelpers.isCompletionListBlocker = function (sourceUnit, position) {
                // We shouldn't be getting a possition that is outside the file because
                // isEntirelyInsideComment can't handle when the position is out of bounds,
                // callers should be fixed, however we should be resiliant to bad inputs
                // so we return true (this position is a blocker for getting completions)
                if (position < 0 || position > TypeScript.fullWidth(sourceUnit)) {
                    return true;
                }

                // This method uses Fidelity completely. Some information can be reached using the AST, but not everything.
                return TypeScript.Syntax.isEntirelyInsideComment(sourceUnit, position) || TypeScript.Syntax.isEntirelyInStringOrRegularExpressionLiteral(sourceUnit, position) || CompletionHelpers.isIdentifierDefinitionLocation(sourceUnit, position) || CompletionHelpers.isRightOfIllegalDot(sourceUnit, position);
            };

            CompletionHelpers.getContainingObjectLiteralApplicableForCompletion = function (sourceUnit, position) {
                // The locations in an object literal expression that are applicable for completion are property name definition locations.
                var previousToken = CompletionHelpers.getNonIdentifierCompleteTokenOnLeft(sourceUnit, position);

                if (previousToken) {
                    var parent = previousToken.parent;

                    switch (previousToken.kind()) {
                        case 70 /* OpenBraceToken */:
                        case 79 /* CommaToken */:
                            if (parent && parent.kind() === 2 /* SeparatedList */) {
                                parent = parent.parent;
                            }

                            if (parent && parent.kind() === 215 /* ObjectLiteralExpression */) {
                                return parent;
                            }

                            break;
                    }
                }

                return null;
            };

            CompletionHelpers.isIdentifierDefinitionLocation = function (sourceUnit, position) {
                var positionedToken = CompletionHelpers.getNonIdentifierCompleteTokenOnLeft(sourceUnit, position);

                if (positionedToken) {
                    var containingNodeKind = TypeScript.Syntax.containingNode(positionedToken) && TypeScript.Syntax.containingNode(positionedToken).kind();
                    switch (positionedToken.kind()) {
                        case 79 /* CommaToken */:
                            return containingNodeKind === 227 /* ParameterList */ || containingNodeKind === 224 /* VariableDeclaration */ || containingNodeKind === 132 /* EnumDeclaration */;

                        case 72 /* OpenParenToken */:
                            return containingNodeKind === 227 /* ParameterList */ || containingNodeKind === 236 /* CatchClause */;

                        case 70 /* OpenBraceToken */:
                            return containingNodeKind === 132 /* EnumDeclaration */;

                        case 57 /* PublicKeyword */:
                        case 55 /* PrivateKeyword */:
                        case 58 /* StaticKeyword */:
                        case 77 /* DotDotDotToken */:
                            return containingNodeKind === 242 /* Parameter */;

                        case 44 /* ClassKeyword */:
                        case 65 /* ModuleKeyword */:
                        case 46 /* EnumKeyword */:
                        case 52 /* InterfaceKeyword */:
                        case 27 /* FunctionKeyword */:
                        case 40 /* VarKeyword */:
                        case 64 /* GetKeyword */:
                        case 68 /* SetKeyword */:
                            return true;
                    }

                    switch (positionedToken.text()) {
                        case "class":
                        case "interface":
                        case "enum":
                        case "module":
                            return true;
                    }
                }

                return false;
            };

            CompletionHelpers.getNonIdentifierCompleteTokenOnLeft = function (sourceUnit, position) {
                var positionedToken = TypeScript.Syntax.findCompleteTokenOnLeft(sourceUnit, position, true);

                if (positionedToken && position === TypeScript.end(positionedToken) && positionedToken.kind() == 10 /* EndOfFileToken */) {
                    // EndOfFile token is not intresting, get the one before it
                    positionedToken = TypeScript.previousToken(positionedToken, true);
                }

                if (positionedToken && position === TypeScript.end(positionedToken) && positionedToken.kind() === 11 /* IdentifierName */) {
                    // The caret is at the end of an identifier, the decession to provide completion depends on the previous token
                    positionedToken = TypeScript.previousToken(positionedToken, true);
                }

                return positionedToken;
            };

            CompletionHelpers.isRightOfIllegalDot = function (sourceUnit, position) {
                var positionedToken = CompletionHelpers.getNonIdentifierCompleteTokenOnLeft(sourceUnit, position);

                if (positionedToken) {
                    switch (positionedToken.kind()) {
                        case 76 /* DotToken */:
                            var leftOfDotPositionedToken = TypeScript.previousToken(positionedToken, true);
                            return leftOfDotPositionedToken && leftOfDotPositionedToken.kind() === 13 /* NumericLiteral */;

                        case 13 /* NumericLiteral */:
                            var text = positionedToken.text();
                            return text.charAt(text.length - 1) === ".";
                    }
                }

                return false;
            };

            CompletionHelpers.getValidCompletionEntryDisplayName = function (displayName) {
                if (displayName && displayName.length > 0) {
                    var firstChar = displayName.charCodeAt(0);
                    if (firstChar === 39 /* singleQuote */ || firstChar === 34 /* doubleQuote */) {
                        // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
                        // invalid identifer name. We need to check if whatever was inside the quotes is actually a valid identifier name.
                        displayName = TypeScript.stripStartAndEndQuotes(displayName);
                    }

                    if (TypeScript.Scanner.isValidIdentifier(TypeScript.SimpleText.fromString(displayName), 1 /* EcmaScript5 */)) {
                        return displayName;
                    }
                }

                return null;
            };
            return CompletionHelpers;
        })();
        Services.CompletionHelpers = CompletionHelpers;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var KeywordCompletions = (function () {
            function KeywordCompletions() {
            }
            KeywordCompletions.getKeywordCompltions = function () {
                if (KeywordCompletions.keywordCompletions === null) {
                    var completions = [];
                    for (var i = 0, n = KeywordCompletions.keywords.length; i < n; i++) {
                        var keyword = KeywordCompletions.keywords[i];
                        var entry = new Services.ResolvedCompletionEntry(keyword, Services.ScriptElementKind.keyword, Services.ScriptElementKindModifier.none, null, keyword, null);
                        completions.push(entry);
                    }

                    KeywordCompletions.keywordCompletions = completions;
                }

                return KeywordCompletions.keywordCompletions;
            };
            KeywordCompletions.keywords = [
                "break",
                "case",
                "catch",
                "class",
                "constructor",
                "continue",
                "debugger",
                "declare",
                "default",
                "delete",
                "do",
                "else",
                "enum",
                "export",
                "extends",
                "false",
                "finally",
                "for",
                "function",
                "get",
                "if",
                "implements",
                "import",
                "in",
                "instanceof",
                "interface",
                "module",
                "new",
                "null",
                "private",
                "public",
                "require",
                "return",
                "set",
                "static",
                "super",
                "switch",
                "this",
                "throw",
                "true",
                "try",
                "typeof",
                "var",
                "while",
                "with"
            ];

            KeywordCompletions.keywordCompletions = null;
            return KeywordCompletions;
        })();
        Services.KeywordCompletions = KeywordCompletions;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var SignatureInfoHelpers = (function () {
            function SignatureInfoHelpers() {
            }
            // A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
            // or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
            // To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
            // will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
            // looking up the type. The method will also keep track of the parameter index inside the expression.
            SignatureInfoHelpers.isInPartiallyWrittenTypeArgumentList = function (syntaxTree, position) {
                var token = TypeScript.Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, true);

                if (token && TypeScript.Syntax.hasAncestorOfKind(token, 229 /* TypeParameterList */)) {
                    // We are in the wrong generic list. bail out
                    return null;
                }

                var stack = 0;
                var argumentIndex = 0;

                whileLoop:
                while (token) {
                    switch (token.kind()) {
                        case 80 /* LessThanToken */:
                            if (stack === 0) {
                                // Found the beginning of the generic argument expression
                                var lessThanToken = token;
                                token = TypeScript.previousToken(token, true);
                                if (!token || token.kind() !== 11 /* IdentifierName */) {
                                    break whileLoop;
                                }

                                // Found the name, return the data
                                return {
                                    genericIdentifer: token,
                                    lessThanToken: lessThanToken,
                                    argumentIndex: argumentIndex
                                };
                            } else if (stack < 0) {
                                break whileLoop;
                            } else {
                                stack--;
                            }

                            break;

                        case 97 /* GreaterThanGreaterThanGreaterThanToken */:
                            stack++;

                        case 81 /* GreaterThanToken */:
                            stack++;
                            break;

                        case 79 /* CommaToken */:
                            if (stack == 0) {
                                argumentIndex++;
                            }

                            break;

                        case 71 /* CloseBraceToken */:
                            // This can be object type, skip untill we find the matching open brace token
                            var unmatchedOpenBraceTokens = 0;

                            // Skip untill the matching open brace token
                            token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, 71 /* CloseBraceToken */, 70 /* OpenBraceToken */);
                            if (!token) {
                                break whileLoop;
                            }

                            break;

                        case 85 /* EqualsGreaterThanToken */:
                            // This can be a function type or a constructor type. In either case, we want to skip the function defintion
                            token = TypeScript.previousToken(token, true);

                            if (token && token.kind() === 73 /* CloseParenToken */) {
                                // Skip untill the matching open paren token
                                token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, 73 /* CloseParenToken */, 72 /* OpenParenToken */);

                                if (token && token.kind() === 81 /* GreaterThanToken */) {
                                    // Another generic type argument list, skip it\
                                    token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, 81 /* GreaterThanToken */, 80 /* LessThanToken */);
                                }

                                if (token && token.kind() === 31 /* NewKeyword */) {
                                    // In case this was a constructor type, skip the new keyword
                                    token = TypeScript.previousToken(token, true);
                                }

                                if (!token) {
                                    break whileLoop;
                                }
                            } else {
                                break whileLoop;
                            }

                            break;

                        case 11 /* IdentifierName */:
                        case 60 /* AnyKeyword */:
                        case 67 /* NumberKeyword */:
                        case 69 /* StringKeyword */:
                        case 41 /* VoidKeyword */:
                        case 61 /* BooleanKeyword */:
                        case 76 /* DotToken */:
                        case 74 /* OpenBracketToken */:
                        case 75 /* CloseBracketToken */:
                            break;

                        default:
                            break whileLoop;
                    }

                    token = TypeScript.previousToken(token, true);
                }

                return null;
            };

            SignatureInfoHelpers.getSignatureInfoFromSignatureSymbol = function (symbol, signatures, enclosingScopeSymbol, compilerState) {
                var signatureGroup = [];

                var hasOverloads = signatures.length > 1;

                for (var i = 0, n = signatures.length; i < n; i++) {
                    var signature = signatures[i];

                    // filter out the definition signature if there are overloads
                    if (hasOverloads && signature.isDefinition()) {
                        continue;
                    }

                    var signatureGroupInfo = new Services.FormalSignatureItemInfo();
                    var paramIndexInfo = [];
                    var functionName = signature.getScopedNameEx(enclosingScopeSymbol).toString();
                    if (!functionName && (!symbol.isType() || symbol.isNamedTypeSymbol())) {
                        functionName = symbol.getScopedNameEx(enclosingScopeSymbol).toString();
                    }

                    var signatureMemberName = signature.getSignatureTypeNameEx(functionName, false, false, enclosingScopeSymbol, true, true);
                    signatureGroupInfo.signatureInfo = TypeScript.MemberName.memberNameToString(signatureMemberName, paramIndexInfo);
                    signatureGroupInfo.docComment = signature.docComments();

                    var parameterMarkerIndex = 0;

                    if (signature.isGeneric()) {
                        var typeParameters = signature.getTypeParameters();
                        for (var j = 0, m = typeParameters.length; j < m; j++) {
                            var typeParameter = typeParameters[j];
                            var signatureTypeParameterInfo = new Services.FormalTypeParameterInfo();
                            signatureTypeParameterInfo.name = typeParameter.getDisplayName();
                            signatureTypeParameterInfo.docComment = typeParameter.docComments();
                            signatureTypeParameterInfo.minChar = paramIndexInfo[2 * parameterMarkerIndex];
                            signatureTypeParameterInfo.limChar = paramIndexInfo[2 * parameterMarkerIndex + 1];
                            parameterMarkerIndex++;
                            signatureGroupInfo.typeParameters.push(signatureTypeParameterInfo);
                        }
                    }

                    var parameters = signature.parameters;
                    for (var j = 0, m = parameters.length; j < m; j++) {
                        var parameter = parameters[j];
                        var signatureParameterInfo = new Services.FormalParameterInfo();
                        signatureParameterInfo.isVariable = signature.hasVarArgs && (j === parameters.length - 1);
                        signatureParameterInfo.name = parameter.getDisplayName();
                        signatureParameterInfo.docComment = parameter.docComments();
                        signatureParameterInfo.minChar = paramIndexInfo[2 * parameterMarkerIndex];
                        signatureParameterInfo.limChar = paramIndexInfo[2 * parameterMarkerIndex + 1];
                        parameterMarkerIndex++;
                        signatureGroupInfo.parameters.push(signatureParameterInfo);
                    }

                    signatureGroup.push(signatureGroupInfo);
                }

                return signatureGroup;
            };

            SignatureInfoHelpers.getSignatureInfoFromGenericSymbol = function (symbol, enclosingScopeSymbol, compilerState) {
                var signatureGroupInfo = new Services.FormalSignatureItemInfo();

                var paramIndexInfo = [];
                var symbolName = symbol.getScopedNameEx(enclosingScopeSymbol, false, true, false, true);

                signatureGroupInfo.signatureInfo = TypeScript.MemberName.memberNameToString(symbolName, paramIndexInfo);
                signatureGroupInfo.docComment = symbol.docComments();

                var parameterMarkerIndex = 0;

                var typeSymbol = symbol.type;

                var typeParameters = typeSymbol.getTypeParameters();
                for (var i = 0, n = typeParameters.length; i < n; i++) {
                    var typeParameter = typeParameters[i];
                    var signatureTypeParameterInfo = new Services.FormalTypeParameterInfo();
                    signatureTypeParameterInfo.name = typeParameter.getDisplayName();
                    signatureTypeParameterInfo.docComment = typeParameter.docComments();
                    signatureTypeParameterInfo.minChar = paramIndexInfo[2 * i];
                    signatureTypeParameterInfo.limChar = paramIndexInfo[2 * i + 1];
                    signatureGroupInfo.typeParameters.push(signatureTypeParameterInfo);
                }

                return [signatureGroupInfo];
            };

            SignatureInfoHelpers.getActualSignatureInfoFromCallExpression = function (ast, caretPosition, typeParameterInformation) {
                if (!ast) {
                    return null;
                }

                var result = new Services.ActualSignatureInfo();

                // The expression is not guaranteed to be complete, we need to populate the min and lim with the most accurate information we have about
                // type argument and argument lists
                var parameterMinChar = caretPosition;
                var parameterLimChar = caretPosition;

                if (ast.argumentList.typeArgumentList) {
                    parameterMinChar = Math.min(TypeScript.start(ast.argumentList.typeArgumentList));
                    parameterLimChar = Math.max(Math.max(TypeScript.start(ast.argumentList.typeArgumentList), TypeScript.end(ast.argumentList.typeArgumentList) + TypeScript.trailingTriviaWidth(ast.argumentList.typeArgumentList)));
                }

                if (ast.argumentList.arguments) {
                    parameterMinChar = Math.min(parameterMinChar, TypeScript.end(ast.argumentList.openParenToken));
                    parameterLimChar = Math.max(parameterLimChar, ast.argumentList.closeParenToken.fullWidth() > 0 ? TypeScript.start(ast.argumentList.closeParenToken) : TypeScript.fullEnd(ast.argumentList));
                }

                result.parameterMinChar = parameterMinChar;
                result.parameterLimChar = parameterLimChar;
                result.currentParameterIsTypeParameter = false;
                result.currentParameter = -1;

                if (typeParameterInformation) {
                    result.currentParameterIsTypeParameter = true;
                    result.currentParameter = typeParameterInformation.argumentIndex;
                } else if (ast.argumentList.arguments && ast.argumentList.arguments.length > 0) {
                    result.currentParameter = 0;
                    for (var index = 0; index < ast.argumentList.arguments.length; index++) {
                        if (caretPosition > TypeScript.end(ast.argumentList.arguments[index]) + TypeScript.lastToken(ast.argumentList.arguments[index]).trailingTriviaWidth()) {
                            result.currentParameter++;
                        }
                    }
                }

                return result;
            };

            SignatureInfoHelpers.getActualSignatureInfoFromPartiallyWritenGenericExpression = function (caretPosition, typeParameterInformation) {
                var result = new Services.ActualSignatureInfo();

                result.parameterMinChar = TypeScript.start(typeParameterInformation.lessThanToken);
                result.parameterLimChar = Math.max(TypeScript.fullEnd(typeParameterInformation.lessThanToken), caretPosition);
                result.currentParameterIsTypeParameter = true;
                result.currentParameter = typeParameterInformation.argumentIndex;

                return result;
            };

            SignatureInfoHelpers.isSignatureHelpBlocker = function (sourceUnit, position) {
                // We shouldn't be getting a possition that is outside the file because
                // isEntirelyInsideComment can't handle when the position is out of bounds,
                // callers should be fixed, however we should be resiliant to bad inputs
                // so we return true (this position is a blocker for getting signature help)
                if (position < 0 || position > TypeScript.fullWidth(sourceUnit)) {
                    return true;
                }

                return TypeScript.Syntax.isEntirelyInsideComment(sourceUnit, position);
            };

            SignatureInfoHelpers.isTargetOfObjectCreationExpression = function (positionedToken) {
                var positionedParent = TypeScript.Syntax.getAncestorOfKind(positionedToken, 216 /* ObjectCreationExpression */);
                if (positionedParent) {
                    var objectCreationExpression = positionedParent;
                    var expressionRelativeStart = objectCreationExpression.newKeyword.fullWidth();
                    var tokenRelativeStart = positionedToken.fullStart() - TypeScript.fullStart(positionedParent);
                    return tokenRelativeStart >= expressionRelativeStart && tokenRelativeStart <= (expressionRelativeStart + TypeScript.fullWidth(objectCreationExpression.expression));
                }

                return false;
            };

            SignatureInfoHelpers.moveBackUpTillMatchingTokenKind = function (token, tokenKind, matchingTokenKind) {
                if (!token || token.kind() !== tokenKind) {
                    throw TypeScript.Errors.invalidOperation();
                }

                // Skip the current token
                token = TypeScript.previousToken(token, true);

                var stack = 0;

                while (token) {
                    if (token.kind() === matchingTokenKind) {
                        if (stack === 0) {
                            // Found the matching token, return
                            return token;
                        } else if (stack < 0) {
                            break;
                        } else {
                            stack--;
                        }
                    } else if (token.kind() === tokenKind) {
                        stack++;
                    }

                    // Move back
                    token = TypeScript.previousToken(token, true);
                }

                // Did not find matching token
                return null;
            };
            return SignatureInfoHelpers;
        })();
        Services.SignatureInfoHelpers = SignatureInfoHelpers;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
///<reference path='references.ts' />
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        var ResolvedCompletionEntry = (function () {
            function ResolvedCompletionEntry(name, kind, kindModifiers, type, fullSymbolName, docComment) {
                this.name = name;
                this.kind = kind;
                this.kindModifiers = kindModifiers;
                this.type = type;
                this.fullSymbolName = fullSymbolName;
                this.docComment = docComment;
            }
            ResolvedCompletionEntry.prototype.isResolved = function () {
                return true;
            };
            return ResolvedCompletionEntry;
        })();
        Services.ResolvedCompletionEntry = ResolvedCompletionEntry;

        var DeclReferenceCompletionEntry = (function () {
            function DeclReferenceCompletionEntry(name, kind, kindModifiers, decl) {
                this.name = name;
                this.kind = kind;
                this.kindModifiers = kindModifiers;
                this.decl = decl;
                this.type = null;
                this.fullSymbolName = null;
                this.docComment = null;
                this.hasBeenResolved = false;
            }
            DeclReferenceCompletionEntry.prototype.isResolved = function () {
                return this.hasBeenResolved;
            };

            DeclReferenceCompletionEntry.prototype.resolve = function (type, fullSymbolName, docComments) {
                this.type = type;
                this.fullSymbolName = fullSymbolName;
                this.docComment = docComments;
                this.hasBeenResolved = true;
            };
            return DeclReferenceCompletionEntry;
        })();
        Services.DeclReferenceCompletionEntry = DeclReferenceCompletionEntry;

        var CompletionSession = (function () {
            function CompletionSession(fileName, position, entries) {
                this.fileName = fileName;
                this.position = position;
                this.entries = entries;
            }
            return CompletionSession;
        })();
        Services.CompletionSession = CompletionSession;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var LanguageService = (function () {
            function LanguageService(host, documentRegistry) {
                this.host = host;
                this.activeCompletionSession = null;
                this.logger = this.host;
                this.cancellationToken = new TypeScript.CancellationToken(this.host.getCancellationToken());
                this.compiler = new Services.LanguageServiceCompiler(this.host, documentRegistry, this.cancellationToken);
                this._syntaxTreeCache = new Services.SyntaxTreeCache(this.host);

                // Check if the localized messages json is set, otherwise query the host for it
                if (!TypeScript.LocalizedDiagnosticMessages) {
                    TypeScript.LocalizedDiagnosticMessages = this.host.getLocalizedDiagnosticMessages();
                }
            }
            LanguageService.prototype.dispose = function () {
                this.compiler.dispose();
            };

            LanguageService.prototype.cleanupSemanticCache = function () {
                this.compiler.cleanupSemanticCache();
            };

            LanguageService.prototype.refresh = function () {
                // No-op.  Only kept around for compatability with the interface we shipped.
            };

            LanguageService.prototype.getSemanticInfoChain = function () {
                return this.compiler.getSemanticInfoChain();
            };

            LanguageService.prototype.getSymbolInfoAtPosition = function (fileName, pos, requireName) {
                var document = this.compiler.getDocument(fileName);
                var sourceUnit = document.sourceUnit();

                /// TODO: this does not allow getting references on "constructor"
                var topNode = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, pos);
                return this.getSymbolInfoAtAST(document, topNode, pos, requireName);
            };

            LanguageService.prototype.getSymbolInfoAtAST = function (document, topNode, pos, requireName) {
                if (topNode === null || (requireName && topNode.kind() !== 11 /* IdentifierName */)) {
                    this.logger.log("No name found at the given position");
                    return null;
                }

                // Store the actual name before calling getSymbolInformationFromPath
                var symbolInfoAtPosition = this.compiler.getSymbolInformationFromAST(topNode, document);
                if (symbolInfoAtPosition === null || (symbolInfoAtPosition.symbol === null && symbolInfoAtPosition.aliasSymbol)) {
                    this.logger.log("No symbol found at the given position");

                    // only single reference
                    return { symbol: null, containingASTOpt: null };
                }

                var symbol = symbolInfoAtPosition.aliasSymbol || symbolInfoAtPosition.symbol;
                var symbolName = symbol.getName();

                // if we are not looking for any but we get an any symbol, then we ran into a wrong symbol
                if (requireName) {
                    var actualNameAtPosition = TypeScript.tokenValueText(topNode);

                    if ((symbol.isError() || symbol.isAny()) && actualNameAtPosition !== symbolName) {
                        this.logger.log("Unknown symbol found at the given position");

                        // only single reference
                        return { symbol: null, containingASTOpt: null };
                    }
                }

                var containingASTOpt = this.getSymbolScopeAST(symbol, topNode);

                return { symbol: symbol, containingASTOpt: containingASTOpt };
            };

            LanguageService.prototype.getReferencesAtPosition = function (fileName, pos) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var symbolAndContainingAST = this.getSymbolInfoAtPosition(fileName, pos, true);
                if (symbolAndContainingAST === null) {
                    // Didn't even have a name at that position.
                    return [];
                }

                if (symbolAndContainingAST.symbol === null) {
                    // Had a name, but couldn't bind it to anything.
                    return this.getSingleNodeReferenceAtPosition(fileName, pos);
                }

                var result = [];
                var symbol = symbolAndContainingAST.symbol;
                var symbolName = symbol.getName();
                var containingASTOpt = symbolAndContainingAST.containingASTOpt;

                var fileNames = this.compiler.fileNames();
                for (var i = 0, n = fileNames.length; i < n; i++) {
                    this.cancellationToken.throwIfCancellationRequested();

                    var tempFileName = fileNames[i];

                    if (containingASTOpt && fileName != tempFileName) {
                        continue;
                    }

                    var tempDocument = this.compiler.getDocument(tempFileName);
                    var filter = tempDocument.bloomFilter();

                    if (filter.probablyContains(symbolName)) {
                        result = result.concat(this.getReferencesInFile(tempFileName, symbol, containingASTOpt));
                    }
                }

                return result;
            };

            LanguageService.prototype.getSymbolScopeAST = function (symbol, ast) {
                if (symbol.kind === TypeScript.PullElementKind.TypeParameter && symbol.getDeclarations().length > 0 && symbol.getDeclarations()[0].getParentDecl() && symbol.getDeclarations()[0].getParentDecl().kind === TypeScript.PullElementKind.Method) {
                    while (ast) {
                        if (ast.kind() === 129 /* FunctionDeclaration */ || ast.kind() === 135 /* MemberFunctionDeclaration */) {
                            return ast;
                        }

                        ast = ast.parent;
                    }
                }

                // Todo: we could add more smarts about things like local variables and parameters here.
                return null;
            };

            LanguageService.prototype.getOccurrencesAtPosition = function (fileName, pos) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var symbolAndContainingAST = this.getSymbolInfoAtPosition(fileName, pos, true);
                if (symbolAndContainingAST === null) {
                    // Didn't even have a name at that position.
                    return [];
                }

                if (symbolAndContainingAST.symbol === null) {
                    // Had a name, but couldn't bind it to anything.
                    return this.getSingleNodeReferenceAtPosition(fileName, pos);
                }

                var symbol = symbolAndContainingAST.symbol;
                var containingASTOpt = symbolAndContainingAST.containingASTOpt;

                return this.getReferencesInFile(fileName, symbol, containingASTOpt);
            };

            LanguageService.prototype.getSingleNodeReferenceAtPosition = function (fileName, position) {
                var document = this.compiler.getDocument(fileName);
                var sourceUnit = document.sourceUnit();

                var node = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, position);
                if (node === null || node.kind() !== 11 /* IdentifierName */) {
                    return [];
                }

                var isWriteAccess = this.isWriteAccess(node);
                return [new Services.ReferenceEntry(this._getHostFileName(fileName), TypeScript.start(node), TypeScript.end(node), isWriteAccess)];
            };

            LanguageService.prototype.getImplementorsAtPosition = function (fileName, pos) {
                var _this = this;
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var result = [];

                var document = this.compiler.getDocument(fileName);
                var sourceUnit = document.sourceUnit();

                var ast = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, pos);
                if (ast === null || ast.kind() !== 11 /* IdentifierName */) {
                    this.logger.log("No identifier at the specified location.");
                    return result;
                }

                // Store the actual name before calling getSymbolInformationFromPath
                var actualNameAtPosition = TypeScript.tokenValueText(ast);

                var symbolInfoAtPosition = this.compiler.getSymbolInformationFromAST(ast, document);
                var symbol = symbolInfoAtPosition.symbol;

                if (symbol === null) {
                    this.logger.log("No symbol annotation on the identifier ISyntaxElement.");
                    return result;
                }

                var symbolName = symbol.getName();

                // if we are not looking for any but we get an any symbol, then we ran into a wrong symbol
                if ((symbol.isError() || symbol.isAny()) && actualNameAtPosition !== symbolName) {
                    this.logger.log("Unknown symbol found at the given position");
                    return result;
                }

                var typeSymbol = symbol.type;
                var typesToSearch;

                if (typeSymbol.isClass() || typeSymbol.isInterface()) {
                    typesToSearch = typeSymbol.getTypesThatExtendThisType();
                } else if (symbol.kind == TypeScript.PullElementKind.Property || typeSymbol.isMethod() || typeSymbol.isProperty()) {
                    var declaration = symbol.getDeclarations()[0];
                    var classSymbol = declaration.getParentDecl().getSymbol(symbol.semanticInfoChain).type;

                    typesToSearch = [];
                    var extendingTypes = classSymbol.getTypesThatExtendThisType();
                    var extendedTypes = classSymbol.getExtendedTypes();
                    extendingTypes.forEach(function (type) {
                        var overrides = _this.getOverrides(type, symbol);
                        overrides.forEach(function (override) {
                            typesToSearch.push(override);
                        });
                    });
                    extendedTypes.forEach(function (type) {
                        var overrides = _this.getOverrides(type, symbol);
                        overrides.forEach(function (override) {
                            typesToSearch.push(override);
                        });
                    });
                }

                if (typesToSearch) {
                    var fileNames = this.compiler.fileNames();
                    for (var i = 0, n = fileNames.length; i < n; i++) {
                        var tempFileName = fileNames[i];

                        var tempDocument = this.compiler.getDocument(tempFileName);
                        var filter = tempDocument.bloomFilter();

                        typesToSearch.forEach(function (typeToSearch) {
                            var symbolName = typeToSearch.getName();
                            if (filter.probablyContains(symbolName)) {
                                result = result.concat(_this.getImplementorsInFile(tempFileName, typeToSearch));
                            }
                        });
                    }
                }
                return result;
            };

            LanguageService.prototype.getOverrides = function (container, memberSym) {
                var result = [];
                var members;
                if (container.isClass()) {
                    members = container.getMembers();
                } else if (container.isInterface()) {
                    members = container.getMembers();
                }

                if (members == null)
                    return null;

                members.forEach(function (member) {
                    var typeMember = member;
                    if (typeMember.getName() === memberSym.getName()) {
                        // Not currently checking whether static-ness matches: typeMember.isStatic() === memberSym.isStatic() or whether
                        //  typeMember.isMethod() === memberSym.isMethod() && typeMember.isProperty() === memberSym.isProperty()
                        result.push(typeMember);
                    }
                });

                return result;
            };

            LanguageService.prototype.getImplementorsInFile = function (fileName, symbol) {
                var _this = this;
                var result = [];
                var symbolName = symbol.getDisplayName();

                var possiblePositions = this.getPossibleSymbolReferencePositions(fileName, symbolName);
                if (possiblePositions && possiblePositions.length > 0) {
                    var document = this.compiler.getDocument(fileName);
                    var sourceUnit = document.sourceUnit();

                    possiblePositions.forEach(function (p) {
                        var nameAST = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, p);
                        if (nameAST === null || nameAST.kind() !== 11 /* IdentifierName */) {
                            return;
                        }
                        var searchSymbolInfoAtPosition = _this.compiler.getSymbolInformationFromAST(nameAST, document);
                        if (searchSymbolInfoAtPosition !== null) {
                            var normalizedSymbol;
                            if (symbol.kind === TypeScript.PullElementKind.Class || symbol.kind === TypeScript.PullElementKind.Interface) {
                                normalizedSymbol = searchSymbolInfoAtPosition.symbol.type;
                            } else {
                                var declaration = searchSymbolInfoAtPosition.symbol.getDeclarations()[0];
                                normalizedSymbol = declaration.getSymbol(symbol.semanticInfoChain);
                            }

                            if (normalizedSymbol === symbol) {
                                var isWriteAccess = _this.isWriteAccess(nameAST);

                                result.push(new Services.ReferenceEntry(_this._getHostFileName(fileName), TypeScript.start(nameAST), TypeScript.end(nameAST), isWriteAccess));
                            }
                        }
                    });
                }

                return result;
            };

            LanguageService.prototype.getReferencesInFile = function (fileName, symbol, containingASTOpt) {
                var _this = this;
                var result = [];
                var symbolName = symbol.getDisplayName();

                var possiblePositions = this.getPossibleSymbolReferencePositions(fileName, symbolName);
                if (possiblePositions && possiblePositions.length > 0) {
                    var document = this.compiler.getDocument(fileName);
                    var sourceUnit = document.sourceUnit();

                    possiblePositions.forEach(function (p) {
                        _this.cancellationToken.throwIfCancellationRequested();

                        // If it's not in the bounds of the ISyntaxElement we're asking for, then this can't possibly be a hit.
                        if (containingASTOpt && (p < TypeScript.start(containingASTOpt) || p > TypeScript.end(containingASTOpt))) {
                            return;
                        }

                        // Each position we're searching for should be at the start of an identifier.
                        // As such, we useTrailingTriviaAsLimChar=false so that the position doesn't
                        // accidently return another node (which may end at that position).
                        var nameAST = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, p, false);

                        // Compare the length so we filter out strict superstrings of the symbol we are looking for
                        if (nameAST === null || nameAST.kind() !== 11 /* IdentifierName */ || (TypeScript.end(nameAST) - TypeScript.start(nameAST) !== symbolName.length)) {
                            return;
                        }

                        var symbolInfoAtPosition = _this.compiler.getSymbolInformationFromAST(nameAST, document);
                        if (symbolInfoAtPosition !== null) {
                            var searchSymbol = symbolInfoAtPosition.aliasSymbol || symbolInfoAtPosition.symbol;

                            if (Services.FindReferenceHelpers.compareSymbolsForLexicalIdentity(searchSymbol, symbol)) {
                                var isWriteAccess = _this.isWriteAccess(nameAST);
                                result.push(new Services.ReferenceEntry(_this._getHostFileName(fileName), TypeScript.start(nameAST), TypeScript.end(nameAST), isWriteAccess));
                            }
                        }
                    });
                }

                return result;
            };

            LanguageService.prototype.isWriteAccess = function (current) {
                var parent = current.parent;
                if (parent !== null) {
                    var parentNodeType = parent.kind();
                    switch (parentNodeType) {
                        case 131 /* ClassDeclaration */:
                            return parent.identifier === current;

                        case 128 /* InterfaceDeclaration */:
                            return parent.identifier === current;

                        case 130 /* ModuleDeclaration */:
                            return parent.name === current || parent.stringLiteral === current;

                        case 129 /* FunctionDeclaration */:
                            return parent.identifier === current;

                        case 133 /* ImportDeclaration */:
                            return parent.identifier === current;

                        case 225 /* VariableDeclarator */:
                            var varDeclarator = parent;
                            return !!(varDeclarator.equalsValueClause && varDeclarator.propertyName === current);

                        case 242 /* Parameter */:
                            return true;

                        case 174 /* AssignmentExpression */:
                        case 175 /* AddAssignmentExpression */:
                        case 176 /* SubtractAssignmentExpression */:
                        case 177 /* MultiplyAssignmentExpression */:
                        case 178 /* DivideAssignmentExpression */:
                        case 179 /* ModuloAssignmentExpression */:
                        case 182 /* OrAssignmentExpression */:
                        case 180 /* AndAssignmentExpression */:
                        case 181 /* ExclusiveOrAssignmentExpression */:
                        case 183 /* LeftShiftAssignmentExpression */:
                        case 185 /* UnsignedRightShiftAssignmentExpression */:
                        case 184 /* SignedRightShiftAssignmentExpression */:
                            return parent.left === current;

                        case 168 /* PreIncrementExpression */:
                        case 210 /* PostIncrementExpression */:
                            return true;

                        case 169 /* PreDecrementExpression */:
                        case 211 /* PostDecrementExpression */:
                            return true;
                    }
                }

                return false;
            };

            LanguageService.prototype.isLetterOrDigit = function (char) {
                return (char >= 97 /* a */ && char <= 122 /* z */) || (char >= 65 /* A */ && char <= 90 /* Z */) || (char >= 48 /* _0 */ && char <= 57 /* _9 */) || char === 95 /* _ */ || char === 36 /* $ */ || (char > 127 && TypeScript.Unicode.isIdentifierPart(char, 1 /* EcmaScript5 */));
            };

            LanguageService.prototype.getPossibleSymbolReferencePositions = function (fileName, symbolName) {
                var positions = [];

                /// TODO: Cache symbol existence for files to save text search
                // Also, need to make this work for unicode escapes.
                // Be reseliant in the face of a symbol with no name or zero length name
                if (!symbolName || !symbolName.length) {
                    return positions;
                }

                var sourceText = this.compiler.getScriptSnapshot(fileName);

                var sourceLength = sourceText.getLength();
                var text = sourceText.getText(0, sourceLength);
                var symbolNameLength = symbolName.length;

                var position = text.indexOf(symbolName);
                while (position >= 0) {
                    this.cancellationToken.throwIfCancellationRequested();

                    // We found a match.  Make sure it's not part of a larger word (i.e. the char
                    // before and after it have to be a non-identifier char).
                    var endPosition = position + symbolNameLength;

                    if ((position <= 0 || !this.isLetterOrDigit(text.charCodeAt(position - 1))) && (endPosition >= sourceLength || !this.isLetterOrDigit(text.charCodeAt(endPosition)))) {
                        // Found a real match.  Keep searching.
                        positions.push(position);
                    }

                    position = text.indexOf(symbolName, position + symbolNameLength + 1);
                }

                return positions;
            };

            LanguageService.prototype.getSignatureAtPosition = function (fileName, position) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var document = this.compiler.getDocument(fileName);

                // First check whether we are in a comment where signature help should not be displayed
                //if (!SignatureInfoHelpers.isSignatureHelpTriggerPosition(document.syntaxTree().sourceUnit(), position)) {
                //    this.logger.log("position is not a valid singature help location");
                //    return null;
                //}
                if (Services.SignatureInfoHelpers.isSignatureHelpBlocker(document.syntaxTree().sourceUnit(), position)) {
                    this.logger.log("position is not a valid singature help location");
                    return null;
                }

                // Second check if we are inside a generic parameter
                var genericTypeArgumentListInfo = Services.SignatureInfoHelpers.isInPartiallyWrittenTypeArgumentList(document.syntaxTree(), position);
                if (genericTypeArgumentListInfo) {
                    // The expression could be messed up because we are parsing a partial generic expression, so set the search path to a place where we know it
                    // can find a call expression
                    return this.getTypeParameterSignatureFromPartiallyWrittenExpression(document, position, genericTypeArgumentListInfo);
                }

                // Third set the path to find ask the type system about the call expression
                var sourceUnit = document.sourceUnit();
                var node = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, position);
                if (!node) {
                    return null;
                }

                while (node) {
                    if (node.kind() === 213 /* InvocationExpression */ || node.kind() === 216 /* ObjectCreationExpression */ || (isSignatureHelpBlocker(node) && position > TypeScript.start(node))) {
                        break;
                    }

                    node = node.parent;
                }

                if (!node) {
                    return null;
                }

                if (node.kind() !== 213 /* InvocationExpression */ && node.kind() !== 216 /* ObjectCreationExpression */) {
                    this.logger.log("No call expression or generic arguments found for the given position");
                    return null;
                }

                var callExpression = node;
                var isNew = (callExpression.kind() === 216 /* ObjectCreationExpression */);

                if (isNew && callExpression.argumentList === null) {
                    this.logger.log("No signature help for a object creation expression without arguments");
                    return null;
                }

                TypeScript.Debug.assert(callExpression.argumentList.arguments !== null, "Expected call expression to have arguments, but it did not");

                var argumentsStart = TypeScript.end(callExpression.argumentList.openParenToken);
                var argumentsEnd = callExpression.argumentList.closeParenToken.fullWidth() > 0 ? TypeScript.start(callExpression.argumentList.closeParenToken) : TypeScript.fullEnd(callExpression.argumentList);

                if (position < argumentsStart || position > argumentsEnd) {
                    this.logger.log("Outside argument list");
                    return null;
                }

                // Resolve symbol
                var callSymbolInfo = this.compiler.getCallInformationFromAST(node, document);
                if (!callSymbolInfo || !callSymbolInfo.targetSymbol || !callSymbolInfo.resolvedSignatures) {
                    this.logger.log("Could not find symbol for call expression");
                    return null;
                }

                // Build the result
                var result = new Services.SignatureInfo();

                result.formal = Services.SignatureInfoHelpers.getSignatureInfoFromSignatureSymbol(callSymbolInfo.targetSymbol, callSymbolInfo.resolvedSignatures, callSymbolInfo.enclosingScopeSymbol, this.compiler);
                result.actual = Services.SignatureInfoHelpers.getActualSignatureInfoFromCallExpression(callExpression, position, genericTypeArgumentListInfo);
                result.activeFormal = (callSymbolInfo.resolvedSignatures && callSymbolInfo.candidateSignature) ? callSymbolInfo.resolvedSignatures.indexOf(callSymbolInfo.candidateSignature) : -1;

                if (result.actual === null || result.formal === null || result.activeFormal === null) {
                    this.logger.log("Can't compute actual and/or formal signature of the call expression");
                    return null;
                }

                return result;
            };

            LanguageService.prototype.getTypeParameterSignatureFromPartiallyWrittenExpression = function (document, position, genericTypeArgumentListInfo) {
                var sourceUnit = document.sourceUnit();

                // Get the identifier information
                var ast = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, TypeScript.start(genericTypeArgumentListInfo.genericIdentifer));
                if (ast === null || ast.kind() !== 11 /* IdentifierName */) {
                    this.logger.log(["getTypeParameterSignatureAtPosition: Unexpected ast found at position:", position, ast === null ? "ast was null" : "ast kind: " + TypeScript.SyntaxKind[ast.kind()]].join(' '));
                    return null;
                }

                var symbolInformation = this.compiler.getSymbolInformationFromAST(ast, document);

                if (!symbolInformation.symbol) {
                    return null;
                }

                // TODO: are we in an new expression?
                var isNew = Services.SignatureInfoHelpers.isTargetOfObjectCreationExpression(genericTypeArgumentListInfo.genericIdentifer);

                var typeSymbol = symbolInformation.symbol.type;

                if (typeSymbol.kind === TypeScript.PullElementKind.FunctionType || (isNew && typeSymbol.kind === TypeScript.PullElementKind.ConstructorType)) {
                    var signatures = isNew ? typeSymbol.getConstructSignatures() : typeSymbol.getCallSignatures();

                    // Build the result
                    var result = new Services.SignatureInfo();

                    result.formal = Services.SignatureInfoHelpers.getSignatureInfoFromSignatureSymbol(symbolInformation.symbol, signatures, symbolInformation.enclosingScopeSymbol, this.compiler);
                    result.actual = Services.SignatureInfoHelpers.getActualSignatureInfoFromPartiallyWritenGenericExpression(position, genericTypeArgumentListInfo);
                    result.activeFormal = 0;

                    return result;
                } else if (typeSymbol.isGeneric()) {
                    // The symbol is a generic type
                    // Get the class symbol for constuctor symbol
                    if (typeSymbol.kind === TypeScript.PullElementKind.ConstructorType) {
                        typeSymbol = typeSymbol.getAssociatedContainerType();
                    }

                    // Build the result
                    var result = new Services.SignatureInfo();

                    result.formal = Services.SignatureInfoHelpers.getSignatureInfoFromGenericSymbol(typeSymbol, symbolInformation.enclosingScopeSymbol, this.compiler);
                    result.actual = Services.SignatureInfoHelpers.getActualSignatureInfoFromPartiallyWritenGenericExpression(position, genericTypeArgumentListInfo);
                    result.activeFormal = 0;

                    return result;
                }

                // Nothing to handle
                return null;
            };

            LanguageService.prototype.getDefinitionAtPosition = function (fileName, position) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var document = this.compiler.getDocument(fileName);
                var sourceUnit = document.sourceUnit();
                var currentNode = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, position);

                // first check if we are at InvocationExpression\ObjectCreationExpression - if yes then try to obtain concrete overload that was used
                var callExpressionTarget = TypeScript.ASTHelpers.getCallExpressionTarget(currentNode);
                var callInformation = callExpressionTarget && callExpressionTarget.parent && this.compiler.getCallInformationFromAST(callExpressionTarget.parent, document);
                var symbol = callInformation && callInformation.candidateSignature;

                if (!symbol) {
                    var symbolInfo = this.getSymbolInfoAtAST(document, currentNode, position, false);
                    if (symbolInfo === null || symbolInfo.symbol === null) {
                        return null;
                    }

                    var symbol = symbolInfo.symbol;

                    TypeScript.Debug.assert(symbol.kind !== 0 /* None */ && symbol.kind !== 0 /* Global */ && symbol.kind !== TypeScript.PullElementKind.Script, "getDefinitionAtPosition - Invalid symbol kind");

                    if (symbol.kind === TypeScript.PullElementKind.Primitive) {
                        // Primitive symbols do not have definition locations that map to host soruces.
                        // Return null to indicate they have no "definition locations".
                        return null;
                    }
                }

                var declarations = symbol.getDeclarations();
                var symbolName = symbol.getDisplayName();
                var symbolKind = this.mapPullElementKind(symbol.kind, symbol);
                var container = symbol.getContainer();
                var containerName = container ? container.fullName() : "";
                var containerKind = container ? this.mapPullElementKind(container.kind, container) : "";

                var result = [];

                if (!this.tryAddDefinition(symbolKind, symbolName, containerKind, containerName, declarations, result) && !this.tryAddSignatures(symbolKind, symbolName, containerKind, containerName, declarations, result) && !this.tryAddConstructor(symbolKind, symbolName, containerKind, containerName, declarations, result)) {
                    // Just add all the declarations.
                    this.addDeclarations(symbolKind, symbolName, containerKind, containerName, declarations, result);
                }

                return result;
            };

            LanguageService.prototype.addDeclarations = function (symbolKind, symbolName, containerKind, containerName, declarations, result) {
                for (var i = 0, n = declarations.length; i < n; i++) {
                    this.addDeclaration(symbolKind, symbolName, containerKind, containerName, declarations[i], result);
                }
            };

            LanguageService.prototype.addDeclaration = function (symbolKind, symbolName, containerKind, containerName, declaration, result) {
                var ast = declaration.ast();
                result.push(new Services.DefinitionInfo(this._getHostFileName(declaration.fileName()), TypeScript.start(ast), TypeScript.end(ast), symbolKind, symbolName, containerKind, containerName));
            };

            LanguageService.prototype.tryAddDefinition = function (symbolKind, symbolName, containerKind, containerName, declarations, result) {
                var _this = this;
                // First, if there are definitions and signatures, then just pick the definition.
                var definitionDeclaration = TypeScript.ArrayUtilities.firstOrDefault(declarations, function (d) {
                    var signature = d.getSignatureSymbol(_this.getSemanticInfoChain());
                    return signature && signature.isDefinition();
                });

                if (!definitionDeclaration) {
                    return false;
                }

                this.addDeclaration(symbolKind, symbolName, containerKind, containerName, definitionDeclaration, result);
                return true;
            };

            LanguageService.prototype.tryAddSignatures = function (symbolKind, symbolName, containerKind, containerName, declarations, result) {
                var _this = this;
                // We didn't have a definition.  Check and see if we have any signatures.  If so, just
                // add the last one.
                var signatureDeclarations = TypeScript.ArrayUtilities.where(declarations, function (d) {
                    var signature = d.getSignatureSymbol(_this.getSemanticInfoChain());
                    return signature && !signature.isDefinition();
                });

                if (signatureDeclarations.length === 0) {
                    return false;
                }

                this.addDeclaration(symbolKind, symbolName, containerKind, containerName, TypeScript.ArrayUtilities.last(signatureDeclarations), result);
                return true;
            };

            LanguageService.prototype.tryAddConstructor = function (symbolKind, symbolName, containerKind, containerName, declarations, result) {
                var constructorDeclarations = TypeScript.ArrayUtilities.where(declarations, function (d) {
                    return d.kind === TypeScript.PullElementKind.ConstructorMethod;
                });

                if (constructorDeclarations.length === 0) {
                    return false;
                }

                this.addDeclaration(symbolKind, symbolName, containerKind, containerName, TypeScript.ArrayUtilities.last(constructorDeclarations), result);
                return true;
            };

            // Return array of NavigateToItems in which each item has matched name with searchValue. If none is found, return an empty array.
            // The function will search all files (both close and open) in the solutions. SearchValue can be either one search term or multiple terms separated by comma.
            LanguageService.prototype.getNavigateToItems = function (searchValue) {
                var _this = this;
                TypeScript.Debug.assert(searchValue !== null && searchValue !== undefined, "The searchValue argument was not supplied or null");

                // Split search value in terms array
                var terms = searchValue.split(" ");

                // default NavigateTo approach: if search term contains only lower-case chars - use case-insensitive search, otherwise switch to case-sensitive version
                var searchTerms = terms.map(function (t) {
                    return ({ caseSensitive: _this.hasAnyUpperCaseCharacter(t), term: t });
                });

                var items = [];

                var fileNames = this.compiler.fileNames();
                for (var i = 0, n = fileNames.length; i < n; i++) {
                    var fileName = fileNames[i];
                    var declaration = this.compiler.getCachedTopLevelDeclaration(fileName);
                    this.findSearchValueInPullDecl(fileName, [declaration], items, searchTerms);
                }
                return items;
            };

            LanguageService.prototype.hasAnyUpperCaseCharacter = function (s) {
                for (var i = 0; i < s.length; ++i) {
                    if (s.charAt(i).toLocaleLowerCase() !== s.charAt(i)) {
                        return true;
                    }
                }

                return false;
            };

            // Search given file's declaration and output matched NavigateToItem into array of NavigateToItem[] which is passed in as
            // one of the function's arguements. The function will recruseively call itself to visit all children declarations
            // of each member of declarations array.
            //
            // @param fileName: name of the file which the function is currently visiting its PullDecl members.
            //        delcarations: array of PullDecl, containing current visiting top level PullDecl objects.
            //        results: array of NavigateToItem to be filled in with matched NavigateToItem objects.
            //        searchTerms: array of search terms.
            //        searchRegExpTerms: array of regular expressions in which each expression corresponding to each item in the searchTerms array.
            //        parentName: a name of the parent of declarations array.
            //        parentKindName: a kind of parent in string format.
            LanguageService.prototype.findSearchValueInPullDecl = function (fileName, declarations, results, searchTerms, parentName, parentkindName) {
                var item;
                var declaration;
                var declName;
                var kindName;
                var matchKind;
                var fullName;

                for (var i = 0, declLength = declarations.length; i < declLength; ++i) {
                    declaration = declarations[i];
                    declName = declaration.getDisplayName();
                    kindName = this.mapPullElementKind(declaration.kind);
                    matchKind = null;

                    for (var j = 0, termsLength = searchTerms.length; j < termsLength; ++j) {
                        var searchTerm = searchTerms[j];
                        var declNameToSearch = searchTerm.caseSensitive ? declName : declName.toLocaleLowerCase();

                        // in case of case-insensitive search searchTerm.term will already be lower-cased
                        var index = declNameToSearch.indexOf(searchTerm.term);

                        if (index !== -1) {
                            if (index === 0) {
                                // here we know that match occur at the beginning of the string.
                                // if search term and declName has the same length - we have an exact match, otherwise declName have longer length and this will be prefix match
                                matchKind = declName.length === searchTerm.term.length ? Services.MatchKind.exact : Services.MatchKind.prefix;
                            } else {
                                // declName have longer length and the match doesn't occur at the beginning of the string; so we must have substring match
                                matchKind = Services.MatchKind.subString;
                            }
                        }
                    }

                    // if there is a match and the match should be included into NavigateToItem array,
                    // create corresponding NavigateToItem and add it into results array
                    if (this.shouldIncludeDeclarationInNavigationItems(declaration)) {
                        fullName = parentName ? parentName + "." + declName : declName;
                        var ast = declaration.ast();
                        if (matchKind) {
                            item = new Services.NavigateToItem();
                            item.name = declName;
                            item.matchKind = matchKind;
                            item.kind = this.mapPullElementKind(declaration.kind);
                            item.kindModifiers = this.getScriptElementKindModifiersFromDecl(declaration);
                            item.fileName = this._getHostFileName(fileName);
                            item.minChar = TypeScript.start(ast);
                            item.limChar = TypeScript.end(ast);
                            item.containerName = parentName || "";
                            item.containerKind = parentkindName || "";
                            results.push(item);
                        }
                    }
                    if (this.isContainerDeclaration(declaration)) {
                        this.findSearchValueInPullDecl(fileName, declaration.getChildDecls(), results, searchTerms, fullName, kindName);
                    }
                }
            };

            // Return ScriptElementKind in string of a given declaration.
            LanguageService.prototype.getScriptElementKindModifiersFromDecl = function (decl) {
                var result = [];
                var flags = decl.flags;

                if (flags & 1 /* Exported */) {
                    result.push(Services.ScriptElementKindModifier.exportedModifier);
                }

                if (flags & TypeScript.PullElementFlags.Ambient) {
                    result.push(Services.ScriptElementKindModifier.ambientModifier);
                }

                if (flags & TypeScript.PullElementFlags.Public) {
                    result.push(Services.ScriptElementKindModifier.publicMemberModifier);
                }

                if (flags & TypeScript.PullElementFlags.Private) {
                    result.push(Services.ScriptElementKindModifier.privateMemberModifier);
                }

                if (flags & TypeScript.PullElementFlags.Static) {
                    result.push(Services.ScriptElementKindModifier.staticModifier);
                }

                return result.length > 0 ? result.join(',') : Services.ScriptElementKindModifier.none;
            };

            // Return true if the declaration has PullElementKind that is one of
            // the following container types and return false otherwise.
            LanguageService.prototype.isContainerDeclaration = function (declaration) {
                switch (declaration.kind) {
                    case TypeScript.PullElementKind.Script:
                    case TypeScript.PullElementKind.Container:
                    case TypeScript.PullElementKind.Class:
                    case TypeScript.PullElementKind.Interface:
                    case TypeScript.PullElementKind.DynamicModule:
                    case TypeScript.PullElementKind.Enum:
                        return true;
                }

                return false;
            };

            // Return true if the declaration should havce corresponding NavigateToItem and false otherwise.
            LanguageService.prototype.shouldIncludeDeclarationInNavigationItems = function (declaration) {
                switch (declaration.kind) {
                    case TypeScript.PullElementKind.Script:
                        // Do not include the script item
                        return false;
                    case TypeScript.PullElementKind.Variable:
                    case TypeScript.PullElementKind.Property:
                        // Do not include the value side of modules or classes, as thier types has already been included
                        return (declaration.flags & (TypeScript.PullElementFlags.ClassConstructorVariable | TypeScript.PullElementFlags.InitializedModule | TypeScript.PullElementFlags.InitializedDynamicModule | TypeScript.PullElementFlags.Enum)) === 0;
                    case TypeScript.PullElementKind.EnumMember:
                        return true;
                    case TypeScript.PullElementKind.FunctionExpression:
                    case TypeScript.PullElementKind.Function:
                        // Ignore anonomus functions
                        return declaration.name !== "";
                    case TypeScript.PullElementKind.ConstructorMethod:
                        return false;
                }

                if (this.isContainerDeclaration(declaration)) {
                    return true;
                }

                return true;
            };

            LanguageService.prototype.getSyntacticDiagnostics = function (fileName) {
                fileName = TypeScript.switchToForwardSlashes(fileName);
                return this.compiler.getSyntacticDiagnostics(fileName);
            };

            LanguageService.prototype.getSemanticDiagnostics = function (fileName) {
                fileName = TypeScript.switchToForwardSlashes(fileName);
                return this.compiler.getSemanticDiagnostics(fileName);
            };

            LanguageService.prototype._getHostSpecificDiagnosticWithFileName = function (diagnostic) {
                return new TypeScript.Diagnostic(this._getHostFileName(diagnostic.fileName()), diagnostic.lineMap(), diagnostic.start(), diagnostic.length(), diagnostic.diagnosticKey(), diagnostic.arguments(), diagnostic.additionalLocations());
            };

            LanguageService.prototype.getCompilerOptionsDiagnostics = function () {
                var _this = this;
                var resolvePath = function (fileName) {
                    return _this.host.resolveRelativePath(fileName, null);
                };
                var compilerOptionsDiagnostics = this.compiler.getCompilerOptionsDiagnostics(resolvePath);
                return compilerOptionsDiagnostics.map(function (d) {
                    return _this._getHostSpecificDiagnosticWithFileName(d);
                });
            };

            LanguageService.prototype._getHostFileName = function (fileName) {
                if (fileName) {
                    return this.compiler.getCachedHostFileName(fileName);
                }
                return fileName;
            };

            LanguageService.prototype.getEmitOutput = function (fileName) {
                var _this = this;
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var resolvePath = function (fileName) {
                    return _this.host.resolveRelativePath(fileName, null);
                };

                var document = this.compiler.getDocument(fileName);
                var emitToSingleFile = document.emitToOwnOutputFile();

                // Check for syntactic errors
                var syntacticDiagnostics = emitToSingleFile ? this.getSyntacticDiagnostics(fileName) : this.getAllSyntacticDiagnostics();
                if (this.containErrors(syntacticDiagnostics)) {
                    // This file has at least one syntactic error, return and do not emit code.
                    return new TypeScript.EmitOutput(1 /* FailedBecauseOfSyntaxErrors */);
                }

                // Force a type check before emit to ensure that all symbols have been resolved
                var semanticDiagnostics = emitToSingleFile ? this.getSemanticDiagnostics(fileName) : this.getAllSemanticDiagnostics();

                // Emit output files and source maps
                // Emit declarations, if there are no semantic errors
                var emitResult = this.compiler.emit(fileName, resolvePath);
                if (emitResult.emitOutputResult == 0 /* Succeeded */) {
                    if (!this.containErrors(semanticDiagnostics)) {
                        // Merge the results
                        var declarationEmitOutput = this.compiler.emitDeclarations(fileName, resolvePath);
                        emitResult.outputFiles.push.apply(emitResult.outputFiles, declarationEmitOutput.outputFiles);
                        TypeScript.Debug.assert(declarationEmitOutput.emitOutputResult == 0 /* Succeeded */);
                    } else if (this.compiler.canEmitDeclarations(fileName)) {
                        emitResult.emitOutputResult = 3 /* FailedToGenerateDeclarationsBecauseOfSemanticErrors */;
                    }
                }

                return emitResult;
            };

            LanguageService.prototype.getAllSyntacticDiagnostics = function () {
                var _this = this;
                var diagnostics = [];

                this.compiler.fileNames().forEach(function (fileName) {
                    return diagnostics.push.apply(diagnostics, _this.compiler.getSyntacticDiagnostics(fileName));
                });

                return diagnostics;
            };

            LanguageService.prototype.getAllSemanticDiagnostics = function () {
                var _this = this;
                var diagnostics = [];

                this.compiler.fileNames().map(function (fileName) {
                    return diagnostics.push.apply(diagnostics, _this.compiler.getSemanticDiagnostics(fileName));
                });

                return diagnostics;
            };

            LanguageService.prototype.containErrors = function (diagnostics) {
                if (diagnostics && diagnostics.length > 0) {
                    for (var i = 0; i < diagnostics.length; i++) {
                        var diagnosticInfo = diagnostics[i].info();
                        if (diagnosticInfo.category === 1 /* Error */) {
                            return true;
                        }
                    }
                }

                return false;
            };

            LanguageService.prototype.getFullNameOfSymbol = function (symbol, enclosingScopeSymbol) {
                var container = symbol.getContainer();
                if (TypeScript.PullHelpers.isSymbolLocal(symbol) || symbol.kind == TypeScript.PullElementKind.Parameter) {
                    // Local var
                    return symbol.getScopedName(enclosingScopeSymbol, false, true);
                }

                var symbolKind = symbol.kind;
                if (symbol.kind == TypeScript.PullElementKind.Primitive) {
                    // Primitive type symbols - do not use symbol name
                    return "";
                }

                if (symbolKind == TypeScript.PullElementKind.ConstructorType) {
                    symbol = symbol.getAssociatedContainerType();
                }

                if (symbolKind != TypeScript.PullElementKind.Property && symbolKind != TypeScript.PullElementKind.EnumMember && symbolKind != TypeScript.PullElementKind.Method && symbolKind != TypeScript.PullElementKind.TypeParameter && !symbol.anyDeclHasFlag(1 /* Exported */)) {
                    // Non exported variable/function
                    return symbol.getScopedName(enclosingScopeSymbol, false, true);
                }

                return symbol.fullName(enclosingScopeSymbol);
            };

            LanguageService.prototype.getTypeInfoEligiblePath = function (fileName, position, isConstructorValidPosition) {
                var document = this.compiler.getDocument(fileName);
                var sourceUnit = document.sourceUnit();

                var ast = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, position, false, true);
                if (ast === null) {
                    return null;
                }

                if (ast.kind() === 227 /* ParameterList */ && ast.parent.kind() === 142 /* CallSignature */ && ast.parent.parent.kind() === 137 /* ConstructorDeclaration */) {
                    ast = ast.parent.parent;
                }

                switch (ast.kind()) {
                    default:
                        return null;
                    case 137 /* ConstructorDeclaration */:
                        var constructorAST = ast;
                        if (!isConstructorValidPosition || !(position >= TypeScript.start(constructorAST) && position <= TypeScript.start(constructorAST) + "constructor".length)) {
                            return null;
                        } else {
                            return ast;
                        }

                    case 129 /* FunctionDeclaration */:
                        return null;

                    case 212 /* MemberAccessExpression */:
                    case 121 /* QualifiedName */:
                    case 50 /* SuperKeyword */:
                    case 14 /* StringLiteral */:
                    case 35 /* ThisKeyword */:
                    case 11 /* IdentifierName */:
                        return ast;
                }
            };

            LanguageService.prototype.getTypeAtPosition = function (fileName, position) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var node = this.getTypeInfoEligiblePath(fileName, position, true);
                if (!node) {
                    return null;
                }

                var document = this.compiler.getDocument(fileName);
                var ast;
                var symbol;
                var typeSymbol;
                var enclosingScopeSymbol;
                var _isCallExpression = false;
                var resolvedSignatures;
                var candidateSignature;
                var isConstructorCall;

                if (TypeScript.ASTHelpers.isDeclarationASTOrDeclarationNameAST(node)) {
                    var declarationInformation = this.compiler.getSymbolInformationFromAST(node, document);
                    if (!declarationInformation) {
                        return null;
                    }

                    ast = declarationInformation.ast;
                    symbol = declarationInformation.symbol;
                    enclosingScopeSymbol = declarationInformation.enclosingScopeSymbol;

                    if (node.kind() === 137 /* ConstructorDeclaration */ || node.kind() === 129 /* FunctionDeclaration */ || node.kind() === 218 /* ParenthesizedArrowFunctionExpression */ || node.kind() === 219 /* SimpleArrowFunctionExpression */ || node.kind() === 135 /* MemberFunctionDeclaration */ || TypeScript.ASTHelpers.isNameOfFunction(node) || TypeScript.ASTHelpers.isNameOfMemberFunction(node)) {
                        var funcDecl = node.kind() === 11 /* IdentifierName */ ? node.parent : node;
                        if (symbol && symbol.kind != TypeScript.PullElementKind.Property) {
                            var signatureInfo = TypeScript.PullHelpers.getSignatureForFuncDecl(this.compiler.getDeclForAST(funcDecl), symbol.semanticInfoChain);
                            _isCallExpression = true;
                            candidateSignature = signatureInfo.signature;
                            resolvedSignatures = signatureInfo.allSignatures;
                        }
                    }
                } else if (TypeScript.ASTHelpers.isCallExpression(node) || TypeScript.ASTHelpers.isCallExpressionTarget(node)) {
                    while (!TypeScript.ASTHelpers.isCallExpression(node)) {
                        node = node.parent;
                    }

                    // Get the call expression symbol
                    var callExpressionInformation = this.compiler.getCallInformationFromAST(node, document);

                    if (!callExpressionInformation || !callExpressionInformation.targetSymbol) {
                        return null;
                    }

                    ast = callExpressionInformation.ast;
                    symbol = callExpressionInformation.targetSymbol;
                    enclosingScopeSymbol = callExpressionInformation.enclosingScopeSymbol;

                    // Check if this is a property or a variable, if so do not treat it as a fuction, but rather as a variable with function type
                    var isPropertyOrVar = symbol.kind == TypeScript.PullElementKind.Property || symbol.kind == TypeScript.PullElementKind.Variable;
                    typeSymbol = symbol.type;
                    if (isPropertyOrVar) {
                        if (typeSymbol.getName() != "") {
                            symbol = typeSymbol;
                        }
                        isPropertyOrVar = (typeSymbol.kind != TypeScript.PullElementKind.Interface && typeSymbol.kind != TypeScript.PullElementKind.ObjectType) || typeSymbol.getName() == "";
                    }

                    if (!isPropertyOrVar) {
                        _isCallExpression = true;
                        resolvedSignatures = callExpressionInformation.resolvedSignatures;
                        candidateSignature = callExpressionInformation.candidateSignature;
                        isConstructorCall = callExpressionInformation.isConstructorCall;
                    }
                } else {
                    var symbolInformation = this.compiler.getSymbolInformationFromAST(node, document);

                    if (!symbolInformation || !symbolInformation.symbol) {
                        return null;
                    }

                    ast = symbolInformation.ast;
                    symbol = symbolInformation.symbol;
                    enclosingScopeSymbol = symbolInformation.enclosingScopeSymbol;

                    if (symbol.kind === TypeScript.PullElementKind.Method || symbol.kind == TypeScript.PullElementKind.Function) {
                        typeSymbol = symbol.type;
                        if (typeSymbol) {
                            _isCallExpression = true;
                            resolvedSignatures = typeSymbol.getCallSignatures();
                        }
                    }
                }

                if (resolvedSignatures && (!candidateSignature || candidateSignature.isDefinition())) {
                    for (var i = 0, len = resolvedSignatures.length; i < len; i++) {
                        if (len > 1 && resolvedSignatures[i].isDefinition()) {
                            continue;
                        }

                        candidateSignature = resolvedSignatures[i];
                        break;
                    }
                }

                var memberName = _isCallExpression ? TypeScript.PullSignatureSymbol.getSignatureTypeMemberName(candidateSignature, resolvedSignatures, enclosingScopeSymbol) : symbol.getTypeNameEx(enclosingScopeSymbol, true);
                var kind = this.mapPullElementKind(symbol.kind, symbol, !_isCallExpression, _isCallExpression, isConstructorCall);

                var docCommentSymbol = candidateSignature || symbol;
                var docComment = docCommentSymbol.docComments(!_isCallExpression);
                var symbolName = this.getFullNameOfSymbol(symbol, enclosingScopeSymbol);
                var minChar = ast ? TypeScript.start(ast) : -1;
                var limChar = ast ? TypeScript.end(ast) : -1;

                return new Services.TypeInfo(memberName, docComment, symbolName, kind, minChar, limChar);
            };

            LanguageService.prototype.getCompletionsAtPosition = function (fileName, position, isMemberCompletion) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var document = this.compiler.getDocument(fileName);
                var sourceUnit = document.sourceUnit();

                if (Services.CompletionHelpers.isCompletionListBlocker(document.syntaxTree().sourceUnit(), position)) {
                    this.logger.log("Returning an empty list because completion was blocked.");
                    return null;
                }

                var node = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, position, true, true);

                if (node && node.kind() === 11 /* IdentifierName */ && TypeScript.start(node) === TypeScript.end(node)) {
                    // Ignore missing name nodes
                    node = node.parent;
                }

                var isRightOfDot = false;
                if (node && node.kind() === 212 /* MemberAccessExpression */ && TypeScript.end(node.expression) < position) {
                    isRightOfDot = true;
                    node = node.expression;
                } else if (node && node.kind() === 121 /* QualifiedName */ && TypeScript.end(node.left) < position) {
                    isRightOfDot = true;
                    node = node.left;
                } else if (node && node.parent && node.kind() === 11 /* IdentifierName */ && node.parent.kind() === 212 /* MemberAccessExpression */ && node.parent.name === node) {
                    isRightOfDot = true;
                    node = node.parent.expression;
                } else if (node && node.parent && node.kind() === 11 /* IdentifierName */ && node.parent.kind() === 121 /* QualifiedName */ && node.parent.right === node) {
                    isRightOfDot = true;
                    node = node.parent.left;
                }

                // Get the completions
                var entries = new TypeScript.IdentiferNameHashTable();

                // Right of dot member completion list
                if (isRightOfDot) {
                    var members = this.compiler.getVisibleMemberSymbolsFromAST(node, document);
                    if (!members) {
                        return null;
                    }

                    isMemberCompletion = true;
                    this.getCompletionEntriesFromSymbols(members, entries);
                } else {
                    var containingObjectLiteral = Services.CompletionHelpers.getContainingObjectLiteralApplicableForCompletion(document.syntaxTree().sourceUnit(), position);

                    // Object literal expression, look up possible property names from contextual type
                    if (containingObjectLiteral) {
                        var searchPosition = Math.min(position, TypeScript.end(containingObjectLiteral));
                        var path = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, searchPosition);

                        while (node && node.kind() !== 215 /* ObjectLiteralExpression */) {
                            node = node.parent;
                        }

                        if (!node || node.kind() !== 215 /* ObjectLiteralExpression */) {
                            // AST Path look up did not result in the same node as Fidelity Syntax Tree look up.
                            // Once we remove AST this will no longer be a problem.
                            return null;
                        }

                        isMemberCompletion = true;

                        // Try to get the object members form contextual typing
                        var contextualMembers = this.compiler.getContextualMembersFromAST(node, document);
                        if (contextualMembers && contextualMembers.symbols && contextualMembers.symbols.length > 0) {
                            // get existing members
                            var existingMembers = this.compiler.getVisibleMemberSymbolsFromAST(node, document);

                            // Add filtterd items to the completion list
                            this.getCompletionEntriesFromSymbols({
                                symbols: Services.CompletionHelpers.filterContextualMembersList(contextualMembers.symbols, existingMembers, fileName, position),
                                enclosingScopeSymbol: contextualMembers.enclosingScopeSymbol
                            }, entries);
                        }
                    } else {
                        isMemberCompletion = false;
                        var decls = this.compiler.getVisibleDeclsFromAST(node, document);
                        this.getCompletionEntriesFromDecls(decls, entries);
                    }
                }

                // Add keywords if this is not a member completion list
                if (!isMemberCompletion) {
                    this.getCompletionEntriesForKeywords(Services.KeywordCompletions.getKeywordCompltions(), entries);
                }

                // Prepare the completion result
                var completions = new Services.CompletionInfo();
                completions.isMemberCompletion = isMemberCompletion;
                completions.entries = [];
                entries.map(function (key, value) {
                    completions.entries.push({
                        name: value.name,
                        kind: value.kind,
                        kindModifiers: value.kindModifiers
                    });
                }, null);

                // Store this completion list as the active completion list
                this.activeCompletionSession = new Services.CompletionSession(fileName, position, entries);

                return completions;
            };

            LanguageService.prototype.getCompletionEntriesFromSymbols = function (symbolInfo, result) {
                for (var i = 0, n = symbolInfo.symbols.length; i < n; i++) {
                    var symbol = symbolInfo.symbols[i];

                    var symbolDisplayName = Services.CompletionHelpers.getValidCompletionEntryDisplayName(symbol.getDisplayName());
                    if (!symbolDisplayName) {
                        continue;
                    }

                    var symbolKind = symbol.kind;

                    var exitingEntry = result.lookup(symbolDisplayName);

                    if (exitingEntry && (symbolKind & TypeScript.PullElementKind.SomeValue)) {
                        continue;
                    }

                    var entry;
                    var kindName = this.mapPullElementKind(symbolKind, symbol, true);
                    var kindModifiersName = this.getScriptElementKindModifiers(symbol);

                    if (symbol.isResolved) {
                        // If the symbol has already been resolved, cache the needed information for completion details.
                        var completionInfo = this.getResolvedCompletionEntryDetailsFromSymbol(symbol, symbolInfo.enclosingScopeSymbol);

                        entry = new Services.ResolvedCompletionEntry(symbolDisplayName, kindName, kindModifiersName, completionInfo.typeName, completionInfo.fullSymbolName, completionInfo.docComments);
                    } else {
                        entry = new Services.DeclReferenceCompletionEntry(symbolDisplayName, kindName, kindModifiersName, symbol.getDeclarations()[0]);
                    }

                    result.addOrUpdate(symbolDisplayName, entry);
                }
            };

            LanguageService.prototype.getCompletionEntriesFromDecls = function (decls, result) {
                var semanticInfoChain = this.getSemanticInfoChain();
                for (var i = 0, n = decls ? decls.length : 0; i < n; i++) {
                    var decl = decls[i];

                    var declDisplaylName = Services.CompletionHelpers.getValidCompletionEntryDisplayName(decl.getDisplayName());
                    if (!declDisplaylName) {
                        continue;
                    }

                    var declKind = decl.kind;

                    var exitingEntry = result.lookup(declDisplaylName);

                    if (exitingEntry && (declKind & TypeScript.PullElementKind.SomeValue)) {
                        continue;
                    }

                    var kindName = this.mapPullElementKind(declKind, null, true);
                    var kindModifiersName = this.getScriptElementKindModifiersFromFlags(decl.flags);

                    var entry = null;

                    // Do not call getSymbol if the decl is not already bound. This would force a bind,
                    // which is too expensive to do for every completion item when we are building the
                    // list.
                    var symbol = decl.hasSymbol(semanticInfoChain) && decl.getSymbol(semanticInfoChain);

                    // If the symbol has already been resolved, cache the needed information for completion details.
                    var enclosingDecl = decl.getEnclosingDecl();
                    var enclosingScopeSymbol = (enclosingDecl && enclosingDecl.hasSymbol(semanticInfoChain)) ? enclosingDecl.getSymbol(semanticInfoChain) : null;

                    if (symbol && symbol.isResolved && enclosingScopeSymbol && enclosingScopeSymbol.isResolved) {
                        var completionInfo = this.getResolvedCompletionEntryDetailsFromSymbol(symbol, enclosingScopeSymbol);
                        entry = new Services.ResolvedCompletionEntry(declDisplaylName, kindName, kindModifiersName, completionInfo.typeName, completionInfo.fullSymbolName, completionInfo.docComments);
                    } else {
                        entry = new Services.DeclReferenceCompletionEntry(declDisplaylName, kindName, kindModifiersName, decl);
                    }

                    result.addOrUpdate(declDisplaylName, entry);
                }
            };

            LanguageService.prototype.getResolvedCompletionEntryDetailsFromSymbol = function (symbol, enclosingScopeSymbol) {
                var typeName = symbol.getTypeName(enclosingScopeSymbol, true);
                var fullSymbolName = this.getFullNameOfSymbol(symbol, enclosingScopeSymbol);

                var type = symbol.type;
                var symbolForDocComments = symbol;
                if (type && type.hasOnlyOverloadCallSignatures()) {
                    symbolForDocComments = type.getCallSignatures()[0];
                }

                var docComments = symbolForDocComments.docComments(true);
                return {
                    typeName: typeName,
                    fullSymbolName: fullSymbolName,
                    docComments: docComments
                };
            };

            LanguageService.prototype.getCompletionEntriesForKeywords = function (keywords, result) {
                for (var i = 0, n = keywords.length; i < n; i++) {
                    var keyword = keywords[i];
                    result.addOrUpdate(keyword.name, keyword);
                }
            };

            LanguageService.prototype.getCompletionEntryDetails = function (fileName, position, entryName) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                // Ensure that the current active completion session is still valid for this request
                if (!this.activeCompletionSession || this.activeCompletionSession.fileName !== fileName || this.activeCompletionSession.position !== position) {
                    return null;
                }

                var entry = this.activeCompletionSession.entries.lookup(entryName);
                if (!entry) {
                    return null;
                }

                if (!entry.isResolved()) {
                    var decl = entry.decl;

                    // If this decl has been invalidated becuase of a user edit, try to find the new
                    // decl that matches it
                    // Theoretically, this corrective measure should just fix decls if the completion
                    // session is older than the file, but we are being defensive, so always correct
                    // the decl.
                    var document = this.compiler.getDocument(fileName);
                    if (decl.fileName() === TypeScript.switchToForwardSlashes(fileName)) {
                        decl = this.tryFindDeclFromPreviousCompilerVersion(decl);

                        if (decl) {
                            var declDisplaylName = Services.CompletionHelpers.getValidCompletionEntryDisplayName(decl.getDisplayName());
                            var declKind = decl.kind;
                            var kindName = this.mapPullElementKind(declKind, null, true);
                            var kindModifiersName = this.getScriptElementKindModifiersFromFlags(decl.flags);

                            // update the existing entry
                            entry = new Services.DeclReferenceCompletionEntry(declDisplaylName, kindName, kindModifiersName, decl);
                            this.activeCompletionSession.entries.addOrUpdate(entryName, entry);
                        }
                    }

                    // This entry has not been resolved yet. Resolve it.
                    if (decl) {
                        var node = TypeScript.ASTHelpers.getAstAtPosition(document.sourceUnit(), position);
                        var symbolInfo = this.compiler.pullGetDeclInformation(decl, node, document);

                        if (!symbolInfo) {
                            return null;
                        }

                        var symbol = symbolInfo.symbol;
                        var completionInfo = this.getResolvedCompletionEntryDetailsFromSymbol(symbol, symbolInfo.enclosingScopeSymbol);

                        // Store the information for next lookup
                        entry.resolve(completionInfo.typeName, completionInfo.fullSymbolName, completionInfo.docComments);
                    }
                }

                return {
                    name: entry.name,
                    kind: entry.kind,
                    kindModifiers: entry.kindModifiers,
                    type: entry.type,
                    fullSymbolName: entry.fullSymbolName,
                    docComment: entry.docComment
                };
            };

            // Given a declaration returned from a previous version of the compiler (i.e. prior to
            // any mutation operations), attempts to find the same decl in this version.
            LanguageService.prototype.tryFindDeclFromPreviousCompilerVersion = function (invalidatedDecl) {
                var fileName = invalidatedDecl.fileName();

                var declsInPath = [];
                var current = invalidatedDecl;
                while (current) {
                    if (current.kind !== TypeScript.PullElementKind.Script) {
                        declsInPath.unshift(current);
                    }

                    current = current.getParentDecl();
                }

                // now search for that decl
                var topLevelDecl = this.compiler.topLevelDeclaration(fileName);
                if (!topLevelDecl) {
                    return null;
                }

                var declsToSearch = [topLevelDecl];
                var foundDecls = [];
                var keepSearching = (invalidatedDecl.kind & TypeScript.PullElementKind.Container) || (invalidatedDecl.kind & TypeScript.PullElementKind.Interface) || (invalidatedDecl.kind & TypeScript.PullElementKind.Class) || (invalidatedDecl.kind & TypeScript.PullElementKind.Enum);

                for (var i = 0; i < declsInPath.length; i++) {
                    var declInPath = declsInPath[i];
                    var decls = [];

                    for (var j = 0; j < declsToSearch.length; j++) {
                        foundDecls = declsToSearch[j].searchChildDecls(declInPath.name, declInPath.kind);

                        decls.push.apply(decls, foundDecls);

                        // Unless we're searching for an interface or module, we've found the one true
                        // decl, so don't bother searching the rest of the top-level decls
                        if (foundDecls.length && !keepSearching) {
                            break;
                        }
                    }

                    declsToSearch = decls;

                    if (declsToSearch.length == 0) {
                        break;
                    }
                }

                return declsToSearch.length === 0 ? null : declsToSearch[0];
            };

            LanguageService.prototype.getModuleOrEnumKind = function (symbol) {
                if (symbol) {
                    var declarations = symbol.getDeclarations();
                    for (var i = 0; i < declarations.length; i++) {
                        var declKind = declarations[i].kind;
                        if (declKind == TypeScript.PullElementKind.Container) {
                            return Services.ScriptElementKind.moduleElement;
                        } else if (declKind == TypeScript.PullElementKind.Enum) {
                            return Services.ScriptElementKind.enumElement;
                        } else if (declKind == TypeScript.PullElementKind.Variable) {
                            var declFlags = declarations[i].flags;
                            if (declFlags & TypeScript.PullElementFlags.InitializedModule) {
                                return Services.ScriptElementKind.moduleElement;
                            } else if (declFlags & TypeScript.PullElementFlags.Enum) {
                                return Services.ScriptElementKind.enumElement;
                            }
                        }
                    }
                }
                return Services.ScriptElementKind.unknown;
            };

            LanguageService.prototype.mapPullElementKind = function (kind, symbol, useConstructorAsClass, varIsFunction, functionIsConstructor) {
                if (functionIsConstructor) {
                    return Services.ScriptElementKind.constructorImplementationElement;
                }

                if (varIsFunction) {
                    switch (kind) {
                        case TypeScript.PullElementKind.Container:
                        case TypeScript.PullElementKind.DynamicModule:
                        case TypeScript.PullElementKind.TypeAlias:
                        case TypeScript.PullElementKind.Interface:
                        case TypeScript.PullElementKind.Class:
                        case TypeScript.PullElementKind.Parameter:
                            return Services.ScriptElementKind.functionElement;
                        case TypeScript.PullElementKind.Variable:
                            return (symbol && TypeScript.PullHelpers.isSymbolLocal(symbol)) ? Services.ScriptElementKind.localFunctionElement : Services.ScriptElementKind.functionElement;
                        case TypeScript.PullElementKind.Property:
                            return Services.ScriptElementKind.memberFunctionElement;
                        case TypeScript.PullElementKind.Function:
                            return (symbol && TypeScript.PullHelpers.isSymbolLocal(symbol)) ? Services.ScriptElementKind.localFunctionElement : Services.ScriptElementKind.functionElement;
                        case TypeScript.PullElementKind.ConstructorMethod:
                            return Services.ScriptElementKind.constructorImplementationElement;
                        case TypeScript.PullElementKind.Method:
                            return Services.ScriptElementKind.memberFunctionElement;
                        case TypeScript.PullElementKind.FunctionExpression:
                            return Services.ScriptElementKind.localFunctionElement;
                        case TypeScript.PullElementKind.GetAccessor:
                            return Services.ScriptElementKind.memberGetAccessorElement;
                        case TypeScript.PullElementKind.SetAccessor:
                            return Services.ScriptElementKind.memberSetAccessorElement;
                        case TypeScript.PullElementKind.CallSignature:
                            return Services.ScriptElementKind.callSignatureElement;
                        case TypeScript.PullElementKind.ConstructSignature:
                            return Services.ScriptElementKind.constructSignatureElement;
                        case TypeScript.PullElementKind.IndexSignature:
                            return Services.ScriptElementKind.indexSignatureElement;
                        case TypeScript.PullElementKind.TypeParameter:
                            return Services.ScriptElementKind.typeParameterElement;
                        case TypeScript.PullElementKind.Primitive:
                            return Services.ScriptElementKind.primitiveType;
                    }
                } else {
                    switch (kind) {
                        case TypeScript.PullElementKind.Script:
                            return Services.ScriptElementKind.scriptElement;
                        case TypeScript.PullElementKind.Container:
                        case TypeScript.PullElementKind.DynamicModule:
                        case TypeScript.PullElementKind.TypeAlias:
                            return Services.ScriptElementKind.moduleElement;
                        case TypeScript.PullElementKind.Interface:
                            return Services.ScriptElementKind.interfaceElement;
                        case TypeScript.PullElementKind.Class:
                            return Services.ScriptElementKind.classElement;
                        case TypeScript.PullElementKind.Enum:
                            return Services.ScriptElementKind.enumElement;
                        case TypeScript.PullElementKind.Variable:
                            var scriptElementKind = this.getModuleOrEnumKind(symbol);
                            if (scriptElementKind != Services.ScriptElementKind.unknown) {
                                return scriptElementKind;
                            }
                            return (symbol && TypeScript.PullHelpers.isSymbolLocal(symbol)) ? Services.ScriptElementKind.localVariableElement : Services.ScriptElementKind.variableElement;
                        case TypeScript.PullElementKind.Parameter:
                            return Services.ScriptElementKind.parameterElement;
                        case TypeScript.PullElementKind.Property:
                            return Services.ScriptElementKind.memberVariableElement;
                        case TypeScript.PullElementKind.Function:
                            return (symbol && TypeScript.PullHelpers.isSymbolLocal(symbol)) ? Services.ScriptElementKind.localFunctionElement : Services.ScriptElementKind.functionElement;
                        case TypeScript.PullElementKind.ConstructorMethod:
                            return useConstructorAsClass ? Services.ScriptElementKind.classElement : Services.ScriptElementKind.constructorImplementationElement;
                        case TypeScript.PullElementKind.Method:
                            return Services.ScriptElementKind.memberFunctionElement;
                        case TypeScript.PullElementKind.FunctionExpression:
                            return Services.ScriptElementKind.localFunctionElement;
                        case TypeScript.PullElementKind.GetAccessor:
                            return Services.ScriptElementKind.memberGetAccessorElement;
                        case TypeScript.PullElementKind.SetAccessor:
                            return Services.ScriptElementKind.memberSetAccessorElement;
                        case TypeScript.PullElementKind.CallSignature:
                            return Services.ScriptElementKind.callSignatureElement;
                        case TypeScript.PullElementKind.ConstructSignature:
                            return Services.ScriptElementKind.constructSignatureElement;
                        case TypeScript.PullElementKind.IndexSignature:
                            return Services.ScriptElementKind.indexSignatureElement;
                        case TypeScript.PullElementKind.EnumMember:
                            return Services.ScriptElementKind.memberVariableElement;
                        case TypeScript.PullElementKind.TypeParameter:
                            return Services.ScriptElementKind.typeParameterElement;
                        case TypeScript.PullElementKind.Primitive:
                            return Services.ScriptElementKind.primitiveType;
                    }
                }

                return Services.ScriptElementKind.unknown;
            };

            LanguageService.prototype.getScriptElementKindModifiers = function (symbol) {
                var result = [];

                if (symbol.anyDeclHasFlag(1 /* Exported */)) {
                    result.push(Services.ScriptElementKindModifier.exportedModifier);
                }
                if (symbol.anyDeclHasFlag(TypeScript.PullElementFlags.Ambient)) {
                    result.push(Services.ScriptElementKindModifier.ambientModifier);
                }
                if (symbol.anyDeclHasFlag(TypeScript.PullElementFlags.Public)) {
                    result.push(Services.ScriptElementKindModifier.publicMemberModifier);
                }
                if (symbol.anyDeclHasFlag(TypeScript.PullElementFlags.Private)) {
                    result.push(Services.ScriptElementKindModifier.privateMemberModifier);
                }
                if (symbol.anyDeclHasFlag(TypeScript.PullElementFlags.Static)) {
                    result.push(Services.ScriptElementKindModifier.staticModifier);
                }

                return result.length > 0 ? result.join(',') : Services.ScriptElementKindModifier.none;
            };

            LanguageService.prototype.getScriptElementKindModifiersFromFlags = function (flags) {
                var result = [];

                if (flags & 1 /* Exported */) {
                    result.push(Services.ScriptElementKindModifier.exportedModifier);
                }

                if (flags & TypeScript.PullElementFlags.Ambient) {
                    result.push(Services.ScriptElementKindModifier.ambientModifier);
                }

                if (flags & TypeScript.PullElementFlags.Public) {
                    result.push(Services.ScriptElementKindModifier.publicMemberModifier);
                }

                if (flags & TypeScript.PullElementFlags.Private) {
                    result.push(Services.ScriptElementKindModifier.privateMemberModifier);
                }

                if (flags & TypeScript.PullElementFlags.Static) {
                    result.push(Services.ScriptElementKindModifier.staticModifier);
                }

                return result.length > 0 ? result.join(',') : Services.ScriptElementKindModifier.none;
            };

            //
            // Syntactic Single-File features
            //
            LanguageService.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var node = this.getTypeInfoEligiblePath(fileName, startPos, false);

                if (!node) {
                    return null;
                }

                while (node) {
                    if (TypeScript.ASTHelpers.isNameOfMemberAccessExpression(node) || TypeScript.ASTHelpers.isRightSideOfQualifiedName(node)) {
                        node = node.parent;
                    } else {
                        break;
                    }
                }

                var spanInfo = new Services.SpanInfo(TypeScript.start(node), TypeScript.end(node));
                return spanInfo;
            };

            LanguageService.prototype.getBreakpointStatementAtPosition = function (fileName, pos) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var syntaxtree = this.getSyntaxTree(fileName);
                return TypeScript.Services.Breakpoints.getBreakpointLocation(syntaxtree, pos);
            };

            LanguageService.prototype.getFormattingEditsForRange = function (fileName, minChar, limChar, options) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var manager = this.getFormattingManager(fileName, options);
                return manager.formatSelection(minChar, limChar);
            };

            LanguageService.prototype.getFormattingEditsForDocument = function (fileName, minChar, limChar, options) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var manager = this.getFormattingManager(fileName, options);
                return manager.formatDocument(minChar, limChar);
            };

            LanguageService.prototype.getFormattingEditsOnPaste = function (fileName, minChar, limChar, options) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var manager = this.getFormattingManager(fileName, options);
                return manager.formatOnPaste(minChar, limChar);
            };

            LanguageService.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var manager = this.getFormattingManager(fileName, options);

                if (key === "}") {
                    return manager.formatOnClosingCurlyBrace(position);
                } else if (key === ";") {
                    return manager.formatOnSemicolon(position);
                } else if (key === "\n") {
                    return manager.formatOnEnter(position);
                }

                return [];
            };

            LanguageService.prototype.getFormattingManager = function (fileName, options) {
                // Ensure rules are initialized and up to date wrt to formatting options
                if (this.formattingRulesProvider == null) {
                    this.formattingRulesProvider = new TypeScript.Services.Formatting.RulesProvider(this.logger);
                }

                this.formattingRulesProvider.ensureUpToDate(options);

                // Get the Syntax Tree
                var syntaxTree = this.getSyntaxTree(fileName);

                // Convert IScriptSnapshot to ITextSnapshot
                var scriptSnapshot = this.compiler.getScriptSnapshot(fileName);
                var scriptText = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot);
                var textSnapshot = new TypeScript.Services.Formatting.TextSnapshot(scriptText);

                var manager = new TypeScript.Services.Formatting.FormattingManager(syntaxTree, textSnapshot, this.formattingRulesProvider, options);

                return manager;
            };

            LanguageService.prototype.getOutliningRegions = function (fileName) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var syntaxTree = this.getSyntaxTree(fileName);
                return Services.OutliningElementsCollector.collectElements(syntaxTree.sourceUnit());
            };

            // Given a script name and position in the script, return the
            // number of spaces equivalent to the desired smart indent
            // (assuming the line is empty). Returns "null" in case the
            // smart indent cannot be determined.
            LanguageService.prototype.getIndentationAtPosition = function (fileName, position, editorOptions) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var syntaxTree = this.getSyntaxTree(fileName);

                var scriptSnapshot = this.compiler.getScriptSnapshot(fileName);
                var scriptText = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot);
                var textSnapshot = new TypeScript.Services.Formatting.TextSnapshot(scriptText);
                var options = new TypeScript.FormattingOptions(!editorOptions.ConvertTabsToSpaces, editorOptions.TabSize, editorOptions.IndentSize, editorOptions.NewLineCharacter);

                return TypeScript.Services.Formatting.SingleTokenIndenter.getIndentationAmount(position, syntaxTree.sourceUnit(), textSnapshot, options);
            };

            // Given a script name and position in the script, return a pair of text range if the
            // position corresponds to a "brace matchin" characters (e.g. "{" or "(", etc.)
            // If the position is not on any range, return "null".
            LanguageService.prototype.getBraceMatchingAtPosition = function (fileName, position) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var syntaxTree = this.getSyntaxTree(fileName);
                return Services.BraceMatcher.getMatchSpans(syntaxTree, position);
            };

            LanguageService.prototype.getScriptLexicalStructure = function (fileName) {
                fileName = TypeScript.switchToForwardSlashes(fileName);

                var syntaxTree = this.getSyntaxTree(fileName);
                var items = [];
                Services.GetScriptLexicalStructureWalker.getListsOfAllScriptLexicalStructure(items, fileName, syntaxTree.sourceUnit());

                return items;
            };

            LanguageService.prototype.getSyntaxTree = function (fileName) {
                fileName = TypeScript.switchToForwardSlashes(fileName);
                return this._syntaxTreeCache.getCurrentFileSyntaxTree(fileName);
            };
            return LanguageService;
        })();
        Services.LanguageService = LanguageService;

        function isSignatureHelpBlocker(ast) {
            if (ast) {
                switch (ast.kind()) {
                    case 131 /* ClassDeclaration */:
                    case 128 /* InterfaceDeclaration */:
                    case 130 /* ModuleDeclaration */:
                    case 137 /* ConstructorDeclaration */:
                    case 129 /* FunctionDeclaration */:
                    case 225 /* VariableDeclarator */:
                    case 218 /* ParenthesizedArrowFunctionExpression */:
                    case 219 /* SimpleArrowFunctionExpression */:
                        return true;
                }
            }

            return false;
        }
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var FindReferenceHelpers = (function () {
            function FindReferenceHelpers() {
            }
            FindReferenceHelpers.compareSymbolsForLexicalIdentity = function (firstSymbol, secondSymbol) {
                // Unwrap modules so that we're always referring to the variable.
                if (!firstSymbol.isAlias() && firstSymbol.isContainer()) {
                    var containerForFirstSymbol = firstSymbol;
                    if (containerForFirstSymbol.getInstanceSymbol()) {
                        firstSymbol = containerForFirstSymbol.getInstanceSymbol();
                    }
                }

                if (!secondSymbol.isAlias() && secondSymbol.isContainer()) {
                    var containerForSecondSymbol = secondSymbol;
                    if (containerForSecondSymbol.getInstanceSymbol()) {
                        secondSymbol = containerForSecondSymbol.getInstanceSymbol();
                    }
                }

                if (firstSymbol.kind === secondSymbol.kind) {
                    if (firstSymbol === secondSymbol) {
                        return true;
                    }

                    // If we have two variables and they have the same name and the same parent, then
                    // they are the same symbol.
                    if (firstSymbol.kind === TypeScript.PullElementKind.Variable && firstSymbol.name === secondSymbol.name && firstSymbol.getDeclarations() && firstSymbol.getDeclarations().length >= 1 && secondSymbol.getDeclarations() && secondSymbol.getDeclarations().length >= 1) {
                        var firstSymbolDecl = firstSymbol.getDeclarations()[0];
                        var secondSymbolDecl = secondSymbol.getDeclarations()[0];

                        return firstSymbolDecl.getParentDecl() === secondSymbolDecl.getParentDecl();
                    }

                    // If we have two properties that belong to an object literal, then we need ot see
                    // if they came from teh same object literal ast.
                    if (firstSymbol.kind === TypeScript.PullElementKind.Property && firstSymbol.name === secondSymbol.name && firstSymbol.getDeclarations() && firstSymbol.getDeclarations().length >= 1 && secondSymbol.getDeclarations() && secondSymbol.getDeclarations().length >= 1) {
                        var firstSymbolDecl = firstSymbol.getDeclarations()[0];
                        var secondSymbolDecl = secondSymbol.getDeclarations()[0];

                        var firstParentDecl = firstSymbolDecl.getParentDecl();
                        var secondParentDecl = secondSymbolDecl.getParentDecl();

                        if (firstParentDecl.kind === TypeScript.PullElementKind.ObjectLiteral && secondParentDecl.kind === TypeScript.PullElementKind.ObjectLiteral) {
                            return firstParentDecl.ast() === secondParentDecl.ast();
                        }
                    }

                    // check if we are dealing with the implementation of interface method or a method override
                    if (firstSymbol.name === secondSymbol.name) {
                        switch (firstSymbol.kind) {
                            case TypeScript.PullElementKind.Property:
                            case TypeScript.PullElementKind.Method:
                            case TypeScript.PullElementKind.GetAccessor:
                            case TypeScript.PullElementKind.SetAccessor:
                                // these kinds can only be defined in types
                                var t1 = firstSymbol.getContainer();
                                var t2 = secondSymbol.getContainer();
                                t1._resolveDeclaredSymbol();
                                t2._resolveDeclaredSymbol();

                                return t1.hasBase(t2) || t2.hasBase(t1);
                                break;
                        }
                    }

                    return false;
                } else {
                    switch (firstSymbol.kind) {
                        case TypeScript.PullElementKind.Class: {
                            return this.checkSymbolsForDeclarationEquality(firstSymbol, secondSymbol);
                        }
                        case TypeScript.PullElementKind.Property: {
                            if (firstSymbol.isAccessor()) {
                                var getterSymbol = firstSymbol.getGetter();
                                var setterSymbol = firstSymbol.getSetter();

                                if (getterSymbol && getterSymbol === secondSymbol) {
                                    return true;
                                }

                                if (setterSymbol && setterSymbol === secondSymbol) {
                                    return true;
                                }
                            }
                            return false;
                        }
                        case TypeScript.PullElementKind.Function: {
                            if (secondSymbol.isAccessor()) {
                                var getterSymbol = secondSymbol.getGetter();
                                var setterSymbol = secondSymbol.getSetter();

                                if (getterSymbol && getterSymbol === firstSymbol) {
                                    return true;
                                }

                                if (setterSymbol && setterSymbol === firstSymbol) {
                                    return true;
                                }
                            }
                            return false;
                        }
                        case TypeScript.PullElementKind.ConstructorMethod: {
                            return this.checkSymbolsForDeclarationEquality(firstSymbol, secondSymbol);
                        }
                    }
                }

                return firstSymbol === secondSymbol;
            };

            FindReferenceHelpers.checkSymbolsForDeclarationEquality = function (firstSymbol, secondSymbol) {
                var firstSymbolDeclarations = firstSymbol.getDeclarations();
                var secondSymbolDeclarations = secondSymbol.getDeclarations();
                for (var i = 0, iLen = firstSymbolDeclarations.length; i < iLen; i++) {
                    for (var j = 0, jLen = secondSymbolDeclarations.length; j < jLen; j++) {
                        if (this.declarationsAreSameOrParents(firstSymbolDeclarations[i], secondSymbolDeclarations[j])) {
                            return true;
                        }
                    }
                }
                return false;
            };

            FindReferenceHelpers.declarationsAreSameOrParents = function (firstDecl, secondDecl) {
                var firstParent = firstDecl.getParentDecl();
                var secondParent = secondDecl.getParentDecl();
                if (firstDecl === secondDecl || firstDecl === secondParent || firstParent === secondDecl || firstParent === secondParent) {
                    return true;
                }
                return false;
            };
            return FindReferenceHelpers;
        })();
        Services.FindReferenceHelpers = FindReferenceHelpers;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        

        

        var ShimBase = (function () {
            function ShimBase(factory) {
                this.factory = factory;
                factory.registerShim(this);
            }
            ShimBase.prototype.dispose = function (dummy) {
                this.factory.unregisterShim(this);
            };
            return ShimBase;
        })();
        Services.ShimBase = ShimBase;

        var ScriptSnapshotShimAdapter = (function () {
            function ScriptSnapshotShimAdapter(scriptSnapshotShim) {
                this.scriptSnapshotShim = scriptSnapshotShim;
                this.lineStartPositions = null;
            }
            ScriptSnapshotShimAdapter.prototype.getText = function (start, end) {
                return this.scriptSnapshotShim.getText(start, end);
            };

            ScriptSnapshotShimAdapter.prototype.getLength = function () {
                return this.scriptSnapshotShim.getLength();
            };

            ScriptSnapshotShimAdapter.prototype.getLineStartPositions = function () {
                if (this.lineStartPositions == null) {
                    this.lineStartPositions = JSON.parse(this.scriptSnapshotShim.getLineStartPositions());
                }

                return this.lineStartPositions;
            };

            ScriptSnapshotShimAdapter.prototype.getTextChangeRangeSinceVersion = function (scriptVersion) {
                var encoded = this.scriptSnapshotShim.getTextChangeRangeSinceVersion(scriptVersion);
                if (encoded == null) {
                    return null;
                }

                var decoded = JSON.parse(encoded);
                return new TypeScript.TextChangeRange(new TypeScript.TextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
            };
            return ScriptSnapshotShimAdapter;
        })();

        var LanguageServiceShimHostAdapter = (function () {
            function LanguageServiceShimHostAdapter(shimHost) {
                this.shimHost = shimHost;
            }
            LanguageServiceShimHostAdapter.prototype.information = function () {
                return this.shimHost.information();
            };

            LanguageServiceShimHostAdapter.prototype.debug = function () {
                return this.shimHost.debug();
            };

            LanguageServiceShimHostAdapter.prototype.warning = function () {
                return this.shimHost.warning();
            };

            LanguageServiceShimHostAdapter.prototype.error = function () {
                return this.shimHost.error();
            };

            LanguageServiceShimHostAdapter.prototype.fatal = function () {
                return this.shimHost.fatal();
            };

            LanguageServiceShimHostAdapter.prototype.log = function (s) {
                this.shimHost.log(s);
            };

            LanguageServiceShimHostAdapter.prototype.getCompilationSettings = function () {
                var settingsJson = this.shimHost.getCompilationSettings();
                if (settingsJson == null || settingsJson == "") {
                    return null;
                }
                var settings = JSON.parse(settingsJson);
                return settings;
            };

            LanguageServiceShimHostAdapter.prototype.getScriptFileNames = function () {
                var encoded = this.shimHost.getScriptFileNames();
                return JSON.parse(encoded);
            };

            LanguageServiceShimHostAdapter.prototype.getScriptSnapshot = function (fileName) {
                return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName));
            };

            LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) {
                return this.shimHost.getScriptVersion(fileName);
            };

            LanguageServiceShimHostAdapter.prototype.getScriptIsOpen = function (fileName) {
                return this.shimHost.getScriptIsOpen(fileName);
            };

            LanguageServiceShimHostAdapter.prototype.getScriptByteOrderMark = function (fileName) {
                return this.shimHost.getScriptByteOrderMark(fileName);
            };

            LanguageServiceShimHostAdapter.prototype.getDiagnosticsObject = function () {
                return this.shimHost.getDiagnosticsObject();
            };

            LanguageServiceShimHostAdapter.prototype.getLocalizedDiagnosticMessages = function () {
                var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages();
                if (diagnosticMessagesJson == null || diagnosticMessagesJson == "") {
                    return null;
                }
                try  {
                    return JSON.parse(diagnosticMessagesJson);
                } catch (e) {
                    this.log(e.description || "diagnosticMessages.generated.json has invalid JSON format");
                    return null;
                }
            };

            LanguageServiceShimHostAdapter.prototype.getCancellationToken = function () {
                return this.shimHost.getCancellationToken();
            };

            // IReferenceResolverHost methods
            LanguageServiceShimHostAdapter.prototype.resolveRelativePath = function (path, directory) {
                return this.shimHost.resolveRelativePath(path, directory);
            };

            LanguageServiceShimHostAdapter.prototype.fileExists = function (path) {
                return this.shimHost.fileExists(path);
            };

            LanguageServiceShimHostAdapter.prototype.directoryExists = function (path) {
                return this.shimHost.directoryExists(path);
            };

            LanguageServiceShimHostAdapter.prototype.getParentDirectory = function (path) {
                return this.shimHost.getParentDirectory(path);
            };
            return LanguageServiceShimHostAdapter;
        })();
        Services.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter;

        function simpleForwardCall(logger, actionDescription, action) {
            logger.log(actionDescription);
            var start = Date.now();
            var result = action();
            var end = Date.now();
            logger.log(actionDescription + " completed in " + (end - start) + " msec");
            if (typeof (result) === "string") {
                var str = result;
                if (str.length > 128) {
                    str = str.substring(0, 128) + "...";
                }
                logger.log("  result.length=" + str.length + ", result='" + JSON.stringify(str) + "'");
            }
            return result;
        }
        Services.simpleForwardCall = simpleForwardCall;

        function forwardJSONCall(logger, actionDescription, action) {
            try  {
                var result = simpleForwardCall(logger, actionDescription, action);
                return JSON.stringify({ result: result });
            } catch (err) {
                if (err instanceof TypeScript.OperationCanceledException) {
                    return JSON.stringify({ canceled: true });
                }
                TypeScript.Services.logInternalError(logger, err);
                err.description = actionDescription;
                return JSON.stringify({ error: err });
            }
        }
        Services.forwardJSONCall = forwardJSONCall;

        var LanguageServiceShim = (function (_super) {
            __extends(LanguageServiceShim, _super);
            function LanguageServiceShim(factory, host, languageService) {
                _super.call(this, factory);
                this.host = host;
                this.languageService = languageService;
                this.logger = this.host;
            }
            LanguageServiceShim.prototype.forwardJSONCall = function (actionDescription, action) {
                return TypeScript.Services.forwardJSONCall(this.logger, actionDescription, action);
            };

            // DISPOSE
            // Ensure (almost) determinstic release of internal Javascript resources when
            // some external native objects holds onto us (e.g. Com/Interop).
            LanguageServiceShim.prototype.dispose = function (dummy) {
                this.logger.log("dispose()");
                this.languageService.dispose();
                this.languageService = null;

                // force a GC
                if (debugObjectHost && debugObjectHost.CollectGarbage) {
                    debugObjectHost.CollectGarbage();
                    this.logger.log("CollectGarbage()");
                }

                this.logger = null;

                _super.prototype.dispose.call(this, dummy);
            };

            // REFRESH
            // Update the list of scripts known to the compiler
            LanguageServiceShim.prototype.refresh = function (throwOnError) {
                var _this = this;
                this.forwardJSONCall("refresh(" + throwOnError + ")", function () {
                    _this.languageService.refresh();
                    return null;
                });
            };

            LanguageServiceShim.prototype.cleanupSemanticCache = function () {
                var _this = this;
                this.forwardJSONCall("cleanupSemanticCache()", function () {
                    _this.languageService.cleanupSemanticCache();
                    return null;
                });
            };

            /// SQUIGGLES
            ///
            LanguageServiceShim.realizeDiagnosticCategory = function (category) {
                switch (category) {
                    case 1 /* Error */:
                        return Services.DiagnosticCategory.error;
                    case 0 /* Warning */:
                        return Services.DiagnosticCategory.warning;
                    case 2 /* Message */:
                        return Services.DiagnosticCategory.message;
                    default:
                        return Services.DiagnosticCategory.none;
                }
            };

            LanguageServiceShim.realizeDiagnostic = function (diagnostic) {
                return {
                    message: diagnostic.text(),
                    start: diagnostic.start(),
                    length: diagnostic.length(),
                    category: LanguageServiceShim.realizeDiagnosticCategory(diagnostic.info().category)
                };
            };

            LanguageServiceShim.prototype.realizeDiagnosticWithFileName = function (diagnostic) {
                return {
                    fileName: diagnostic.fileName(),
                    message: diagnostic.text(),
                    start: diagnostic.start(),
                    length: diagnostic.length(),
                    category: LanguageServiceShim.realizeDiagnosticCategory(diagnostic.info().category)
                };
            };

            LanguageServiceShim.prototype.getSyntacticDiagnostics = function (fileName) {
                var _this = this;
                return this.forwardJSONCall("getSyntacticDiagnostics(\"" + fileName + "\")", function () {
                    var errors = _this.languageService.getSyntacticDiagnostics(fileName);
                    return errors.map(LanguageServiceShim.realizeDiagnostic);
                });
            };

            LanguageServiceShim.prototype.getSemanticDiagnostics = function (fileName) {
                var _this = this;
                return this.forwardJSONCall("getSemanticDiagnostics(\"" + fileName + "\")", function () {
                    var errors = _this.languageService.getSemanticDiagnostics(fileName);
                    return errors.map(LanguageServiceShim.realizeDiagnostic);
                });
            };

            LanguageServiceShim.prototype.getCompilerOptionsDiagnostics = function () {
                var _this = this;
                return this.forwardJSONCall("getCompilerOptionsDiagnostics()", function () {
                    var errors = _this.languageService.getCompilerOptionsDiagnostics();
                    return errors.map(function (d) {
                        return _this.realizeDiagnosticWithFileName(d);
                    });
                });
            };

            /// QUICKINFO
            /// Computes a string representation of the type at the requested position
            /// in the active file.
            LanguageServiceShim.prototype.getTypeAtPosition = function (fileName, position) {
                var _this = this;
                return this.forwardJSONCall("getTypeAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    var typeInfo = _this.languageService.getTypeAtPosition(fileName, position);
                    return typeInfo;
                });
            };

            /// NAMEORDOTTEDNAMESPAN
            /// Computes span information of the name or dotted name at the requested position
            // in the active file.
            LanguageServiceShim.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) {
                var _this = this;
                return this.forwardJSONCall("getNameOrDottedNameSpan(\"" + fileName + "\", " + startPos + ", " + endPos + ")", function () {
                    var spanInfo = _this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos);
                    return spanInfo;
                });
            };

            /// STATEMENTSPAN
            /// Computes span information of statement at the requested position in the active file.
            LanguageServiceShim.prototype.getBreakpointStatementAtPosition = function (fileName, position) {
                var _this = this;
                return this.forwardJSONCall("getBreakpointStatementAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    var spanInfo = _this.languageService.getBreakpointStatementAtPosition(fileName, position);
                    return spanInfo;
                });
            };

            /// SIGNATUREHELP
            /// Computes a string representation of the signatures at the requested position
            /// in the active file.
            LanguageServiceShim.prototype.getSignatureAtPosition = function (fileName, position) {
                var _this = this;
                return this.forwardJSONCall("getSignatureAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    var signatureInfo = _this.languageService.getSignatureAtPosition(fileName, position);
                    return signatureInfo;
                });
            };

            /// GOTO DEFINITION
            /// Computes the definition location and file for the symbol
            /// at the requested position.
            LanguageServiceShim.prototype.getDefinitionAtPosition = function (fileName, position) {
                var _this = this;
                return this.forwardJSONCall("getDefinitionAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    return _this.languageService.getDefinitionAtPosition(fileName, position);
                });
            };

            /// GET BRACE MATCHING
            LanguageServiceShim.prototype.getBraceMatchingAtPosition = function (fileName, position) {
                var _this = this;
                return this.forwardJSONCall("getBraceMatchingAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    var textRanges = _this.languageService.getBraceMatchingAtPosition(fileName, position);
                    return textRanges;
                });
            };

            /// GET SMART INDENT
            LanguageServiceShim.prototype.getIndentationAtPosition = function (fileName, position, options /*Services.EditorOptions*/ ) {
                var _this = this;
                return this.forwardJSONCall("getIndentationAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    var localOptions = JSON.parse(options);
                    var columnOffset = _this.languageService.getIndentationAtPosition(fileName, position, localOptions);
                    return { value: columnOffset };
                });
            };

            /// GET REFERENCES
            ///  Return references to a symbol at the requested position.
            ///  References are separated by "\n".
            ///  Each reference is a "fileindex min lim" sub-string.
            LanguageServiceShim.prototype.getReferencesAtPosition = function (fileName, position) {
                var _this = this;
                return this.forwardJSONCall("getReferencesAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    return _this.languageService.getReferencesAtPosition(fileName, position);
                });
            };

            LanguageServiceShim.prototype.getOccurrencesAtPosition = function (fileName, position) {
                var _this = this;
                return this.forwardJSONCall("getOccurrencesAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    return _this.languageService.getOccurrencesAtPosition(fileName, position);
                });
            };

            /// GET IMPLEMENTORS
            LanguageServiceShim.prototype.getImplementorsAtPosition = function (fileName, position) {
                var _this = this;
                return this.forwardJSONCall("getImplementorsAtPosition(\"" + fileName + "\", " + position + ")", function () {
                    return _this.languageService.getImplementorsAtPosition(fileName, position);
                });
            };

            /// COMPLETION LISTS
            /// Get a string based representation of the completions
            /// to provide at the given source position and providing a member completion
            /// list if requested.
            LanguageServiceShim.prototype.getCompletionsAtPosition = function (fileName, position, isMemberCompletion) {
                var _this = this;
                return this.forwardJSONCall("getCompletionsAtPosition(\"" + fileName + "\", " + position + ", " + isMemberCompletion + ")", function () {
                    var completion = _this.languageService.getCompletionsAtPosition(fileName, position, isMemberCompletion);
                    return completion;
                });
            };

            /// Get a string based representation of a completion list entry details
            LanguageServiceShim.prototype.getCompletionEntryDetails = function (fileName, position, entryName) {
                var _this = this;
                return this.forwardJSONCall("getCompletionEntryDetails(\"" + fileName + "\", " + position + ", " + entryName + ")", function () {
                    var details = _this.languageService.getCompletionEntryDetails(fileName, position, entryName);
                    return details;
                });
            };

            /// FORMAT SELECTION
            LanguageServiceShim.prototype.getFormattingEditsForRange = function (fileName, minChar, limChar, options /*Services.FormatCodeOptions*/ ) {
                var _this = this;
                return this.forwardJSONCall("getFormattingEditsForRange(\"" + fileName + "\", " + minChar + ", " + limChar + ")", function () {
                    var localOptions = JSON.parse(options);
                    var edits = _this.languageService.getFormattingEditsForRange(fileName, minChar, limChar, localOptions);
                    return edits;
                });
            };

            /// FORMAT DOCUMENT
            LanguageServiceShim.prototype.getFormattingEditsForDocument = function (fileName, minChar, limChar, options /*Services.FormatCodeOptions*/ ) {
                var _this = this;
                return this.forwardJSONCall("getFormattingEditsForDocument(\"" + fileName + "\", " + minChar + ", " + limChar + ")", function () {
                    var localOptions = JSON.parse(options);
                    var edits = _this.languageService.getFormattingEditsForDocument(fileName, minChar, limChar, localOptions);
                    return edits;
                });
            };

            /// FORMAT ON PASTE
            LanguageServiceShim.prototype.getFormattingEditsOnPaste = function (fileName, minChar, limChar, options /*Services.FormatCodeOptions*/ ) {
                var _this = this;
                return this.forwardJSONCall("getFormattingEditsOnPaste(\"" + fileName + "\", " + minChar + ", " + limChar + ")", function () {
                    var localOptions = JSON.parse(options);
                    var edits = _this.languageService.getFormattingEditsOnPaste(fileName, minChar, limChar, localOptions);
                    return edits;
                });
            };

            /// FORMAT
            LanguageServiceShim.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options /*Services.FormatCodeOptions*/ ) {
                var _this = this;
                return this.forwardJSONCall("getFormattingEditsAfterKeystroke(\"" + fileName + "\", " + position + ", \"" + key + "\")", function () {
                    var localOptions = JSON.parse(options);
                    var edits = _this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions);
                    return edits;
                });
            };

            /// NAVIGATE TO
            ///  Return a list of symbols that are interesting to navigate to
            LanguageServiceShim.prototype.getNavigateToItems = function (searchValue) {
                var _this = this;
                return this.forwardJSONCall("getNavigateToItems(\"" + searchValue + "\")", function () {
                    var items = _this.languageService.getNavigateToItems(searchValue);
                    var result = _this._navigateToItemsToString(items);
                    return result;
                });
            };

            // GET SCRIPT LEXICAL STRUCTURE
            //
            LanguageServiceShim.prototype.getScriptLexicalStructure = function (fileName) {
                var _this = this;
                return this.forwardJSONCall("getScriptLexicalStructure(\"" + fileName + "\")", function () {
                    var items = _this.languageService.getScriptLexicalStructure(fileName);
                    var result = _this._navigateToItemsToString(items);
                    return result;
                });
            };

            // GET OUTLINING REGIONS
            //
            LanguageServiceShim.prototype.getOutliningRegions = function (fileName) {
                var _this = this;
                return this.forwardJSONCall("getOutliningRegions(\"" + fileName + "\")", function () {
                    var items = _this.languageService.getOutliningRegions(fileName);
                    return items;
                });
            };

            /// Emit
            LanguageServiceShim.prototype.getEmitOutput = function (fileName) {
                var _this = this;
                return this.forwardJSONCall("getEmitOutput(\"" + fileName + "\")", function () {
                    var output = _this.languageService.getEmitOutput(fileName);
                    return output;
                });
            };

            LanguageServiceShim.prototype._navigateToItemsToString = function (items) {
                var result = [];

                for (var i = 0; i < items.length; i++) {
                    var item = items[i];

                    result.push({
                        name: item.name,
                        kind: item.kind,
                        kindModifiers: item.kindModifiers,
                        containerName: item.containerName,
                        containerKind: item.containerKind,
                        matchKind: item.matchKind,
                        fileName: item.fileName,
                        minChar: item.minChar,
                        limChar: item.limChar,
                        additionalSpans: item.additionalSpans ? item.additionalSpans.map(function (i) {
                            return { start: i.minChar, end: i.limChar };
                        }) : undefined
                    });
                }

                return result;
            };
            return LanguageServiceShim;
        })(ShimBase);
        Services.LanguageServiceShim = LanguageServiceShim;

        var ClassifierShim = (function (_super) {
            __extends(ClassifierShim, _super);
            function ClassifierShim(factory, host) {
                _super.call(this, factory);
                this.host = host;
                this.classifier = new TypeScript.Services.Classifier(this.host);
            }
            /// COLORIZATION
            ClassifierShim.prototype.getClassificationsForLine = function (text, lexState) {
                var classification = this.classifier.getClassificationsForLine(text, lexState);
                var items = classification.entries;
                var result = "";
                for (var i = 0; i < items.length; i++) {
                    result += items[i].length + "\n";
                    result += items[i].classification + "\n";
                }
                result += classification.finalLexState;
                return result;
            };
            return ClassifierShim;
        })(ShimBase);
        Services.ClassifierShim = ClassifierShim;

        var CoreServicesShim = (function (_super) {
            __extends(CoreServicesShim, _super);
            function CoreServicesShim(factory, host) {
                _super.call(this, factory);
                this.host = host;
                this.logger = this.host.logger;
                this.services = new TypeScript.Services.CoreServices(this.host);
            }
            CoreServicesShim.prototype.forwardJSONCall = function (actionDescription, action) {
                return TypeScript.Services.forwardJSONCall(this.logger, actionDescription, action);
            };

            ///
            /// getPreProcessedFileInfo
            ///
            CoreServicesShim.prototype.getPreProcessedFileInfo = function (fileName, sourceText) {
                var _this = this;
                return this.forwardJSONCall("getPreProcessedFileInfo(\"" + fileName + "\")", function () {
                    var result = _this.services.getPreProcessedFileInfo(fileName, sourceText);
                    return result;
                });
            };

            ///
            /// getDefaultCompilationSettings
            ///
            CoreServicesShim.prototype.getDefaultCompilationSettings = function () {
                var _this = this;
                return this.forwardJSONCall("getDefaultCompilationSettings()", function () {
                    var result = _this.services.getDefaultCompilationSettings();
                    return result;
                });
            };

            ///
            /// dumpMemory
            ///
            CoreServicesShim.prototype.dumpMemory = function (dummy) {
                var _this = this;
                return this.forwardJSONCall("dumpMemory()", function () {
                    return _this.services.dumpMemory();
                });
            };

            ///
            /// getMemoryInfo
            ///
            CoreServicesShim.prototype.getMemoryInfo = function (dummy) {
                var _this = this;
                return this.forwardJSONCall("getMemoryInfo()", function () {
                    var result = _this.services.getMemoryInfo();
                    return result;
                });
            };
            return CoreServicesShim;
        })(ShimBase);
        Services.CoreServicesShim = CoreServicesShim;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var OutliningElementsCollector = (function (_super) {
            __extends(OutliningElementsCollector, _super);
            function OutliningElementsCollector() {
                _super.call(this, OutliningElementsCollector.MaximumDepth);
                this.inObjectLiteralExpression = false;
                this.elements = [];
            }
            OutliningElementsCollector.prototype.visitClassDeclaration = function (node) {
                this.addOutlineRange(node, node.openBraceToken, node.closeBraceToken);
                _super.prototype.visitClassDeclaration.call(this, node);
            };

            OutliningElementsCollector.prototype.visitInterfaceDeclaration = function (node) {
                this.addOutlineRange(node, node.body.openBraceToken, node.body.closeBraceToken);
                _super.prototype.visitInterfaceDeclaration.call(this, node);
            };

            OutliningElementsCollector.prototype.visitModuleDeclaration = function (node) {
                this.addOutlineRange(node, node.openBraceToken, node.closeBraceToken);
                _super.prototype.visitModuleDeclaration.call(this, node);
            };

            OutliningElementsCollector.prototype.visitEnumDeclaration = function (node) {
                this.addOutlineRange(node, node.openBraceToken, node.closeBraceToken);
                _super.prototype.visitEnumDeclaration.call(this, node);
            };

            OutliningElementsCollector.prototype.visitFunctionDeclaration = function (node) {
                this.addOutlineRange(node, node.block, node.block);
                _super.prototype.visitFunctionDeclaration.call(this, node);
            };

            OutliningElementsCollector.prototype.visitFunctionExpression = function (node) {
                this.addOutlineRange(node, node.block, node.block);
                _super.prototype.visitFunctionExpression.call(this, node);
            };

            OutliningElementsCollector.prototype.visitConstructorDeclaration = function (node) {
                this.addOutlineRange(node, node.block, node.block);
                _super.prototype.visitConstructorDeclaration.call(this, node);
            };

            OutliningElementsCollector.prototype.visitMemberFunctionDeclaration = function (node) {
                this.addOutlineRange(node, node.block, node.block);
                _super.prototype.visitMemberFunctionDeclaration.call(this, node);
            };

            OutliningElementsCollector.prototype.visitGetAccessor = function (node) {
                if (!this.inObjectLiteralExpression) {
                    this.addOutlineRange(node, node.block, node.block);
                }
                _super.prototype.visitGetAccessor.call(this, node);
            };

            OutliningElementsCollector.prototype.visitSetAccessor = function (node) {
                if (!this.inObjectLiteralExpression) {
                    this.addOutlineRange(node, node.block, node.block);
                }
                _super.prototype.visitSetAccessor.call(this, node);
            };

            OutliningElementsCollector.prototype.visitObjectLiteralExpression = function (node) {
                var savedInObjectLiteralExpression = this.inObjectLiteralExpression;
                this.inObjectLiteralExpression = true;
                _super.prototype.visitObjectLiteralExpression.call(this, node);
                this.inObjectLiteralExpression = savedInObjectLiteralExpression;
            };

            OutliningElementsCollector.prototype.addOutlineRange = function (node, startElement, endElement) {
                if (startElement && endElement && !TypeScript.isShared(startElement) && !TypeScript.isShared(endElement)) {
                    // Compute the position
                    var start = TypeScript.start(startElement);
                    var end = TypeScript.end(endElement);

                    // Push the new range
                    this.elements.push(TypeScript.TextSpan.fromBounds(start, end));
                }
            };

            OutliningElementsCollector.collectElements = function (node) {
                var collector = new OutliningElementsCollector();
                TypeScript.visitNodeOrToken(collector, node);
                return collector.elements;
            };
            // The maximum depth for collecting spans; this will cause us to miss deeply nested function/modules spans,
            // but will guarantee performance will not be closely tied to tree depth.
            OutliningElementsCollector.MaximumDepth = 10;
            return OutliningElementsCollector;
        })(TypeScript.DepthLimitedWalker);
        Services.OutliningElementsCollector = OutliningElementsCollector;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var BraceMatcher = (function () {
            function BraceMatcher() {
            }
            // Given a script name and position in the script, return a pair of text range if the
            // position corresponds to a "brace matchin" characters (e.g. "{" or "(", etc.)
            // If the position is not on any range, return an empty set.
            BraceMatcher.getMatchSpans = function (syntaxTree, position) {
                var result = [];

                var currentToken = TypeScript.findToken(syntaxTree.sourceUnit(), position);

                BraceMatcher.getMatchingCloseBrace(currentToken, position, result);
                BraceMatcher.getMatchingOpenBrace(currentToken, position, result);

                return result;
            };

            BraceMatcher.getMatchingCloseBrace = function (currentToken, position, result) {
                if (TypeScript.start(currentToken) === position) {
                    var closingBraceKind = BraceMatcher.getMatchingCloseBraceTokenKind(currentToken);
                    if (closingBraceKind !== null) {
                        var parentElement = currentToken.parent;
                        var currentPosition = TypeScript.fullStart(currentToken.parent);
                        for (var i = 0, n = TypeScript.childCount(parentElement); i < n; i++) {
                            var element = TypeScript.childAt(parentElement, i);
                            if (element !== null && TypeScript.fullWidth(element) > 0) {
                                if (element.kind() === closingBraceKind) {
                                    var range1 = new TypeScript.TextSpan(position, TypeScript.width(currentToken));
                                    var range2 = new TypeScript.TextSpan(currentPosition + TypeScript.leadingTriviaWidth(element), TypeScript.width(element));
                                    result.push(range1, range2);
                                    break;
                                }

                                currentPosition += TypeScript.fullWidth(element);
                            }
                        }
                    }
                }
            };

            BraceMatcher.getMatchingOpenBrace = function (currentToken, position, result) {
                // Check if the current token to the left is a close brace
                if (currentToken.fullStart() === position) {
                    currentToken = TypeScript.previousToken(currentToken);
                }

                if (currentToken !== null && TypeScript.start(currentToken) === (position - 1)) {
                    var openBraceKind = BraceMatcher.getMatchingOpenBraceTokenKind(currentToken);
                    if (openBraceKind !== null) {
                        var parentElement = currentToken.parent;
                        var currentPosition = TypeScript.fullStart(currentToken.parent) + TypeScript.fullWidth(parentElement);
                        for (var i = TypeScript.childCount(parentElement) - 1; i >= 0; i--) {
                            var element = TypeScript.childAt(parentElement, i);
                            if (element !== null && TypeScript.fullWidth(element) > 0) {
                                if (element.kind() === openBraceKind) {
                                    var range1 = new TypeScript.TextSpan(position - 1, TypeScript.width(currentToken));
                                    var range2 = new TypeScript.TextSpan(currentPosition - TypeScript.lastToken(element).trailingTriviaWidth() - TypeScript.width(element), TypeScript.width(element));
                                    result.push(range1, range2);
                                    break;
                                }

                                currentPosition -= TypeScript.fullWidth(element);
                            }
                        }
                    }
                }
            };

            BraceMatcher.getMatchingCloseBraceTokenKind = function (positionedElement) {
                var element = positionedElement !== null && positionedElement;
                switch (element.kind()) {
                    case 70 /* OpenBraceToken */:
                        return 71 /* CloseBraceToken */;
                    case 72 /* OpenParenToken */:
                        return 73 /* CloseParenToken */;
                    case 74 /* OpenBracketToken */:
                        return 75 /* CloseBracketToken */;
                    case 80 /* LessThanToken */:
                        return TypeScript.SyntaxUtilities.isAngleBracket(positionedElement) ? 81 /* GreaterThanToken */ : null;
                }
                return null;
            };

            BraceMatcher.getMatchingOpenBraceTokenKind = function (positionedElement) {
                var element = positionedElement !== null && positionedElement;
                switch (element.kind()) {
                    case 71 /* CloseBraceToken */:
                        return 70 /* OpenBraceToken */;
                    case 73 /* CloseParenToken */:
                        return 72 /* OpenParenToken */;
                    case 75 /* CloseBracketToken */:
                        return 74 /* OpenBracketToken */;
                    case 81 /* GreaterThanToken */:
                        return TypeScript.SyntaxUtilities.isAngleBracket(positionedElement) ? 80 /* LessThanToken */ : null;
                }
                return null;
            };
            return BraceMatcher;
        })();
        Services.BraceMatcher = BraceMatcher;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var Indenter = (function () {
            function Indenter() {
            }
            Indenter.getIndentation = function (node, soruceText, position, editorOptions) {
                var indentation = 0;
                var currentToken = TypeScript.findToken(node, position);
                var currentNode = currentToken;

                if (currentToken.kind() === 10 /* EndOfFileToken */) {
                    // Ignore EOF tokens, pick the one before it
                    currentNode = TypeScript.previousToken(currentToken);
                } else if (Indenter.belongsToBracket(soruceText, currentToken, position)) {
                    // Let braces and brackets take the indentation of thier parents
                    currentNode = currentToken.parent;
                }

                if (currentNode === null) {
                    return indentation;
                }

                // Check if this is a valid node to provide indentation
                if (currentNode.kind() === 14 /* StringLiteral */ || currentNode.kind() === 12 /* RegularExpressionLiteral */) {
                    return indentation;
                }

                var currentElement = currentNode;
                var parent = currentNode.parent;

                while (parent !== null) {
                    // Skip nodes that start at the position, these will have the indentation level of thier parent
                    if (TypeScript.fullStart(parent) !== TypeScript.fullStart(currentNode)) {
                        if (Indenter.isInContainerNode(parent, currentElement)) {
                            indentation += editorOptions.IndentSize;
                        } else {
                            var listIndentation = Indenter.getCustomListIndentation(parent, currentElement);
                            if (listIndentation !== -1) {
                                // Found a list node with special indentation, If the list items span multiple lines, we want
                                // to use the user-specified indentation; return.
                                return indentation + listIndentation;
                            }
                        }
                    }
                    currentNode = parent;
                    currentElement = parent;
                    parent = parent.parent;
                }

                return indentation;
            };

            Indenter.belongsToBracket = function (sourceText, token, position) {
                switch (token.kind()) {
                    case 70 /* OpenBraceToken */:
                    case 71 /* CloseBraceToken */:
                    case 72 /* OpenParenToken */:
                    case 73 /* CloseParenToken */:
                    case 74 /* OpenBracketToken */:
                    case 75 /* CloseBracketToken */:
                        // the current token is a bracket, check if the current position is separated from it by a new line
                        if (position < TypeScript.start(token)) {
                            var text = sourceText.getText(position, TypeScript.start(token));
                            for (var i = 0; i < text.length; i++) {
                                if (TypeScript.CharacterInfo.isLineTerminator(text.charCodeAt(i))) {
                                    return false;
                                }
                            }
                        }
                        return true;
                }
                return false;
            };

            Indenter.isInContainerNode = function (parent, element) {
                switch (parent.kind()) {
                    case 131 /* ClassDeclaration */:
                    case 130 /* ModuleDeclaration */:
                    case 132 /* EnumDeclaration */:
                    case 133 /* ImportDeclaration */:
                    case 146 /* Block */:
                    case 151 /* SwitchStatement */:
                    case 233 /* CaseSwitchClause */:
                    case 234 /* DefaultSwitchClause */:
                        return true;

                    case 122 /* ObjectType */:
                        return true;

                    case 128 /* InterfaceDeclaration */:
                        return element.kind() !== 122 /* ObjectType */;

                    case 129 /* FunctionDeclaration */:
                    case 135 /* MemberFunctionDeclaration */:
                    case 139 /* GetAccessor */:
                    case 140 /* SetAccessor */:
                    case 222 /* FunctionExpression */:
                    case 236 /* CatchClause */:
                    case 237 /* FinallyClause */:
                    case 129 /* FunctionDeclaration */:
                    case 137 /* ConstructorDeclaration */:
                    case 154 /* ForStatement */:
                    case 155 /* ForInStatement */:
                    case 158 /* WhileStatement */:
                    case 161 /* DoStatement */:
                    case 163 /* WithStatement */:
                    case 147 /* IfStatement */:
                    case 235 /* ElseClause */:
                        // The block has already been conted before, ignore the container node
                        return element.kind() !== 146 /* Block */;

                    case 159 /* TryStatement */:
                        // If inside the try body, the block element will take care of the indentation
                        // If not, we do not want to indent, as the next token would probally be catch or finally
                        // and we want these on the same indentation level.
                        return false;
                    default:
                        return TypeScript.isNode(parent) && TypeScript.SyntaxUtilities.isStatement(parent);
                }
            };

            Indenter.getCustomListIndentation = function (list, element) {
                switch (list.kind()) {
                    case 2 /* SeparatedList */:
                        for (var i = 0, n = TypeScript.childCount(list); i < n; i++) {
                            var child = TypeScript.childAt(list, i);
                            if (child !== null && child === element)
                                return Indenter.getListItemIndentation(list, i - 1);
                        }
                        break;

                    case 226 /* ArgumentList */:
                        // The separated list has been handled in the previous case, this is just if we are after
                        // the last element of the list, we want to get the indentation of the last element of the list
                        var argumentList = list;
                        var _arguments = argumentList.arguments;
                        if (_arguments !== null && argumentList.closeParenToken === element) {
                            return Indenter.getListItemIndentation(_arguments, TypeScript.childCount(_arguments) - 1);
                        }
                        break;

                    case 227 /* ParameterList */:
                        // The separated list has been handled in the previous case, this is just if we are after
                        // the last element of the list, we want to get the indentation of the last element of the list
                        var parameterList = list;
                        var parameters = parameterList.parameters;
                        if (parameters !== null && parameterList.closeParenToken === element) {
                            return Indenter.getListItemIndentation(parameters, TypeScript.childCount(parameters) - 1);
                        }
                        break;

                    case 228 /* TypeArgumentList */:
                        // The separated list has been handled in the previous case, this is just if we are after
                        // the last element of the list, we want to get the indentation of the last element of the list
                        var typeArgumentList = list;
                        var typeArguments = typeArgumentList.typeArguments;
                        if (typeArguments !== null && typeArgumentList.greaterThanToken === element) {
                            return Indenter.getListItemIndentation(typeArguments, TypeScript.childCount(typeArguments) - 1);
                        }
                        break;

                    case 229 /* TypeParameterList */:
                        // The separated list has been handled in the previous case, this is just if we are after
                        // the last element of the list, we want to get the indentation of the last element of the list
                        var typeParameterList = list;
                        var typeParameters = typeParameterList.typeParameters;
                        if (typeParameters !== null && typeParameterList.greaterThanToken === element) {
                            return Indenter.getListItemIndentation(typeParameters, TypeScript.childCount(typeParameters) - 1);
                        }
                        break;
                }
                return -1;
            };

            Indenter.getListItemIndentation = function (list, elementIndex) {
                for (var i = elementIndex; i > 0; i--) {
                    var child = TypeScript.childAt(list, i);
                    var previousChild = TypeScript.childAt(list, i - 1);
                    if ((child !== null && TypeScript.firstToken(child).leadingTrivia().hasNewLine()) || (previousChild !== null && TypeScript.lastToken(previousChild).trailingTrivia().hasNewLine())) {
                        // TODO: get the trivia after new line
                        return TypeScript.leadingTriviaWidth(child);
                    }
                }
                return -1;
            };
            return Indenter;
        })();
        Services.Indenter = Indenter;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
var TypeScript;
(function (TypeScript) {
    (function (Services) {
        ///<reference path='references.ts' />
        (function (Breakpoints) {
            function createBreakpointSpanInfo(parentElement) {
                var childElements = [];
                for (var _i = 0; _i < (arguments.length - 1); _i++) {
                    childElements[_i] = arguments[_i + 1];
                }
                if (!parentElement) {
                    return null;
                }

                if (childElements.length == 0) {
                    return new Services.SpanInfo(TypeScript.start(parentElement), TypeScript.end(parentElement));
                }

                var start;
                var end;
                for (var i = 0; i < childElements.length; i++) {
                    var element = childElements[i];
                    if (element && !TypeScript.isShared(element)) {
                        if (start == undefined) {
                            start = TypeScript.start(element);
                        }
                        end = TypeScript.end(element);
                    }
                }

                return new Services.SpanInfo(start, end);
            }

            function createBreakpointSpanInfoWithLimChar(startElement, limChar) {
                return new Services.SpanInfo(TypeScript.start(startElement), limChar);
            }

            var BreakpointResolver = (function () {
                function BreakpointResolver(posLine, lineMap) {
                    this.posLine = posLine;
                    this.lineMap = lineMap;
                }
                BreakpointResolver.prototype.breakpointSpanOfToken = function (positionedToken) {
                    switch (positionedToken.kind()) {
                        case 70 /* OpenBraceToken */:
                            return this.breakpointSpanOfOpenBrace(positionedToken);

                        case 71 /* CloseBraceToken */:
                            return this.breakpointSpanOfCloseBrace(positionedToken);

                        case 79 /* CommaToken */:
                            return this.breakpointSpanOfComma(positionedToken);

                        case 78 /* SemicolonToken */:
                        case 10 /* EndOfFileToken */:
                            return this.breakpointSpanIfStartsOnSameLine(TypeScript.previousToken(positionedToken));

                        case 73 /* CloseParenToken */:
                            return this.breakpointSpanOfCloseParen(positionedToken);

                        case 22 /* DoKeyword */:
                            var parentElement = positionedToken.parent;
                            if (parentElement && parentElement.kind() == 161 /* DoStatement */) {
                                return this.breakpointSpanIfStartsOnSameLine(TypeScript.nextToken(positionedToken));
                            }
                            break;
                    }

                    return this.breakpointSpanOfContainingNode(positionedToken);
                };

                BreakpointResolver.prototype.breakpointSpanOfOpenBrace = function (openBraceToken) {
                    var container = TypeScript.Syntax.containingNode(openBraceToken);
                    if (container) {
                        var originalContainer = container;
                        if (container && container.kind() == 146 /* Block */) {
                            // We have to check the parent and decide what to do with the breakpoint
                            container = TypeScript.Syntax.containingNode(container);
                            if (!container) {
                                container = originalContainer;
                            }
                        }

                        switch (container.kind()) {
                            case 146 /* Block */:
                                if (!this.canHaveBreakpointInBlock(container)) {
                                    return null;
                                }
                                return this.breakpointSpanOfFirstStatementInBlock(container);
                                break;

                            case 130 /* ModuleDeclaration */:
                            case 131 /* ClassDeclaration */:
                            case 129 /* FunctionDeclaration */:
                            case 137 /* ConstructorDeclaration */:
                            case 135 /* MemberFunctionDeclaration */:
                            case 139 /* GetAccessor */:
                            case 140 /* SetAccessor */:
                            case 222 /* FunctionExpression */:
                            case 218 /* ParenthesizedArrowFunctionExpression */:
                            case 219 /* SimpleArrowFunctionExpression */:
                                if (!this.canHaveBreakpointInDeclaration(container)) {
                                    return null;
                                }
                                if (this.posLine != this.lineMap.getLineNumberFromPosition(TypeScript.start(container))) {
                                    return this.breakpointSpanOfFirstChildOfSyntaxList(this.getSyntaxListOfDeclarationWithElements(container));
                                } else {
                                    return this.breakpointSpanOf(container);
                                }

                            case 132 /* EnumDeclaration */:
                                if (!this.canHaveBreakpointInDeclaration(container)) {
                                    return null;
                                }
                                if (this.posLine != this.lineMap.getLineNumberFromPosition(TypeScript.start(container))) {
                                    return this.breakpointSpanOfFirstEnumElement(container);
                                } else {
                                    return this.breakpointSpanOf(container);
                                }

                            case 147 /* IfStatement */:
                            case 155 /* ForInStatement */:
                            case 158 /* WhileStatement */:
                            case 236 /* CatchClause */:
                                if (this.posLine != this.lineMap.getLineNumberFromPosition(TypeScript.start(container))) {
                                    return this.breakpointSpanOfFirstStatementInBlock(originalContainer);
                                } else {
                                    return this.breakpointSpanOf(container);
                                }

                            case 161 /* DoStatement */:
                                return this.breakpointSpanOfFirstStatementInBlock(originalContainer);

                            case 154 /* ForStatement */:
                                if (this.posLine != this.lineMap.getLineNumberFromPosition(TypeScript.start(container))) {
                                    return this.breakpointSpanOfFirstStatementInBlock(originalContainer);
                                } else {
                                    return this.breakpointSpanOf(TypeScript.previousToken(openBraceToken));
                                }

                            case 235 /* ElseClause */:
                            case 233 /* CaseSwitchClause */:
                            case 234 /* DefaultSwitchClause */:
                            case 163 /* WithStatement */:
                            case 159 /* TryStatement */:
                            case 237 /* FinallyClause */:
                                return this.breakpointSpanOfFirstStatementInBlock(originalContainer);

                            case 151 /* SwitchStatement */:
                                if (this.posLine != this.lineMap.getLineNumberFromPosition(TypeScript.start(container))) {
                                    return this.breakpointSpanOfFirstStatementOfFirstCaseClause(container);
                                } else {
                                    return this.breakpointSpanOf(container);
                                }
                        }
                    }

                    return null;
                };

                BreakpointResolver.prototype.breakpointSpanOfCloseBrace = function (closeBraceToken) {
                    var container = TypeScript.Syntax.containingNode(closeBraceToken);
                    if (container) {
                        var originalContainer = container;
                        if (container.kind() == 146 /* Block */) {
                            // We have to check the parent and decide what to do with the breakpoint
                            container = TypeScript.Syntax.containingNode(container);
                            if (!container) {
                                container = originalContainer;
                            }
                        }

                        switch (container.kind()) {
                            case 146 /* Block */:
                                if (!this.canHaveBreakpointInBlock(container)) {
                                    return null;
                                }
                                return this.breakpointSpanOfLastStatementInBlock(container);
                                break;

                            case 130 /* ModuleDeclaration */:
                                if (!this.canHaveBreakpointInDeclaration(container)) {
                                    return null;
                                }
                                var moduleSyntax = container;
                                if (moduleSyntax.moduleElements && moduleSyntax.moduleElements.length > 0) {
                                    return createBreakpointSpanInfo(closeBraceToken);
                                } else {
                                    return null;
                                }

                            case 131 /* ClassDeclaration */:
                            case 129 /* FunctionDeclaration */:
                            case 137 /* ConstructorDeclaration */:
                            case 135 /* MemberFunctionDeclaration */:
                            case 139 /* GetAccessor */:
                            case 140 /* SetAccessor */:
                            case 222 /* FunctionExpression */:
                                if (!this.canHaveBreakpointInDeclaration(container)) {
                                    return null;
                                }
                                return createBreakpointSpanInfo(closeBraceToken);

                            case 132 /* EnumDeclaration */:
                                if (!this.canHaveBreakpointInDeclaration(container)) {
                                    return null;
                                }
                                return createBreakpointSpanInfo(closeBraceToken);

                            case 147 /* IfStatement */:
                            case 235 /* ElseClause */:
                            case 155 /* ForInStatement */:
                            case 154 /* ForStatement */:
                            case 158 /* WhileStatement */:
                            case 161 /* DoStatement */:
                            case 233 /* CaseSwitchClause */:
                            case 234 /* DefaultSwitchClause */:
                            case 163 /* WithStatement */:
                            case 159 /* TryStatement */:
                            case 236 /* CatchClause */:
                            case 237 /* FinallyClause */:
                            case 218 /* ParenthesizedArrowFunctionExpression */:
                            case 219 /* SimpleArrowFunctionExpression */:
                                return this.breakpointSpanOfLastStatementInBlock(originalContainer);

                            case 151 /* SwitchStatement */:
                                return this.breakpointSpanOfLastStatementOfLastCaseClause(container);
                        }
                    }

                    return null;
                };

                BreakpointResolver.prototype.breakpointSpanOfComma = function (commaToken) {
                    var commaParent = commaToken.parent;
                    if (TypeScript.isSeparatedList(commaParent)) {
                        var grandParent = commaParent.parent;
                        if (grandParent) {
                            switch (grandParent.kind()) {
                                case 224 /* VariableDeclaration */:
                                case 132 /* EnumDeclaration */:
                                case 227 /* ParameterList */:
                                    var index = TypeScript.Syntax.childIndex(commaParent, commaToken);

                                    // Use the previous child
                                    if (index > 0) {
                                        var child = TypeScript.childAt(commaParent, index - 1);
                                        return this.breakpointSpanOf(child);
                                    }

                                    // If we cant set breakpoint on enum element, just dont set breakpoint
                                    if (grandParent.kind() == 132 /* EnumDeclaration */) {
                                        return null;
                                    }
                                    break;
                            }
                        }
                    }

                    return this.breakpointSpanOfContainingNode(commaToken);
                };

                BreakpointResolver.prototype.breakpointSpanOfCloseParen = function (closeParenToken) {
                    var closeParenParent = closeParenToken.parent;
                    if (closeParenParent) {
                        switch (closeParenParent.kind()) {
                            case 154 /* ForStatement */:
                            case 227 /* ParameterList */:
                                return this.breakpointSpanOf(TypeScript.previousToken(closeParenToken));
                        }
                    }

                    return this.breakpointSpanOfContainingNode(closeParenToken);
                };

                BreakpointResolver.prototype.canHaveBreakpointInBlock = function (blockNode) {
                    if (!blockNode || TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(blockNode)) {
                        return false;
                    }

                    var blockSyntax = blockNode;
                    return blockSyntax.statements && blockSyntax.statements.length != 0;
                };

                BreakpointResolver.prototype.breakpointSpanOfFirstStatementInBlock = function (blockNode) {
                    if (!blockNode) {
                        return null;
                    }

                    var blockSyntax = blockNode;
                    var statementsNode = blockSyntax.statements;
                    if (!statementsNode || statementsNode.length == 0) {
                        return null;
                    }

                    var firstStatement = TypeScript.childAt(statementsNode, 0);
                    if (firstStatement && firstStatement.kind() == 146 /* Block */) {
                        if (this.canHaveBreakpointInBlock(firstStatement)) {
                            return this.breakpointSpanOfFirstStatementInBlock(firstStatement);
                        }
                        return null;
                    } else {
                        return this.breakpointSpanOf(firstStatement);
                    }
                };

                BreakpointResolver.prototype.breakpointSpanOfLastStatementInBlock = function (blockNode) {
                    if (!blockNode) {
                        return null;
                    }

                    var blockSyntax = blockNode;
                    var statementsNode = blockSyntax.statements;
                    if (!statementsNode || statementsNode.length == 0) {
                        return null;
                    }

                    var lastStatement = TypeScript.childAt(statementsNode, statementsNode.length - 1);
                    if (lastStatement && lastStatement.kind() == 146 /* Block */) {
                        if (this.canHaveBreakpointInBlock(lastStatement)) {
                            return this.breakpointSpanOfLastStatementInBlock(lastStatement);
                        }
                        return null;
                    } else {
                        return this.breakpointSpanOf(lastStatement);
                    }
                };

                BreakpointResolver.prototype.breakpointSpanOfFirstChildOfSyntaxList = function (positionedList) {
                    if (!positionedList) {
                        return null;
                    }

                    // Find the first syntax element
                    var listSyntax = positionedList;
                    if (listSyntax.length == 0) {
                        return null;
                    }

                    var firstStatement = TypeScript.childAt(positionedList, 0);
                    if (firstStatement && firstStatement.kind() == 146 /* Block */) {
                        if (this.canHaveBreakpointInBlock(firstStatement)) {
                            return this.breakpointSpanOfFirstStatementInBlock(firstStatement);
                        }

                        return null;
                    } else {
                        return this.breakpointSpanOf(firstStatement);
                    }
                };

                BreakpointResolver.prototype.breakpointSpanOfLastChildOfSyntaxList = function (positionedList) {
                    if (!positionedList) {
                        return null;
                    }

                    // Find the first syntax element
                    var listSyntax = positionedList;
                    if (listSyntax.length == 0) {
                        return null;
                    }
                    var lastStatement = TypeScript.childAt(positionedList, 0);
                    if (lastStatement && lastStatement.kind() == 146 /* Block */) {
                        if (this.canHaveBreakpointInBlock(lastStatement)) {
                            return this.breakpointSpanOfLastStatementInBlock(lastStatement);
                        }
                        return null;
                    } else {
                        return this.breakpointSpanOf(lastStatement);
                    }
                };

                BreakpointResolver.prototype.breakpointSpanOfNode = function (positionedNode) {
                    var node = positionedNode;
                    switch (node.kind()) {
                        case 130 /* ModuleDeclaration */:
                        case 131 /* ClassDeclaration */:
                        case 129 /* FunctionDeclaration */:
                        case 137 /* ConstructorDeclaration */:
                        case 135 /* MemberFunctionDeclaration */:
                        case 139 /* GetAccessor */:
                        case 140 /* SetAccessor */:
                        case 222 /* FunctionExpression */:
                            return this.breakpointSpanOfDeclarationWithElements(positionedNode);

                        case 225 /* VariableDeclarator */:
                            return this.breakpointSpanOfVariableDeclarator(positionedNode);

                        case 224 /* VariableDeclaration */:
                            return this.breakpointSpanOfVariableDeclaration(positionedNode);

                        case 148 /* VariableStatement */:
                            return this.breakpointSpanOfVariableStatement(positionedNode);

                        case 242 /* Parameter */:
                            return this.breakpointSpanOfParameter(positionedNode);

                        case 136 /* MemberVariableDeclaration */:
                            return this.breakpointSpanOfMemberVariableDeclaration(positionedNode);

                        case 133 /* ImportDeclaration */:
                            return this.breakpointSpanOfImportDeclaration(positionedNode);

                        case 132 /* EnumDeclaration */:
                            return this.breakpointSpanOfEnumDeclaration(positionedNode);

                        case 243 /* EnumElement */:
                            return this.breakpointSpanOfEnumElement(positionedNode);

                        case 147 /* IfStatement */:
                            return this.breakpointSpanOfIfStatement(positionedNode);
                        case 235 /* ElseClause */:
                            return this.breakpointSpanOfElseClause(positionedNode);
                        case 155 /* ForInStatement */:
                            return this.breakpointSpanOfForInStatement(positionedNode);
                        case 154 /* ForStatement */:
                            return this.breakpointSpanOfForStatement(positionedNode);
                        case 158 /* WhileStatement */:
                            return this.breakpointSpanOfWhileStatement(positionedNode);
                        case 161 /* DoStatement */:
                            return this.breakpointSpanOfDoStatement(positionedNode);
                        case 151 /* SwitchStatement */:
                            return this.breakpointSpanOfSwitchStatement(positionedNode);
                        case 233 /* CaseSwitchClause */:
                            return this.breakpointSpanOfCaseSwitchClause(positionedNode);
                        case 234 /* DefaultSwitchClause */:
                            return this.breakpointSpanOfDefaultSwitchClause(positionedNode);
                        case 163 /* WithStatement */:
                            return this.breakpointSpanOfWithStatement(positionedNode);
                        case 159 /* TryStatement */:
                            return this.breakpointSpanOfTryStatement(positionedNode);
                        case 236 /* CatchClause */:
                            return this.breakpointSpanOfCatchClause(positionedNode);
                        case 237 /* FinallyClause */:
                            return this.breakpointSpanOfFinallyClause(positionedNode);

                        case 218 /* ParenthesizedArrowFunctionExpression */:
                            return this.breakpointSpanOfParenthesizedArrowFunctionExpression(positionedNode);

                        case 219 /* SimpleArrowFunctionExpression */:
                            return this.breakpointSpanOfSimpleArrowFunctionExpression(positionedNode);

                        default:
                            if (TypeScript.SyntaxUtilities.isStatement(node)) {
                                return this.breakpointSpanOfStatement(positionedNode);
                            } else {
                                return this.breakpointOfExpression(positionedNode);
                            }
                    }
                };

                BreakpointResolver.prototype.isExpressionOfArrowExpressions = function (expression) {
                    if (!expression) {
                        return false;
                    }

                    var expressionParent = expression.parent;
                    if (expressionParent) {
                        if (expressionParent.kind() == 218 /* ParenthesizedArrowFunctionExpression */) {
                            var parenthesizedArrowExpression = expressionParent;
                            var expressionOfParenthesizedArrowExpression = parenthesizedArrowExpression.expression;
                            return expressionOfParenthesizedArrowExpression == expression;
                        } else if (expressionParent.kind() == 219 /* SimpleArrowFunctionExpression */) {
                            var simpleArrowExpression = expressionParent;
                            var expressionOfSimpleArrowExpression = simpleArrowExpression.expression;
                            return expressionOfSimpleArrowExpression == expression;
                        } else if (expressionParent.kind() == 173 /* CommaExpression */) {
                            return this.isExpressionOfArrowExpressions(expressionParent);
                        }
                    }
                    return false;
                };

                BreakpointResolver.prototype.isInitializerOfForStatement = function (expressionNode) {
                    if (!expressionNode) {
                        return false;
                    }

                    var expressionParent = expressionNode.parent;
                    if (expressionParent && expressionParent.kind() == 154 /* ForStatement */) {
                        var expression = expressionNode;
                        var forStatement = expressionParent;
                        var initializer = forStatement.initializer;
                        return initializer === expression;
                    } else if (expressionParent && expressionParent.kind() == 173 /* CommaExpression */) {
                        return this.isInitializerOfForStatement(expressionParent);
                    }

                    return false;
                };

                BreakpointResolver.prototype.isConditionOfForStatement = function (expressionNode) {
                    if (!expressionNode) {
                        return false;
                    }

                    var expressionParent = expressionNode.parent;
                    if (expressionParent && expressionParent.kind() == 154 /* ForStatement */) {
                        var expression = expressionNode;
                        var forStatement = expressionParent;
                        var condition = forStatement.condition;
                        return condition === expression;
                    } else if (expressionParent && expressionParent.kind() == 173 /* CommaExpression */) {
                        return this.isConditionOfForStatement(expressionParent);
                    }

                    return false;
                };

                BreakpointResolver.prototype.isIncrememtorOfForStatement = function (expressionNode) {
                    if (!expressionNode) {
                        return false;
                    }

                    var expressionParent = expressionNode.parent;
                    if (expressionParent && expressionParent.kind() == 154 /* ForStatement */) {
                        var expression = expressionNode;
                        var forStatement = expressionParent;
                        var incrementor = forStatement.incrementor;
                        return incrementor === expression;
                    } else if (expressionParent && expressionParent.kind() == 173 /* CommaExpression */) {
                        return this.isIncrememtorOfForStatement(expressionParent);
                    }

                    return false;
                };

                BreakpointResolver.prototype.breakpointOfLeftOfCommaExpression = function (commaExpressionNode) {
                    var commaExpression = commaExpressionNode;
                    return this.breakpointSpanOf(commaExpression.left);
                };

                BreakpointResolver.prototype.breakpointOfExpression = function (expressionNode) {
                    if (this.isInitializerOfForStatement(expressionNode) || this.isConditionOfForStatement(expressionNode) || this.isIncrememtorOfForStatement(expressionNode)) {
                        if (expressionNode.kind() == 173 /* CommaExpression */) {
                            return this.breakpointOfLeftOfCommaExpression(expressionNode);
                        }
                        return createBreakpointSpanInfo(expressionNode);
                    }

                    if (this.isExpressionOfArrowExpressions(expressionNode)) {
                        if (expressionNode.kind() == 173 /* CommaExpression */) {
                            return this.breakpointOfLeftOfCommaExpression(expressionNode);
                        }
                        return createBreakpointSpanInfo(expressionNode);
                    }

                    if (expressionNode.kind() == 134 /* ExportAssignment */) {
                        var exportAssignmentSyntax = expressionNode;
                        return createBreakpointSpanInfo(expressionNode, exportAssignmentSyntax.exportKeyword, exportAssignmentSyntax.equalsToken, exportAssignmentSyntax.identifier);
                    }

                    return this.breakpointSpanOfContainingNode(expressionNode);
                };

                BreakpointResolver.prototype.breakpointSpanOfStatement = function (statementNode) {
                    var statement = statementNode;
                    if (statement.kind() == 156 /* EmptyStatement */) {
                        return null;
                    }

                    var containingNode = TypeScript.Syntax.containingNode(statementNode);
                    if (TypeScript.SyntaxUtilities.isStatement(containingNode)) {
                        // Check if not the declarations and the compound statements
                        var useNodeForBreakpoint = false;
                        switch (containingNode.kind()) {
                            case 130 /* ModuleDeclaration */:
                            case 131 /* ClassDeclaration */:
                            case 129 /* FunctionDeclaration */:
                            case 137 /* ConstructorDeclaration */:
                            case 135 /* MemberFunctionDeclaration */:
                            case 139 /* GetAccessor */:
                            case 140 /* SetAccessor */:
                            case 146 /* Block */:

                            case 147 /* IfStatement */:
                            case 235 /* ElseClause */:
                            case 155 /* ForInStatement */:
                            case 154 /* ForStatement */:
                            case 158 /* WhileStatement */:
                            case 161 /* DoStatement */:
                            case 151 /* SwitchStatement */:
                            case 233 /* CaseSwitchClause */:
                            case 234 /* DefaultSwitchClause */:
                            case 163 /* WithStatement */:
                            case 159 /* TryStatement */:
                            case 236 /* CatchClause */:
                            case 237 /* FinallyClause */:
                            case 146 /* Block */:
                                useNodeForBreakpoint = true;
                        }

                        if (!useNodeForBreakpoint) {
                            return this.breakpointSpanOfContainingNode(statementNode);
                        }
                    }

                    switch (statement.kind()) {
                        case 149 /* ExpressionStatement */:
                            var expressionSyntax = statement;
                            return createBreakpointSpanInfo(expressionSyntax.expression);

                        case 150 /* ReturnStatement */:
                            var returnStatementSyntax = statement;
                            return createBreakpointSpanInfo(statementNode, returnStatementSyntax.returnKeyword, returnStatementSyntax.expression);

                        case 157 /* ThrowStatement */:
                            var throwStatementSyntax = statement;
                            return createBreakpointSpanInfo(statementNode, throwStatementSyntax.throwKeyword, throwStatementSyntax.expression);

                        case 152 /* BreakStatement */:
                            var breakStatementSyntax = statement;
                            return createBreakpointSpanInfo(statementNode, breakStatementSyntax.breakKeyword, breakStatementSyntax.identifier);

                        case 153 /* ContinueStatement */:
                            var continueStatementSyntax = statement;
                            return createBreakpointSpanInfo(statementNode, continueStatementSyntax.continueKeyword, continueStatementSyntax.identifier);

                        case 162 /* DebuggerStatement */:
                            var debuggerStatementSyntax = statement;
                            return createBreakpointSpanInfo(debuggerStatementSyntax.debuggerKeyword);

                        case 160 /* LabeledStatement */:
                            var labeledStatementSyntax = statement;
                            return this.breakpointSpanOf(labeledStatementSyntax.statement);
                    }

                    return null;
                };

                BreakpointResolver.prototype.getSyntaxListOfDeclarationWithElements = function (positionedNode) {
                    var node = positionedNode;
                    var elementsList;
                    var block;

                    switch (node.kind()) {
                        case 130 /* ModuleDeclaration */:
                            elementsList = node.moduleElements;
                            break;

                        case 131 /* ClassDeclaration */:
                            elementsList = node.classElements;
                            break;

                        case 129 /* FunctionDeclaration */:
                            block = node.block;
                            break;

                        case 137 /* ConstructorDeclaration */:
                            block = node.block;
                            break;

                        case 135 /* MemberFunctionDeclaration */:
                            block = node.block;
                            break;

                        case 139 /* GetAccessor */:
                            block = node.block;
                            break;

                        case 140 /* SetAccessor */:
                            block = node.block;
                            break;

                        case 222 /* FunctionExpression */:
                            block = node.block;
                            break;

                        case 218 /* ParenthesizedArrowFunctionExpression */:
                            block = node.block;
                            break;

                        case 219 /* SimpleArrowFunctionExpression */:
                            block = node.block;
                            break;

                        default:
                            throw TypeScript.Errors.argument('positionNode', 'unknown node kind in getSyntaxListOfDeclarationWithElements');
                    }

                    var parentElement = positionedNode;
                    if (block) {
                        parentElement = block;
                        elementsList = block.statements;
                    }

                    return elementsList;
                };

                BreakpointResolver.prototype.canHaveBreakpointInDeclaration = function (positionedNode) {
                    return positionedNode && !TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(positionedNode);
                };

                BreakpointResolver.prototype.breakpointSpanOfDeclarationWithElements = function (positionedNode) {
                    if (!this.canHaveBreakpointInDeclaration(positionedNode)) {
                        return null;
                    }

                    // If inside another module the whole declaration is debuggable
                    var node = positionedNode;
                    var moduleSyntax = positionedNode;
                    if ((TypeScript.SyntaxUtilities.isModuleElement(node) && TypeScript.Syntax.containingNode(positionedNode).kind() != 120 /* SourceUnit */) || TypeScript.SyntaxUtilities.isClassElement(node) || (moduleSyntax.kind() == 130 /* ModuleDeclaration */ && moduleSyntax.name && moduleSyntax.name.kind() == 121 /* QualifiedName */)) {
                        return createBreakpointSpanInfo(positionedNode);
                    } else {
                        // Try to get the breakpoint in first element declaration
                        return this.breakpointSpanOfFirstChildOfSyntaxList(this.getSyntaxListOfDeclarationWithElements(positionedNode));
                    }
                };

                BreakpointResolver.prototype.canHaveBreakpointInVariableDeclarator = function (varDeclaratorNode) {
                    if (!varDeclaratorNode || TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(varDeclaratorNode)) {
                        return false;
                    }

                    var varDeclaratorSyntax = varDeclaratorNode;
                    return !!varDeclaratorSyntax.equalsValueClause;
                };

                BreakpointResolver.prototype.breakpointSpanOfVariableDeclarator = function (varDeclaratorNode) {
                    if (!this.canHaveBreakpointInVariableDeclarator(varDeclaratorNode)) {
                        return null;
                    }

                    var container = TypeScript.Syntax.containingNode(varDeclaratorNode);
                    if (container && container.kind() == 224 /* VariableDeclaration */) {
                        var parentDeclaratorsList = varDeclaratorNode.parent;

                        // If this is the first declarator in the list use the declaration instead
                        if (parentDeclaratorsList && TypeScript.childAt(parentDeclaratorsList, 0) == varDeclaratorNode) {
                            return this.breakpointSpanOfVariableDeclaration(container);
                        }

                        // Create breakpoint on this var declarator
                        if (this.canHaveBreakpointInVariableDeclarator(varDeclaratorNode)) {
                            return createBreakpointSpanInfo(varDeclaratorNode);
                        } else {
                            return null;
                        }
                    } else if (container) {
                        // Member Variable syntax
                        return this.breakpointSpanOfMemberVariableDeclaration(container);
                    }

                    return null;
                };

                BreakpointResolver.prototype.canHaveBreakpointInVariableDeclaration = function (varDeclarationNode) {
                    if (!varDeclarationNode || TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(varDeclarationNode)) {
                        return false;
                    }

                    var varDeclarationSyntax = varDeclarationNode;
                    var containerChildren = varDeclarationSyntax.variableDeclarators;
                    if (!containerChildren || TypeScript.childCount(containerChildren) == 0) {
                        return false;
                    }

                    var child = TypeScript.childAt(containerChildren, 0);
                    if (TypeScript.isNode(child)) {
                        return this.canHaveBreakpointInVariableDeclarator(child);
                    }

                    return false;
                };

                BreakpointResolver.prototype.breakpointSpanOfVariableDeclaration = function (varDeclarationNode) {
                    if (!this.canHaveBreakpointInDeclaration(varDeclarationNode)) {
                        return null;
                    }

                    var container = TypeScript.Syntax.containingNode(varDeclarationNode);
                    var varDeclarationSyntax = varDeclarationNode;
                    var varDeclarators = varDeclarationSyntax.variableDeclarators;
                    var varDeclaratorsCount = TypeScript.childCount(varDeclarators);

                    if (container && container.kind() == 148 /* VariableStatement */) {
                        return this.breakpointSpanOfVariableStatement(container);
                    }

                    if (this.canHaveBreakpointInVariableDeclaration(varDeclarationNode)) {
                        return createBreakpointSpanInfoWithLimChar(varDeclarationNode, TypeScript.end(TypeScript.childAt(varDeclarators, 0)));
                    } else {
                        return null;
                    }
                };

                BreakpointResolver.prototype.canHaveBreakpointInVariableStatement = function (varStatementNode) {
                    if (!varStatementNode || TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(varStatementNode)) {
                        return false;
                    }

                    var variableStatement = varStatementNode;
                    return this.canHaveBreakpointInVariableDeclaration(variableStatement.variableDeclaration);
                };

                BreakpointResolver.prototype.breakpointSpanOfVariableStatement = function (varStatementNode) {
                    if (!this.canHaveBreakpointInVariableStatement(varStatementNode)) {
                        return null;
                    }

                    var variableStatement = varStatementNode;
                    var variableDeclaration = variableStatement.variableDeclaration;
                    var varDeclarationSyntax = variableDeclaration;
                    var varDeclarators = varDeclarationSyntax.variableDeclarators;
                    return createBreakpointSpanInfoWithLimChar(varStatementNode, TypeScript.end(TypeScript.childAt(varDeclarators, 0)));
                };

                BreakpointResolver.prototype.breakpointSpanOfParameter = function (parameterNode) {
                    if (parameterNode.parent.kind() === 219 /* SimpleArrowFunctionExpression */) {
                        return this.breakpointSpanOfNode(parameterNode.parent);
                    }

                    if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(parameterNode)) {
                        return null;
                    }

                    var parameterSyntax = parameterNode;
                    if (parameterSyntax.dotDotDotToken || parameterSyntax.equalsValueClause || parameterSyntax.modifiers.length > 0) {
                        return createBreakpointSpanInfo(parameterNode);
                    } else {
                        return null;
                    }
                };

                BreakpointResolver.prototype.breakpointSpanOfMemberVariableDeclaration = function (memberVarDeclarationNode) {
                    if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(memberVarDeclarationNode)) {
                        return null;
                    }

                    var memberVariableDeclaration = memberVarDeclarationNode;
                    if (this.canHaveBreakpointInVariableDeclarator(memberVariableDeclaration.variableDeclarator)) {
                        return createBreakpointSpanInfo(memberVarDeclarationNode, memberVariableDeclaration.modifiers, memberVariableDeclaration.variableDeclarator);
                    } else {
                        return null;
                    }
                };

                BreakpointResolver.prototype.breakpointSpanOfImportDeclaration = function (importDeclarationNode) {
                    if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(importDeclarationNode)) {
                        return null;
                    }

                    var importSyntax = importDeclarationNode;
                    return createBreakpointSpanInfo(importDeclarationNode, importSyntax.modifiers, importSyntax.importKeyword, importSyntax.identifier, importSyntax.equalsToken, importSyntax.moduleReference);
                };

                BreakpointResolver.prototype.breakpointSpanOfEnumDeclaration = function (enumDeclarationNode) {
                    if (!this.canHaveBreakpointInDeclaration(enumDeclarationNode)) {
                        return null;
                    }

                    return createBreakpointSpanInfo(enumDeclarationNode);
                };

                BreakpointResolver.prototype.breakpointSpanOfFirstEnumElement = function (enumDeclarationNode) {
                    var enumDeclarationSyntax = enumDeclarationNode;
                    var enumElements = enumDeclarationSyntax.enumElements;
                    if (enumElements && TypeScript.childCount(enumElements)) {
                        return this.breakpointSpanOf(TypeScript.childAt(enumElements, 0));
                    }

                    return null;
                };

                BreakpointResolver.prototype.breakpointSpanOfEnumElement = function (enumElementNode) {
                    if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(enumElementNode)) {
                        return null;
                    }

                    return createBreakpointSpanInfo(enumElementNode);
                };

                BreakpointResolver.prototype.breakpointSpanOfIfStatement = function (ifStatementNode) {
                    var ifStatement = ifStatementNode;
                    return createBreakpointSpanInfo(ifStatementNode, ifStatement.ifKeyword, ifStatement.openParenToken, ifStatement.condition, ifStatement.closeParenToken);
                };

                BreakpointResolver.prototype.breakpointSpanOfElseClause = function (elseClauseNode) {
                    var elseClause = elseClauseNode;
                    return this.breakpointSpanOf(elseClause.statement);
                };

                BreakpointResolver.prototype.breakpointSpanOfForInStatement = function (forInStatementNode) {
                    var forInStatement = forInStatementNode;
                    return createBreakpointSpanInfo(forInStatementNode, forInStatement.forKeyword, forInStatement.openParenToken, forInStatement.variableDeclaration, forInStatement.left, forInStatement.inKeyword, forInStatement.expression, forInStatement.closeParenToken);
                };

                BreakpointResolver.prototype.breakpointSpanOfForStatement = function (forStatementNode) {
                    var forStatement = forStatementNode;
                    return this.breakpointSpanOf(forStatement.variableDeclaration ? forStatement.variableDeclaration : forStatement.initializer);
                };

                BreakpointResolver.prototype.breakpointSpanOfWhileStatement = function (whileStatementNode) {
                    var whileStatement = whileStatementNode;
                    return createBreakpointSpanInfo(whileStatementNode, whileStatement.whileKeyword, whileStatement.openParenToken, whileStatement.condition, whileStatement.closeParenToken);
                };

                BreakpointResolver.prototype.breakpointSpanOfDoStatement = function (doStatementNode) {
                    var doStatement = doStatementNode;
                    return createBreakpointSpanInfo(doStatementNode, doStatement.whileKeyword, doStatement.openParenToken, doStatement.condition, doStatement.closeParenToken);
                };

                BreakpointResolver.prototype.breakpointSpanOfSwitchStatement = function (switchStatementNode) {
                    var switchStatement = switchStatementNode;
                    return createBreakpointSpanInfo(switchStatementNode, switchStatement.switchKeyword, switchStatement.openParenToken, switchStatement.expression, switchStatement.closeParenToken);
                };

                BreakpointResolver.prototype.breakpointSpanOfFirstStatementOfFirstCaseClause = function (switchStatementNode) {
                    var switchStatement = switchStatementNode;
                    if (switchStatement.switchClauses && switchStatement.switchClauses.length == 0) {
                        return null;
                    }

                    var switchClauses = switchStatement.switchClauses;
                    if (switchClauses.length == 0) {
                        return null;
                    }

                    var firstCaseClause = switchClauses[0];
                    var statements = firstCaseClause.statements;

                    return this.breakpointSpanOfFirstChildOfSyntaxList(statements);
                };

                BreakpointResolver.prototype.breakpointSpanOfLastStatementOfLastCaseClause = function (switchStatementNode) {
                    var switchStatement = switchStatementNode;
                    if (switchStatement.switchClauses && switchStatement.switchClauses.length == 0) {
                        return null;
                    }

                    var switchClauses = switchStatement.switchClauses;
                    if (switchClauses.length == 0) {
                        return null;
                    }

                    var lastClauseNode = switchClauses[switchClauses.length - 1];
                    var statements = lastClauseNode.statements;

                    return this.breakpointSpanOfLastChildOfSyntaxList(statements);
                };

                BreakpointResolver.prototype.breakpointSpanOfCaseSwitchClause = function (caseClauseNode) {
                    var caseSwitchClause = caseClauseNode;
                    return this.breakpointSpanOfFirstChildOfSyntaxList(caseSwitchClause.statements);
                };

                BreakpointResolver.prototype.breakpointSpanOfDefaultSwitchClause = function (defaultSwithClauseNode) {
                    var defaultSwitchClause = defaultSwithClauseNode;
                    return this.breakpointSpanOfFirstChildOfSyntaxList(defaultSwitchClause.statements);
                };

                BreakpointResolver.prototype.breakpointSpanOfWithStatement = function (withStatementNode) {
                    var withStatement = withStatementNode;
                    return this.breakpointSpanOf(withStatement.statement);
                };

                BreakpointResolver.prototype.breakpointSpanOfTryStatement = function (tryStatementNode) {
                    var tryStatement = tryStatementNode;
                    return this.breakpointSpanOfFirstStatementInBlock(tryStatement.block);
                };

                BreakpointResolver.prototype.breakpointSpanOfCatchClause = function (catchClauseNode) {
                    var catchClause = catchClauseNode;
                    return createBreakpointSpanInfo(catchClauseNode, catchClause.catchKeyword, catchClause.openParenToken, catchClause.identifier, catchClause.typeAnnotation, catchClause.closeParenToken);
                };

                BreakpointResolver.prototype.breakpointSpanOfFinallyClause = function (finallyClauseNode) {
                    var finallyClause = finallyClauseNode;
                    return this.breakpointSpanOfFirstStatementInBlock(finallyClause.block);
                };

                BreakpointResolver.prototype.breakpointSpanOfParenthesizedArrowFunctionExpression = function (arrowFunctionExpression) {
                    if (arrowFunctionExpression.block) {
                        return this.breakpointSpanOfFirstStatementInBlock(arrowFunctionExpression.block);
                    } else {
                        return this.breakpointSpanOf(arrowFunctionExpression.expression);
                    }
                };

                BreakpointResolver.prototype.breakpointSpanOfSimpleArrowFunctionExpression = function (arrowFunctionExpression) {
                    if (arrowFunctionExpression.block) {
                        return this.breakpointSpanOfFirstStatementInBlock(arrowFunctionExpression.block);
                    } else {
                        return this.breakpointSpanOf(arrowFunctionExpression.expression);
                    }
                };

                BreakpointResolver.prototype.breakpointSpanOfContainingNode = function (positionedElement) {
                    var current = positionedElement.parent;
                    while (!TypeScript.isNode(current)) {
                        current = current.parent;
                    }

                    return this.breakpointSpanOf(current);
                };

                BreakpointResolver.prototype.breakpointSpanIfStartsOnSameLine = function (positionedElement) {
                    if (positionedElement && this.posLine == this.lineMap.getLineNumberFromPosition(TypeScript.start(positionedElement))) {
                        return this.breakpointSpanOf(positionedElement);
                    }

                    return null;
                };

                BreakpointResolver.prototype.breakpointSpanOf = function (positionedElement) {
                    if (!positionedElement) {
                        return null;
                    }

                    for (var containingNode = TypeScript.Syntax.containingNode(positionedElement); containingNode != null; containingNode = TypeScript.Syntax.containingNode(containingNode)) {
                        if (containingNode.kind() == 244 /* TypeAnnotation */) {
                            return this.breakpointSpanIfStartsOnSameLine(containingNode);
                        }
                    }

                    var element = positionedElement;

                    // Syntax node
                    if (TypeScript.isNode(element)) {
                        return this.breakpointSpanOfNode(positionedElement);
                    }

                    // Token
                    if (TypeScript.isToken(element)) {
                        return this.breakpointSpanOfToken(positionedElement);
                    }

                    // List
                    // Separated List
                    return this.breakpointSpanOfContainingNode(positionedElement);
                };
                return BreakpointResolver;
            })();

            function getBreakpointLocation(syntaxTree, askedPos) {
                // Cannot set breakpoint in dts file
                if (TypeScript.isDTSFile(syntaxTree.fileName())) {
                    return null;
                }

                var sourceUnit = syntaxTree.sourceUnit();
                var positionedToken = TypeScript.findToken(sourceUnit, askedPos);

                var lineMap = syntaxTree.lineMap();
                var posLine = lineMap.getLineNumberFromPosition(askedPos);
                var tokenStartLine = lineMap.getLineNumberFromPosition(TypeScript.start(positionedToken));
                if (posLine < tokenStartLine) {
                    return null;
                }

                var breakpointResolver = new BreakpointResolver(posLine, lineMap);
                return breakpointResolver.breakpointSpanOf(positionedToken);
            }
            Breakpoints.getBreakpointLocation = getBreakpointLocation;
        })(Services.Breakpoints || (Services.Breakpoints = {}));
        var Breakpoints = Services.Breakpoints;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    ///<reference path='references.ts' />
    (function (Services) {
        var GetScriptLexicalStructureWalker = (function (_super) {
            __extends(GetScriptLexicalStructureWalker, _super);
            function GetScriptLexicalStructureWalker(fileName) {
                _super.call(this);
                this.fileName = fileName;
                this.nameStack = [];
                this.kindStack = [];
                this.parentScopes = [];
                this.currentScope = this.createScope();
            }
            GetScriptLexicalStructureWalker.prototype.createScope = function () {
                return {
                    items: TypeScript.createIntrinsicsObject(),
                    childScopes: TypeScript.createIntrinsicsObject(),
                    childScopeNames: [],
                    itemNames: []
                };
            };

            GetScriptLexicalStructureWalker.prototype.pushNewContainerScope = function (containerName, kind) {
                TypeScript.Debug.assert(containerName, "No scope name provided");

                var key = kind + "+" + containerName;
                this.nameStack.push(containerName);
                this.kindStack.push(kind);

                var parentScope = this.currentScope;
                this.parentScopes.push(parentScope);

                var scope = parentScope.childScopes[key];
                if (!scope) {
                    scope = this.createScope();
                    parentScope.childScopes[key] = scope;
                    parentScope.childScopeNames.push(key);
                }

                this.currentScope = scope;
                return parentScope;
            };

            GetScriptLexicalStructureWalker.prototype.popScope = function () {
                TypeScript.Debug.assert(this.parentScopes.length > 0, "No parent scopes to return to");
                this.currentScope = this.parentScopes.pop();
                this.kindStack.pop();
                this.nameStack.pop();
            };

            GetScriptLexicalStructureWalker.prototype.collectItems = function (items, scope) {
                var _this = this;
                if (typeof scope === "undefined") { scope = this.currentScope; }
                scope.itemNames.forEach(function (item) {
                    items.push(scope.items[item]);
                });

                scope.childScopeNames.forEach(function (childScope) {
                    _this.collectItems(items, scope.childScopes[childScope]);
                });
            };

            GetScriptLexicalStructureWalker.getListsOfAllScriptLexicalStructure = function (items, fileName, unit) {
                var visitor = new GetScriptLexicalStructureWalker(fileName);
                TypeScript.visitNodeOrToken(visitor, unit);
                visitor.collectItems(items);
            };

            GetScriptLexicalStructureWalker.prototype.createItem = function (node, modifiers, kind, name) {
                var key = kind + "+" + name;

                if (this.currentScope.items[key] !== undefined) {
                    this.addAdditionalSpan(node, key);
                    return;
                }

                var item = new Services.NavigateToItem();
                item.name = name;
                item.kind = kind;
                item.matchKind = Services.MatchKind.exact;
                item.fileName = this.fileName;
                item.kindModifiers = this.getKindModifiers(modifiers);
                item.minChar = TypeScript.start(node);
                item.limChar = TypeScript.end(node);
                item.containerName = this.nameStack.join(".");
                item.containerKind = this.kindStack.length === 0 ? "" : TypeScript.ArrayUtilities.last(this.kindStack);

                this.currentScope.items[key] = item;
                this.currentScope.itemNames.push(key);
            };

            GetScriptLexicalStructureWalker.prototype.addAdditionalSpan = function (node, key) {
                var item = this.currentScope.items[key];
                TypeScript.Debug.assert(item !== undefined);

                var start = TypeScript.start(node);
                var span = new Services.SpanInfo(start, start + TypeScript.width(node));

                if (item.additionalSpans) {
                    item.additionalSpans.push(span);
                } else {
                    item.additionalSpans = [span];
                }
            };

            GetScriptLexicalStructureWalker.prototype.getKindModifiers = function (modifiers) {
                var result = [];

                for (var i = 0, n = modifiers.length; i < n; i++) {
                    result.push(modifiers[i].text());
                }

                return result.length > 0 ? result.join(',') : Services.ScriptElementKindModifier.none;
            };

            GetScriptLexicalStructureWalker.prototype.visitModuleDeclaration = function (node) {
                var names = this.getModuleNames(node);
                this.visitModuleDeclarationWorker(node, names, 0);
            };

            GetScriptLexicalStructureWalker.prototype.visitModuleDeclarationWorker = function (node, names, nameIndex) {
                if (nameIndex === names.length) {
                    // We're after all the module names, descend and process all children.
                    _super.prototype.visitModuleDeclaration.call(this, node);
                } else {
                    var name = names[nameIndex];
                    var kind = Services.ScriptElementKind.moduleElement;

                    this.createItem(node, node.modifiers, kind, name);

                    this.pushNewContainerScope(name, kind);

                    this.visitModuleDeclarationWorker(node, names, nameIndex + 1);

                    this.popScope();
                }
            };

            GetScriptLexicalStructureWalker.prototype.getModuleNames = function (node) {
                var result = [];

                if (node.stringLiteral) {
                    result.push(node.stringLiteral.text());
                } else {
                    this.getModuleNamesHelper(node.name, result);
                }

                return result;
            };

            GetScriptLexicalStructureWalker.prototype.getModuleNamesHelper = function (name, result) {
                if (name.kind() === 121 /* QualifiedName */) {
                    var qualifiedName = name;
                    this.getModuleNamesHelper(qualifiedName.left, result);
                    result.push(qualifiedName.right.text());
                } else {
                    result.push(name.text());
                }
            };

            GetScriptLexicalStructureWalker.prototype.visitClassDeclaration = function (node) {
                var name = node.identifier.text();
                var kind = Services.ScriptElementKind.classElement;

                this.createItem(node, node.modifiers, kind, name);

                this.pushNewContainerScope(name, kind);

                _super.prototype.visitClassDeclaration.call(this, node);

                this.popScope();
            };

            GetScriptLexicalStructureWalker.prototype.visitInterfaceDeclaration = function (node) {
                var name = node.identifier.text();
                var kind = Services.ScriptElementKind.interfaceElement;

                this.createItem(node, node.modifiers, kind, name);

                this.pushNewContainerScope(name, kind);

                _super.prototype.visitInterfaceDeclaration.call(this, node);

                this.popScope();
            };

            GetScriptLexicalStructureWalker.prototype.visitObjectType = function (node) {
                // Ignore an object type if we aren't inside an interface declaration.  We don't want
                // to add some random object type's members to the nav bar.
                if (node.parent.kind() === 128 /* InterfaceDeclaration */) {
                    _super.prototype.visitObjectType.call(this, node);
                }
            };

            GetScriptLexicalStructureWalker.prototype.visitEnumDeclaration = function (node) {
                var name = node.identifier.text();
                var kind = Services.ScriptElementKind.enumElement;

                this.createItem(node, node.modifiers, kind, name);

                this.pushNewContainerScope(name, kind);

                _super.prototype.visitEnumDeclaration.call(this, node);

                this.popScope();
            };

            GetScriptLexicalStructureWalker.prototype.visitConstructorDeclaration = function (node) {
                this.createItem(node, TypeScript.Syntax.emptyList(), Services.ScriptElementKind.constructorImplementationElement, "constructor");

                // Search the parameter list of class properties
                var parameters = node.callSignature.parameterList.parameters;
                if (parameters) {
                    for (var i = 0, n = parameters.length; i < n; i++) {
                        var parameter = parameters[i];

                        TypeScript.Debug.assert(parameter.kind() === 242 /* Parameter */);

                        if (TypeScript.SyntaxUtilities.containsToken(parameter.modifiers, 57 /* PublicKeyword */) || TypeScript.SyntaxUtilities.containsToken(parameter.modifiers, 55 /* PrivateKeyword */)) {
                            this.createItem(node, parameter.modifiers, Services.ScriptElementKind.memberVariableElement, parameter.identifier.text());
                        }
                    }
                }
                // No need to descend into a constructor;
            };

            GetScriptLexicalStructureWalker.prototype.visitMemberFunctionDeclaration = function (node) {
                this.createItem(node, node.modifiers, Services.ScriptElementKind.memberFunctionElement, node.propertyName.text());
                // No need to descend into a member function;
            };

            GetScriptLexicalStructureWalker.prototype.visitGetAccessor = function (node) {
                this.createItem(node, node.modifiers, Services.ScriptElementKind.memberGetAccessorElement, node.propertyName.text());
                // No need to descend into a member accessor;
            };

            GetScriptLexicalStructureWalker.prototype.visitSetAccessor = function (node) {
                this.createItem(node, node.modifiers, Services.ScriptElementKind.memberSetAccessorElement, node.propertyName.text());
                // No need to descend into a member accessor;
            };

            GetScriptLexicalStructureWalker.prototype.visitVariableDeclarator = function (node) {
                var modifiers = node.parent.kind() === 136 /* MemberVariableDeclaration */ ? node.parent.modifiers : TypeScript.Syntax.emptyList();
                var kind = node.parent.kind() === 136 /* MemberVariableDeclaration */ ? Services.ScriptElementKind.memberVariableElement : Services.ScriptElementKind.variableElement;
                this.createItem(node, modifiers, kind, node.propertyName.text());
                // No need to descend into a variable declarator;
            };

            GetScriptLexicalStructureWalker.prototype.visitIndexSignature = function (node) {
                this.createItem(node, TypeScript.Syntax.emptyList(), Services.ScriptElementKind.indexSignatureElement, "[]");
                // No need to descend into an index signature;
            };

            GetScriptLexicalStructureWalker.prototype.visitEnumElement = function (node) {
                this.createItem(node, TypeScript.Syntax.emptyList(), Services.ScriptElementKind.memberVariableElement, node.propertyName.text());
                // No need to descend into an enum element;
            };

            GetScriptLexicalStructureWalker.prototype.visitCallSignature = function (node) {
                this.createItem(node, TypeScript.Syntax.emptyList(), Services.ScriptElementKind.callSignatureElement, "()");
                // No need to descend into a call signature;
            };

            GetScriptLexicalStructureWalker.prototype.visitConstructSignature = function (node) {
                this.createItem(node, TypeScript.Syntax.emptyList(), Services.ScriptElementKind.constructSignatureElement, "new()");
                // No need to descend into a construct signature;
            };

            GetScriptLexicalStructureWalker.prototype.visitMethodSignature = function (node) {
                this.createItem(node, TypeScript.Syntax.emptyList(), Services.ScriptElementKind.memberFunctionElement, node.propertyName.text());
                // No need to descend into a method signature;
            };

            GetScriptLexicalStructureWalker.prototype.visitPropertySignature = function (node) {
                this.createItem(node, TypeScript.Syntax.emptyList(), Services.ScriptElementKind.memberVariableElement, node.propertyName.text());
                // No need to descend into a property signature;
            };

            GetScriptLexicalStructureWalker.prototype.visitFunctionDeclaration = function (node) {
                // in the case of:
                //    declare function
                // the parser will synthesize an identifier.
                // we shouldn't add an unnamed function declaration
                if (TypeScript.width(node.identifier) > 0) {
                    this.createItem(node, node.modifiers, Services.ScriptElementKind.functionElement, node.identifier.text());
                }
                // No need to descend into a function declaration;
            };

            // Common statement types.  Don't even bother walking into them as we'll never find anything
            // inside that we'd put in the navbar.
            GetScriptLexicalStructureWalker.prototype.visitBlock = function (node) {
            };

            GetScriptLexicalStructureWalker.prototype.visitIfStatement = function (node) {
            };

            GetScriptLexicalStructureWalker.prototype.visitExpressionStatement = function (node) {
            };

            GetScriptLexicalStructureWalker.prototype.visitThrowStatement = function (node) {
            };

            GetScriptLexicalStructureWalker.prototype.visitReturnStatement = function (node) {
            };

            GetScriptLexicalStructureWalker.prototype.visitSwitchStatement = function (node) {
            };

            GetScriptLexicalStructureWalker.prototype.visitWithStatement = function (node) {
            };

            GetScriptLexicalStructureWalker.prototype.visitTryStatement = function (node) {
            };

            GetScriptLexicalStructureWalker.prototype.visitLabeledStatement = function (node) {
            };
            return GetScriptLexicalStructureWalker;
        })(TypeScript.SyntaxWalker);
        Services.GetScriptLexicalStructureWalker = GetScriptLexicalStructureWalker;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
///<reference path='es5compat.ts' />
///<reference path='..\compiler\typescript.ts' />
// document.ts depends on incrementalParser.ts being run first.
///<reference path='..\compiler\syntax\incrementalParser.ts' />
///<reference path='document.ts' />
///<reference path='syntaxUtilities.generated.ts' />
///<reference path='coreServices.ts' />
///<reference path='classifier.ts' />
///<reference path='compilerState.ts' />
///<reference path='indentation.ts' />
///<reference path='languageService.ts' />
///<reference path='completionHelpers.ts' />
///<reference path='keywordCompletions.ts' />
///<reference path='signatureInfoHelpers.ts' />
///<reference path='completionSession.ts' />
///<reference path='pullLanguageService.ts' />
///<reference path='findReferenceHelpers.ts' />
///<reference path='shims.ts' />
///<reference path='formatting\formatting.ts' />
///<reference path='outliningElementsCollector.ts' />
///<reference path='braceMatcher.ts' />
///<reference path='indenter.ts' />
///<reference path='breakpoints.ts' />
///<reference path='getScriptLexicalStructureWalker.ts' />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// 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.
//
var TypeScript;
(function (TypeScript) {
    ///<reference path="references.ts" />
    (function (Services) {
        function copyDataObject(dst, src) {
            for (var e in dst) {
                if (typeof dst[e] == "object") {
                    copyDataObject(dst[e], src[e]);
                } else if (typeof dst[e] != "function") {
                    dst[e] = src[e];
                }
            }
            return dst;
        }
        Services.copyDataObject = copyDataObject;

        var TypeScriptServicesFactory = (function () {
            function TypeScriptServicesFactory() {
                this._shims = [];
                this.documentRegistry = new TypeScript.DocumentRegistry();
            }
            TypeScriptServicesFactory.prototype.createPullLanguageService = function (host) {
                try  {
                    return new TypeScript.Services.LanguageService(host, this.documentRegistry);
                } catch (err) {
                    TypeScript.Services.logInternalError(host, err);
                    throw err;
                }
            };

            TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) {
                try  {
                    var hostAdapter = new Services.LanguageServiceShimHostAdapter(host);
                    var pullLanguageService = this.createPullLanguageService(hostAdapter);
                    return new Services.LanguageServiceShim(this, host, pullLanguageService);
                } catch (err) {
                    TypeScript.Services.logInternalError(host, err);
                    throw err;
                }
            };

            TypeScriptServicesFactory.prototype.createClassifier = function (host) {
                try  {
                    return new TypeScript.Services.Classifier(host);
                } catch (err) {
                    TypeScript.Services.logInternalError(host, err);
                    throw err;
                }
            };

            TypeScriptServicesFactory.prototype.createClassifierShim = function (host) {
                try  {
                    return new Services.ClassifierShim(this, host);
                } catch (err) {
                    TypeScript.Services.logInternalError(host, err);
                    throw err;
                }
            };

            TypeScriptServicesFactory.prototype.createCoreServices = function (host) {
                try  {
                    return new TypeScript.Services.CoreServices(host);
                } catch (err) {
                    TypeScript.Services.logInternalError(host.logger, err);
                    throw err;
                }
            };

            TypeScriptServicesFactory.prototype.createCoreServicesShim = function (host) {
                try  {
                    return new Services.CoreServicesShim(this, host);
                } catch (err) {
                    TypeScript.Services.logInternalError(host.logger, err);
                    throw err;
                }
            };

            TypeScriptServicesFactory.prototype.close = function () {
                // Forget all the registered shims
                this._shims = [];
                this.documentRegistry = new TypeScript.DocumentRegistry();
            };

            TypeScriptServicesFactory.prototype.registerShim = function (shim) {
                this._shims.push(shim);
            };

            TypeScriptServicesFactory.prototype.unregisterShim = function (shim) {
                for (var i = 0, n = this._shims.length; i < n; i++) {
                    if (this._shims[i] === shim) {
                        delete this._shims[i];
                        return;
                    }
                }

                throw TypeScript.Errors.invalidOperation();
            };
            return TypeScriptServicesFactory;
        })();
        Services.TypeScriptServicesFactory = TypeScriptServicesFactory;
    })(TypeScript.Services || (TypeScript.Services = {}));
    var Services = TypeScript.Services;
})(TypeScript || (TypeScript = {}));
// Copyright (c) Microsoft, Claus Reinke. All rights reserved.
// Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='../typescript/src/compiler/io.ts'/>
///<reference path='../typescript/src/compiler/typescript.ts'/>
///<reference path='../typescript/src/services/typescriptServices.ts' />
// from src/harness/harness.ts, without the test (TODO: remove shim stuff again)
function switchToForwardSlashes(path) {
    return path.replace(/\\/g, "/");
}

function readFile(file) {
    return TypeScript.Environment.readFile(file, null);
}

var Harness;
(function (Harness) {
    // Settings
    Harness.userSpecifiedroot = "";
    var global = Function("return this").call(null);

    /** Splits the given string on \r\n or on only \n if that fails */
    function splitContentByNewlines(content) {
        // Split up the input file by line
        // Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so
        // we have to string-based splitting instead and try to figure out the delimiting chars
        var lines = content.split('\r\n');
        if (lines.length === 1) {
            lines = content.split('\n');
        }
        return lines;
    }
    Harness.splitContentByNewlines = splitContentByNewlines;

    var ScriptInfo = (function () {
        function ScriptInfo(fileName, content, isOpen, byteOrderMark) {
            if (typeof isOpen === "undefined") { isOpen = true; }
            if (typeof byteOrderMark === "undefined") { byteOrderMark = 0 /* None */; }
            this.fileName = fileName;
            this.content = content;
            this.isOpen = isOpen;
            this.byteOrderMark = byteOrderMark;
            this.version = 1;
            this.editRanges = [];
            this.lineMap = null;
            this.setContent(content);
        }
        ScriptInfo.prototype.setContent = function (content) {
            this.content = content;
            this.lineMap = TypeScript.LineMap1.fromString(content);
        };

        ScriptInfo.prototype.updateContent = function (content) {
            var old_length = this.content.length;
            this.setContent(content);
            this.editRanges.push({
                length: content.length,
                textChangeRange: new TypeScript.TextChangeRange(new TypeScript.TextSpan(0, old_length), content.length)
            });
            this.version++;
        };

        ScriptInfo.prototype.editContent = function (minChar, limChar, newText) {
            // Apply edits
            var prefix = this.content.substring(0, minChar);
            var middle = newText;
            var suffix = this.content.substring(limChar);
            this.setContent(prefix + middle + suffix);

            // Store edit range + new length of script
            this.editRanges.push({
                length: this.content.length,
                textChangeRange: new TypeScript.TextChangeRange(TypeScript.TextSpan.fromBounds(minChar, limChar), newText.length)
            });

            // Update version #
            this.version++;
        };

        ScriptInfo.prototype.getTextChangeRangeBetweenVersions = function (startVersion, endVersion) {
            if (startVersion === endVersion) {
                // No edits!
                return TypeScript.TextChangeRange.unchanged;
            }

            var initialEditRangeIndex = this.editRanges.length - (this.version - startVersion);
            var lastEditRangeIndex = this.editRanges.length - (this.version - endVersion);

            var entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex);
            return TypeScript.TextChangeRange.collapseChangesAcrossMultipleVersions(entries.map(function (e) {
                return e.textChangeRange;
            }));
        };
        return ScriptInfo;
    })();
    Harness.ScriptInfo = ScriptInfo;

    var ScriptSnapshotShim = (function () {
        function ScriptSnapshotShim(scriptInfo) {
            this.scriptInfo = scriptInfo;
            this.lineMap = null;
            this.textSnapshot = scriptInfo.content;
            this.version = scriptInfo.version;
        }
        ScriptSnapshotShim.prototype.getText = function (start, end) {
            return this.textSnapshot.substring(start, end);
        };

        ScriptSnapshotShim.prototype.getLength = function () {
            return this.textSnapshot.length;
        };

        ScriptSnapshotShim.prototype.getLineStartPositions = function () {
            if (this.lineMap === null) {
                this.lineMap = TypeScript.LineMap1.fromString(this.textSnapshot);
            }

            return JSON.stringify(this.lineMap.lineStarts());
        };

        ScriptSnapshotShim.prototype.getTextChangeRangeSinceVersion = function (scriptVersion) {
            var range = this.scriptInfo.getTextChangeRangeBetweenVersions(scriptVersion, this.version);
            if (range === null) {
                return null;
            }

            return JSON.stringify({ span: { start: range.span().start(), length: range.span().length() }, newLength: range.newLength() });
        };
        return ScriptSnapshotShim;
    })();

    var TypeScriptLS = (function () {
        function TypeScriptLS(cancellationToken) {
            if (typeof cancellationToken === "undefined") { cancellationToken = TypeScript.CancellationToken.None; }
            this.cancellationToken = cancellationToken;
            this.ls = null;
            this.fileNameToScript = new TypeScript.StringHashTable();
        }
        TypeScriptLS.prototype.addDefaultLibrary = function () {
            throw ("addDefaultLibrary not implemented");
            this.addScript("lib.d.ts", null);
        };

        TypeScriptLS.prototype.addFile = function (fileName) {
            var code = readFile(fileName).contents;
            this.addScript(fileName, code);
        };

        TypeScriptLS.prototype.getScriptInfo = function (fileName) {
            return this.fileNameToScript.lookup(fileName);
        };

        TypeScriptLS.prototype.addScript = function (fileName, content) {
            var script = new ScriptInfo(fileName, content);
            this.fileNameToScript.add(fileName, script);
        };

        TypeScriptLS.prototype.updateScript = function (fileName, content) {
            var script = this.getScriptInfo(fileName);
            if (script !== null) {
                script.updateContent(content);
                return;
            }

            this.addScript(fileName, content);
        };

        TypeScriptLS.prototype.editScript = function (fileName, minChar, limChar, newText) {
            var script = this.getScriptInfo(fileName);
            if (script !== null) {
                script.editContent(minChar, limChar, newText);
                return;
            }

            throw new Error("No script with name '" + fileName + "'");
        };

        //////////////////////////////////////////////////////////////////////
        // ILogger implementation
        //
        TypeScriptLS.prototype.information = function () {
            return false;
        };
        TypeScriptLS.prototype.debug = function () {
            return true;
        };
        TypeScriptLS.prototype.warning = function () {
            return true;
        };
        TypeScriptLS.prototype.error = function () {
            return true;
        };
        TypeScriptLS.prototype.fatal = function () {
            return true;
        };

        TypeScriptLS.prototype.log = function (s) {
            // For debugging...
            //TypeScript.Environment.printLine("TypeScriptLS:" + s);
        };

        // collect Diagnostics
        TypeScriptLS.prototype.getErrors = function () {
            var _this = this;
            var addPhase = function (phase) {
                return function (d) {
                    d.phase = phase;
                    return d;
                };
            };
            var errors = [];
            this.ls.refresh(false);
            this.fileNameToScript.getAllKeys().forEach(function (file) {
                var syntactic = _this.ls.languageService.getSyntacticDiagnostics(file);
                var semantic = _this.ls.languageService.getSemanticDiagnostics(file);

                // this.ls.languageService.getEmitOutput(file).diagnostics);
                errors = errors.concat(syntactic.map(addPhase("Syntax")), semantic.map(addPhase("Semantics")));
            });
            return errors;
        };

        //////////////////////////////////////////////////////////////////////
        // ILanguageServiceShimHost implementation
        //
        TypeScriptLS.prototype.getCompilationSettings = function () {
            return "";
        };

        TypeScriptLS.prototype.getCancellationToken = function () {
            return this.cancellationToken;
        };

        TypeScriptLS.prototype.getScriptFileNames = function () {
            return JSON.stringify(this.fileNameToScript.getAllKeys());
        };

        TypeScriptLS.prototype.getScriptSnapshot = function (fileName) {
            return new ScriptSnapshotShim(this.getScriptInfo(fileName));
        };

        TypeScriptLS.prototype.getScriptVersion = function (fileName) {
            return this.getScriptInfo(fileName).version;
        };

        TypeScriptLS.prototype.getScriptIsOpen = function (fileName) {
            return this.getScriptInfo(fileName).isOpen;
        };

        TypeScriptLS.prototype.getScriptByteOrderMark = function (fileName) {
            return this.getScriptInfo(fileName).byteOrderMark;
        };

        TypeScriptLS.prototype.getDiagnosticsObject = function () {
            return new LanguageServicesDiagnostics("");
        };

        TypeScriptLS.prototype.getLocalizedDiagnosticMessages = function () {
            return "";
        };

        TypeScriptLS.prototype.fileExists = function (s) {
            return TypeScript.Environment.fileExists(s);
        };

        TypeScriptLS.prototype.directoryExists = function (s) {
            return TypeScript.Environment.directoryExists(s);
        };

        TypeScriptLS.prototype.resolveRelativePath = function (path, directory) {
            if (TypeScript.isRooted(path) || !directory) {
                return TypeScript.Environment.absolutePath(path);
            } else {
                return TypeScript.Environment.absolutePath(TypeScript.IOUtils.combine(directory, path));
            }
        };

        TypeScriptLS.prototype.getParentDirectory = function (path) {
            return TypeScript.Environment.directoryName(path);
        };

        /** Return a new instance of the language service shim, up-to-date wrt to typecheck.
        *  To access the non-shim (i.e. actual) language service, use the "ls.languageService" property.
        */
        TypeScriptLS.prototype.getLanguageService = function () {
            var ls = new TypeScript.Services.TypeScriptServicesFactory().createLanguageServiceShim(this);
            ls.refresh(true);
            this.ls = ls;
            return ls;
        };

        /** Parse file given its source text */
        TypeScriptLS.prototype.parseSourceText = function (fileName, sourceText) {
            var compilationSettings = new TypeScript.CompilationSettings();
            compilationSettings.codeGenTarget = 1 /* EcmaScript5 */;

            var settings = TypeScript.ImmutableCompilationSettings.fromCompilationSettings(compilationSettings);
            var parseOptions = settings.codeGenTarget();
            return TypeScript.Parser.parse(fileName, TypeScript.SimpleText.fromScriptSnapshot(sourceText), parseOptions, TypeScript.isDTSFile(fileName)).sourceUnit();
        };

        /** Parse a file on disk given its fileName */
        TypeScriptLS.prototype.parseFile = function (fileName) {
            var sourceText = TypeScript.ScriptSnapshot.fromString(readFile(fileName).contents);
            return this.parseSourceText(fileName, sourceText);
        };

        /**
        * @param line 1 based index
        * @param col 1 based index
        */
        TypeScriptLS.prototype.lineColToPosition = function (fileName, line, col) {
            var script = this.fileNameToScript.lookup(fileName);

            return script.lineMap.getPosition(line - 1, col - 1);
        };

        /**
        * @param line 1 based index
        * @param col 1 based index
        */
        TypeScriptLS.prototype.positionToLineCol = function (fileName, position) {
            var script = this.fileNameToScript.lookup(fileName);

            var result = script.lineMap.getLineAndCharacterFromPosition(position);

            return { line: result.line() + 1, character: result.character() + 1 };
        };

        /**
        * @param line 0 based index
        * @param col 0 based index
        */
        TypeScriptLS.prototype.positionToZeroBasedLineCol = function (fileName, position) {
            var script = this.fileNameToScript.lookup(fileName);

            var result = script.lineMap.getLineAndCharacterFromPosition(position);

            return { line: result.line(), character: result.character() };
        };

        /** Verify that applying edits to sourceFileName result in the content of the file baselineFileName */
        TypeScriptLS.prototype.checkEdits = function (sourceFileName, baselineFileName, edits) {
            var script = readFile(sourceFileName);
            var formattedScript = this.applyEdits(script.contents, edits);
            var baseline = readFile(baselineFileName).contents;
        };

        /** Apply an array of text edits to a string, and return the resulting string. */
        TypeScriptLS.prototype.applyEdits = function (content, edits) {
            var result = content;
            edits = this.normalizeEdits(edits);

            for (var i = edits.length - 1; i >= 0; i--) {
                var edit = edits[i];
                var prefix = result.substring(0, edit.minChar);
                var middle = edit.text;
                var suffix = result.substring(edit.limChar);
                result = prefix + middle + suffix;
            }
            return result;
        };

        /** Normalize an array of edits by removing overlapping entries and sorting entries on the minChar position. */
        TypeScriptLS.prototype.normalizeEdits = function (edits) {
            var result = [];

            function mapEdits(edits) {
                var result = [];
                for (var i = 0; i < edits.length; i++) {
                    result.push({ edit: edits[i], index: i });
                }
                return result;
            }

            var temp = mapEdits(edits).sort(function (a, b) {
                var result = a.edit.minChar - b.edit.minChar;
                if (result === 0)
                    result = a.index - b.index;
                return result;
            });

            var current = 0;
            var next = 1;
            while (current < temp.length) {
                var currentEdit = temp[current].edit;

                // Last edit
                if (next >= temp.length) {
                    result.push(currentEdit);
                    current++;
                    continue;
                }
                var nextEdit = temp[next].edit;

                var gap = nextEdit.minChar - currentEdit.limChar;

                // non-overlapping edits
                if (gap >= 0) {
                    result.push(currentEdit);
                    current = next;
                    next++;
                    continue;
                }

                // overlapping edits: for now, we only support ignoring an next edit
                // entirely contained in the current edit.
                if (currentEdit.limChar >= nextEdit.limChar) {
                    next++;
                    continue;
                } else {
                    throw new Error("Trying to apply overlapping edits");
                }
            }

            return result;
        };
        return TypeScriptLS;
    })();
    Harness.TypeScriptLS = TypeScriptLS;

    var LanguageServicesDiagnostics = (function () {
        function LanguageServicesDiagnostics(destination) {
            this.destination = destination;
        }
        LanguageServicesDiagnostics.prototype.log = function (content) {
            TypeScript.Environment.standardError.WriteLine(content);
            //Imitates the LanguageServicesDiagnostics object when not in Visual Studio
        };
        return LanguageServicesDiagnostics;
    })();
    Harness.LanguageServicesDiagnostics = LanguageServicesDiagnostics;
})(Harness || (Harness = {}));
// Copyright (c) Microsoft, Claus Reinke. All rights reserved.
// Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='./harness.ts'/>
var defaultLibs = __dirname + "/defaultLibs.d.ts";



// bypass import, we don't want to drop out of the global module;
// use fixed readline (https://github.com/joyent/node/issues/3305),
// fixed version should be in nodejs from about v0.9.9/v0.8.19?
var readline = require("./readline");

var EOL = require("os").EOL;

/** TypeScript Services Server,
an interactive commandline tool
for getting info on .ts projects */
var TSS = (function () {
    function TSS(ioHost, prettyJSON) {
        if (typeof prettyJSON === "undefined") { prettyJSON = false; }
        this.ioHost = ioHost;
        this.prettyJSON = prettyJSON;
    }
    // IReferenceResolverHost methods (from HarnessCompiler, modulo test-specific code)
    TSS.prototype.getScriptSnapshot = function (filename) {
        var content = this.fileNameToContent.lookup(filename);
        if (!content) {
            content = readFile(filename).contents;
            this.fileNameToContent.add(filename, content);
        }
        var snapshot = TypeScript.ScriptSnapshot.fromString(content);

        /* TODO
        if (!snapshot) {
        this.addDiagnostic(new TypeScript.Diagnostic(null, 0, 0, TypeScript.DiagnosticCode.Cannot_read_file_0_1, [filename, '']));
        }
        */
        return snapshot;
    };

    TSS.prototype.resolveRelativePath = function (path, directory) {
        var unQuotedPath = TypeScript.stripStartAndEndQuotes(path);
        var normalizedPath;

        if (TypeScript.isRooted(unQuotedPath) || !directory) {
            normalizedPath = unQuotedPath;
        } else {
            normalizedPath = TypeScript.IOUtils.combine(directory, unQuotedPath);
        }

        // get the absolute path
        normalizedPath = TypeScript.Environment.absolutePath(normalizedPath);

        // Switch to forward slashes
        normalizedPath = TypeScript.switchToForwardSlashes(normalizedPath).replace(/^(.:)/, function (_, drive) {
            return drive.toLowerCase();
        });

        return normalizedPath;
    };

    TSS.prototype.fileExists = function (s) {
        return TypeScript.Environment.fileExists(s);
    };
    TSS.prototype.directoryExists = function (path) {
        return TypeScript.Environment.directoryExists(path);
    };
    TSS.prototype.getParentDirectory = function (path) {
        return TypeScript.Environment.directoryName(path);
    };

    // IDiagnosticReporter
    TSS.prototype.addDiagnostic = function (diagnostic) {
        if (diagnostic.fileName()) {
            var scriptSnapshot = this.getScriptSnapshot(diagnostic.fileName());
            if (scriptSnapshot) {
                var lineMap = new TypeScript.LineMap(scriptSnapshot.getLineStartPositions, scriptSnapshot.getLength());
                var lineCol = { line: -1, character: -1 };
                lineMap.fillLineAndCharacterFromPosition(diagnostic.start(), lineCol);
                TypeScript.Environment.standardError.Write(diagnostic.fileName() + "(" + (lineCol.line + 1) + "," + (lineCol.character + 1) + "): ");
            }
        }

        TypeScript.Environment.standardError.WriteLine(diagnostic.message());
    };

    /** load file and dependencies, prepare language service for queries */
    TSS.prototype.setup = function (file) {
        var _this = this;
        this.compilationSettings = new TypeScript.CompilationSettings();
        this.compilationSettings.gatherDiagnostics = true;
        this.compilationSettings.codeGenTarget = 1 /* EcmaScript5 */;

        var useDefaultLib = true;

        /*
        TypeScript.CompilerDiagnostics.debug = true;
        TypeScript.CompilerDiagnostics.diagnosticWriter =
        { Alert: (s: string) => { this.ioHost.standardError.WriteLine(s); } };
        */
        this.typescriptLS = new Harness.TypeScriptLS();
        this.fileNameToContent = new TypeScript.StringHashTable();

        // chase dependencies (references and imports)
        this.resolutionResult = TypeScript.ReferenceResolver.resolve([defaultLibs, file], this, this.compilationSettings.useCaseSensitiveFileResolution);

        // TODO: what about resolution diagnostics?
        var resolvedFiles = this.resolutionResult.resolvedFiles;

        // remember project root, resolved
        this.rootFile = resolvedFiles[resolvedFiles.length - 1];

        /*
        if (useDefaultLib && !this.resolutionResult.seenNoDefaultLibTag) {
        var libraryResolvedFile: TypeScript.IResolvedFile = {
        path: this.resolveRelativePath(defaultLibs),
        referencedFiles: [],
        importedFiles: []
        };
        
        // Prepend default library to the resolved list
        resolvedFiles = [libraryResolvedFile].concat(resolvedFiles);
        }
        */
        // initialize languageService code units
        resolvedFiles.forEach(function (code, i) {
            // this.ioHost.standardError.WriteLine(i+': '+code.path);
            _this.typescriptLS.addScript(code.path, _this.fileNameToContent.lookup(code.path));
        });

        // Get the language service
        this.ls = this.typescriptLS.getLanguageService().languageService;
        this.ls.refresh();
    };

    TSS.prototype.output = function (info) {
        if (this.prettyJSON) {
            this.ioHost.standardOut.WriteLine(JSON.stringify(info, null, " ").trim());
        } else {
            this.ioHost.standardOut.WriteLine(JSON.stringify(info).trim());
        }
    };

    TSS.prototype.outputJSON = function (json) {
        this.ioHost.standardOut.WriteLine(json.trim());
    };

    /** commandline server main routine: commands in, JSON info out */
    TSS.prototype.listen = function () {
        var _this = this;
        var line;
        var col;

        var rl = readline.createInterface({ input: process.stdin, output: process.stdout });

        var cmd, pos, file, script, added, range, check, def, refs, locs, info, source, brief, member;

        var collecting = 0, on_collected_callback, lines = [];

        var commands = {};
        function match(cmd, regexp) {
            commands[regexp.source] = true;
            return cmd.match(regexp);
        }

        rl.on('line', function (input) {
            var m;
            try  {
                cmd = input.trim();

                if (collecting > 0) {
                    lines.push(input);
                    collecting--;

                    if (collecting === 0) {
                        on_collected_callback();
                    }
                } else if (m = match(cmd, /^type (\d+) (\d+) (.*)$/)) {
                    line = parseInt(m[1]);
                    col = parseInt(m[2]);
                    file = _this.resolveRelativePath(m[3]);

                    pos = _this.typescriptLS.lineColToPosition(file, line, col);

                    info = (_this.ls.getTypeAtPosition(file, pos) || {});
                    info.type = (info.memberName || "").toString();

                    _this.output(info);
                } else if (m = match(cmd, /^definition (\d+) (\d+) (.*)$/)) {
                    line = parseInt(m[1]);
                    col = parseInt(m[2]);
                    file = _this.resolveRelativePath(m[3]);

                    pos = _this.typescriptLS.lineColToPosition(file, line, col);
                    locs = _this.ls.getDefinitionAtPosition(file, pos); // NOTE: multiple definitions

                    info = locs.map(function (def) {
                        return ({
                            def: def,
                            file: def && def.fileName,
                            min: def && _this.typescriptLS.positionToLineCol(def.fileName, def.minChar),
                            lim: def && _this.typescriptLS.positionToLineCol(def.fileName, def.limChar)
                        });
                    });

                    // TODO: what about multiple definitions?
                    _this.output(info[0] || null);
                } else if (m = match(cmd, /^(references|occurrences|implementors) (\d+) (\d+) (.*)$/)) {
                    line = parseInt(m[2]);
                    col = parseInt(m[3]);
                    file = _this.resolveRelativePath(m[4]);

                    pos = _this.typescriptLS.lineColToPosition(file, line, col);
                    switch (m[1]) {
                        case "references":
                            refs = _this.ls.getReferencesAtPosition(file, pos);
                            break;
                        case "occurrences":
                            refs = _this.ls.getOccurrencesAtPosition(file, pos);
                            break;
                        case "implementors":
                            refs = _this.ls.getImplementorsAtPosition(file, pos);
                            break;
                        default:
                            throw "cannot happen";
                    }

                    info = refs.map(function (ref) {
                        return ({
                            ref: ref,
                            file: ref && ref.fileName,
                            min: ref && _this.typescriptLS.positionToLineCol(ref.fileName, ref.minChar),
                            lim: ref && _this.typescriptLS.positionToLineCol(ref.fileName, ref.limChar)
                        });
                    });

                    _this.output(info);
                } else if (m = match(cmd, /^structure (.*)$/)) {
                    file = _this.resolveRelativePath(m[1]);

                    locs = _this.ls.getScriptLexicalStructure(file);

                    info = locs.map(function (loc) {
                        return ({
                            loc: loc,
                            file: loc && loc.fileName,
                            min: loc && _this.typescriptLS.positionToLineCol(loc.fileName, loc.minChar),
                            lim: loc && _this.typescriptLS.positionToLineCol(loc.fileName, loc.limChar)
                        });
                    });

                    _this.output(info);
                } else if (m = match(cmd, /^completions(-brief)? (true|false) (\d+) (\d+) (.*)$/)) {
                    brief = m[1];
                    member = m[2] === 'true';
                    line = parseInt(m[3]);
                    col = parseInt(m[4]);
                    file = _this.resolveRelativePath(m[5]);

                    pos = _this.typescriptLS.lineColToPosition(file, line, col);

                    info = _this.ls.getCompletionsAtPosition(file, pos, member);

                    if (info) {
                        // fill in completion entry details, unless briefness requested
                        !brief && (info.entries = info.entries.map(function (e) {
                            return _this.ls.getCompletionEntryDetails(file, pos, e.name) || e;
                        }));

                        // NOTE: details null for primitive type symbols, see TS #1592
                        (function () {
                            var languageVersion = _this.compilationSettings.codeGenTarget;
                            var source = _this.typescriptLS.getScriptInfo(file).content;
                            var startPos = pos;
                            var idPart = function (p) {
                                return /[0-9a-zA-Z_$]/.test(source[p]) || TypeScript.Unicode.isIdentifierPart(source.charCodeAt(p), languageVersion);
                            };
                            var idStart = function (p) {
                                return /[a-zA-Z_$]/.test(source[p]) || TypeScript.Unicode.isIdentifierStart(source.charCodeAt(p), languageVersion);
                            };
                            while ((--startPos >= 0) && idPart(startPos))
                                ;
                            if ((++startPos < pos) && idStart(startPos)) {
                                var prefix = source.slice(startPos, pos);
                                info["prefix"] = prefix;
                                var len = prefix.length;
                                info.entries = info.entries.filter(function (e) {
                                    return e.name.substr(0, len) === prefix;
                                });
                            }
                        })();
                    }

                    _this.output(info);
                } else if (m = match(cmd, /^info (\d+) (\d+) (.*)$/)) {
                    line = parseInt(m[1]);
                    col = parseInt(m[2]);
                    file = _this.resolveRelativePath(m[3]);

                    pos = _this.typescriptLS.lineColToPosition(file, line, col);

                    def = _this.ls.getDefinitionAtPosition(file, pos)[0];

                    // source       = this.ls.getScriptSyntaxAST(file).getSourceText();
                    // var span     = this.ls.getNameOrDottedNameSpan(file,pos,-1);
                    // var spanText = span && source.getText(span.minChar,span.limChar);
                    // member       = span && spanText.indexOf('.') !== -1;
                    var typeInfo = _this.ls.getTypeAtPosition(file, pos);
                    var type = typeInfo.memberName;
                    var symbol = typeInfo.fullSymbolName;

                    info = {
                        pos: pos,
                        linecol: _this.typescriptLS.positionToLineCol(file, pos),
                        symbol: symbol,
                        type: (type || "").toString(),
                        def: def,
                        file: def && def.fileName,
                        min: def && _this.typescriptLS.positionToLineCol(def.fileName, def.minChar),
                        lim: def && _this.typescriptLS.positionToLineCol(def.fileName, def.limChar)
                    };

                    _this.output(info);
                } else if (m = match(cmd, /^update( nocheck)? (\d+)( (\d+)-(\d+))? (.*)$/)) {
                    file = _this.resolveRelativePath(m[6]);
                    script = _this.typescriptLS.getScriptInfo(file);
                    added = script == null;
                    range = !!m[3];
                    check = !m[1];

                    // TODO: handle dependency changes
                    if (!added || !range) {
                        collecting = parseInt(m[2]);
                        on_collected_callback = function () {
                            if (!range) {
                                _this.typescriptLS.updateScript(file, lines.join(EOL));
                            } else {
                                var startLine = parseInt(m[4]);
                                var endLine = parseInt(m[5]);
                                var maxLines = script.lineMap.lineCount();
                                var startPos = startLine <= maxLines ? (startLine < 1 ? 0 : _this.typescriptLS.lineColToPosition(file, startLine, 1)) : script.content.length;
                                var endPos = endLine < maxLines ? (endLine < 1 ? 0 : _this.typescriptLS.lineColToPosition(file, endLine + 1, 1) - 1) : script.content.length;

                                _this.typescriptLS.editScript(file, startPos, endPos, lines.join(EOL));
                            }
                            var syn, sem;
                            if (check) {
                                syn = _this.ls.getSyntacticDiagnostics(file).length;
                                sem = _this.ls.getSemanticDiagnostics(file).length;
                            }
                            on_collected_callback = undefined;
                            lines = [];

                            _this.outputJSON((added ? '"added ' : '"updated ') + (range ? 'lines' + m[3] + ' in ' : '') + file + (check ? ', (' + syn + '/' + sem + ') errors' : '') + '"');
                        };
                    } else {
                        _this.outputJSON('"cannot update line range in new file"');
                    }
                } else if (m = match(cmd, /^showErrors$/)) {
                    info = _this.resolutionResult.diagnostics.map(function (d) {
                        d["phase"] = "Resolution";
                        return d;
                    }).concat(_this.typescriptLS.getErrors()).map(function (d) {
                        var file = d.fileName();
                        var lc = _this.typescriptLS.positionToLineCol(file, d.start());
                        var len = _this.typescriptLS.getScriptInfo(file).content.length;
                        var end = Math.min(len, d.start() + d.length());
                        var lc2 = _this.typescriptLS.positionToLineCol(file, end);
                        var diagInfo = d.info();
                        var category = TypeScript.DiagnosticCategory[diagInfo.category];
                        return {
                            file: file,
                            start: { line: lc.line, character: lc.character },
                            end: { line: lc2.line, character: lc2.character },
                            text: /* file+"("+lc.line+"/"+lc.character+"): "+ */ d.message(),
                            phase: d["phase"],
                            category: category
                        };
                    });

                    _this.output(info);
                } else if (m = match(cmd, /^files$/)) {
                    info = _this.typescriptLS.getScriptFileNames(); // TODO: shim/JSON vs real-ls/array

                    _this.outputJSON(info);
                } else if (m = match(cmd, /^lastError(Dump)?$/)) {
                    if (_this.lastError)
                        if (m[1])
                            _this.ioHost.standardOut.WriteLine(JSON.parse(_this.lastError).stack);
                        else
                            _this.outputJSON(_this.lastError);
                    else
                        _this.outputJSON('"no last error"');
                } else if (m = match(cmd, /^dump (\S+) (.*)$/)) {
                    var dump = m[1];
                    file = _this.resolveRelativePath(m[2]);

                    source = _this.typescriptLS.getScriptInfo(file).content;
                    if (dump === "-") {
                        _this.ioHost.standardOut.WriteLine('dumping ' + file);
                        _this.ioHost.standardOut.WriteLine(source);
                    } else {
                        _this.ioHost.writeFile(dump, source, false);

                        _this.outputJSON('"dumped ' + file + ' to ' + dump + '"');
                    }
                } else if (m = match(cmd, /^reload$/)) {
                    // TODO: keep updated (in-memory-only) files?
                    _this.setup(_this.rootFile.path);
                    _this.outputJSON('"reloaded ' + _this.rootFile.path + ', TSS listening.."');
                } else if (m = match(cmd, /^quit$/)) {
                    rl.close();
                } else if (m = match(cmd, /^prettyJSON (true|false)$/)) {
                    _this.prettyJSON = m[1] === 'true';

                    _this.outputJSON('"pretty JSON: ' + _this.prettyJSON + '"');
                } else if (m = match(cmd, /^help$/)) {
                    _this.ioHost.standardOut.WriteLine(Object.keys(commands).join(EOL));
                } else {
                    _this.outputJSON('"TSS command syntax error: ' + cmd + '"');
                }
            } catch (e) {
                _this.lastError = (JSON.stringify({ msg: e.toString(), stack: e.stack })).trim();
                _this.outputJSON('"TSS command processing error: ' + e + '"');
            }
        }).on('close', function () {
            _this.outputJSON('"TSS closing"');
        });

        this.outputJSON('"loaded ' + this.rootFile.path + ', TSS listening.."');
    };
    return TSS;
})();

if (TypeScript.Environment.arguments.indexOf("--version") !== -1) {
    console.log(require("../package.json").version);
    process.exit(0);
}

var tss = new TSS(TypeScript.Environment);
tss.setup(TypeScript.Environment.arguments[0]);
tss.listen();
