function getImmediatelyContainingArgumentInfo(node) {
                if (node.parent.kind === 168 /* CallExpression */ || node.parent.kind === 169 /* NewExpression */) {
                    var callExpression = node.parent;
                    // There are 3 cases to handle:
                    //   1. The token introduces a list, and should begin a sig help session
                    //   2. The token is either not associated with a list, or ends a list, so the session should end
                    //   3. The token is buried inside a list, and should give sig help
                    //
                    // The following are examples of each:
                    //
                    //    Case 1:
                    //          foo<#T, U>(#a, b)    -> The token introduces a list, and should begin a sig help session
                    //    Case 2:
                    //          fo#o<T, U>#(a, b)#   -> The token is either not associated with a list, or ends a list, so the session should end
                    //    Case 3:
                    //          foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give sig help
                    // Find out if 'node' is an argument, a type argument, or neither
                    if (node.kind === 25 /* LessThanToken */ ||
                        node.kind === 17 /* OpenParenToken */) {
                        // Find the list that starts right *after* the < or ( token.
                        // If the user has just opened a list, consider this item 0.
                        var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
                        var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
                        ts.Debug.assert(list !== undefined);
                        return {
                            kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */,
                            invocation: callExpression,
                            argumentsSpan: getApplicableSpanForArguments(list),
                            argumentIndex: 0,
                            argumentCount: getArgumentCount(list)
                        };
                    }
                    // findListItemInfo can return undefined if we are not in parent's argument list
                    // or type argument list. This includes cases where the cursor is:
                    //   - To the right of the closing paren, non-substitution template, or template tail.
                    //   - Between the type arguments and the arguments (greater than token)
                    //   - On the target of the call (parent.func)
                    //   - On the 'new' keyword in a 'new' expression
                    var listItemInfo = ts.findListItemInfo(node);
                    if (listItemInfo) {
                        var list = listItemInfo.list;
                        var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
                        var argumentIndex = getArgumentIndex(list, node);
                        var argumentCount = getArgumentCount(list);
                        ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
                        return {
                            kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */,
                            invocation: callExpression,
                            argumentsSpan: getApplicableSpanForArguments(list),
                            argumentIndex: argumentIndex,
                            argumentCount: argumentCount
                        };
                    }
                }
                else if (node.kind === 11 /* NoSubstitutionTemplateLiteral */ && node.parent.kind === 170 /* TaggedTemplateExpression */) {
                    // Check if we're actually inside the template;
                    // otherwise we'll fall out and return undefined.
                    if (ts.isInsideTemplateLiteral(node, position)) {
                        return getArgumentListInfoForTemplate(node.parent, /*argumentIndex*/ 0);
                    }
                }
                else if (node.kind === 12 /* TemplateHead */ && node.parent.parent.kind === 170 /* TaggedTemplateExpression */) {
                    var templateExpression = node.parent;
                    var tagExpression = templateExpression.parent;
                    ts.Debug.assert(templateExpression.kind === 183 /* TemplateExpression */);
                    var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1;
                    return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
                }
                else if (node.parent.kind === 190 /* TemplateSpan */ && node.parent.parent.parent.kind === 170 /* TaggedTemplateExpression */) {
                    var templateSpan = node.parent;
                    var templateExpression = templateSpan.parent;
                    var tagExpression = templateExpression.parent;
                    ts.Debug.assert(templateExpression.kind === 183 /* TemplateExpression */);
                    // If we're just after a template tail, don't show signature help.
                    if (node.kind === 14 /* TemplateTail */ && !ts.isInsideTemplateLiteral(node, position)) {
                        return undefined;
                    }
                    var spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
                    var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
                    return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
                }
                return undefined;
            }