/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.netbeans.modules.php.editor.completion;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.editor.document.LineDocumentUtils;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenId;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.api.lexer.TokenUtilities;
import org.netbeans.editor.BaseDocument;
import org.netbeans.modules.csl.api.CodeCompletionContext;
import org.netbeans.modules.csl.api.CodeCompletionHandler.QueryType;
import org.netbeans.modules.csl.api.CodeCompletionHandler2;
import org.netbeans.modules.csl.api.CodeCompletionResult;
import org.netbeans.modules.csl.api.CompletionProposal;
import org.netbeans.modules.csl.api.Documentation;
import org.netbeans.modules.csl.api.ElementHandle;
import org.netbeans.modules.csl.api.ParameterInfo;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.csl.spi.support.CancelSupport;
import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind;
import org.netbeans.modules.php.api.PhpVersion;
import org.netbeans.modules.php.editor.CodeUtils;
import org.netbeans.modules.php.editor.NavUtils;
import org.netbeans.modules.php.editor.PredefinedSymbols;
import org.netbeans.modules.php.editor.api.AliasedName;
import org.netbeans.modules.php.editor.api.ElementQueryFactory;
import org.netbeans.modules.php.editor.api.NameKind;
import org.netbeans.modules.php.editor.api.NameKind.CaseInsensitivePrefix;
import org.netbeans.modules.php.editor.api.PhpElementKind;
import org.netbeans.modules.php.editor.api.QualifiedName;
import org.netbeans.modules.php.editor.api.QualifiedNameKind;
import org.netbeans.modules.php.editor.api.elements.AliasedElement.Trait;
import org.netbeans.modules.php.editor.api.elements.ClassElement;
import org.netbeans.modules.php.editor.api.elements.ConstantElement;
import org.netbeans.modules.php.editor.api.elements.ElementFilter;
import org.netbeans.modules.php.editor.api.elements.FieldElement;
import org.netbeans.modules.php.editor.api.elements.FunctionElement;
import org.netbeans.modules.php.editor.api.elements.InterfaceElement;
import org.netbeans.modules.php.editor.api.elements.MethodElement;
import org.netbeans.modules.php.editor.api.elements.NamespaceElement;
import org.netbeans.modules.php.editor.api.elements.ParameterElement;
import org.netbeans.modules.php.editor.api.elements.PhpElement;
import org.netbeans.modules.php.editor.api.elements.TraitElement;
import org.netbeans.modules.php.editor.api.elements.TypeConstantElement;
import org.netbeans.modules.php.editor.api.elements.TypeElement;
import org.netbeans.modules.php.editor.api.elements.TypeMemberElement;
import org.netbeans.modules.php.editor.api.elements.VariableElement;
import org.netbeans.modules.php.editor.completion.CompletionContextFinder.CompletionContext;
import org.netbeans.modules.php.editor.completion.CompletionContextFinder.KeywordCompletionType;
import static org.netbeans.modules.php.editor.completion.CompletionContextFinder.lexerToASTOffset;
import org.netbeans.modules.php.editor.completion.PHPCompletionItem.CompletionRequest;
import org.netbeans.modules.php.editor.completion.PHPCompletionItem.FieldItem;
import org.netbeans.modules.php.editor.completion.PHPCompletionItem.MethodElementItem;
import org.netbeans.modules.php.editor.completion.PHPCompletionItem.TypeConstantItem;
import org.netbeans.modules.php.editor.elements.TypeResolverImpl;
import org.netbeans.modules.php.editor.elements.VariableElementImpl;
import org.netbeans.modules.php.editor.indent.CodeStyle;
import org.netbeans.modules.php.editor.lexer.LexUtilities;
import org.netbeans.modules.php.editor.lexer.PHPTokenId;
import org.netbeans.modules.php.editor.model.ArrowFunctionScope;
import org.netbeans.modules.php.editor.model.FunctionScope;
import org.netbeans.modules.php.editor.model.Model;
import org.netbeans.modules.php.editor.model.ModelElement;
import org.netbeans.modules.php.editor.model.ModelUtils;
import org.netbeans.modules.php.editor.model.NamespaceScope;
import org.netbeans.modules.php.editor.model.ParameterInfoSupport;
import org.netbeans.modules.php.editor.model.Scope;
import org.netbeans.modules.php.editor.model.TypeScope;
import org.netbeans.modules.php.editor.model.VariableName;
import org.netbeans.modules.php.editor.model.VariableScope;
import org.netbeans.modules.php.editor.model.impl.Type;
import org.netbeans.modules.php.editor.model.impl.VariousUtils;
import org.netbeans.modules.php.editor.options.CodeCompletionPanel.VariablesScope;
import org.netbeans.modules.php.editor.options.OptionsUtils;
import org.netbeans.modules.php.editor.parser.PHPParseResult;
import org.netbeans.modules.php.editor.parser.astnodes.ASTNode;
import org.netbeans.modules.php.editor.parser.astnodes.Block;
import org.netbeans.modules.php.editor.parser.astnodes.ClassDeclaration;
import org.netbeans.modules.php.editor.parser.astnodes.ClassInstanceCreation;
import org.netbeans.modules.php.editor.parser.astnodes.Expression;
import org.netbeans.modules.php.editor.parser.astnodes.TraitDeclaration;
import org.netbeans.modules.php.editor.parser.astnodes.TypeDeclaration;
import org.openide.filesystems.FileObject;
import org.openide.util.Pair;

/**
 *
 * @author Tomasz.Slota@Sun.COM
 */
public class PHPCodeCompletion implements CodeCompletionHandler2 {

    // for unit tests
    static volatile PhpVersion PHP_VERSION = null;
    private static final Logger LOGGER = Logger.getLogger(PHPCodeCompletion.class.getName());

    private static enum UseType {
        TYPE,
        CONST,
        FUNCTION,
    };

    static final Map<String, KeywordCompletionType> PHP_KEYWORDS = new HashMap<>();

    static {
        PHP_KEYWORDS.put("use", KeywordCompletionType.SIMPLE); //NOI18N
        PHP_KEYWORDS.put("namespace", KeywordCompletionType.SIMPLE); //NOI18N
        PHP_KEYWORDS.put("class", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("const", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("continue", KeywordCompletionType.ENDS_WITH_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("function", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("fn", KeywordCompletionType.SIMPLE); // NOI18N PHP 7.4
        PHP_KEYWORDS.put("new", KeywordCompletionType.SIMPLE); //NOI18N
        PHP_KEYWORDS.put("static", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("var", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("final", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("interface", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("instanceof", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("implements", KeywordCompletionType.SIMPLE); //NOI18N
        PHP_KEYWORDS.put("extends", KeywordCompletionType.SIMPLE); //NOI18N
        PHP_KEYWORDS.put("public", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("private", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("protected", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("abstract", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("readonly", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("clone", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("global", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("goto", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("throw", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("if", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("switch", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("match", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("for", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("array", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("foreach", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("while", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("catch", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("try", KeywordCompletionType.ENDS_WITH_CURLY_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("default", KeywordCompletionType.ENDS_WITH_COLON); //NOI18N
        PHP_KEYWORDS.put("default =>", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N PHP 8.0 match expression
        PHP_KEYWORDS.put("break", KeywordCompletionType.ENDS_WITH_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("endif", KeywordCompletionType.ENDS_WITH_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("endfor", KeywordCompletionType.ENDS_WITH_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("endforeach", KeywordCompletionType.ENDS_WITH_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("endwhile", KeywordCompletionType.ENDS_WITH_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("endswitch", KeywordCompletionType.ENDS_WITH_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("case", KeywordCompletionType.ENDS_WITH_COLON); //NOI18N
        PHP_KEYWORDS.put("and", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("as", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("declare", KeywordCompletionType.CURSOR_INSIDE_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("do", KeywordCompletionType.ENDS_WITH_CURLY_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("else", KeywordCompletionType.ENDS_WITH_CURLY_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("elseif", KeywordCompletionType.ENDS_WITH_BRACKETS_AND_CURLY_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("enddeclare", KeywordCompletionType.ENDS_WITH_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("or", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("xor", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
        PHP_KEYWORDS.put("finally", KeywordCompletionType.ENDS_WITH_CURLY_BRACKETS); //NOI18N
        PHP_KEYWORDS.put("yield", KeywordCompletionType.CURSOR_BEFORE_ENDING_SEMICOLON); //NOI18N
        PHP_KEYWORDS.put("yield from", KeywordCompletionType.ENDS_WITH_SPACE); //NOI18N
    }
    private static final String[] PHP_LANGUAGE_CONSTRUCTS_WITH_QUOTES = {
        "echo", "include", "include_once", "require", "require_once", "print" // NOI18N
    };
    private static final String[] PHP_LANGUAGE_CONSTRUCTS_WITH_PARENTHESES = {
        "die", "eval", "exit", "empty", "isset", "list", "unset" // NOI18N
    };
    private static final String[] PHP_LANGUAGE_CONSTRUCTS_WITH_SEMICOLON = {
        "return" // NOI18N
    };
    static final String PHP_CLASS_KEYWORD_THIS = "$this->"; //NOI18N
    static final String[] PHP_CLASS_KEYWORDS = {
        PHP_CLASS_KEYWORD_THIS, "self::", "parent::", "static::" //NOI18N
    };
    static final String[] PHP_STATIC_CLASS_KEYWORDS = {
        "self::", "parent::", "static::" //NOI18N
    };
    static final List<String> PHP_GLOBAL_CONST_KEYWORDS = Arrays.asList(
            "array", // NOI18N
            "new" // NOI18N
    );
    static final List<String> PHP_CLASS_CONST_KEYWORDS = Arrays.asList(
            "array", // NOI18N
            "self::", // NOI18N
            "parent::" // NOI18N
    );
    private static final List<String> PHP_MATCH_EXPRESSION_KEYWORDS = Arrays.asList(
            "function", // NOI18N
            "fn", // NOI18N
            "new", // NOI18N
            "static", // NOI18N
            "instanceof", // NOI18N
            "clone", // NOI18N
            "throw", // NOI18N
            "match", // NOI18N
            "array", // NOI18N
            "default =>", // NOI18N
            "and", // NOI18N
            "or", // NOI18N
            "xor" // NOI18N
    );
    private static final List<String> PHP_VISIBILITY_KEYWORDS = Arrays.asList(
            "public", // NOI18N
            "protected", // NOI18N
            "private" // NOI18N
    );
    private static final Collection<Character> AUTOPOPUP_STOP_CHARS = new TreeSet<>(
            Arrays.asList('=', ';', '+', '-', '*', '/',
            '%', '(', ')', '[', ']', '{', '}', '?'));
    private static final Collection<PHPTokenId> TOKENS_TRIGGERING_AUTOPUP_TYPES_WS =
            Arrays.asList(PHPTokenId.PHP_NEW, PHPTokenId.PHP_EXTENDS, PHPTokenId.PHP_IMPLEMENTS, PHPTokenId.PHP_INSTANCEOF);
    private static final List<String> INVALID_PROPOSALS_FOR_CLS_MEMBERS =
            Arrays.asList(new String[]{"__construct", "__destruct", "__call", "__callStatic",
                "__clone", "__get", "__invoke", "__isset", "__set", "__set_state",
                "__sleep", "__toString", "__unset", "__wakeup"}); //NOI18N
    private static final List<String> CLASS_CONTEXT_KEYWORD_PROPOSAL =
            Arrays.asList(new String[]{"abstract", "const", "function", "private", "final",
                "protected", "public", "static", "var", "readonly"}); //NOI18N
    private static final List<String> INTERFACE_CONTEXT_KEYWORD_PROPOSAL =
            Arrays.asList(new String[]{"const", "function", "public", "static"}); //NOI18N
    private static final List<String> INHERITANCE_KEYWORDS =
            Arrays.asList(new String[]{"extends", "implements"}); //NOI18N
    private static final String EXCEPTION_CLASS_NAME = "\\Exception"; // NOI18N
    private static final List<PHPTokenId> VALID_UNION_TYPE_TOKENS = Arrays.asList(
            PHPTokenId.WHITESPACE, PHPTokenId.PHP_STRING, PHPTokenId.PHP_NS_SEPARATOR,
            PHPTokenId.PHP_TYPE_BOOL, PHPTokenId.PHP_TYPE_FLOAT, PHPTokenId.PHP_TYPE_INT, PHPTokenId.PHP_TYPE_STRING, PHPTokenId.PHP_TYPE_VOID,
            PHPTokenId.PHP_TYPE_OBJECT, PHPTokenId.PHP_TYPE_MIXED, PHPTokenId.PHP_SELF, PHPTokenId.PHP_PARENT, PHPTokenId.PHP_STATIC,
            PHPTokenId.PHP_NULL, PHPTokenId.PHP_FALSE, PHPTokenId.PHP_ARRAY, PHPTokenId.PHP_ITERABLE, PHPTokenId.PHP_CALLABLE,
            PHPTokenId.PHPDOC_COMMENT_START, PHPTokenId.PHPDOC_COMMENT, PHPTokenId.PHPDOC_COMMENT_END,
            PHPTokenId.PHP_COMMENT_START, PHPTokenId.PHP_COMMENT, PHPTokenId.PHP_COMMENT_END
    );
    private boolean caseSensitive;
    private QuerySupport.Kind nameKind;

    @Override
    public CodeCompletionResult complete(CodeCompletionContext completionContext) {
        long startTime = 0;
        if (LOGGER.isLoggable(Level.FINE)) {
            startTime = System.currentTimeMillis();
        }

        BaseDocument doc = (BaseDocument) completionContext.getParserResult().getSnapshot().getSource().getDocument(false);
        if (doc == null) {
            return CodeCompletionResult.NONE;
        }

        if (CancelSupport.getDefault().isCancelled()) {
            return CodeCompletionResult.NONE;
        }

        // TODO: separate the code that uses informatiom from lexer
        // and avoid running the index/ast analysis under read lock
        // in order to improve responsiveness
        // doc.readLock();        //TODO: use token hierarchy from snapshot and not use read lock in CC #171702

        final PHPCompletionResult completionResult = new PHPCompletionResult(completionContext);
        ParserResult info = completionContext.getParserResult();
        final int caretOffset = completionContext.getCaretOffset();

        this.caseSensitive = completionContext.isCaseSensitive();
        this.nameKind = caseSensitive ? QuerySupport.Kind.PREFIX : QuerySupport.Kind.CASE_INSENSITIVE_PREFIX;

        PHPParseResult result = (PHPParseResult) info;

        if (result.getProgram() == null) {
            return CodeCompletionResult.NONE;
        }
        final FileObject fileObject = result.getSnapshot().getSource().getFileObject();
        if (fileObject == null) {
            return CodeCompletionResult.NONE;
        }

        if (CancelSupport.getDefault().isCancelled()) {
            return CodeCompletionResult.NONE;
        }

        CompletionContext context = CompletionContextFinder.findCompletionContext(info, caretOffset);
        LOGGER.log(Level.FINE, "CC context: {0}", context);

        if (context == CompletionContext.NONE) {
            return CodeCompletionResult.NONE;
        }

        PHPCompletionItem.CompletionRequest request = new PHPCompletionItem.CompletionRequest();
        request.context = context;
        String prefix = getPrefix(info, caretOffset, true, PrefixBreaker.WITH_NS_PARTS);
        if (prefix == null) {
            return CodeCompletionResult.NONE;
        }
        prefix = prefix.trim().isEmpty() ? completionContext.getPrefix() : prefix;
        // prefix for index search (used for group use, equals to the base NS (before curly open))
        String searchPrefix;
        switch (context) {
            case GROUP_USE_KEYWORD:
            case GROUP_USE_CONST_KEYWORD:
            case GROUP_USE_FUNCTION_KEYWORD:
                searchPrefix = getPrefix(info, findBaseNamespaceEnd(info, caretOffset), true, PrefixBreaker.WITH_NS_PARTS);
                break;
            case EXPRESSION: // no break
                if (prefix.startsWith("@")) { // NOI18N
                    prefix = prefix.substring(1);
                }
            default:
                searchPrefix = null;
                break;
        }
        request.extraPrefix = searchPrefix;

        request.anchor = caretOffset
                // can't just use 'prefix.getLength()' here cos it might have been calculated with
                // the 'upToOffset' flag set to false
                - prefix.length();

        request.result = result;
        request.info = info;
        request.prefix = prefix;
        request.index = ElementQueryFactory.getIndexQuery(info);
        request.currentlyEditedFileURL = fileObject.toURL().toString();

        if (CancelSupport.getDefault().isCancelled()) {
            return CodeCompletionResult.NONE;
        }

        CodeStyle codeStyle;
        switch (context) {
            case DEFAULT_PARAMETER_VALUE:
                final CaseInsensitivePrefix nameKindPrefix = NameKind.caseInsensitivePrefix(request.prefix);
                autoCompleteKeywords(completionResult, request, Arrays.asList("array", "new")); //NOI18N
                autoCompleteNamespaces(completionResult, request);
                autoCompleteTypeNames(completionResult, request, null, true);
                if (CancelSupport.getDefault().isCancelled()) {
                    return CodeCompletionResult.NONE;
                }
                final ElementFilter forName = ElementFilter.forName(nameKindPrefix);
                final Model model = request.result.getModel();
                final Set<AliasedName> aliasedNames = ModelUtils.getAliasedNames(model, request.anchor);
                Set<ConstantElement> constants = request.index.getConstants(nameKindPrefix, aliasedNames, Trait.ALIAS);
                for (ConstantElement constant : forName.filter(constants)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return CodeCompletionResult.NONE;
                    }
                    completionResult.add(new PHPCompletionItem.ConstantItem(constant, request));
                }
                final EnclosingClass enclosingClass = findEnclosingClass(request.info, lexerToASTOffset(request.result, request.anchor));
                if (enclosingClass != null) {
                    String clsName = enclosingClass.getClassName();
                    for (String classKeyword : PHP_STATIC_CLASS_KEYWORDS) {
                        if (classKeyword.toLowerCase().startsWith(request.prefix)) { //NOI18N
                            completionResult.add(new PHPCompletionItem.ClassScopeKeywordItem(clsName, classKeyword, request));
                        }
                    }
                }
                break;
            case NAMESPACE_KEYWORD:
                if (CancelSupport.getDefault().isCancelled()) {
                    return CodeCompletionResult.NONE;
                }
                Set<NamespaceElement> namespaces = request.index.getNamespaces(
                        NameKind.caseInsensitivePrefix(QualifiedName.create(request.prefix).toNotFullyQualified()));
                for (NamespaceElement namespace : namespaces) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return CodeCompletionResult.NONE;
                    }
                    completionResult.add(new PHPCompletionItem.NamespaceItem(namespace, request, QualifiedNameKind.QUALIFIED));
                }
                break;
            case GLOBAL:
                autoCompleteGlobals(completionResult, request);
                break;
            case MATCH_EXPRESSION:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteExpression(completionResult, request, PHP_MATCH_EXPRESSION_KEYWORDS);
                break;
            case EXPRESSION:
                autoCompleteExpression(completionResult, request);
                break;
            case CLASS_MEMBER_PARAMETER_NAME:
                autoCompleteExpression(completionResult, request);
                autoCompleteClassMethodParameterName(completionResult, request, false);
                break;
            case STATIC_CLASS_MEMBER_PARAMETER_NAME:
                autoCompleteExpression(completionResult, request);
                autoCompleteClassMethodParameterName(completionResult, request, true);
                break;
            case FUNCTION_PARAMETER_NAME:
                autoCompleteExpression(completionResult, request);
                autoCompleteFunctionParameterName(completionResult, request);
                break;
            case GLOBAL_CONST_EXPRESSION:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteTypeNames(completionResult, request, null, true);
                autoCompleteConstants(completionResult, request);
                autoCompleteKeywords(completionResult, request, PHP_GLOBAL_CONST_KEYWORDS);
                break;
            case CLASS_CONST_EXPRESSION:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteTypeNames(completionResult, request, null, true);
                autoCompleteConstants(completionResult, request);
                autoCompleteKeywords(completionResult, request, PHP_CLASS_CONST_KEYWORDS);
                // NETBEANS-1855
                if (!request.prefix.contains("\\")) { // NOI18N
                    // e.g. const CONSTANT = \^Foo\Bar::CONSTANT;
                    autoCompleteClassConstants(completionResult, request);
                }
                break;
            case HTML:
            case OPEN_TAG:
                completionResult.add(new PHPCompletionItem.TagItem("<?php", 1, request)); //NOI18N
                completionResult.add(new PHPCompletionItem.TagItem("<?=", 2, request)); //NOI18N
                break;
            case NEW_CLASS:
                autoCompleteKeywords(completionResult, request, Arrays.asList("class")); //NOI18N
                autoCompleteNamespaces(completionResult, request);
                autoCompleteNewClass(completionResult, request);
                break;
            case CLASS_NAME:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteClassNames(completionResult, request, false);
                break;
            case INTERFACE_NAME:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteInterfaceNames(completionResult, request);
                break;
            case GROUP_USE_KEYWORD:
                autoCompleteGroupUse(UseType.TYPE, completionResult, request);
                List<String> keywords = Arrays.asList("const", "function"); // NOI18N
                for (String keyword : keywords) {
                    if (startsWith(keyword, request.prefix)) {
                        completionResult.add(new PHPCompletionItem.KeywordItem(keyword, request));
                    }
                }
                break;
            case GROUP_USE_CONST_KEYWORD:
                autoCompleteGroupUse(UseType.CONST, completionResult, request);
                break;
            case GROUP_USE_FUNCTION_KEYWORD:
                autoCompleteGroupUse(UseType.FUNCTION, completionResult, request);
                break;
            case USE_KEYWORD:
                codeStyle = CodeStyle.get(request.result.getSnapshot().getSource().getDocument(caseSensitive));
                autoCompleteAfterUse(
                        UseType.TYPE,
                        completionResult,
                        request,
                        codeStyle.startUseWithNamespaceSeparator() ? QualifiedNameKind.FULLYQUALIFIED : QualifiedNameKind.QUALIFIED);
                break;
            case USE_CONST_KEYWORD:
                codeStyle = CodeStyle.get(request.result.getSnapshot().getSource().getDocument(caseSensitive));
                autoCompleteAfterUse(
                        UseType.CONST,
                        completionResult,
                        request,
                        codeStyle.startUseWithNamespaceSeparator() ? QualifiedNameKind.FULLYQUALIFIED : QualifiedNameKind.QUALIFIED);
                break;
            case USE_FUNCTION_KEYWORD:
                codeStyle = CodeStyle.get(request.result.getSnapshot().getSource().getDocument(caseSensitive));
                autoCompleteAfterUse(
                        UseType.FUNCTION,
                        completionResult,
                        request,
                        codeStyle.startUseWithNamespaceSeparator() ? QualifiedNameKind.FULLYQUALIFIED : QualifiedNameKind.QUALIFIED);
                break;
            case USE_TRAITS:
                codeStyle = CodeStyle.get(request.result.getSnapshot().getSource().getDocument(caseSensitive));
                autoCompleteAfterUseTrait(
                        completionResult,
                        request,
                        codeStyle.startUseWithNamespaceSeparator() ? QualifiedNameKind.FULLYQUALIFIED : QualifiedNameKind.QUALIFIED);
                break;
            case VISIBILITY_MODIFIER_OR_TYPE_NAME: // no break
                autoCompleteKeywords(completionResult, request, PHP_VISIBILITY_KEYWORDS);
                autoCompleteKeywords(completionResult, request, Arrays.asList("readonly")); // NOI18N
            case TYPE_NAME:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteTypeNames(completionResult, request);
                final ArrayList<String> typesForTypeName = new ArrayList<>(Type.getTypesForEditor());
                if (isInType(request)) {
                    // add self and parent
                    typesForTypeName.addAll(Type.getSpecialTypesForType());
                }
                if (isNullableType(info, caretOffset)) {
                    typesForTypeName.remove(Type.FALSE);
                    typesForTypeName.remove(Type.NULL);
                }
                if (isUnionType(info, caretOffset)) {
                    typesForTypeName.remove(Type.MIXED);
                }
                autoCompleteKeywords(completionResult, request, typesForTypeName);
                break;
            case RETURN_UNION_TYPE_NAME: // no break
            case RETURN_TYPE_NAME:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteTypeNames(completionResult, request);
                final ArrayList<String> typesForReturnTypeName = new ArrayList<>(Type.getTypesForReturnType());
                if (isInType(request)) {
                    // add self and parent
                    typesForReturnTypeName.addAll(Type.getSpecialTypesForType());
                    typesForReturnTypeName.add(Type.STATIC);
                }
                if (isNullableType(info, caretOffset)) {
                    typesForReturnTypeName.remove(Type.FALSE);
                    typesForReturnTypeName.remove(Type.NULL);
                    typesForReturnTypeName.remove(Type.VOID);
                    typesForReturnTypeName.remove(Type.NEVER);
                } else if (context == CompletionContext.RETURN_UNION_TYPE_NAME) {
                    typesForReturnTypeName.remove(Type.VOID);
                    typesForReturnTypeName.remove(Type.NEVER);
                    typesForReturnTypeName.remove(Type.MIXED);
                }
                autoCompleteKeywords(completionResult, request, typesForReturnTypeName);
                break;
            case FIELD_TYPE_NAME:
                autoCompleteFieldType(info, caretOffset, completionResult, request, false);
                break;
            case STRING:
                // LOCAL VARIABLES
                completionResult.addAll(getVariableProposals(request, null));
                // are we in class?
                if (request.prefix.length() == 0 || startsWith(PHP_CLASS_KEYWORD_THIS, request.prefix)) {
                    final EnclosingClass enclosingCls = findEnclosingClass(info, caretOffset);
                    if (enclosingCls != null) {
                        final String className = enclosingCls.extractClassName();
                        if (className != null) {
                            completionResult.add(new PHPCompletionItem.ClassScopeKeywordItem(className, PHP_CLASS_KEYWORD_THIS, request));
                        }
                    }
                }
                break;
            case CLASS_MEMBER:
                autoCompleteClassMembers(completionResult, request, false);
                break;
            case STATIC_CLASS_MEMBER:
                autoCompleteClassMembers(completionResult, request, true);
                break;
            case PHPDOC:
                PHPDOCCodeCompletion.complete(completionResult, request);
                if (PHPDOCCodeCompletion.isTypeCtx(request)) {
                    autoCompleteTypeNames(completionResult, request);
                    autoCompleteNamespaces(completionResult, request);
                    autoCompleteKeywordsInPHPDoc(completionResult, request);
                }
                break;
            case CLASS_CONTEXT_KEYWORDS:
                autoCompleteInClassContext(info, caretOffset, completionResult, request);
                break;
            case INTERFACE_CONTEXT_KEYWORDS:
                autoCompleteInInterfaceContext(completionResult, request);
                break;
            case METHOD_NAME:
                autoCompleteMethodName(info, caretOffset, completionResult, request);
                break;
            case IMPLEMENTS:
                autoCompleteKeywords(completionResult, request, Collections.singletonList("implements")); //NOI18N
                break;
            case EXTENDS:
                autoCompleteKeywords(completionResult, request, Collections.singletonList("extends")); //NOI18N
                break;
            case INHERITANCE:
                autoCompleteKeywords(completionResult, request, INHERITANCE_KEYWORDS);
                break;
            case THROW_NEW:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteExceptions(completionResult, request, true);
                break;
            case THROW:
                autoCompleteKeywords(completionResult, request, Collections.singletonList("new")); // NOI18N
                autoCompleteNamespaces(completionResult, request);
                // XXX allow all class names for static factory methods? e.g. ExceptionFactory::create("Something");
                // currently, restrict to classes extending the Exception class
                autoCompleteExceptions(completionResult, request, false);
                break;
            case CATCH:
                autoCompleteNamespaces(completionResult, request);
                autoCompleteExceptions(completionResult, request, false);
                break;
            case CLASS_MEMBER_IN_STRING:
                autoCompleteClassFields(completionResult, request);
                break;
            case SERVER_ENTRY_CONSTANTS:
                //TODO: probably better PHPCompletionItem instance should be used
                //autoCompleteMagicItems(proposals, request, PredefinedSymbols.SERVER_ENTRY_CONSTANTS);
                for (String keyword : PredefinedSymbols.SERVER_ENTRY_CONSTANTS) {
                    if (keyword.startsWith(request.prefix)) {
                        completionResult.add(new PHPCompletionItem.KeywordItem(keyword, request) {
                            @Override
                            public ImageIcon getIcon() {
                                return null;
                            }
                        });
                    }
                }

                break;
            default:
                assert false : context;
        }

        if (CancelSupport.getDefault().isCancelled()) {
            return CodeCompletionResult.NONE;
        }

        if (LOGGER.isLoggable(Level.FINE)) {
            long time = System.currentTimeMillis() - startTime;
            LOGGER.fine(String.format("complete() took %d ms, result contains %d items", time, completionResult.getItems().size()));
        }

        return completionResult;
    }

    private List<ElementFilter> createTypeFilter(final EnclosingClass enclosingClass) {
        List<ElementFilter> superTypeIndices = new ArrayList<>();
        Expression superClass = enclosingClass.getSuperClass();
        if (superClass != null) {
            String superClsName = enclosingClass.extractUnqualifiedSuperClassName();
            superTypeIndices.add(ElementFilter.forSuperClassName(QualifiedName.create(superClsName)));
        }
        List<Expression> interfaces = enclosingClass.getInterfaces();
        Set<QualifiedName> superIfaceNames = new HashSet<>();
        for (Expression identifier : interfaces) {
            String ifaceName = CodeUtils.extractUnqualifiedName(identifier);
            if (ifaceName != null) {
                superIfaceNames.add(QualifiedName.create(ifaceName));
            }
        }
        if (!superIfaceNames.isEmpty()) {
            superTypeIndices.add(ElementFilter.forSuperInterfaceNames(superIfaceNames));
        }
        return superTypeIndices;
    }

    private void autoCompleteMethodName(ParserResult info, int caretOffset, final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        EnclosingClass enclosingClass = findEnclosingClass(info, lexerToASTOffset(info, caretOffset));
        if (enclosingClass != null) {
            List<ElementFilter> superTypeIndices = createTypeFilter(enclosingClass);
            String clsName = enclosingClass.getClassName();
            NamespaceScope namespaceScope = ModelUtils.getNamespaceScope(request.result.getModel().getFileScope(), request.anchor);
            String fullyQualifiedClassName = VariousUtils.qualifyTypeNames(clsName, request.anchor, namespaceScope);
            if (fullyQualifiedClassName != null) {
                final FileObject fileObject = request.result.getSnapshot().getSource().getFileObject();
                final ElementFilter classFilter = ElementFilter.allOf(
                        ElementFilter.forFiles(fileObject), ElementFilter.allOf(superTypeIndices));
                Set<ClassElement> classes = classFilter.filter(request.index.getClasses(NameKind.exact(fullyQualifiedClassName)));
                for (ClassElement classElement : classes) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    ElementFilter methodFilter = ElementFilter.allOf(
                            ElementFilter.forExcludedNames(toNames(request.index.getDeclaredMethods(classElement)), PhpElementKind.METHOD),
                            ElementFilter.forName(NameKind.caseInsensitivePrefix(QualifiedName.create(request.prefix))));
                    Set<MethodElement> accessibleMethods = methodFilter.filter(request.index.getAccessibleMethods(classElement, classElement));
                    for (MethodElement method : accessibleMethods) {
                        if (CancelSupport.getDefault().isCancelled()) {
                            return;
                        }
                        if (!method.isFinal()) {
                            completionResult.add(PHPCompletionItem.MethodDeclarationItem.forMethodName(method, request));
                        }
                    }
                    Set<MethodElement> magicMethods = methodFilter.filter(request.index.getAccessibleMagicMethods(classElement));
                    for (MethodElement magicMethod : magicMethods) {
                        if (magicMethod != null) {
                            completionResult.add(PHPCompletionItem.MethodDeclarationItem.forMethodName(magicMethod, request));
                        }
                    }
                    break;
                }
            }
        }

    }

    /**
     * Finding item after new keyword.
     *
     * @param completionResult
     * @param request
     */
    private void autoCompleteNewClass(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        // At first find all classes that match the prefix
        final boolean isCamelCase = isCamelCaseForTypeNames(request.prefix);
        final QualifiedName prefix = QualifiedName.create(request.prefix).toNotFullyQualified();
        final NameKind nameQuery = NameKind.create(request.prefix,
                isCamelCase ? Kind.CAMEL_CASE : Kind.CASE_INSENSITIVE_PREFIX);
        Model model = request.result.getModel();
        Set<ClassElement> classes = request.index.getClasses(nameQuery, ModelUtils.getAliasedNames(model, request.anchor), Trait.ALIAS);
        if (!classes.isEmpty()) {
            completionResult.setFilterable(false);
        }
        boolean addedExact = false;
        final NameKind query;
        if (classes.size() == 1) {
            ClassElement clazz = (ClassElement) classes.toArray()[0];
            if (!clazz.isAbstract()
                    && !clazz.isAnonymous()) {
                // if there is only once class find constructors for it
                query = isCamelCase ? NameKind.create(prefix.toString(), QuerySupport.Kind.CAMEL_CASE) : NameKind.caseInsensitivePrefix(prefix);
                autoCompleteConstructors(completionResult, request, model, query);
            }
        } else {
            for (ClassElement clazz : classes) {
                if (CancelSupport.getDefault().isCancelled()) {
                    return;
                }
                if (!clazz.isAbstract()
                        && !clazz.isAnonymous()) {
                    // check whether the prefix is exactly the class
                    NamespaceScope namespaceScope = ModelUtils.getNamespaceScope(request.result.getModel().getFileScope(), request.anchor);
                    String fqPrefixName = VariousUtils.qualifyTypeNames(request.prefix, request.anchor, namespaceScope);
                    if (clazz.getFullyQualifiedName().toString().equals(fqPrefixName)) {
                        // find constructor of the class
                        if (!addedExact) { // add the constructors only once
                            autoCompleteConstructors(completionResult, request, model, NameKind.exact(fqPrefixName));
                            addedExact = true;
                        }
                    } else {
                        // put to the cc just the class
                        completionResult.add(new PHPCompletionItem.ClassItem(clazz, request, false, null));
                    }
                }
            }
        }
    }

    private void autoCompleteConstructors(final PHPCompletionResult completionResult, final PHPCompletionItem.CompletionRequest request, final Model model, final NameKind query) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        Set<AliasedName> aliasedNames = ModelUtils.getAliasedNames(model, request.anchor);
        Set<MethodElement> constructors = request.index.getConstructors(query, aliasedNames, Trait.ALIAS);
        for (MethodElement constructor : constructors) {
            for (final PHPCompletionItem.NewClassItem newClassItem : PHPCompletionItem.NewClassItem.getNewClassItems(constructor, request)) {
                if (CancelSupport.getDefault().isCancelled()) {
                    return;
                }
                completionResult.add(newClassItem);
            }
        }
    }

    private void autoCompleteExceptions(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request, boolean withConstructors) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        final boolean isCamelCase = isCamelCaseForTypeNames(request.prefix);
        final NameKind nameQuery = NameKind.create(request.prefix, isCamelCase ? Kind.CAMEL_CASE : Kind.CASE_INSENSITIVE_PREFIX);
        final Set<ClassElement> classes = request.index.getClasses(nameQuery);
        final Model model = request.result.getModel();
        final Set<QualifiedName> constructorClassNames = new HashSet<>();
        for (ClassElement classElement : classes) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            if (isExceptionClass(classElement)) {
                completionResult.add(new PHPCompletionItem.ClassItem(classElement, request, false, null));
                if (withConstructors) {
                    constructorClassNames.add(classElement.getFullyQualifiedName());
                }
                continue;
            }
            if (classElement.getSuperClassName() != null) {
                Set<ClassElement> inheritedClasses = request.index.getInheritedClasses(classElement);
                for (ClassElement inheritedClass : inheritedClasses) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    if (isExceptionClass(inheritedClass)) {
                        completionResult.add(new PHPCompletionItem.ClassItem(classElement, request, false, null));
                        if (withConstructors) {
                            constructorClassNames.add(classElement.getFullyQualifiedName());
                        }
                        break;
                    }
                }
            }
        }
        for (QualifiedName qualifiedName : constructorClassNames) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            autoCompleteConstructors(completionResult, request, model, NameKind.exact(qualifiedName));
        }
    }

    private boolean isExceptionClass(ClassElement classElement) {
        return classElement.getFullyQualifiedName().toString().equals(EXCEPTION_CLASS_NAME);
    }

    private void autoCompleteClassNames(final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request, boolean endWithDoubleColon) {
        autoCompleteClassNames(completionResult, request, endWithDoubleColon, null);
    }

    private void autoCompleteClassNames(final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request, boolean endWithDoubleColon, QualifiedNameKind kind) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        final boolean isCamelCase = isCamelCaseForTypeNames(request.prefix);
        final NameKind nameQuery = NameKind.create(request.prefix,
                isCamelCase ? Kind.CAMEL_CASE : Kind.CASE_INSENSITIVE_PREFIX);
        Model model = request.result.getModel();
        Set<ClassElement> classes = request.index.getClasses(nameQuery, ModelUtils.getAliasedNames(model, request.anchor), Trait.ALIAS);

        if (!classes.isEmpty()) {
            completionResult.setFilterable(false);
        }
        for (ClassElement clazz : classes) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            if (!clazz.isAnonymous()) {
                completionResult.add(new PHPCompletionItem.ClassItem(clazz, request, endWithDoubleColon, kind));
            }
        }
    }

    private void autoCompleteInterfaceNames(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request) {
        autoCompleteInterfaceNames(completionResult, request, null);
    }

    private void autoCompleteInterfaceNames(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request, QualifiedNameKind kind) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        final boolean isCamelCase = isCamelCaseForTypeNames(request.prefix);
        final NameKind nameQuery = NameKind.create(request.prefix,
                isCamelCase ? Kind.CAMEL_CASE : Kind.CASE_INSENSITIVE_PREFIX);

        Model model = request.result.getModel();
        Set<InterfaceElement> interfaces = request.index.getInterfaces(nameQuery, ModelUtils.getAliasedNames(model, request.anchor), Trait.ALIAS);
        if (!interfaces.isEmpty()) {
            completionResult.setFilterable(false);
        }

        for (InterfaceElement iface : interfaces) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            completionResult.add(new PHPCompletionItem.InterfaceItem(iface, request, kind, false));
        }
    }

    private void autoCompleteTypeNames(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request) {
        autoCompleteTypeNames(completionResult, request, null, false);
    }

    private void autoCompleteAfterUseTrait(final PHPCompletionResult completionResult, final PHPCompletionItem.CompletionRequest request, final QualifiedNameKind kind) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        Set<NamespaceElement> namespaces = request.index.getNamespaces(
                NameKind.caseInsensitivePrefix(QualifiedName.create(request.prefix).toNotFullyQualified()));
        for (NamespaceElement namespace : namespaces) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            completionResult.add(new PHPCompletionItem.NamespaceItem(namespace, request, QualifiedNameKind.FULLYQUALIFIED));
        }
        final NameKind nameQuery = NameKind.caseInsensitivePrefix(request.prefix);
        for (TraitElement trait : request.index.getTraits(nameQuery)) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            completionResult.add(new PHPCompletionItem.TraitItem(trait, request));
        }
    }

    private void autoCompleteGroupUse(UseType useType, PHPCompletionResult completionResult, CompletionRequest request) {
        assert request.extraPrefix != null;
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        request.insertOnlyMethodsName = true;
        // we will "complete" FQN so handle search prefix as well
        if (!request.extraPrefix.startsWith("\\")) { // NOI18N
            request.extraPrefix = "\\" + request.extraPrefix; // NOI18N
        }
        final String prefix = request.extraPrefix + request.prefix;
        Set<NamespaceElement> namespaces = request.index.getNamespaces(
                NameKind.caseInsensitivePrefix(QualifiedName.create(prefix).toNotFullyQualified()));
        for (NamespaceElement namespace : namespaces) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            completionResult.add(new PHPCompletionItem.NamespaceItem(namespace, request, QualifiedNameKind.FULLYQUALIFIED));
        }
        final NameKind nameQuery = NameKind.caseInsensitivePrefix(prefix);
        switch (useType) {
            case TYPE:
                for (ClassElement clazz : request.index.getClasses(nameQuery)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    completionResult.add(new PHPCompletionItem.ClassItem(clazz, request, false, QualifiedNameKind.FULLYQUALIFIED));
                }
                for (InterfaceElement iface : request.index.getInterfaces(nameQuery)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    completionResult.add(new PHPCompletionItem.InterfaceItem(iface, request, QualifiedNameKind.FULLYQUALIFIED, false));
                }
                // NETBEANS-4650
                for (TraitElement trait : request.index.getTraits(nameQuery)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    completionResult.add(new PHPCompletionItem.TraitItem(trait, request));
                }
                break;
            case CONST:
                for (ConstantElement constant : request.index.getConstants(nameQuery)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    completionResult.add(new PHPCompletionItem.ConstantItem(constant, request, QualifiedNameKind.FULLYQUALIFIED));
                }
                break;
            case FUNCTION:
                for (FunctionElement function : request.index.getFunctions(nameQuery)) {
                    for (PHPCompletionItem.FunctionElementItem item : PHPCompletionItem.FunctionElementItem.getItems(function, request, QualifiedNameKind.FULLYQUALIFIED)) {
                        if (CancelSupport.getDefault().isCancelled()) {
                            return;
                        }
                        completionResult.add(item);
                    }
                }
                break;
            default:
                assert false : "Unknown use type: " + useType;
        }
    }

    private void autoCompleteAfterUse(
            UseType useType,
            final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request,
            QualifiedNameKind kind) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        Set<NamespaceElement> namespaces = request.index.getNamespaces(
                NameKind.caseInsensitivePrefix(QualifiedName.create(request.prefix).toNotFullyQualified()));
        for (NamespaceElement namespace : namespaces) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            completionResult.add(new PHPCompletionItem.NamespaceItem(namespace, request, kind));
        }
        final NameKind nameQuery = NameKind.caseInsensitivePrefix(request.prefix);
        switch (useType) {
            case TYPE:
                for (ClassElement clazz : request.index.getClasses(nameQuery)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    completionResult.add(new PHPCompletionItem.ClassItem(clazz, request, false, kind));
                }
                for (InterfaceElement iface : request.index.getInterfaces(nameQuery)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    completionResult.add(new PHPCompletionItem.InterfaceItem(iface, request, kind, false));
                }
                // NETBEANS-4650
                for (TraitElement trait : request.index.getTraits(nameQuery)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    completionResult.add(new PHPCompletionItem.TraitItem(trait, request));
                }
                break;
            case CONST:
                for (ConstantElement constant : request.index.getConstants(nameQuery)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    completionResult.add(new PHPCompletionItem.ConstantItem(constant, request));
                }
                break;
            case FUNCTION:
                for (FunctionElement function : request.index.getFunctions(nameQuery)) {
                    List<PHPCompletionItem.FunctionElementItem> items = PHPCompletionItem.FunctionElementItem.getItems(function, request);
                    for (PHPCompletionItem.FunctionElementItem item : items) {
                        if (CancelSupport.getDefault().isCancelled()) {
                            return;
                        }
                        completionResult.add(item);
                    }
                }
                break;
            default:
                assert false : "Unknown use type: " + useType;
        }
    }

    private void autoCompleteTypeNames(
            final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request,
            QualifiedNameKind kind,
            boolean endWithDoubleColon) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        if (request.prefix.trim().length() > 0) {
            autoCompleteClassNames(completionResult, request, endWithDoubleColon, kind);
            autoCompleteInterfaceNames(completionResult, request, kind);
        } else {
            Model model = request.result.getModel();
            Set<AliasedName> aliasedNames = ModelUtils.getAliasedNames(model, request.anchor);
            Collection<PhpElement> allTopLevel = request.index.getTopLevelElements(NameKind.empty(), aliasedNames, Trait.ALIAS);
            for (PhpElement element : allTopLevel) {
                if (CancelSupport.getDefault().isCancelled()) {
                    return;
                }
                if (element instanceof ClassElement) {
                    ClassElement classElement = (ClassElement) element;
                    if (!classElement.isAnonymous()) {
                        completionResult.add(new PHPCompletionItem.ClassItem(classElement, request, endWithDoubleColon, kind));
                    }
                } else if (element instanceof InterfaceElement) {
                    completionResult.add(new PHPCompletionItem.InterfaceItem((InterfaceElement) element, request, kind, endWithDoubleColon));
                }
            }
        }
    }

    private void autoCompleteKeywords(final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request, List<String> keywordList) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        for (String keyword : keywordList) {
            if (keyword.startsWith(request.prefix)) {
                completionResult.add(new PHPCompletionItem.KeywordItem(keyword, request));
            }
        }

    }

    private void autoCompleteKeywordsInPHPDoc(final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        BaseDocument doc = (BaseDocument) request.info.getSnapshot().getSource().getDocument(false);
        if (doc == null) {
            return;
        }
        try {
            int start = request.anchor - 1;
            if (start >= 0) {
                String prefix = doc.getText(start, 1);
                if (CodeUtils.NULLABLE_TYPE_PREFIX.equals(prefix)) {
                    List<String> keywords = new ArrayList<>(Type.getTypesForEditor());
                    keywords.remove(Type.FALSE);
                    keywords.remove(Type.NULL);
                    autoCompleteKeywords(completionResult, request, keywords);
                } else {
                    autoCompleteKeywords(completionResult, request, Type.getTypesForPhpDoc());
                }
            }
        } catch (BadLocationException ex) {
            LOGGER.log(Level.WARNING, "Incorrect offset for the nullable type prefix: {0}", ex.offsetRequested()); // NOI18N
        }
    }

    private void autoCompleteNamespaces(final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request) {
        autoCompleteNamespaces(completionResult, request, null);
    }

    private void autoCompleteNamespaces(final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request, QualifiedNameKind kind) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        final QualifiedName prefix = QualifiedName.create(request.prefix).toNotFullyQualified();
        Model model = request.result.getModel();
        Set<NamespaceElement> namespaces = request.index.getNamespaces(NameKind.caseInsensitivePrefix(prefix),
                ModelUtils.getAliasedNames(model, request.anchor), Trait.ALIAS);
        for (NamespaceElement namespace : namespaces) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            completionResult.add(new PHPCompletionItem.NamespaceItem(namespace, request, kind));
        }
    }

    private void autoCompleteInInterfaceContext(final PHPCompletionResult completionResult, final PHPCompletionItem.CompletionRequest request) {
        autoCompleteKeywords(completionResult, request, INTERFACE_CONTEXT_KEYWORD_PROPOSAL);
    }

    private void autoCompleteInClassContext(
            ParserResult info,
            int caretOffset,
            final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        TokenHierarchy<?> th = info.getSnapshot().getTokenHierarchy();
        TokenSequence<PHPTokenId> tokenSequence = th.tokenSequence(PHPTokenId.language());
        assert tokenSequence != null;

        autoCompleteKeywords(completionResult, request, CLASS_CONTEXT_KEYWORD_PROPOSAL);
        if (offerMagicAndInherited(tokenSequence, caretOffset, th)) {
            EnclosingClass enclosingClass = findEnclosingClass(info, lexerToASTOffset(info, caretOffset));
            if (enclosingClass != null) {
                List<ElementFilter> superTypeIndices = createTypeFilter(enclosingClass);
                String clsName = enclosingClass.getClassName();
                NamespaceScope namespaceScope = ModelUtils.getNamespaceScope(request.result.getModel().getFileScope(), request.anchor);
                String fullyQualifiedClassName = VariousUtils.qualifyTypeNames(clsName, request.anchor, namespaceScope);
                if (fullyQualifiedClassName != null) {
                    final FileObject fileObject = request.result.getSnapshot().getSource().getFileObject();
                    final ElementFilter classFilter = ElementFilter.allOf(
                            ElementFilter.forFiles(fileObject), ElementFilter.allOf(superTypeIndices));
                    Set<ClassElement> classes = classFilter.filter(request.index.getClasses(NameKind.exact(fullyQualifiedClassName)));
                    for (ClassElement classElement : classes) {
                        if (CancelSupport.getDefault().isCancelled()) {
                            return;
                        }
                        ElementFilter methodFilter = ElementFilter.allOf(
                                ElementFilter.forExcludedNames(toNames(request.index.getDeclaredMethods(classElement)), PhpElementKind.METHOD),
                                ElementFilter.forName(NameKind.caseInsensitivePrefix(QualifiedName.create(request.prefix))));
                        Set<MethodElement> accessibleMethods = methodFilter.filter(request.index.getAccessibleMethods(classElement, classElement));
                        for (MethodElement method : accessibleMethods) {
                            if (CancelSupport.getDefault().isCancelled()) {
                                return;
                            }
                            if (!method.isFinal()) {
                                completionResult.add(PHPCompletionItem.MethodDeclarationItem.getDeclarationItem(method, request));
                            }
                        }
                        Set<MethodElement> magicMethods = methodFilter.filter(request.index.getAccessibleMagicMethods(classElement));
                        for (MethodElement magicMethod : magicMethods) {
                            if (CancelSupport.getDefault().isCancelled()) {
                                return;
                            }
                            if (magicMethod != null) {
                                completionResult.add(PHPCompletionItem.MethodDeclarationItem.getDeclarationItem(magicMethod, request));
                            }
                        }
                        break;
                    }
                }
            }
        } else if (completeFieldTypes(tokenSequence, caretOffset, th, info.getSnapshot().getSource().getFileObject())){
            autoCompleteFieldType(info, caretOffset, completionResult, request, true);
        }
    }

    private void autoCompleteFieldType(ParserResult info, int caretOffset, final PHPCompletionResult completionResult, CompletionRequest request, boolean isInClassContext) {
        // PHP 7.4 Typed Properties 2.0
        // https://wiki.php.net/rfc/typed_properties_v2
        autoCompleteNamespaces(completionResult, request);
        autoCompleteTypeNames(completionResult, request);
        List<String> keywords = new ArrayList<>(Type.getTypesForFieldType());
        boolean isNullableType = isNullableType(info, caretOffset);
        if (!isInClassContext && !isNullableType) {
            // e.g. private stat^
            TokenHierarchy<?> th = info.getSnapshot().getTokenHierarchy();
            TokenSequence<PHPTokenId> tokenSequence = th.tokenSequence(PHPTokenId.language());
            assert tokenSequence != null;
            tokenSequence.move(caretOffset);
            boolean addStaticKeyword = false;
            boolean addReadonlyKeyword = false;
            boolean addVisibilityKeyword = false;
            if (!(!tokenSequence.moveNext() && !tokenSequence.movePrevious())) {
                Token<PHPTokenId> token = tokenSequence.token();
                int tokenIdOffset = tokenSequence.token().offset(th);
                addStaticKeyword = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
                        PHPTokenId.PHP_STATIC,
                        PHPTokenId.PHP_READONLY,
                        PHPTokenId.PHP_OPERATOR // "|"
                ));
                addReadonlyKeyword = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
                        PHPTokenId.PHP_READONLY,
                        PHPTokenId.PHP_OPERATOR // "|"
                ));
                addVisibilityKeyword = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
                        PHPTokenId.PHP_PUBLIC,
                        PHPTokenId.PHP_PRIVATE,
                        PHPTokenId.PHP_PROTECTED,
                        PHPTokenId.PHP_OPERATOR // "|"
                ));
            }
            if (addStaticKeyword) {
                keywords.add("static"); // NOI18N
            }
            if (addReadonlyKeyword) {
                keywords.add("readonly"); // NOI18N
            }
            if (addVisibilityKeyword) {
                keywords.addAll(PHP_VISIBILITY_KEYWORDS);
            }
        }
        if (isNullableType) {
            keywords.remove(Type.FALSE);
            keywords.remove(Type.NULL);
        }
        if (isUnionType(info, caretOffset)) {
            keywords.remove(Type.MIXED);
        }
        autoCompleteKeywords(completionResult, request, keywords);
    }

    private boolean offerMagicAndInherited(TokenSequence<PHPTokenId> tokenSequence, int caretOffset, TokenHierarchy<?> th) {
        boolean offerMagicAndInherited = true;
        tokenSequence.move(caretOffset);
        if (!(!tokenSequence.moveNext() && !tokenSequence.movePrevious())) {
            Token<PHPTokenId> token = tokenSequence.token();
            int tokenIdOffset = tokenSequence.token().offset(th);
            offerMagicAndInherited = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
                PHPTokenId.PHP_PRIVATE,
                PHPTokenId.PHP_PUBLIC,
                PHPTokenId.PHP_PROTECTED,
                PHPTokenId.PHP_ABSTRACT,
                PHPTokenId.PHP_VAR,
                PHPTokenId.PHP_STATIC,
                PHPTokenId.PHP_CONST,
                PHPTokenId.PHP_READONLY
            ));
        }
        return offerMagicAndInherited;
    }

    private boolean completeFieldTypes(TokenSequence<PHPTokenId> tokenSequence, int caretOffset, TokenHierarchy<?> th, FileObject fileObject) {
        if (!isPhp74OrNewer(fileObject)) {
            return false;
        }
        // e.g. private static s^tring|int $field; private bool ^$bool;
        boolean completeTypes = false;
        tokenSequence.move(caretOffset);
        if (!(!tokenSequence.moveNext() && !tokenSequence.movePrevious())) {
            Token<PHPTokenId> token = tokenSequence.token();
            int tokenIdOffset = tokenSequence.token().offset(th);
            completeTypes = !CompletionContextFinder.lineContainsAny(token, caretOffset - tokenIdOffset, tokenSequence, Arrays.asList(
                PHPTokenId.PHP_TYPE_BOOL,
                PHPTokenId.PHP_TYPE_INT,
                PHPTokenId.PHP_TYPE_FLOAT,
                PHPTokenId.PHP_TYPE_STRING,
                PHPTokenId.PHP_ARRAY,
                PHPTokenId.PHP_TYPE_OBJECT,
                PHPTokenId.PHP_ITERABLE,
                PHPTokenId.PHP_SELF,
                PHPTokenId.PHP_PARENT,
                PHPTokenId.PHP_FALSE,
                PHPTokenId.PHP_NULL,
                PHPTokenId.PHP_STRING,
                PHPTokenId.PHP_CONST
            ));
        }
        return completeTypes;
    }

    private static Set<String> toNames(Set<? extends PhpElement> elements) {
        Set<String> names = new HashSet<>();
        for (PhpElement elem : elements) {
            names.add(elem.getName());
        }
        return names;
    }

    private void autoCompleteClassMembers(
            final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request,
            boolean staticContext) {
        autoCompleteClassMembers(completionResult, request, staticContext, false);
    }

    private void autoCompleteClassMembers(
            final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request,
            boolean staticContext,
            boolean completeAccessPrefix) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        // TODO: remove duplicate/redundant code from here

        TokenHierarchy<?> th = request.info.getSnapshot().getTokenHierarchy();
        TokenSequence<PHPTokenId> tokenSequence = LexUtilities.getPHPTokenSequence(th, request.anchor);

        if (tokenSequence == null) {
            return;
        }

        tokenSequence.move(request.anchor);
        if (tokenSequence.movePrevious()) {
            boolean instanceContext = !staticContext;

            if (tokenSequence.token().id() != PHPTokenId.PHP_PAAMAYIM_NEKUDOTAYIM
                    && tokenSequence.token().id() != PHPTokenId.PHP_OBJECT_OPERATOR
                    && tokenSequence.token().id() != PHPTokenId.PHP_NULLSAFE_OBJECT_OPERATOR) {
                tokenSequence.movePrevious();
            }
            tokenSequence.movePrevious();
            if (tokenSequence.token().id() == PHPTokenId.WHITESPACE) {
                tokenSequence.movePrevious();
            }
            final CharSequence varName = tokenSequence.token().text();
            tokenSequence.moveNext();

            List<String> invalidProposalsForClsMembers = INVALID_PROPOSALS_FOR_CLS_MEMBERS;
            Model model = request.result.getModel();

            boolean selfContext = false;
            boolean staticLateBindingContext = false;
            boolean specialVariable = false;
            if (TokenUtilities.textEquals(varName, "$this")) { // NOI18N
                specialVariable = true;
            } else if (TokenUtilities.textEquals(varName, "self")) { // NOI18N
                staticContext = true;
                selfContext = true;
                specialVariable = true;
            } else if (TokenUtilities.textEquals(varName, "parent")) { // NOI18N
                invalidProposalsForClsMembers = Collections.emptyList();
                staticContext = true;
                instanceContext = true;
                specialVariable = true;
            } else if (TokenUtilities.textEquals(varName, "static")) { // NOI18N
                staticContext = true;
                instanceContext = false;
                staticLateBindingContext = true;
                specialVariable = true;
            }

            Collection<? extends TypeScope> types = ModelUtils.resolveTypeAfterReferenceToken(model, tokenSequence, request.anchor, specialVariable);
            if (types != null) {
                TypeElement enclosingType = getEnclosingType(request, types);
                if (completeAccessPrefix) {
                    // NETBEANS-1855
                    types = ModelUtils.resolveType(model, request.anchor);
                }
                Set<PhpElement> duplicateElementCheck = new HashSet<>();
                for (TypeScope typeScope : types) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    final ElementFilter staticFlagFilter = !completeAccessPrefix
                            ? new StaticOrInstanceMembersFilter(staticContext, instanceContext, selfContext, staticLateBindingContext)
                            : new ElementFilter() { // NETBEANS-1855
                        @Override
                        public boolean isAccepted(PhpElement element) {
                            return true;
                        }
                    };

                    final ElementFilter methodsFilter = ElementFilter.allOf(
                            ElementFilter.forKind(PhpElementKind.METHOD),
                            ElementFilter.forName(NameKind.caseInsensitivePrefix(request.prefix)),
                            staticFlagFilter,
                            ElementFilter.forExcludedNames(invalidProposalsForClsMembers, PhpElementKind.METHOD),
                            ElementFilter.forInstanceOf(MethodElement.class));
                    final ElementFilter fieldsFilter = ElementFilter.allOf(
                            ElementFilter.forKind(PhpElementKind.FIELD),
                            ElementFilter.forName(NameKind.caseInsensitivePrefix(request.prefix)),
                            staticFlagFilter,
                            ElementFilter.forInstanceOf(FieldElement.class));
                    final ElementFilter constantsFilter = ElementFilter.allOf(
                            ElementFilter.forKind(PhpElementKind.TYPE_CONSTANT),
                            ElementFilter.forName(NameKind.caseInsensitivePrefix(request.prefix)),
                            ElementFilter.forInstanceOf(TypeConstantElement.class));
                    HashSet<TypeMemberElement> accessibleTypeMembers = new HashSet<>();
                    accessibleTypeMembers.addAll(request.index.getAccessibleTypeMembers(typeScope, enclosingType));
                    // for @mixin tag #241740
                    if (typeScope instanceof ClassElement) {
                        ClassElement classElement = (ClassElement) typeScope;
                        if (!classElement.getFQMixinClassNames().isEmpty()) {
                            // XXX currently, only when mixins are used directly in the class. should support all cases?
                            accessibleTypeMembers.addAll(request.index.getAccessibleMixinTypeMembers(typeScope, enclosingType));
                        }
                    }
                    for (final PhpElement phpElement : accessibleTypeMembers) {
                        if (CancelSupport.getDefault().isCancelled()) {
                            return;
                        }
                        if (duplicateElementCheck.add(phpElement)) {
                            if (methodsFilter.isAccepted(phpElement)) {
                                MethodElement method = (MethodElement) phpElement;
                                List<MethodElementItem> items = PHPCompletionItem.MethodElementItem.getItems(method, request, completeAccessPrefix);
                                for (MethodElementItem methodItem : items) {
                                    if (CancelSupport.getDefault().isCancelled()) {
                                        return;
                                    }
                                    completionResult.add(methodItem);
                                }
                            } else if (fieldsFilter.isAccepted(phpElement)) {
                                FieldElement field = (FieldElement) phpElement;
                                FieldItem fieldItem = PHPCompletionItem.FieldItem.getItem(field, request, false, completeAccessPrefix);
                                completionResult.add(fieldItem);
                            } else if ((staticContext || completeAccessPrefix) && constantsFilter.isAccepted(phpElement)) {
                                TypeConstantElement constant = (TypeConstantElement) phpElement;
                                TypeConstantItem constantItem = PHPCompletionItem.TypeConstantItem.getItem(constant, request, completeAccessPrefix);
                                completionResult.add(constantItem);
                            }
                        }
                    }
                    if (staticContext) {
                        Set<TypeConstantElement> magicConstants = constantsFilter.filter(request.index.getAccessibleMagicConstants(typeScope));
                        for (TypeConstantElement magicConstant : magicConstants) {
                            if (CancelSupport.getDefault().isCancelled()) {
                                return;
                            }
                            if (magicConstant != null) {
                                // NETBEANS-4443
                                // PHP 8.0 allows ::class on objects (e.g. $instance::class, create()::class)
                                // so don't restrict dynamic access any more
                                // https://wiki.php.net/rfc/class_name_literal_on_object
                                completionResult.add(PHPCompletionItem.TypeConstantItem.getItem(magicConstant, request));
                            }
                        }
                    }
                }
            }
        }
    }

    private void autoCompleteClassMethodParameterName(
            final PHPCompletionResult completionResult,
            PHPCompletionItem.CompletionRequest request,
            boolean staticContext
    ) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        TokenHierarchy<?> th = request.info.getSnapshot().getTokenHierarchy();
        TokenSequence<PHPTokenId> tokenSequence = LexUtilities.getPHPTokenSequence(th, request.anchor);
        if (tokenSequence == null) {
            return;
        }
        Token<? extends PHPTokenId> functionName = CompletionContextFinder.findFunctionInvocationName(tokenSequence, request.anchor);
        if (functionName != null) {
            int originalAnchor = request.anchor;
            try {
                request.anchor = tokenSequence.offset();
                boolean isInstanceContext = !staticContext;
                boolean isStaticContext = staticContext;

                if (tokenSequence.token().id() != PHPTokenId.PHP_PAAMAYIM_NEKUDOTAYIM
                        && tokenSequence.token().id() != PHPTokenId.PHP_OBJECT_OPERATOR
                        && tokenSequence.token().id() != PHPTokenId.PHP_NULLSAFE_OBJECT_OPERATOR) {
                    tokenSequence.movePrevious();
                }
                tokenSequence.movePrevious();
                if (tokenSequence.token().id() == PHPTokenId.WHITESPACE) {
                    tokenSequence.movePrevious();
                }
                final CharSequence varName = tokenSequence.token().text();
                tokenSequence.moveNext();

                List<String> invalidProposalsForClsMembers = INVALID_PROPOSALS_FOR_CLS_MEMBERS;
                Model model = request.result.getModel();

                boolean selfContext = false;
                boolean staticLateBindingContext = false;
                boolean specialVariable = false;
                if (TokenUtilities.textEquals(varName, "$this")) { // NOI18N
                    specialVariable = true;
                } else if (TokenUtilities.textEquals(varName, "self")) { // NOI18N
                    isStaticContext = true;
                    selfContext = true;
                    specialVariable = true;
                } else if (TokenUtilities.textEquals(varName, "parent")) { // NOI18N
                    invalidProposalsForClsMembers = Collections.emptyList();
                    isStaticContext = true;
                    isInstanceContext = true;
                    specialVariable = true;
                } else if (TokenUtilities.textEquals(varName, "static")) { // NOI18N
                    isStaticContext = true;
                    isInstanceContext = false;
                    staticLateBindingContext = true;
                    specialVariable = true;
                }

                Collection<? extends TypeScope> types = ModelUtils.resolveTypeAfterReferenceToken(model, tokenSequence, request.anchor, specialVariable);
                TypeElement enclosingType = getEnclosingType(request, types);
                Set<PhpElement> duplicateElementCheck = new HashSet<>();
                for (TypeScope typeScope : types) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    final ElementFilter staticFlagFilter = new StaticOrInstanceMembersFilter(isStaticContext, isInstanceContext, selfContext, staticLateBindingContext);
                    final ElementFilter methodsFilter = ElementFilter.allOf(
                            ElementFilter.forKind(PhpElementKind.METHOD),
                            ElementFilter.forName(NameKind.exact(functionName.text().toString())),
                            staticFlagFilter,
                            ElementFilter.forExcludedNames(invalidProposalsForClsMembers, PhpElementKind.METHOD),
                            ElementFilter.forInstanceOf(MethodElement.class));
                    HashSet<TypeMemberElement> accessibleTypeMembers = new HashSet<>();
                    accessibleTypeMembers.addAll(request.index.getAccessibleTypeMembers(typeScope, enclosingType));
                    if (typeScope instanceof ClassElement) {
                        ClassElement classElement = (ClassElement) typeScope;
                        if (!classElement.getFQMixinClassNames().isEmpty()) {
                            accessibleTypeMembers.addAll(request.index.getAccessibleMixinTypeMembers(typeScope, enclosingType));
                        }
                    }
                    for (final PhpElement phpElement : accessibleTypeMembers) {
                        if (CancelSupport.getDefault().isCancelled()) {
                            return;
                        }
                        if (duplicateElementCheck.add(phpElement)) {
                            if (methodsFilter.isAccepted(phpElement)) {
                                MethodElement method = (MethodElement) phpElement;
                                for (ParameterElement parameter : method.getParameters()) {
                                    if (CancelSupport.getDefault().isCancelled()) {
                                        return;
                                    }
                                    String name = parameter.getName();
                                    if (name != null) {
                                        name = name.substring(1);
                                    }
                                    if (name != null
                                            && name.startsWith(request.prefix)) {
                                        completionResult.add(new PHPCompletionItem.ParameterNameItem(parameter, request));
                                    }
                                }
                            }
                        }
                    }
                }
            } finally {
                request.anchor = originalAnchor;
            }
        }
    }

    private void autoCompleteFunctionParameterName(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        TokenHierarchy<?> th = request.info.getSnapshot().getTokenHierarchy();
        TokenSequence<PHPTokenId> tokenSequence = LexUtilities.getPHPTokenSequence(th, request.anchor);
        if (tokenSequence == null) {
            return;
        }
        Token<? extends PHPTokenId> functionName = CompletionContextFinder.findFunctionInvocationName(tokenSequence, request.anchor);
        if (functionName != null) {
            Set<PhpElement> elements = request.index.getTopLevelElements(NameKind.exact(functionName.text().toString()));
            // usually, php doesn't have the same name functions
            // but just check duplicate name
            Set<String> duplicateCheck = new HashSet<>();
            for (PhpElement element : elements) {
                if (CancelSupport.getDefault().isCancelled()) {
                    return;
                }
                if (element instanceof FunctionElement) {
                    FunctionElement functionElement = (FunctionElement) element;
                    if (functionElement.isAnonymous()) {
                        continue;
                    }
                    for (ParameterElement parameter : functionElement.getParameters()) {
                        if (CancelSupport.getDefault().isCancelled()) {
                            return;
                        }
                        String name = parameter.getName();
                        if (name != null) {
                            name = name.substring(1);
                        }
                        if (name != null
                                && name.startsWith(request.prefix)
                                && duplicateCheck.add(name)) {
                            completionResult.add(new PHPCompletionItem.ParameterNameItem(parameter, request));
                        }
                    }
                }
            }
        }
    }

    private void autoCompleteClassConstants(final PHPCompletionResult completionResult, final PHPCompletionItem.CompletionRequest request) {
        // NETBANS-1855
        // complete access prefix i.e. add "self::" to the top of constant names
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        final ElementFilter constantsFilter = ElementFilter.allOf(
                ElementFilter.forKind(PhpElementKind.TYPE_CONSTANT),
                ElementFilter.forName(NameKind.caseInsensitivePrefix(request.prefix)),
                ElementFilter.forInstanceOf(TypeConstantElement.class)
        );
        Model model = request.result.getModel();
        Collection<? extends TypeScope> types = ModelUtils.resolveType(model, request.anchor);
        TypeElement enclosingType = getEnclosingType(request, types);
        for (TypeScope typeScope : types) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            for (final PhpElement phpElement : request.index.getAccessibleTypeMembers(typeScope, enclosingType)) {
                if (CancelSupport.getDefault().isCancelled()) {
                    return;
                }
                if (constantsFilter.isAccepted(phpElement)) {
                    TypeConstantElement constant = (TypeConstantElement) phpElement;
                    TypeConstantItem constantItem = PHPCompletionItem.TypeConstantItem.getItem(constant, request, true);
                    completionResult.add(constantItem);
                }
            }
        }

    }

    private void autoCompleteClassFields(final PHPCompletionResult completionResult, final PHPCompletionItem.CompletionRequest request) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        TokenHierarchy<?> th = request.info.getSnapshot().getTokenHierarchy();
        TokenSequence<PHPTokenId> tokenSequence = LexUtilities.getPHPTokenSequence(th, request.anchor);
        Model model = request.result.getModel();
        Collection<? extends TypeScope> types = ModelUtils.resolveTypeAfterReferenceToken(model, tokenSequence, request.anchor, false);
        final ElementFilter fieldsFilter = ElementFilter.allOf(
                ElementFilter.forKind(PhpElementKind.FIELD),
                ElementFilter.forName(NameKind.caseInsensitivePrefix(request.prefix)),
                ElementFilter.forInstanceOf(FieldElement.class));
        if (types != null) {
            TypeElement enclosingType = getEnclosingType(request, types);
            for (TypeScope typeScope : types) {
                if (CancelSupport.getDefault().isCancelled()) {
                    return;
                }
                for (final PhpElement phpElement : request.index.getAccessibleTypeMembers(typeScope, enclosingType)) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return;
                    }
                    if (fieldsFilter.isAccepted(phpElement)) {
                        FieldElement field = (FieldElement) phpElement;
                        FieldItem fieldItem = PHPCompletionItem.FieldItem.getItem(field, request);
                        completionResult.add(fieldItem);
                    }
                }
            }
        }
    }

    @CheckForNull
    private TypeElement getEnclosingType(CompletionRequest request, Collection<? extends TypeScope> types) {
        final EnclosingType enclosingType = findEnclosingType(request.info, lexerToASTOffset(request.result, request.anchor));
        final String enclosingTypeName = enclosingType != null ? enclosingType.extractTypeName() : null;
        NamespaceScope namespaceScope = ModelUtils.getNamespaceScope(request.result.getModel().getFileScope(), request.anchor);
        final String enclosingFQTypeName = VariousUtils.qualifyTypeNames(enclosingTypeName, request.anchor, namespaceScope);
        final NameKind enclosingTypeNameKind = (enclosingFQTypeName != null && !enclosingFQTypeName.trim().isEmpty()) ? NameKind.exact(enclosingFQTypeName) : null;
        Set<FileObject> preferedFileObjects = new HashSet<>();
        Set<TypeElement> enclosingTypes = null;
        FileObject currentFile = request.result.getSnapshot().getSource().getFileObject();
        if (currentFile != null) {
            preferedFileObjects.add(currentFile);
        }
        for (TypeScope typeScope : types) {
            final FileObject fileObject = typeScope.getFileObject();
            if (fileObject != null) {
                preferedFileObjects.add(fileObject);
            }
            if (enclosingTypeNameKind != null && enclosingTypes == null) {
                if (enclosingTypeNameKind.matchesName(typeScope)) {
                    enclosingTypes = Collections.<TypeElement>singleton((TypeElement) typeScope);
                }
            }
        }
        if (enclosingTypeNameKind != null && enclosingTypes == null) {
            final ElementFilter forFiles = ElementFilter.forFiles(preferedFileObjects.toArray(new FileObject[preferedFileObjects.size()]));
            Set<TypeElement> indexTypes = forFiles.prefer(request.index.getTypes(enclosingTypeNameKind));
            if (!indexTypes.isEmpty()) {
                enclosingTypes = new HashSet<>(indexTypes);
            }
        }
        return (enclosingTypes == null || enclosingTypes.isEmpty()) ? null : enclosingTypes.iterator().next();
    }

    private static boolean isNullableType(ParserResult info, int caretOffset) {
            TokenHierarchy<?> th = info.getSnapshot().getTokenHierarchy();
            TokenSequence<PHPTokenId> tokenSequence = th.tokenSequence(PHPTokenId.language());
        assert tokenSequence != null;
        tokenSequence.move(caretOffset);
        if (tokenSequence.movePrevious()) {
            Token<? extends PHPTokenId> previousToken = LexUtilities.findPrevious(tokenSequence, Arrays.asList(PHPTokenId.WHITESPACE, PHPTokenId.PHP_STRING));
            if (previousToken.id() == PHPTokenId.PHP_TOKEN && TokenUtilities.textEquals(previousToken.text(), "?")) { // NOI18N
                return true;
            }
        }
        return false;
    }

    private static boolean isUnionType(ParserResult info, int caretOffset) {
            TokenHierarchy<?> th = info.getSnapshot().getTokenHierarchy();
            TokenSequence<PHPTokenId> tokenSequence = th.tokenSequence(PHPTokenId.language());
        assert tokenSequence != null;
        tokenSequence.move(caretOffset);
        if (tokenSequence.movePrevious()) {
            Token<? extends PHPTokenId> previousToken = LexUtilities.findPrevious(tokenSequence, VALID_UNION_TYPE_TOKENS);
            if (previousToken.id() == PHPTokenId.PHP_OPERATOR && TokenUtilities.textEquals(previousToken.text(), Type.SEPARATOR)) {
                return true;
            }
        }
        return false;
    }

    private static boolean isInType(CompletionRequest request) {
        return findEnclosingType(request.info, lexerToASTOffset(request.result, request.anchor)) != null;
    }

    @CheckForNull
    private static EnclosingType findEnclosingType(ParserResult info, int offset) {
        List<ASTNode> nodes = NavUtils.underCaret(info, offset);
        for (int i = nodes.size() - 1; i >= 0; i--) {
            ASTNode node = nodes.get(i);
            if (node instanceof TypeDeclaration
                    && node.getEndOffset() > offset) {
                return EnclosingType.forTypeDeclaration((TypeDeclaration) node);
            }
            if (node instanceof ClassInstanceCreation
                    && node.getEndOffset() > offset) {
                ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) node;
                if (classInstanceCreation.isAnonymous()) {
                    Block body = classInstanceCreation.getBody();
                    if (body != null
                            && body.getStartOffset() <= offset
                            && body.getEndOffset() >= offset) {
                        return EnclosingType.forClassInstanceCreation(classInstanceCreation);
                    }
                }
            }
        }
        return null;
    }

    @CheckForNull
    private static EnclosingClass findEnclosingClass(ParserResult info, int offset) {
        List<ASTNode> nodes = NavUtils.underCaret(info, offset);
        for (int i = nodes.size() - 1; i >= 0; i--) {
            ASTNode node = nodes.get(i);
            if (node instanceof ClassDeclaration
                    && node.getEndOffset() > offset) {
                return EnclosingClass.forClassDeclaration((ClassDeclaration) node);
            }
            if (node instanceof ClassInstanceCreation
                    && node.getEndOffset() > offset) {
                ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) node;
                if (classInstanceCreation.isAnonymous()) {
                    Block body = classInstanceCreation.getBody();
                    if (body != null
                            && body.getStartOffset() <= offset
                            && body.getEndOffset() >= offset) {
                        return EnclosingClass.forClassInstanceCreation((ClassInstanceCreation) node);
                    }
                }
            }
        }
        return null;
    }

    private void autoCompleteExpression(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        autoCompleteNamespaces(completionResult, request);
        List<String> defaultKeywords = new ArrayList<>(PHP_KEYWORDS.keySet());
        defaultKeywords.remove("default =>"); // NOI18N
        autoCompleteExpression(completionResult, request, defaultKeywords);
    }

    private void autoCompleteExpression(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request, List<String> keywords) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        // KEYWORDS
        for (String keyword : keywords) {
            if (startsWith(keyword, request.prefix)) {
                completionResult.add(new PHPCompletionItem.KeywordItem(keyword, request));
            }
        }

        for (String keyword : PHP_LANGUAGE_CONSTRUCTS_WITH_QUOTES) {
            if (startsWith(keyword, request.prefix)) {
                completionResult.add(new PHPCompletionItem.LanguageConstructWithQuotesItem(keyword, request));
            }
        }

        for (String construct : PHP_LANGUAGE_CONSTRUCTS_WITH_PARENTHESES) {
            if (startsWith(construct, request.prefix)) {
                completionResult.add(new PHPCompletionItem.LanguageConstructWithParenthesesItem(construct, request));
            }
        }

        for (String construct : PHP_LANGUAGE_CONSTRUCTS_WITH_SEMICOLON) {
            if (startsWith(construct, request.prefix)) {
                completionResult.add(new PHPCompletionItem.LanguageConstructWithSemicolonItem(construct, request));
            }
        }

        final boolean offerGlobalVariables = OptionsUtils.codeCompletionVariablesScope().equals(VariablesScope.ALL);
        final boolean isCamelCase = isCamelCaseForTypeNames(request.prefix);
        final NameKind prefix = NameKind.create(request.prefix,
                isCamelCase ? Kind.CAMEL_CASE : Kind.CASE_INSENSITIVE_PREFIX);

        final Set<VariableElement> globalVariables = new HashSet<>();

        Model model = request.result.getModel();
        Set<AliasedName> aliasedNames = ModelUtils.getAliasedNames(model, request.anchor);

        for (final PhpElement element : request.index.getTopLevelElements(prefix, aliasedNames, Trait.ALIAS)) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            if (element instanceof FunctionElement) {
                FunctionElement functionElement = (FunctionElement) element;
                if (!functionElement.isAnonymous()) {
                    for (final PHPCompletionItem.FunctionElementItem functionItem
                            : PHPCompletionItem.FunctionElementItem.getItems(functionElement, request)) {
                        completionResult.add(functionItem);
                    }
                }
            } else if (element instanceof ClassElement) {
                ClassElement classElement = (ClassElement) element;
                if (!classElement.isAnonymous()) {
                    completionResult.add(new PHPCompletionItem.ClassItem(classElement, request, true, null));
                }
            } else if (element instanceof InterfaceElement) {
                completionResult.add(new PHPCompletionItem.InterfaceItem((InterfaceElement) element, request, true));
            } else if (offerGlobalVariables && element instanceof VariableElement) {
                globalVariables.add((VariableElement) element);
            } else if (element instanceof ConstantElement) {
                completionResult.add(new PHPCompletionItem.ConstantItem((ConstantElement) element, request));
            }
        }
        FileObject fileObject = request.result.getSnapshot().getSource().getFileObject();
        final ElementFilter forCurrentFile = ElementFilter.forFiles(fileObject);
        completionResult.addAll(getVariableProposals(request, forCurrentFile.reverseFilter(globalVariables)));

        // Special keywords applicable only inside a class or trait
        final EnclosingType enclosingType = findEnclosingType(request.info, lexerToASTOffset(request.result, request.anchor));
        if (enclosingType != null
                && (enclosingType.isClassDeclaration() || enclosingType.isTraitDeclaration())) {
            final String typeName = enclosingType.extractTypeName();
            if (typeName != null) {
                for (final String keyword : PHP_CLASS_KEYWORDS) {
                    if (startsWith(keyword, request.prefix)) {
                        completionResult.add(new PHPCompletionItem.ClassScopeKeywordItem(typeName, keyword, request));
                    }
                }
                // NETBEANS-1855
                autoCompleteClassMembers(completionResult, request, false, true);
            }
        }
    }

    private void autoCompleteGlobals(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request) {
        if (CancelSupport.getDefault().isCancelled()) {
            return;
        }
        if (OptionsUtils.codeCompletionVariablesScope().equals(VariablesScope.ALL)) {
            final CaseInsensitivePrefix prefix = NameKind.caseInsensitivePrefix(QualifiedName.create(request.prefix));
            for (VariableElement variableElement : request.index.getTopLevelVariables(prefix)) {
                if (CancelSupport.getDefault().isCancelled()) {
                    return;
                }
                completionResult.add(new PHPCompletionItem.VariableItem(variableElement, request));
            }
        }
    }

    private void autoCompleteConstants(final PHPCompletionResult completionResult, PHPCompletionItem.CompletionRequest request) {
        final boolean isCamelCase = isCamelCaseForTypeNames(request.prefix);
        final NameKind prefix = NameKind.create(request.prefix,
                isCamelCase ? Kind.CAMEL_CASE : Kind.CASE_INSENSITIVE_PREFIX);
        Model model = request.result.getModel();
        Set<AliasedName> aliasedNames = ModelUtils.getAliasedNames(model, request.anchor);
        for (final ConstantElement element : request.index.getConstants(prefix, aliasedNames, Trait.ALIAS)) {
            if (CancelSupport.getDefault().isCancelled()) {
                return;
            }
            completionResult.add(new PHPCompletionItem.ConstantItem((ConstantElement) element, request));
        }
    }

    /**
     * @param globalVariables (can be bull) if null then will be looked up in
     * index
     */
    private Collection<CompletionProposal> getVariableProposals(final CompletionRequest request, Set<VariableElement> globalVariables) {
        if (CancelSupport.getDefault().isCancelled()) {
            return Collections.emptyList();
        }
        final Map<String, CompletionProposal> proposals = new LinkedHashMap<>();
        Model model = request.result.getModel();
        VariableScope variableScope = model.getVariableScope(request.anchor);
        if (variableScope != null) {
            if (variableScope instanceof NamespaceScope
                    || variableScope instanceof ArrowFunctionScope) {
                if (globalVariables == null) {
                    FileObject fileObject = request.result.getSnapshot().getSource().getFileObject();
                    final ElementFilter forCurrentFile = ElementFilter.forFiles(fileObject);
                    globalVariables = forCurrentFile.reverseFilter(request.index.getTopLevelVariables(NameKind.caseInsensitivePrefix(QualifiedName.create(request.prefix))));
                }

                for (final VariableElement globalVariable : globalVariables) {
                    if (CancelSupport.getDefault().isCancelled()) {
                        return Collections.emptyList();
                    }
                    proposals.put(globalVariable.getName(), new PHPCompletionItem.VariableItem(globalVariable, request));
                }
            }

            List<VariableName> allDeclaredVariables = new ArrayList<>(variableScope.getDeclaredVariables());
            // for nested arrow functions
            if (variableScope instanceof ArrowFunctionScope) {
                Scope inScope = variableScope.getInScope();
                while (inScope instanceof FunctionScope || inScope instanceof NamespaceScope) {
                    allDeclaredVariables.addAll(((VariableScope) inScope).getDeclaredVariables());
                    if (inScope instanceof FunctionScope
                            && !(inScope instanceof ArrowFunctionScope)) {
                        break;
                    }
                    inScope = inScope.getInScope();
                }
            }

            Collection<? extends VariableName> declaredVariables = ModelUtils.filter(allDeclaredVariables, nameKind, request.prefix);
            final int caretOffset = request.anchor + request.prefix.length();
            for (VariableName varName : declaredVariables) {
                if (CancelSupport.getDefault().isCancelled()) {
                    return Collections.emptyList();
                }
                final FileObject realFileObject = varName.getRealFileObject();
                if (realFileObject != null || varName.getNameRange().getEnd() < caretOffset) {
                    final String name = varName.getName();
                    String notDollaredName = name.startsWith("$") ? name.substring(1) : name;
                    if (PredefinedSymbols.SUPERGLOBALS.contains(notDollaredName)) {
                        continue;
                    }
                    if (varName.representsThis()) {
                        continue;
                    }
                    final Collection<? extends String> typeNames = varName.getTypeNames(request.anchor);
                    String typeName = typeNames.size() > 1 ? Type.MIXED : ModelUtils.getFirst(typeNames);
                    final Set<Pair<QualifiedName, Boolean>> qualifiedNames = typeName != null
                            ? Collections.singleton(Pair.of(QualifiedName.create(typeName), false))
                            : Collections.<Pair<QualifiedName, Boolean>>emptySet();
                    if (realFileObject != null) {
                        //#183928 -  Extend model to allow CTRL + click for 'view/action' variables
                        proposals.put(name, new PHPCompletionItem.VariableItem(
                                VariableElementImpl.create(name, 0, realFileObject,
                                varName.getElementQuery(), TypeResolverImpl.forNames(qualifiedNames), varName.isDeprecated()), request) {
                            @Override
                            public boolean isSmart() {
                                return true;
                            }
                        });
                    } else {
                        proposals.put(name, new PHPCompletionItem.VariableItem(
                                VariableElementImpl.create(name, 0, request.currentlyEditedFileURL,
                                varName.getElementQuery(), TypeResolverImpl.forNames(qualifiedNames), varName.isDeprecated()), request));
                    }
                }
            }

            for (final String name : PredefinedSymbols.SUPERGLOBALS) {
                if (isPrefix("$" + name, request.prefix)) { //NOI18N
                    proposals.put(name, new PHPCompletionItem.SuperGlobalItem(request, name));
                }
            }

        }
        return proposals.values();
    }

    private boolean isPrefix(String name, String prefix) {
        return name != null && (name.startsWith(prefix)
                || nameKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && name.toLowerCase().startsWith(prefix.toLowerCase()));
    }

    @Override
    public Documentation documentElement(ParserResult info, ElementHandle element, Callable<Boolean> cancel) {
        Documentation result;
        if (element instanceof ModelElement) {
            ModelElement mElem = (ModelElement) element;
            ModelElement parentElem = mElem.getInScope();
            FileObject fileObject = mElem.getFileObject();
            String fName = fileObject == null ? "?" : fileObject.getNameExt(); //NOI18N
            String tooltip;
            if (parentElem instanceof TypeScope) {
                tooltip = mElem.getPhpElementKind() + ": " + parentElem.getName() + "<b> " + mElem.getName() + " </b>" + "(" + fName + ")"; //NOI18N
            } else {
                tooltip = mElem.getPhpElementKind() + ":<b> " + mElem.getName() + " </b>" + "(" + fName + ")"; //NOI18N
            }
            result = Documentation.create(String.format("<div align=\"right\"><font size=-1>%s</font></div>", tooltip)); //NOI18N
        } else {
            result = ((element instanceof MethodElement) && ((MethodElement) element).isMagic()) ? null : DocRenderer.document(info, element);
        }
        return result;
    }

    @Override
    public String document(ParserResult info, ElementHandle element) {
        return null;
    }

    @Override
    public ElementHandle resolveLink(String link, ElementHandle originalHandle) {
        return null;
    }

    private static boolean isPHPIdentifierPart(char c) {
        return Character.isJavaIdentifierPart(c) || c == '@';
    }

    @org.netbeans.api.annotations.common.SuppressWarnings(value = "INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE", justification = "Not sure about FB analysis correctness")
    private String getPrefix(ParserResult info, int caretOffset, boolean upToOffset, PrefixBreaker prefixBreaker) {
        try {
            BaseDocument doc = (BaseDocument) info.getSnapshot().getSource().getDocument(false);
            if (doc == null) {
                return null;
            }
            int lineBegin = LineDocumentUtils.getLineStart(doc, caretOffset);
            if (lineBegin != -1) {
                int lineEnd = LineDocumentUtils.getLineEnd(doc, caretOffset);
                String line = doc.getText(lineBegin, lineEnd - lineBegin);
                int lineOffset = caretOffset - lineBegin;
                int start = lineOffset;
                if (lineOffset > 0) {
                    char c = 0;
                    for (int i = lineOffset - 1; i >= 0; i--) {
                        assert i >= 0 && i <= line.length() - 1 : "line:" + line + " | i:" + i + " | line.length():" + line.length() + " | lineBegin:" + lineBegin + " | lineEnd:" + lineEnd + " | caretOffset:" + caretOffset;
                        if (i >= 0 && i <= line.length() - 1) {
                            c = line.charAt(i);
                            if (!isPHPIdentifierPart(c) && c != '\\') {
                                break;
                            } else {
                                start = i;
                            }
                        }
                    }
                    if (start == lineOffset && c == '?'
                            && lineOffset - 2 >= 0 && line.charAt(lineOffset - 2) == '<') {
                        start -= 2;
                    }
                }

                // Find identifier end
                String prefix;
                if (upToOffset) {
                    prefix = line.substring(start, lineOffset);
                    int lastIndexOfDollar = prefix.lastIndexOf('$'); //NOI18N
                    if (lastIndexOfDollar > 0) {
                        prefix = prefix.substring(lastIndexOfDollar);
                    }
                } else {
                    if (lineOffset == line.length()) {
                        prefix = line.substring(start);
                    } else {
                        int n = line.length();
                        int end = lineOffset;
                        for (int j = lineOffset; j < n; j++) {
                            char d = line.charAt(j);
                            // Try to accept Foo::Bar as well
                            if (!isPHPIdentifierPart(d)) {
                                break;
                            } else {
                                end = j + 1;
                            }
                        }
                        prefix = line.substring(start, end);
                    }
                }

                if (prefix.length() > 0) {
                    if (prefix.endsWith("::")) {
                        return "";
                    }

                    if (prefix.endsWith(":") && prefix.length() > 1) {
                        return null;
                    }

                    // Strip out LHS if it's a qualified method, e.g.  Benchmark::measure -> measure
                    int q = prefix.lastIndexOf("::");

                    if (q != -1) {
                        prefix = prefix.substring(q + 2);
                    }

                    // The identifier chars identified by JsLanguage are a bit too permissive;
                    // they include things like "=", "!" and even "&" such that double-clicks will
                    // pick up the whole "token" the user is after. But "=" is only allowed at the
                    // end of identifiers for example.
                    if (prefix.length() == 1) {
                        char c = prefix.charAt(0);
                        if (prefixBreaker.isBreaker(c)) {
                            return null;
                        }
                    } else if (!"<?".equals(prefix)) {    //NOI18N
                        for (int i = prefix.length() - 1; i >= 0; i--) { // -2: the last position (-1) can legally be =, ! or ?

                            char c = prefix.charAt(i);
                            if (i == 0 && c == ':') {
                                // : is okay at the begining of prefixes
                            } else if (prefixBreaker.isBreaker(c)) {
                                prefix = prefix.substring(i + 1);
                                break;
                            }
                        }
                    }
                }

                if (prefix != null && prefix.startsWith("@")) { //NOI18N
                    final TokenHierarchy<?> tokenHierarchy = info.getSnapshot().getTokenHierarchy();
                    TokenSequence<PHPTokenId> tokenSequence = tokenHierarchy != null ? LexUtilities.getPHPTokenSequence(tokenHierarchy, caretOffset) : null;
                    if (tokenSequence != null) {
                        tokenSequence.move(caretOffset);
                        if (tokenSequence.moveNext() && tokenSequence.movePrevious()) {
                            Token<PHPTokenId> token = tokenSequence.token();
                            PHPTokenId id = token.id();
                            if (id.equals(PHPTokenId.PHP_STRING) || id.equals(PHPTokenId.PHP_TOKEN)) {
                                prefix = prefix.substring(1);
                            }
                        }
                    }
                }
                return prefix;
            }
            // Else: normal identifier: just return null and let the machinery do the rest
        } catch (BadLocationException ble) {
            //Exceptions.printStackTrace(ble);
        }

        return null;
    }

    @Override
    public String getPrefix(ParserResult info, int caretOffset, boolean upToOffset) {
        return getPrefix(info, caretOffset, upToOffset, PrefixBreaker.COMMON);
    }

    @Override
    public QueryType getAutoQuery(JTextComponent component, String typedText) {
        if (typedText.length() == 0) {
            return QueryType.NONE;
        }
        char lastChar = typedText.charAt(typedText.length() - 1);
        Document document = component.getDocument();
        //TokenHierarchy th = TokenHierarchy.get(document);
        int offset = component.getCaretPosition();
        TokenSequence<PHPTokenId> ts = LexUtilities.getPHPTokenSequence(document, offset);
        if (ts == null) {
            return QueryType.STOP;
        }
        int diff = ts.move(offset);
        if (diff > 0 && ts.moveNext() || ts.movePrevious()) {
            Token t = ts.token();
            if (t != null) {
                if (t.id() == PHPTokenId.T_INLINE_HTML) {
                    return QueryType.NONE;
                } else {
                    if (AUTOPOPUP_STOP_CHARS.contains(Character.valueOf(lastChar))) {
                        return QueryType.STOP;
                    }
                    if (OptionsUtils.autoCompletionTypes()) {
                        if (lastChar == ' ' || lastChar == '\t') {
                            if (ts.movePrevious()
                                    && TOKENS_TRIGGERING_AUTOPUP_TYPES_WS.contains(ts.token().id())) {

                                return QueryType.ALL_COMPLETION;
                            } else {
                                return QueryType.STOP;
                            }
                        }

                        if (t.id() == PHPTokenId.PHP_OBJECT_OPERATOR
                                || t.id() == PHPTokenId.PHP_NULLSAFE_OBJECT_OPERATOR
                                || t.id() == PHPTokenId.PHP_PAAMAYIM_NEKUDOTAYIM) {
                            return QueryType.ALL_COMPLETION;
                        }
                    }
                    if (OptionsUtils.autoCompletionVariables()) {
                        if ((t.id() == PHPTokenId.PHP_TOKEN && lastChar == '$')
                                || (t.id() == PHPTokenId.PHP_CONSTANT_ENCAPSED_STRING && lastChar == '$')) {
                            return QueryType.ALL_COMPLETION;
                        }
                    }
                    if (OptionsUtils.autoCompletionNamespaces()) {
                        if (t.id() == PHPTokenId.PHP_NS_SEPARATOR) {
                            return isPhp53OrNewer(document) ? QueryType.ALL_COMPLETION : QueryType.NONE;
                        }
                    }
                    if (t.id() == PHPTokenId.PHPDOC_COMMENT && lastChar == '@') {
                        return QueryType.ALL_COMPLETION;
                    }
                    if (OptionsUtils.autoCompletionFull()) {
                        TokenId id = t.id();
                        if ((id.equals(PHPTokenId.PHP_STRING) || id.equals(PHPTokenId.PHP_VARIABLE)) && t.length() > 0) {
                            return QueryType.ALL_COMPLETION;
                        }
                    }
                }
            }
        }
        return QueryType.NONE;
    }

    public static boolean isPhp53OrNewer(Document document) {
        final FileObject fileObject = CodeUtils.getFileObject(document);
        assert fileObject != null;
        return CodeUtils.isPhpVersionGreaterThan(fileObject, PhpVersion.PHP_5);
    }

    private static boolean isPhp74OrNewer(FileObject fileObject) {
        if (PHP_VERSION != null) {
            return PHP_VERSION.compareTo(PhpVersion.PHP_74) >= 0;
        }
        assert fileObject != null;
        return CodeUtils.isPhpVersionGreaterThan(fileObject, PhpVersion.PHP_73);
    }

    @Override
    public String resolveTemplateVariable(String variable, ParserResult info, int caretOffset, String name, Map parameters) {
        return null;
    }

    @Override
    public Set<String> getApplicableTemplates(Document doc, int selectionBegin, int selectionEnd) {
        return null;
    }

    @Override
    public ParameterInfo parameters(final ParserResult info, final int caretOffset, CompletionProposal proposal) {
        final org.netbeans.modules.php.editor.model.Model model = ((PHPParseResult) info).getModel();
        ParameterInfoSupport infoSupport = model.getParameterInfoSupport(caretOffset);
        ParameterInfo parameterInfo = infoSupport.getParameterInfo();
        return parameterInfo == null ? ParameterInfo.NONE : parameterInfo;
    }

    private boolean startsWith(String theString, String prefix) {
        if (prefix.length() == 0) {
            return true;
        }

        return caseSensitive ? theString.startsWith(prefix)
                : theString.toLowerCase().startsWith(prefix.toLowerCase());
    }

    private int findBaseNamespaceEnd(ParserResult info, int caretOffset) {
        TokenHierarchy<?> th = info.getSnapshot().getTokenHierarchy();
        assert th != null;
        TokenSequence<PHPTokenId> tokenSequence = LexUtilities.getPHPTokenSequence(th, caretOffset);
        assert tokenSequence != null;
        tokenSequence.move(caretOffset);
        final boolean moveNextSucces = tokenSequence.moveNext();
        if (!moveNextSucces && !tokenSequence.movePrevious()) {
            assert false;
            return caretOffset;
        }
        boolean hasCurly = false;
        while (tokenSequence.movePrevious()) {
            if (!hasCurly) {
                if (tokenSequence.token().id() == PHPTokenId.PHP_CURLY_OPEN) {
                    hasCurly = true;
                }
            } else {
                // possibly some whitespace before curly open?
                if (tokenSequence.token().id() != PHPTokenId.WHITESPACE) {
                    tokenSequence.moveNext();
                    break;
                }
            }
        }
        if (hasCurly) {
            return tokenSequence.offset();
        }
        assert false;
        return caretOffset;
    }


    private static class StaticOrInstanceMembersFilter extends ElementFilter {

        private final boolean forStaticContext;
        private final boolean forInstanceContext;
        private final boolean forSelfContext;
        private final boolean staticAllowed;
        private final boolean nonstaticAllowed;
        private final boolean forStaticLateBinding;

        public StaticOrInstanceMembersFilter(final boolean forStaticContext, final boolean forInstanceContext,
                final boolean forSelfContext, final boolean forStaticLateBinding) {
            this.forStaticContext = forStaticContext;
            this.forInstanceContext = forInstanceContext;
            this.forSelfContext = forSelfContext;
            this.forStaticLateBinding = forStaticLateBinding;
            this.staticAllowed = OptionsUtils.codeCompletionStaticMethods();
            this.nonstaticAllowed = OptionsUtils.codeCompletionNonStaticMethods();
        }

        @Override
        public boolean isAccepted(final PhpElement element) {
            if (forSelfContext && isAcceptedForSelfContext(element)) {
                return true;
            }
            if (forStaticContext && isAcceptedForStaticContext(element)) {
                return true;
            }
            if (forInstanceContext && isAcceptedForNotStaticContext(element)) {
                return true;
            }
            return false;
        }

        private boolean isAcceptedForNotStaticContext(final PhpElement element) {
            final boolean isStatic = element.getPhpModifiers().isStatic();
            return !isStatic || (staticAllowed && element.getPhpElementKind().equals(PhpElementKind.METHOD));
        }

        private boolean isAcceptedForStaticContext(final PhpElement element) {
            final boolean isStatic = element.getPhpModifiers().isStatic();
            return isStatic || (nonstaticAllowed && !forStaticLateBinding && element.getPhpElementKind().equals(PhpElementKind.METHOD));
        }

        private boolean isAcceptedForSelfContext(final PhpElement element) {
            return forSelfContext && nonstaticAllowed && !element.getPhpElementKind().equals(PhpElementKind.FIELD);
        }
    }

    private interface PrefixBreaker {
        PrefixBreaker COMMON = new PrefixBreaker() {

            @Override
            public boolean isBreaker(char c) {
                return !(isPHPIdentifierPart(c) || c == ':');
            }
        };

        PrefixBreaker WITH_NS_PARTS = new PrefixBreaker() {

            @Override
            public boolean isBreaker(char c) {
                return !(isPHPIdentifierPart(c) || c == '\\' || c == ':');
            }
        };

        boolean isBreaker(char c);
    }

    private static boolean isCamelCaseForTypeNames(final String query) {
        return false;
    }

    private interface EnclosingType {

        boolean isClassDeclaration();

        boolean isTraitDeclaration();

        String extractTypeName();

        //~ Factories

        static EnclosingType forTypeDeclaration(final TypeDeclaration typeDeclaration) {
            return new EnclosingType() {
                @Override
                public boolean isClassDeclaration() {
                    return typeDeclaration instanceof ClassDeclaration;
                }

                @Override
                public boolean isTraitDeclaration() {
                    return typeDeclaration instanceof TraitDeclaration;
                }

                @Override
                public String extractTypeName() {
                    return CodeUtils.extractTypeName(typeDeclaration);
                }
            };
        }

        static EnclosingType forClassInstanceCreation(final ClassInstanceCreation classInstanceCreation) {
            assert classInstanceCreation.isAnonymous() : classInstanceCreation;
            return new EnclosingType() {
                @Override
                public boolean isClassDeclaration() {
                    return true;
                }

                @Override
                public boolean isTraitDeclaration() {
                    return false;
                }

                @Override
                public String extractTypeName() {
                    return CodeUtils.extractClassName(classInstanceCreation);
                }
            };
        }

    }

    private interface EnclosingClass {

        String getClassName();

        Expression getSuperClass();

        List<Expression> getInterfaces();

        String extractClassName();

        String extractUnqualifiedSuperClassName();

        //~ Factories

        static EnclosingClass forClassDeclaration(final ClassDeclaration classDeclaration) {
            return new EnclosingClass() {
                @Override
                public String getClassName() {
                    return classDeclaration.getName().getName();
                }

                @Override
                public Expression getSuperClass() {
                    return classDeclaration.getSuperClass();
                }

                @Override
                public List<Expression> getInterfaces() {
                    return classDeclaration.getInterfaes();
                }

                @Override
                public String extractClassName() {
                    return CodeUtils.extractClassName(classDeclaration);
                }

                @Override
                public String extractUnqualifiedSuperClassName() {
                    return CodeUtils.extractUnqualifiedSuperClassName(classDeclaration);
                }
            };
        }

        static EnclosingClass forClassInstanceCreation(final ClassInstanceCreation classInstanceCreation) {
            assert classInstanceCreation.isAnonymous() : classInstanceCreation;
            return new EnclosingClass() {
                @Override
                public String getClassName() {
                    return CodeUtils.extractClassName(classInstanceCreation);
                }

                @Override
                public Expression getSuperClass() {
                    return classInstanceCreation.getSuperClass();
                }

                @Override
                public List<Expression> getInterfaces() {
                    return classInstanceCreation.getInterfaces();
                }

                @Override
                public String extractClassName() {
                    return CodeUtils.extractClassName(classInstanceCreation);
                }

                @Override
                public String extractUnqualifiedSuperClassName() {
                    return CodeUtils.extractUnqualifiedSuperClassName(classInstanceCreation);
                }
            };
        }

    }

}
