/*
 * 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 parentContext = false;
            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;
                parentContext = 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, parentContext)
                            : 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 parentContext = false;
                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;
                    parentContext = 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, true);
                    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;
        private final boolean forParentContext;

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

        @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();
            if (forParentContext
                    && !isStatic
                    && element.getPhpElementKind().equals(PhpElementKind.FIELD)) {
                // parent::fieldName is invalid
                // this is constant
                return false;
            }
            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);
                }
            };
        }

    }

}
