 /*
 * 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.javascript2.model;


import org.netbeans.modules.javascript2.model.spi.PathNodeVisitor;
import org.netbeans.modules.javascript2.model.api.ModelUtils;
import com.oracle.js.parser.Token;
import com.oracle.js.parser.ir.AccessNode;
import com.oracle.js.parser.ir.BinaryNode;
import com.oracle.js.parser.ir.Block;
import com.oracle.js.parser.ir.BlockStatement;
import com.oracle.js.parser.ir.CallNode;
import com.oracle.js.parser.ir.CatchNode;
import com.oracle.js.parser.ir.ClassNode;
import com.oracle.js.parser.ir.ExpressionStatement;
import com.oracle.js.parser.ir.ForNode;
import com.oracle.js.parser.ir.FunctionNode;
import com.oracle.js.parser.ir.IdentNode;
import com.oracle.js.parser.ir.IndexNode;
import com.oracle.js.parser.ir.JoinPredecessorExpression;
import com.oracle.js.parser.ir.LabelNode;
import com.oracle.js.parser.ir.LexicalContext;
import com.oracle.js.parser.ir.LiteralNode;
import com.oracle.js.parser.ir.Node;
import com.oracle.js.parser.ir.ObjectNode;
import com.oracle.js.parser.ir.PropertyNode;
import com.oracle.js.parser.ir.ReturnNode;
import com.oracle.js.parser.ir.Statement;
import com.oracle.js.parser.ir.Symbol;
import com.oracle.js.parser.ir.TernaryNode;
import com.oracle.js.parser.ir.TryNode;
import com.oracle.js.parser.ir.UnaryNode;
import com.oracle.js.parser.ir.VarNode;
import com.oracle.js.parser.ir.WithNode;
import com.oracle.js.parser.ir.visitor.NodeVisitor;
import com.oracle.js.parser.TokenType;
import com.oracle.js.parser.ir.ExportClauseNode;
import com.oracle.js.parser.ir.ExportNode;
import com.oracle.js.parser.ir.ExportSpecifierNode;
import com.oracle.js.parser.ir.Expression;
import com.oracle.js.parser.ir.FromNode;
import com.oracle.js.parser.ir.ImportClauseNode;
import com.oracle.js.parser.ir.ImportNode;
import com.oracle.js.parser.ir.ImportSpecifierNode;
import com.oracle.js.parser.ir.NameSpaceImportNode;
import com.oracle.js.parser.ir.NamedImportsNode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.csl.api.Documentation;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.csl.api.Modifier;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.javascript2.doc.api.JsDocumentationSupport;
import org.netbeans.modules.javascript2.lexer.api.JsTokenId;
import org.netbeans.modules.javascript2.doc.spi.DocParameter;
import org.netbeans.modules.javascript2.doc.spi.JsComment;
import org.netbeans.modules.javascript2.doc.spi.JsDocumentationHolder;
import org.netbeans.modules.javascript2.doc.spi.JsModifier;
import org.netbeans.modules.javascript2.types.api.DeclarationScope;
import org.netbeans.modules.javascript2.types.api.Identifier;
import org.netbeans.modules.javascript2.types.api.Type;
import org.netbeans.modules.javascript2.types.api.TypeUsage;
import static org.netbeans.modules.javascript2.model.ModelElementFactory.create;
import org.netbeans.modules.javascript2.model.api.JsArray;
import org.netbeans.modules.javascript2.model.api.JsElement;
import org.netbeans.modules.javascript2.model.api.JsFunction;
import org.netbeans.modules.javascript2.model.api.JsObject;
import org.netbeans.modules.javascript2.model.api.JsWith;
import org.netbeans.modules.javascript2.model.api.Model;
import org.netbeans.modules.javascript2.model.api.Occurrence;
import org.netbeans.modules.javascript2.model.spi.FunctionArgument;
import org.netbeans.modules.javascript2.model.spi.FunctionInterceptor;
import org.netbeans.modules.javascript2.types.spi.ParserResult;
import org.openide.filesystems.FileObject;
import org.openide.util.lookup.ServiceProvider;

/**
 *
 * @author Petr Pisl
 */
public class ModelVisitor extends PathNodeVisitor implements ModelResolver {

    private static final Logger LOGGER = Logger.getLogger(ModelVisitor.class.getName());
    private static final boolean log = true;
    
    private final ModelBuilder modelBuilder;
    private final OccurrenceBuilder occurrenceBuilder;
    /**
     * Keeps the name of the visited properties
     */
    private final ParserResult parserResult;

    // keeps objects that are created as arguments of a function call
    private final Stack<Collection<JsObjectImpl>> functionArgumentStack = new Stack<Collection<JsObjectImpl>>();
    private Map<FunctionInterceptor, Collection<FunctionCall>> functionCalls = null;
    private final String scriptName;
    private LexicalContext lc;

    private final static String BLOCK_OBJECT_NAME_PREFIX = "block-"; //NOI18N

    public ModelVisitor(ParserResult parserResult, OccurrenceBuilder occurrenceBuilder) {
        super();
        FileObject fileObject = parserResult.getSnapshot().getSource().getFileObject();
        this.modelBuilder = new ModelBuilder(JsFunctionImpl.createGlobal(
                fileObject, Integer.MAX_VALUE, parserResult.getSnapshot().getMimeType()));
        this.occurrenceBuilder = occurrenceBuilder;
        this.parserResult = parserResult; 
        this.scriptName = fileObject != null ? fileObject.getName().replace('.', '_') : "";
        lc = getLexicalContext();
    }

    @Override
    public void init() {
        final FunctionNode root = parserResult.getLookup().lookup(FunctionNode.class);
        if (root != null) {
            root.accept(this);
        }
    }

    public JsObject getGlobalObject() {
        return modelBuilder.getGlobal();
    }

    @Override
    public void processCalls(
            org.netbeans.modules.javascript2.model.spi.ModelElementFactory elementFactory,
            Map<String, Map<Integer, List<TypeUsage>>> returnTypesFromFrameworks) {
        final Map<FunctionInterceptor, Collection<ModelVisitor.FunctionCall>> calls = getCallsForProcessing();
        if (calls != null && !calls.isEmpty()) {
            for (Map.Entry<FunctionInterceptor, Collection<ModelVisitor.FunctionCall>> entry : calls.entrySet()) {
                Collection<ModelVisitor.FunctionCall> fncCalls = entry.getValue();
                if (fncCalls != null && !fncCalls.isEmpty()) {
                    for (ModelVisitor.FunctionCall call : fncCalls) {
                        Collection<TypeUsage> returnTypes = entry.getKey().intercept(parserResult.getSnapshot(), call.getName(),
                                getGlobalObject(), call.getScope(), elementFactory, call.getArguments());
                        if (returnTypes != null) {
                            Map<Integer, List<TypeUsage>> functionCalls = returnTypesFromFrameworks.get(call.getName());
                            if (functionCalls == null) {
                                functionCalls = new HashMap<Integer, List<TypeUsage>>();
                                returnTypesFromFrameworks.put(call.getName(), functionCalls);
                            }
                            List<TypeUsage> types = functionCalls.get(call.getCallOffset());
                            if (types == null) {
                                types = new ArrayList<>();
                                functionCalls.put(new Integer(call.getCallOffset()), types);
                            }
                            for (TypeUsage type: returnTypes) {
                                if (!types.contains(type)) {
                                    types.add(type);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public List<Identifier> getASTNodeName(final Object astNode) {
        if (astNode instanceof Node) {
            return getNodeName((Node)astNode, parserResult);
        }
        return Collections.emptyList();
    }


    @Override
    public boolean enterAccessNode(AccessNode accessNode) {
        BinaryNode node = getPath().get(getPath().size() - 1) instanceof BinaryNode
                ? (BinaryNode)getPath().get(getPath().size() - 1) : null;
        if (!(node != null && node.tokenType() == TokenType.ASSIGN)) {
            if (accessNode.getBase() instanceof IdentNode && ModelUtils.THIS.equals(((IdentNode)accessNode.getBase()).getName())) { //NOI18N
                String iNode = accessNode.getProperty();
                JsObject current = modelBuilder.getCurrentDeclarationFunction();
                JsObject property = current.getProperty(iNode);
                if (property == null && current.getParent() != null && (current.getParent().getJSKind() == JsElement.Kind.CONSTRUCTOR
                        || current.getParent().getJSKind() == JsElement.Kind.OBJECT)) {
                    current = current.getParent();
                    property = current.getProperty(iNode);
                    if (property == null && ModelUtils.PROTOTYPE.equals(current.getName())) {
                        current = current.getParent();
                        property = current.getProperty(iNode);
                    }
                }
                if (property == null && current.getParent() == null) {
                    // probably we are in global space and there is used this
                    property = modelBuilder.getGlobal().getProperty(iNode);
                }
                if (property != null && !property.getModifiers().contains(Modifier.PRIVATE)) {
                    // we don't want to add occurrences for cases like var buf = this.buf. See issue #267694
                    ((JsObjectImpl)property).addOccurrence(new OffsetRange(accessNode.getFinish() - iNode.length(), accessNode.getFinish()));
                }
            }
        }
        return super.enterAccessNode(accessNode);
    }

    @Override
    public Node leaveAccessNode(AccessNode accessNode) {
        createJsObject(accessNode, parserResult, modelBuilder);
        return super.leaveAccessNode(accessNode);
    }

    @Override
    public boolean enterBlock(Block block) {
        DeclarationScopeImpl blockScope = (DeclarationScopeImpl)modelBuilder.getCurrentDeclarationScope().getProperty(BLOCK_OBJECT_NAME_PREFIX + block.getStart());
        if ( blockScope!= null) {
            // in this block there are a declarations that we are interested in. 
            modelBuilder.setCurrentObject(blockScope);
        }
        return super.enterBlock(block); 
    }

    @Override
    public Node leaveBlock(Block block) {
        DeclarationScopeImpl currentScope = modelBuilder.getCurrentDeclarationScope();
        if (currentScope.getJSKind() == JsElement.Kind.BLOCK && currentScope.getName().equals(BLOCK_OBJECT_NAME_PREFIX + block.getStart())) {
            // removing the block as declaration scope from 
            modelBuilder.reset();
        }
        return super.leaveBlock(block); 
    }
    
    @Override
    public boolean enterBinaryNode(BinaryNode binaryNode) {
        Node lhs = binaryNode.lhs();
        Node rhs = binaryNode.rhs();
        if (lhs instanceof LiteralNode.ArrayLiteralNode && binaryNode.tokenType() == TokenType.ASSIGN) {
            // case of destructuring assgnment like [a,b] = ....
            LiteralNode.ArrayLiteralNode lan = (LiteralNode.ArrayLiteralNode)lhs;
            if (rhs instanceof LiteralNode.ArrayLiteralNode) {
                // case [a, b] = [1, 2]
                LiteralNode.ArrayLiteralNode ran = (LiteralNode.ArrayLiteralNode)rhs;
                List<Expression> lExpressions = lan.getElementExpressions();
                List<Expression> rExpressions = ran.getElementExpressions();
                for (int i = 0; i < lExpressions.size(); i++) {
                    Expression lExpression = lExpressions.get(i);
                    if (i < rExpressions.size()) {
                        Expression rExpression = rExpressions.get(i);
                        processBinaryNode(lExpression, rExpression, TokenType.ASSIGN);
                    } else {
                        break;
                    }
                }
            } else {
                // other cases
                rhs.accept(this);
            }
        } else if (lhs instanceof ObjectNode && binaryNode.tokenType() == TokenType.ASSIGN) {
            // cases {a, b} = ...
            ObjectNode lObjectNode = (ObjectNode)lhs;
            JsObjectImpl rObject = null;
            
            // prepare variables that are available in the current scope for later usage
            DeclarationScopeImpl scope = modelBuilder.getCurrentDeclarationScope();
            Collection<? extends JsObject> variables = ModelUtils.getVariables(scope);
                
            if (rhs instanceof ObjectNode) {
                // case {a, b} = {a:1, b:2}
                // the rhs object we have to put to the model as anonymous object. At least will be colored in the right way
                ObjectNode rObjectNode = (ObjectNode)rhs;
                rObject = ModelElementFactory.createAnonymousObject(parserResult, rObjectNode,  modelBuilder);
                modelBuilder.setCurrentObject(rObject);
                rObject.setJsKind(JsElement.Kind.OBJECT_LITERAL);
                if (!functionArgumentStack.isEmpty()) {
                    functionArgumentStack.peek().add(rObject);
                }
                for (PropertyNode rPropertyNode : rObjectNode.getElements()) {
                    rPropertyNode.accept(this);
                }
                modelBuilder.reset();
            } else {
                rhs.accept(this);
                if (rhs instanceof IdentNode) {
                    // we will try to find the right object literal        
                    rObject = (JsObjectImpl)ModelUtils.getScopeVariable(scope, ((IdentNode)rhs).getName());
                }
            }
            if (rObject != null) {
                // find variables that are mentioned on the left site and assign the types from
                // property with the same name from the right site
                for (PropertyNode lPropertyNode : lObjectNode.getElements()) {
                    String variableName = null;
                    if (isKeyAndValueEquals(lPropertyNode)) {
                        // case {p:var1, q:var2} = {p:1, q:2} or {p:var1, q:var2} = objectLiteral
                        variableName = lPropertyNode.getKeyName();
                        lPropertyNode.accept(this);
                    } else if (lPropertyNode.getValue() instanceof IdentNode) {
                        variableName = ((IdentNode)lPropertyNode.getValue()).getName();
                    } else if (lPropertyNode.getValue() instanceof BinaryNode) {
                        BinaryNode bNode = (BinaryNode)lPropertyNode.getValue();
                        if (bNode.tokenType() == TokenType.ASSIGN && bNode.lhs() instanceof IdentNode) {
                            // the default parameter {a=10, b=20} = ....
                            variableName = ((IdentNode)bNode.lhs()).getName();
                        }
                    }
                    if (variableName != null) {
                        JsObject variable = ModelUtils.getScopeVariable(scope, variableName);
                        JsObject rProperty = rObject.getProperty(lPropertyNode.getKeyName());
                        if (variable != null && rProperty != null) {
                            // copy types from the properties
                            for (TypeUsage assignment : rProperty.getAssignments()){
                                variable.addAssignment(assignment, rProperty.getOffset());
                            }
                            if (!isKeyAndValueEquals(lPropertyNode)) {
                                // mark occurrences in case {p:var1, q:var2} = {p:1, q:2} or {p:var1, q:var2} = objectLiteral
                                rProperty.addOccurrence(new OffsetRange(lPropertyNode.getStart(), lPropertyNode.getStart() + lPropertyNode.getKeyName().length()));
                            }
                        }
                    }
                }
                return false;
            }
        }else {
            processBinaryNode(lhs, rhs, binaryNode.tokenType());
        }
        return super.enterBinaryNode(binaryNode);
    }

    private boolean isKeyAndValueEquals(PropertyNode pNode) {
        if (pNode.getKey() instanceof IdentNode && pNode.getValue() instanceof IdentNode) {
            IdentNode key = (IdentNode)pNode.getKey();
            IdentNode value = (IdentNode)pNode.getValue();
            return key.getName().equals(value.getName()) && key.getStart() == value.getStart();
        }
        if (pNode.getKey() instanceof IdentNode && pNode.getValue() instanceof BinaryNode 
                && ((BinaryNode)pNode.getValue()).tokenType() == TokenType.ASSIGN && ((BinaryNode)pNode.getValue()).lhs() instanceof IdentNode) {
            IdentNode key = (IdentNode)pNode.getKey();
            IdentNode value = (IdentNode)((BinaryNode)pNode.getValue()).lhs();
            return key.getName().equals(value.getName()) && key.getStart() == value.getStart();
        }
        return false;
    }
    
    private void processBinaryNode(Node lhs, Node rhs, TokenType tokenType) {
        if (tokenType == TokenType.ASSIGN
                && !(/*rhs instanceof ReferenceNode ||*/ rhs instanceof ObjectNode)
                && (lhs instanceof AccessNode || lhs instanceof IdentNode || lhs instanceof IndexNode)) {
            // TODO probably not only assign
            JsObjectImpl parent = modelBuilder.getCurrentDeclarationFunction();
            if (parent == null) {
                // should not happened
                return;
            }
            String fieldName = null;
            if (lhs instanceof AccessNode) {
                AccessNode aNode = (AccessNode)lhs;
                JsObjectImpl property = null;
                List<Identifier> fqName = getName(aNode, parserResult);
                if (fqName != null && ModelUtils.THIS.equals(fqName.get(0).getName())) { //NOI18N
                    // a usage of field
                    fieldName = aNode.getProperty();
                    if (rhs instanceof IdentNode) {
                        // resolve occurrence of the indent node sooner, then is created the field. 
                        addOccurrence((IdentNode)rhs, fieldName);
                    }
                    property = (JsObjectImpl)createJsObject(aNode, parserResult, modelBuilder);
                } else {
                    // probably a property of an object
                    if (fqName != null) {
                        property = ModelUtils.getJsObject(modelBuilder, fqName, true);
                        if (property.getParent().getJSKind().isFunction() && !property.getModifiers().contains(Modifier.STATIC)) {
                            property.getModifiers().add(Modifier.STATIC);
                        }
                    }
                }
                if (property != null) {
                    String parameter = null;
                    JsFunction function = (JsFunction)modelBuilder.getCurrentDeclarationFunction();
                    if(rhs instanceof IdentNode) {
                        IdentNode iNode = (IdentNode)rhs;
                        if(/*function.getProperty(rhs.getName()) == null &&*/ function.getParameter(iNode.getName()) != null) {
                            parameter = "@param;" + function.getFullyQualifiedName() + ":" + iNode.getName(); //NOI18N
                        }
                    }
                    Collection<TypeUsage> types; 
                    if (parameter == null) {
                        types =  ModelUtils.resolveSemiTypeOfExpression(modelBuilder, rhs);
                        Collection<TypeUsage> correctedTypes = new ArrayList<TypeUsage>(types.size());
                        for (TypeUsage type : types) {
                            String typeName = type.getType();
                            // we have to check, whether a variable comming from resolvedr is not a parameter of function where the binary node is
                            if (typeName.startsWith(SemiTypeResolverVisitor.ST_VAR)) {
                                String varName = typeName.substring(SemiTypeResolverVisitor.ST_VAR.length());
                                if (function.getParameter(varName) != null) {
                                    correctedTypes.add(new TypeUsage("@param;" + function.getFullyQualifiedName() + ":" + varName, type.getOffset(), false));
                                } else {
                                    correctedTypes.add(type);
                                }
                            } else {
                                correctedTypes.add(type);
                            }
                        }
                        types = correctedTypes;
                    } else {
                        types = new ArrayList<TypeUsage>();
                        types.add(new TypeUsage(parameter, rhs.getStart(), false));
                    }

                    for (TypeUsage type : types) {
                        // plus 5 due to the this.
                        property.addAssignment(type, lhs.getStart() + 5);
                    }
                }

            } else {
                JsObject lObject = null;
                boolean indexNodeReferProperty = false;
                int assignmentOffset = lhs.getFinish();
                if (lhs instanceof IndexNode) {
                    IndexNode iNode = (IndexNode)lhs;
                    if (iNode.getBase() instanceof IdentNode) {
                        lObject = processLhs(ModelElementFactory.create(parserResult, (IdentNode)iNode.getBase()), parent, false);
                        assignmentOffset = iNode.getFinish();
                    }
                    if (lObject != null && iNode.getIndex() instanceof LiteralNode) {
                        LiteralNode lNode = (LiteralNode)iNode.getIndex();
                        if (lNode.isString()) {
                            Identifier newPropName = ModelElementFactory.create(parserResult, lNode);
                            if (newPropName != null) {
                                indexNodeReferProperty = true;
                                if (lObject.getProperty(lNode.getString()) == null) {
                                    JsObject newProperty = new JsObjectImpl(lObject, newPropName, newPropName.getOffsetRange(), true, parserResult.getSnapshot().getMimeType(), null);
                                    lObject.addProperty(newPropName.getName(), newProperty);
                                    assignmentOffset = lNode.getFinish();
                                }
                                lObject = processLhs(newPropName, lObject, true);
                            }
                        }
                    }
                } else if (lhs instanceof IdentNode) {
                    lObject = processLhs(ModelElementFactory.create(parserResult, (IdentNode)lhs), parent, true);
                }
                
                if (lObject != null && !(rhs instanceof FunctionNode)) {
                    Collection<TypeUsage> types = ModelUtils.resolveSemiTypeOfExpression(modelBuilder, rhs);
                    if (lhs instanceof IndexNode && lObject instanceof JsArrayImpl) {
                        ((JsArrayImpl)lObject).addTypesInArray(types);
                    } else {
                        boolean isIndexNode = lhs instanceof IndexNode;
                        if (!isIndexNode || (isIndexNode && indexNodeReferProperty)) {
                            for (TypeUsage type : types) {
                                lObject.addAssignment(type, assignmentOffset);
                            }
                        }
                    }
                }
            }
            if (fieldName == null && rhs instanceof IdentNode) {
                addOccurence((IdentNode)rhs, false);
            }
        } else if(tokenType != TokenType.ASSIGN
                || (tokenType == TokenType.ASSIGN && lhs instanceof IndexNode)) {
            if (lhs instanceof IdentNode) {
                addOccurence((IdentNode)lhs, tokenType == TokenType.ASSIGN);
            }
            if (rhs instanceof IdentNode) {
                addOccurence((IdentNode)rhs, false);
            }
        }
    }
    
    @Override
    public Node leaveBinaryNode(BinaryNode binaryNode) {
        Node lhs = binaryNode.lhs();
        Node rhs = binaryNode.rhs();
        if (lhs instanceof IdentNode && rhs instanceof BinaryNode) {
            Node rlhs = ((BinaryNode)rhs).lhs();
            if (rlhs instanceof IdentNode) {
                JsObject origFunction = modelBuilder.getCurrentDeclarationFunction().getProperty(((IdentNode)rlhs).getName());
                if (origFunction != null && origFunction.getJSKind().isFunction()) {
                    JsObject refFunction = modelBuilder.getCurrentDeclarationFunction().getProperty(((IdentNode)lhs).getName());
                    if (refFunction != null && !refFunction.getJSKind().isFunction()) {
                        JsFunctionReference newReference = new JsFunctionReference(refFunction.getParent(), refFunction.getDeclarationName(), (JsFunction)origFunction, true, origFunction.getModifiers());
                        refFunction.getParent().addProperty(newReference.getName(), newReference);
                    }
                }
            }
        }
        return super.leaveBinaryNode(binaryNode); 
    }
    
    @Override
    public boolean enterCallNode(CallNode callNode) {
        functionArgumentStack.push(new ArrayList<JsObjectImpl>(3));
        if (callNode.getFunction() instanceof IdentNode) {
            IdentNode iNode = (IdentNode)callNode.getFunction();
            addOccurence(iNode, false, true);
        }
        for (Node argument : callNode.getArgs()) {
            if (argument instanceof IdentNode) {
                addOccurence((IdentNode) argument, false);
            }
        }
        processObjectPropertyAssignment(callNode);
        return super.enterCallNode(callNode);
    }

    @Override
    public Node leaveCallNode(CallNode callNode) {
        Collection<JsObjectImpl> functionArguments = functionArgumentStack.pop();

        Node function = callNode.getFunction();
        if (function instanceof AccessNode || function instanceof IdentNode) {
            List<Identifier> funcName;
            if (function instanceof AccessNode) {
                funcName = getName((AccessNode) function, parserResult);
            } else {
                funcName = new ArrayList<Identifier>();
                funcName.add(new Identifier(((IdentNode) function).getName(), ((IdentNode) function).getStart()));
            }
                if (funcName != null) {
                    StringBuilder sb = new StringBuilder();
                    for (Identifier identifier : funcName) {
                        sb.append(identifier.getName());
                        sb.append(".");
                    }
                    if (functionCalls == null) {
                        functionCalls = new LinkedHashMap<FunctionInterceptor, Collection<FunctionCall>>();
                    }

                    String name = sb.substring(0, sb.length() - 1);
                    List<FunctionInterceptor> interceptorsToUse = new ArrayList<FunctionInterceptor>();
                    for (FunctionInterceptor interceptor : ModelExtender.getDefault().getFunctionInterceptors()) {
                        if (interceptor.getNamePattern().matcher(name).matches()) {
                            interceptorsToUse.add(interceptor);
                        }
                    }


                    for (FunctionInterceptor interceptor : interceptorsToUse) {
                        Collection<FunctionArgument> funcArg = new ArrayList<FunctionArgument>();
                        for (int i = 0; i < callNode.getArgs().size(); i++) {
                            Node argument = callNode.getArgs().get(i);
                            createFunctionArgument(argument, i, functionArguments, funcArg);
                        }
                        Collection<FunctionCall> calls = functionCalls.get(interceptor);
                        if (calls == null) {
                            calls = new ArrayList<FunctionCall>();
                            functionCalls.put(interceptor, calls);
                        }
                        int callOffset = callNode.getFunction().getStart();
                        if (callNode.getFunction() instanceof AccessNode) {
                            AccessNode anode = (AccessNode)callNode.getFunction();
                            callOffset = anode.getFinish() - anode.getProperty().length();
                        }
                        calls.add(new FunctionCall(name, modelBuilder.getCurrentDeclarationScope(), funcArg, callOffset));
                    }
                }
            }
        return super.leaveCallNode(callNode);
    }

    private void createFunctionArgument(Node argument, int position, Collection<JsObjectImpl> functionArguments,
            Collection<FunctionArgument> result) {

        if (argument instanceof LiteralNode) {
            LiteralNode ln = (LiteralNode)argument;
            if (ln.isString()) {
                result.add(FunctionArgumentAccessor.getDefault().createForString(
                        position, argument.getStart(), ln.getString()));
            } else if (ln instanceof LiteralNode.ArrayLiteralNode) {
                for (JsObjectImpl jsObject: functionArguments) {
                    if (jsObject.getOffset() == argument.getStart()) {
                        result.add(FunctionArgumentAccessor.getDefault().createForArray(position, jsObject.getOffset(), jsObject));
                        break;
                    }
                }
            }
        } else if (argument instanceof ObjectNode) {
            for (JsObjectImpl jsObject: functionArguments) {
                if (jsObject.getOffset() == argument.getStart()) {
                    result.add(FunctionArgumentAccessor.getDefault().createForAnonymousObject(position, jsObject.getOffset(), jsObject));
                    break;
                }
            }
        } else if (argument instanceof AccessNode) {
            List<String> strFqn = new ArrayList<String>();
            if(fillName((AccessNode) argument, strFqn)) {
                result.add(FunctionArgumentAccessor.getDefault().createForReference(
                        position, argument.getStart(), strFqn));
            } else {
                result.add(FunctionArgumentAccessor.getDefault().createForUnknown(position));
            }
        } else if (argument instanceof IndexNode) {
            List<String> strFqn = new ArrayList<String>();
            if(fillName((IndexNode) argument, strFqn)) {
                result.add(FunctionArgumentAccessor.getDefault().createForReference(
                        position, argument.getStart(), strFqn));
            } else {
                result.add(FunctionArgumentAccessor.getDefault().createForUnknown(position));
            }
        } else if (argument instanceof IdentNode) {
            IdentNode in = (IdentNode) argument;
            String inName = in.getName();
            result.add(FunctionArgumentAccessor.getDefault().createForReference(
                    position, argument.getStart(),
                    Collections.singletonList(inName)));
        } else if (argument instanceof UnaryNode) {
            // we are handling foo(new Something())
            UnaryNode un = (UnaryNode) argument;
            if (un.tokenType() == TokenType.NEW) {
                CallNode constructor = (CallNode) un.getExpression();
                createFunctionArgument(constructor.getFunction(), position, functionArguments, result);
            }
        } else if (argument instanceof FunctionNode) {
            FunctionNode reference = (FunctionNode) argument;
            result.add(FunctionArgumentAccessor.getDefault().createForReference(
                    position, argument.getStart(),
                    Collections.singletonList(modelBuilder.getFunctionName(reference))));
        } else {
            result.add(FunctionArgumentAccessor.getDefault().createForUnknown(position));
        }
    }

    @Override
    public boolean enterCatchNode(CatchNode catchNode) {
        Identifier exception = ModelElementFactory.create(parserResult, catchNode.getException());
        if (exception != null) {
            DeclarationScopeImpl inScope = modelBuilder.getCurrentDeclarationScope();
            CatchBlockImpl catchBlock  = new CatchBlockImpl(inScope, exception,
                    new OffsetRange(catchNode.getStart(), catchNode.getFinish()), parserResult.getSnapshot().getMimeType());
            inScope.addDeclaredScope(catchBlock);
            modelBuilder.setCurrentObject(catchBlock);
        }
        return super.enterCatchNode(catchNode);
    }

    @Override
    public Node leaveCatchNode(CatchNode catchNode) {
        if (!EmbeddingHelper.containsGeneratedIdentifier(catchNode.getException().getName())) {
            modelBuilder.reset();
        }
        return super.leaveCatchNode(catchNode);
    }

    

    @Override
    public boolean enterClassNode(ClassNode node) {
        IdentNode cnIdent = node.getIdent();
        Node lastNode = getPreviousFromPath(1);
        VarNode varNode = (lastNode instanceof VarNode) ? (VarNode)lastNode : null;
        JsObject parent = modelBuilder.getCurrentObject();
        JsObjectImpl classObject = null;
        Identifier className = null;
        Identifier refName = null;
        if ((varNode != null  && cnIdent != null && varNode.getName().getName().equals(cnIdent.getName()))
            // case1: var Polygon = class Polygon {}
            // case2: class Polygon {}
                || (varNode != null && !varNode.isExport() && cnIdent == null) ) {
            // case 3: var Polygon = class{}
            // we create just one object
            className = ModelElementFactory.create(parserResult, varNode.getName());
        } else if (varNode != null && cnIdent != null && !varNode.getName().getName().equals(cnIdent.getName())) {
            // case 4: var Polygon = class PolygonOther{}
            // The PolygonOther is available just for the inside the class. 
            className = ModelElementFactory.create(parserResult, varNode.getName());
            refName = ModelElementFactory.create(parserResult, cnIdent);
        } else if (varNode == null && cnIdent != null) {
            className = ModelElementFactory.create(parserResult, cnIdent);
        }
        
        if (className != null) {
            classObject = new JsObjectImpl(parent, className, new OffsetRange(node.getStart(), node.getFinish()), true, parent.getMimeType(), parent.getSourceLabel());
            parent.addProperty(className.getName(), classObject);
            classObject.setJsKind(JsElement.Kind.CLASS);
            if (refName != null) {
                JsObjectReference reference = new JsObjectReference(classObject, refName, classObject, true, EnumSet.of(Modifier.PRIVATE));
                classObject.addProperty(refName.getName(), reference);
                reference.addOccurrence(refName.getOffsetRange());
            }
        }
        if (classObject != null) {
            if (node.getClassHeritage() != null) {
                Expression classHeritage = node.getClassHeritage();
                if (classHeritage instanceof IdentNode) {
                    JsObjectImpl proto = new JsObjectImpl(classObject, ModelUtils.PROTOTYPE, true, OffsetRange.NONE, EnumSet.of(Modifier.PUBLIC), classObject.getMimeType(), classObject.getSourceLabel());
                    classObject.addProperty(ModelUtils.PROTOTYPE, proto);
                    IdentNode type = (IdentNode)classHeritage;
                    proto.addAssignment(new TypeUsage(type.getName(), type.getStart(), true), type.getStart());
                }
                
            }
            modelBuilder.setCurrentObject(classObject);
            // visit constructor
            node.getConstructor().accept(this);
            // visit rest of declaration
            for (PropertyNode element : node.getClassElements()) {
                element.accept(this);
            }
            modelBuilder.reset();
        }
        return false;
    }
    
    
    
    @Override
    public boolean enterIdentNode(IdentNode identNode) {
        Node previousVisited = getPath().get(getPath().size() - 1);
        if(!(previousVisited instanceof AccessNode
                || previousVisited instanceof VarNode
                || previousVisited instanceof BinaryNode
                || previousVisited instanceof PropertyNode
                || previousVisited instanceof CatchNode
                || previousVisited instanceof LabelNode)) {
            //boolean declared = previousVisited instanceof CatchNode;
            addOccurence(identNode, false);
        }
        return super.enterIdentNode(identNode);
    }

    @Override
    public Node leaveIndexNode(IndexNode indexNode) {
        if (indexNode.getIndex() instanceof LiteralNode) {
            Node base = indexNode.getBase();
            JsObjectImpl parent = null;
            if (base instanceof AccessNode) {
               parent = (JsObjectImpl)createJsObject((AccessNode)base, parserResult, modelBuilder);
            } else if (base instanceof IdentNode) {
                IdentNode iNode = (IdentNode)base;
                if (!ModelUtils.THIS.equals(iNode.getName())) {
                    Identifier parentName = ModelElementFactory.create(parserResult, iNode);
                    if (parentName != null) {
                        List<Identifier> fqName = new ArrayList<Identifier>();
                        fqName.add(parentName);
                        parent = ModelUtils.getJsObject(modelBuilder, fqName, false);
                        parent.addOccurrence(parentName.getOffsetRange());
                    }
                }/* else {
                    JsObject current = modelBuilder.getCurrentDeclarationFunction();
                    fromAN = (JsObjectImpl)resolveThis(current);
                }*/
            }
            if (parent != null && indexNode.getIndex() instanceof LiteralNode) {
                LiteralNode literal = (LiteralNode)indexNode.getIndex();
                if (literal.isString()) {
                    String index = literal.getPropertyName();
                    JsObjectImpl property = (JsObjectImpl)parent.getProperty(index);
                    if (property != null) {
                        property.addOccurrence(new OffsetRange(indexNode.getIndex().getStart(), indexNode.getIndex().getFinish()));
                    } else {
                        Identifier name = ModelElementFactory.create(parserResult, (LiteralNode)indexNode.getIndex());
                        if (name != null) {
                            property = new JsObjectImpl(parent, name, name.getOffsetRange(), parserResult.getSnapshot().getMimeType(), null);
                            parent.addProperty(name.getName(), property);
                        }
                    }
                }
            }
        }
        return super.leaveIndexNode(indexNode);
    }

    @Override
    public boolean enterImportNode(ImportNode iNode) {
        ImportClauseNode iClause = iNode.getImportClause();
        FromNode from = iNode.getFrom();
        if (iClause != null) {
            IdentNode defaultBinding = iClause.getDefaultBinding();
            NameSpaceImportNode nameSpaceImport = iClause.getNameSpaceImport();
            NamedImportsNode namedImports = iClause.getNamedImports();
            if (defaultBinding != null) {
                Identifier importedAs = create(parserResult, defaultBinding);
                // create a variable, which have assignment the same variable name  from FromNode
                JsObjectImpl property = createVariableFromImport(importedAs);
                property.addAssignment(new TypeUsage(importedAs.getName()), importedAs.getOffsetRange().getEnd());
            }
            if (nameSpaceImport != null) {
                Identifier importedAs = create(parserResult, nameSpaceImport.getBindingIdentifier());
                // create a variable, which has all properties from FromNode module
                createVariableFromImport(importedAs);
            }
            if (namedImports != null && namedImports.getImportSpecifiers() != null) {
                List<ImportSpecifierNode> importSpecifiers = namedImports.getImportSpecifiers();
                for (ImportSpecifierNode importSpecifier : importSpecifiers) {
                    Identifier importedAs = create(parserResult, importSpecifier.getBindingIdentifier());
                    JsObjectImpl property;
                    property = createVariableFromImport(importedAs);
                    property.addOccurrence(importedAs.getOffsetRange());
                    if (importSpecifier.getIdentifier() != null) {
                        Identifier inModuleName = create(parserResult, importSpecifier.getIdentifier());
                        property.addAssignment(new TypeUsage(inModuleName.getName()), inModuleName.getOffsetRange().getEnd());
                    }
                    
                }
            }
        }
        return false;
    }

    private JsObjectImpl createVariableFromImport(Identifier name) {
        JsFunctionImpl scope = modelBuilder.getCurrentDeclarationFunction();
        JsObject existingProp = scope.getProperty(name.getName());
        JsObjectImpl property = new JsObjectImpl(scope, name, name.getOffsetRange(), true, scope.getMimeType(), scope.getSourceLabel());
        if (existingProp != null) {
            ModelUtils.copyOccurrences(existingProp, property);
        }
        scope.addProperty(name.getName(), property);
        return property;
    }

    @Override
    public boolean enterExportNode(ExportNode exportNode) {
        final ExportClauseNode exportClause = exportNode.getExportClause();
        final FromNode from = exportNode.getFrom();
        final Expression expression = exportNode.getExpression();
        
        if (exportClause != null) {
            for (ExportSpecifierNode esNode :exportClause.getExportSpecifiers()) {
                IdentNode exported = esNode.getExportIdentifier();
                IdentNode local = esNode.getIdentifier();
                JsObjectImpl property = (JsObjectImpl)modelBuilder.getCurrentDeclarationFunction().getProperty(local.getName());
                if (exported == null) {
                    if (property == null) {
                        property = createVariableFromImport(create(parserResult, local));
                    }
                    property.addOccurrence(getOffsetRange(local));
                } else {
                    addOccurence (local, false);
                    property = createVariableFromImport(create(parserResult, exported));
                }
                if (from != null && property != null) {
                    TypeUsage type = new TypeUsage(local.getName(), local.getFinish());
                    property.addAssignment(type, local.getFinish());
                }
            }
        }
        if (expression != null) {
            addToPath(exportNode);
            expression.accept(this);
            removeFromPathTheLast();
        }
        return false;
    }
    
    @Override
    public boolean enterForNode(ForNode forNode) {
        if (forNode.getInit() instanceof IdentNode) {
            JsObject parent = modelBuilder.getCurrentObject();
            while (parent instanceof JsWith) {
                parent = parent.getParent();
            }
            IdentNode name = (IdentNode)forNode.getInit();
            JsObjectImpl variable = (JsObjectImpl)parent.getProperty(name.getName());
            if (variable != null) {
                Collection<TypeUsage> types = ModelUtils.resolveSemiTypeOfExpression(modelBuilder, forNode.getModify());
                for (TypeUsage type : types) {
                    if (type.getType().contains(SemiTypeResolverVisitor.ST_VAR)) {
                        int index = type.getType().lastIndexOf(SemiTypeResolverVisitor.ST_VAR);
                        String newType = type.getType().substring(0, index) + SemiTypeResolverVisitor.ST_ARR + type.getType().substring(index + SemiTypeResolverVisitor.ST_VAR.length());
                        type = new TypeUsage(newType, type.getOffset(), false);
                    } else if (type.getType().contains(SemiTypeResolverVisitor.ST_PRO)) {
                        int index = type.getType().lastIndexOf(SemiTypeResolverVisitor.ST_PRO);
                        String newType = type.getType().substring(0, index) + SemiTypeResolverVisitor.ST_ARR + type.getType().substring(index + SemiTypeResolverVisitor.ST_PRO.length());
                        type = new TypeUsage(newType, type.getOffset(), false);
                    }
                    variable.addAssignment(type, forNode.getModify().getStart());
                }
            }
        }
        return super.enterForNode(forNode);
    }
    
    @Override
    public boolean enterFunctionNode(FunctionNode functionNode) {
        if (functionNode.isClassConstructor() && !(ModelUtils.CONSTRUCTOR.equals(functionNode.getName()) || functionNode.getName().startsWith(ModelUtils.CONSTRUCTOR))) {
            // don't process artificail constructors. 
            return false;
        }
        addToPath(functionNode);
        // Find the function in the model. It's has to be already there
        JsFunctionImpl fncParent = modelBuilder.getCurrentDeclarationFunction();
        JsFunctionImpl fncScope = null;
        if (functionNode.isProgram()) {
            fncScope = fncParent;
            if (this.parserResult.getSnapshot().getSource().getFileObject() != null) {
                LOGGER.log(Level.FINE, "Creating model for: {0}", this.parserResult.getSnapshot().getSource().getFileObject().getPath()); //NOI18N
            }
        } else {
            JsObject property = fncParent.getProperty(modelBuilder.getFunctionName(functionNode));
            if (property == null && functionNode.isStrict()) {
                property = modelBuilder.getCurrentDeclarationScope().getProperty(modelBuilder.getFunctionName(functionNode));
            }
            if(!(property instanceof JsFunction)) {
                property = fncParent.getProperty(modelBuilder.getGlobal().getName() + modelBuilder.getFunctionName(functionNode));
            }
            if (property != null && property instanceof JsFunction) {
                if (property instanceof JsFunctionReference) {
                    fncScope = (JsFunctionImpl)((JsFunctionReference)property).getOriginal();
                } else {
                    fncScope = (JsFunctionImpl)property;
                }
            }
            if (property == null) {
                LOGGER.log(Level.FINE, "FunctionNode: " + functionNode.toString() + " is not processed, because parent function " + fncParent.toString() + " doesn't contain such property."); //NOI18N
                return false;
            }
        }
        
        // add to the model functions and variables declared in this scope
        // this is needed, to handle usege before declaration
        processDeclarations(fncScope, functionNode);
        fncScope.setStrict(functionNode.isStrict());
        
        if (!functionNode.isProgram() && !functionNode.isModule()) {
            correctNameAndOffsets(fncScope, functionNode);
            setParent(fncScope, functionNode);
            // set modifiers for the processed function
            setModifiers(fncScope, functionNode);
            modelBuilder.setCurrentObject(fncScope);
        }
        
        processJsDoc(fncScope, functionNode, JsDocumentationSupport.getDocumentationHolder(parserResult));

        if (functionNode.isModule()) {
            // visit all imports and exports
            List<ImportNode> imports = functionNode.getModule().getImports();
            for (ImportNode moduleImport : imports) {
                moduleImport.accept(this);
            }
            List<ExportNode> exports = functionNode.getModule().getExports();
            for (ExportNode moduleExport : exports) {
                moduleExport.accept(this);
            }
        }
        
        // visit all statements of the function
        functionNode.getBody().accept(this);
        
        if (functionNode.getKind() == FunctionNode.Kind.GENERATOR) {
            // set the return type as Generator object
            fncScope.addReturnType(new TypeUsage("Generator", 1, true));
        } else {
            // seting undefinded return type
            if (fncScope.areReturnTypesEmpty()) {
                // the function doesn't have return statement -> returns undefined
                fncScope.addReturnType(new TypeUsage(Type.UNDEFINED, -1, false));
            }
        }
        
        if (!functionNode.isProgram() && !functionNode.isModule()) {
            processModifiersFromJsDoc(fncScope, functionNode, JsDocumentationSupport.getDocumentationHolder(parserResult));
            if (canBeSingletonPattern(1)) {
                // move all properties to the parent
                JsObject singleton = resolveThisInSingletonPattern(fncScope);
                if (singleton != null) {
                    fncScope.setJsKind(JsElement.Kind.CONSTRUCTOR);
                    if (fncScope.isAnonymous()) {
                        // TODO we probably should not move the properties, or at least increase offset range
                        // of the singleton to fit offsets of these methods in the singleton object
                        List<JsObject> properties = new ArrayList<>(fncScope.getProperties().values());
                        for (JsObject property : properties) {
                            ModelUtils.moveProperty(singleton, property);
                        }
                    }
                }
            }
            modelBuilder.reset();
        }
        removeFromPathTheLast();
        return false;
    }
    
    private void correctNameAndOffsets(JsFunctionImpl jsFunction, FunctionNode fn) {
        OffsetRange decNameOffset = jsFunction.getDeclarationName().getOffsetRange();
        Node lastVisited = getPreviousFromPath(2);
        Identifier newIdentifier = null;
        if (decNameOffset.getLength() == 0) {
            // the function name is not between function and (
            if (lastVisited instanceof PropertyNode && fn.getKind() != FunctionNode.Kind.ARROW) {
                PropertyNode pNode = (PropertyNode)lastVisited;
                newIdentifier = new Identifier(pNode.getKeyName(), getOffsetRange(pNode.getKey()));
            } else if ((lastVisited instanceof VarNode) && fn.isAnonymous()) {
                VarNode vNode = (VarNode)lastVisited;
                newIdentifier = new Identifier(vNode.getName().getName(), getOffsetRange(vNode.getName()));
            } else if (fn.isAnonymous() && lastVisited instanceof JoinPredecessorExpression
                    && getPreviousFromPath(3) instanceof BinaryNode 
                    && getPreviousFromPath(4) instanceof VarNode) {
                // case var f1 = xxx || function () {}
                VarNode vNode = (VarNode)getPreviousFromPath(4);
                newIdentifier = new Identifier(vNode.getName().getName(), getOffsetRange(vNode.getName()));
            }
        }
        if (newIdentifier != null) {
//            if (fn.getKind() == FunctionNode.Kind.ARROW) {
//                jsFunction.getParent().getProperties().remove(jsFunction.getName());
//                jsFunction.getParent().addProperty(newIdentifier.getName(), jsFunction);
//            }
            jsFunction.setDeclarationName(newIdentifier);
            jsFunction.addOccurrence(newIdentifier.getOffsetRange());
            
        }
    }
    
    private void setModifiers(JsFunctionImpl jsFunction, FunctionNode fn) {
        //Node lastVisited = getPreviousFromPath(2);
        boolean isPrivate = false;
        boolean isPrivilage = false;
        boolean isStatic = false;
        
        Node lastVisited = getPreviousFromPath(2);
        
        if (!lc.getParentFunction(fn).isProgram() 
                && !(lastVisited instanceof PropertyNode || lastVisited instanceof BinaryNode)) {
            // it can be a part of anonymous object 
            isPrivate = true;
        }
        if (lastVisited instanceof PropertyNode) {
            PropertyNode pNode = (PropertyNode)lastVisited;
            isStatic = pNode.isStatic();
            if (fn.isClassConstructor() || fn.isSubclassConstructor()) {
                jsFunction.setJsKind(JsElement.Kind.CONSTRUCTOR);
            } else if (fn.isMethod()) {
                if (fn.equals(pNode.getGetter())) {
                    jsFunction.setJsKind(JsElement.Kind.PROPERTY_GETTER);
                } else if (fn.equals(pNode.getSetter())) {
                    jsFunction.setJsKind(JsElement.Kind.PROPERTY_SETTER);
                } else {
                    jsFunction.setJsKind(JsElement.Kind.METHOD);
                }
            }
        } else if (lastVisited instanceof BinaryNode) {
            BinaryNode bNode = (BinaryNode)lastVisited;
            if (bNode.getAssignmentDest() instanceof AccessNode) {
                // case like A.f1 = function (){} -> f1 is a public static property
                AccessNode aNode = (AccessNode)bNode.getAssignmentDest();
                List<Identifier> name = getName(aNode, parserResult);
                if (name != null && ModelUtils.THIS.equals(name.get(0).getName())) {
                    isPrivilage = true;
                } else {
                    if (!ModelUtils.PROTOTYPE.equals(aNode.getProperty()) && jsFunction.getParent().getJSKind().isFunction()) {
                        if (aNode.getBase() instanceof AccessNode) {
                            if (!ModelUtils.PROTOTYPE.equals(((AccessNode)aNode.getBase()).getProperty())) {
                                // case like A.B.f1 = function () {}
                                isStatic = true;
                            }
                        } else {
                            isStatic = true;
                        }
                    }
                }
            }
        } else if (lastVisited instanceof CallNode) {
            if (getPreviousFromPath(3) instanceof UnaryNode) {
                if (getPreviousFromPath(4) instanceof VarNode) {
                    isPrivate = true;
                }
            }
        }
        
        if (fn.getKind() == FunctionNode.Kind.GENERATOR) {
            // marking the function as generator
            jsFunction.setJsKind(JsElement.Kind.GENERATOR);
        }
        
        Set<Modifier> modifiers = jsFunction.getModifiers();
        if (isPrivate || isPrivilage) {
            modifiers.remove(Modifier.PUBLIC);
            if (isPrivate) {
                modifiers.add(Modifier.PRIVATE);
            } else {
                modifiers.add(Modifier.PROTECTED);
            }
        }
        if (isStatic) {
            modifiers.add(Modifier.STATIC);
        }
        // setting whether the function is anonymous
        if (isFunctionAnonymous(fn)) {
            jsFunction.setAnonymous(true);
        }
    }
    
    private void setParent(JsFunctionImpl jsFunction, FunctionNode fn) {
        Node lastVisited = getPreviousFromPath(2);
        JsObject parent = jsFunction.getParent();
        if (lastVisited instanceof JoinPredecessorExpression
                && getPreviousFromPath(3) instanceof BinaryNode 
                && getPreviousFromPath(4) instanceof VarNode) {
            // this handle case var f1 = xxx || function () {}
            // just skip the binary node and continue like in case var f1 = function (){}
            lastVisited = getPreviousFromPath(4);           
        }
        if (lastVisited instanceof PropertyNode) {
            // the parent of the function is the literal object
            parent = modelBuilder.getCurrentObject();
        } else if (lastVisited instanceof VarNode) {
            VarNode varNode = (VarNode)lastVisited;
            if (fn.isNamedFunctionExpression()) {
                // case: var f1 = function fx() {}
                // the fx can be used only in fx, in other cases is unaccessible -> basically private function of f1
                // fx will be feference of f1
                parent.getProperties().remove(modelBuilder.getFunctionName(fn));
                JsObject variable = parent.getProperty(varNode.getName().getName());
                Identifier refName = new Identifier(fn.getIdent().getName(), new OffsetRange(fn.getIdent().getStart(), fn.getIdent().getFinish()));
                JsFunctionReference jsRef = new JsFunctionReference(jsFunction, refName, jsFunction, true,  EnumSet.of(Modifier.PRIVATE));
                jsRef.addOccurrence(jsRef.getDeclarationName().getOffsetRange());
                jsFunction.setDeclarationName(new Identifier(varNode.getName().getName(), getOffsetRange(varNode.getName())));
                if (variable != null) {
                    ModelUtils.copyOccurrences(variable, jsFunction);
                }
                parent.addProperty(jsFunction.getName(), jsFunction);
                jsFunction.addProperty(jsRef.getName(), jsRef);
            } else if ((varNode.isFunctionDeclaration() || fn.isAnonymous())) {
                // correct key name of properties in cases
                // var f1 = function () {}
                // var f1 = function f1() {}
                parent.getProperties().remove(modelBuilder.getFunctionName(fn));
                parent.addProperty(varNode.getName().getName(), jsFunction);
            }
        } else if (lastVisited instanceof BinaryNode) {
            // case like A.f1 = function () {}
            BinaryNode bNode = (BinaryNode)lastVisited;
            List<Identifier> name = getName(bNode, parserResult);
            boolean isPriviliged = false;
            
            if (name != null && !name.isEmpty()) {
                if (ModelUtils.THIS.equals(name.get(0).getName())) {
                    name.remove(0);
                    isPriviliged = true;
                    parent = (JsObjectImpl)resolveThis(parent);
                    JsObject hParent = parent;
                    while(hParent != null && hParent.getKind() != ElementKind.FILE && hParent.getDeclarationName() != null) {
                        name.add(0, hParent.getDeclarationName());
                        hParent = hParent.getParent();
                    }
                } 
                
                boolean parentHasSameName = false;
                if (name.size() > 1 && name.get(0).getName().equals(jsFunction.getName())) {
                    JsObject property = parent.getProperty(modelBuilder.getFunctionName(fn));
                    if (property != null && property.equals(jsFunction)) {
                        // this handles case like:
                        // theSameName.theSameName = function theSameName () {}
                        parent.getProperties().remove(modelBuilder.getFunctionName(fn));
                        ((JsObjectImpl)property).clearOccurrences();
                        parentHasSameName = true;
                    }
                }
                JsObjectImpl jsObject = ModelUtils.getJsObject(modelBuilder, name, !parentHasSameName);
                if (!isPriviliged) {
                    parent = jsObject.getParent();
                }
                if (fn.isNamedFunctionExpression()) {
                    // case like A.f1 = function f1(){}
                    Identifier refName = new Identifier(fn.getIdent().getName(), new OffsetRange(fn.getIdent().getStart(), fn.getIdent().getFinish()));
                    JsFunctionReference jsRef = new JsFunctionReference(jsFunction, refName, jsFunction, true,  EnumSet.of(Modifier.PRIVATE));
                    jsRef.addOccurrence(jsRef.getDeclarationName().getOffsetRange());
                    jsFunction.addProperty(jsRef.getName(), jsRef);
                }
                jsFunction.setDeclarationName(jsObject.getDeclarationName());
                ModelUtils.copyOccurrences(jsObject, jsFunction);
                if (!parentHasSameName) {
                    String builderName = modelBuilder.getFunctionName(fn);
                    if (jsFunction.getParent().getProperties().remove(builderName) == null) {
                        // we need to check, whether is not declared in a block of the parent for handling cases like:
                        // onreadystatechange = function() {
                        //      if (true) {
                        //          onreadystatechange = function () {console.log("true");};
                        //      } else {
                        //          onreadystatechange = function () {console.log("false");};
                        //      }
                        // };
                        for (JsObject property : jsFunction.getParent().getProperties().values()) {
                            if (property.getJSKind() == JsElement.Kind.BLOCK && property.getProperties().remove(builderName) != null) {
                                if (property.getProperties().size() == 0) {
                                    // remove the empty block from model
                                    property.getParent().getProperties().remove(property.getName());
                                }
                                break;
                            }
                        }
                    }
                }
                if (parent == null) {
                    parent = jsObject.getParent();
                }
                parent.addProperty(jsObject.getName(), jsFunction);
                jsFunction.setParent(parent);
            }
        } else if (lastVisited instanceof CallNode) {
            if (getPreviousFromPath(3) instanceof UnaryNode) {
                if (getPreviousFromPath(4) instanceof VarNode) {
                    // case var MyLib = new function XXX? () {}
                    VarNode varNode = (VarNode) getPreviousFromPath(4);
                    Expression init = varNode.getInit();
                    Identifier varName = new Identifier(varNode.getName().getName(), getOffsetRange(varNode.getName()));
                    OffsetRange range = varNode.getInit() instanceof ObjectNode ? new OffsetRange(varNode.getName().getStart(), ((ObjectNode)varNode.getInit()).getFinish()) 
                            : varName.getOffsetRange();
                    
                    JsObject variable = handleArrayCreation(varNode.getInit(), parent, varName);
                    if (variable == null) {
                        JsObjectImpl newObject = new JsObjectImpl(parent, varName, range, jsFunction.getMimeType(), jsFunction.getSourceLabel());
                        newObject.setDeclared(true);
                        variable = newObject;
                    }
                    variable.addOccurrence(varName.getOffsetRange());
                    parent.getProperties().remove(jsFunction.getName());
                    parent.addProperty(varName.getName(), variable);
                    variable.addProperty(jsFunction.getName(), jsFunction);
                    jsFunction.setParent(variable);
//                    Collection<TypeUsage> returns = ModelUtils.resolveSemiTypeOfExpression(modelBuilder, init);
//                    for (TypeUsage type : returns) {
                    variable.addAssignment(new TypeUsage(SemiTypeResolverVisitor.ST_NEW + variable.getName() + '.' + jsFunction.getName(), jsFunction.getDeclarationName().getOffsetRange().getStart()), init.getStart());
//                    }
                    if (fn.isNamedFunctionExpression() && fn.getName().equals(varName.getName())) {
                        // the name of function is the same as the variable
                        // var MyLib = new function MyLib() {};
                        ModelUtils.copyOccurrences(jsFunction, variable);
                    }
                    parent = variable;
                    int index = getPath().size() - 5;
                    while ( index > -1 && !(getPath().get(index) instanceof FunctionNode)) {
                        index--;
                    }   
                    if(index > 0) {
                        // the variable is defined in a function -> the object is private
                        variable.getModifiers().remove(Modifier.PUBLIC);
                        variable.getModifiers().add(Modifier.PRIVATE);
                    }
                } 
            }
        }
        
        if (!parent.equals(jsFunction.getParent())) {
            jsFunction.getParent().getProperties().remove(modelBuilder.getFunctionName(fn));
            jsFunction.setParent(parent);
            JsObject property = parent.getProperty(jsFunction.getName());
            if (property != null) {
                ModelUtils.copyOccurrences(property, jsFunction);
            }
            parent.addProperty(jsFunction.getName(), jsFunction);
        }
        
        DeclarationScopeImpl fnScope = (DeclarationScopeImpl)jsFunction;
        DeclarationScope parentScope = fnScope.getParentScope();
        if (parentScope != null) {
            parentScope.addDeclaredScope(fnScope);
        }
    }
    
    private boolean isFunctionAnonymous(FunctionNode fn) {
        boolean result = false;
        if (fn.isAnonymous() ) {
            Node lastVisited = getPreviousFromPath(2);
            if (fn.getIdent().getName().startsWith("L:") && !(lastVisited instanceof PropertyNode)) { //NOI18N
                // XXX this depends on the implemenation of parser. Find the better way
                result = true;
            } else if (fn.getIdent().getStart() == fn.getIdent().getFinish()) {
                if (lastVisited instanceof CallNode) {
                    result = true;
                }
            }
        }
        return result;
    }
    
    private void processJsDoc(JsFunctionImpl jsFunction, FunctionNode fn, JsDocumentationHolder docHolder) {
        if (!fn.isProgram()) {
            // the documentation for the function
            Documentation documentation = docHolder.getDocumentation(fn);
            jsFunction.setDocumentation(documentation);
            // parameters
            List<DocParameter> docParams = docHolder.getParameters(fn);
            for (DocParameter docParameter : docParams) {
                Identifier paramName = docParameter.getParamName();
                if (paramName != null) {
                    String sParamName = paramName.getName();
                    if(sParamName != null && !sParamName.isEmpty()) {
                        JsObjectImpl param = (JsObjectImpl) jsFunction.getParameter(sParamName);
                        if (param != null) {
                            for (Type type : docParameter.getParamTypes()) {
                                param.addAssignment(new TypeUsage(type.getType(), type.getOffset(), true), param.getOffset());
                            }
                            // param occurence in the doc
                            addDocNameOccurence(param);
                        }
                    }
                }
            }
            // mark constructors 
            if (docHolder.isClass(fn)) {
                // needs to be marked before going through the nodes
                jsFunction.setJsKind(JsElement.Kind.CONSTRUCTOR);
            }
            
            jsFunction.setDeprecated(docHolder.isDeprecated(fn));
            
            // process @extends tag
            List<Type> extendTypes = docHolder.getExtends(fn);
            if (!extendTypes.isEmpty()) {
                JsObject prototype = jsFunction.getProperty(ModelUtils.PROTOTYPE);
                if (prototype == null) {
                    prototype = new JsObjectImpl(jsFunction, ModelUtils.PROTOTYPE, true, OffsetRange.NONE, EnumSet.of(Modifier.PUBLIC), parserResult.getSnapshot().getMimeType(), null);
                    jsFunction.addProperty(ModelUtils.PROTOTYPE, prototype);
                }
                for (Type type : extendTypes) {
                    prototype.addAssignment(new TypeUsage(type.getType(), type.getOffset(), true), type.getOffset());
                }
            }
            
            // process @returns tag
            List<Type> types = docHolder.getReturnType(fn);
            if (types != null && !types.isEmpty()) {
                for(Type type : types) {
                    jsFunction.addReturnType(new TypeUsage(type.getType(), type.getOffset(), true /*ModelUtils.isKnownGLobalType(type.getType())*/));
                }
            }
        }
        // look for the type defined through comment like @typedef
        Map<Integer, ? extends JsComment> commentBlocks = docHolder.getCommentBlocks();
        for (JsComment comment : commentBlocks.values()) {
            DocParameter definedType = comment.getDefinedType();
            if (definedType != null) {
                    // XXX the param name now can contains names with dot.
                // it would be better if the getParamName returns list of identifiers
                String typeName = definedType.getParamName().getName();
                List<Identifier> fqn = new ArrayList<Identifier>();
                JsObject whereOccurrence = getGlobalObject();
                if (typeName.indexOf('.') > -1) {
                    String[] parts = typeName.split("\\.");
                    int offset = definedType.getParamName().getOffsetRange().getStart();
                    int delta = 0;
                    for (int i = 0; i < parts.length; i++) {
                        fqn.add(new Identifier(parts[i], offset + delta));
                        if (whereOccurrence != null) {
                            whereOccurrence = whereOccurrence.getProperty(parts[i]);
                            if (whereOccurrence != null) {
                                whereOccurrence.addOccurrence(new OffsetRange(offset + delta, offset + delta + parts[i].length()));
                            }
                        }
                        delta = delta + parts[i].length() + 1;
                    }
                } else {
                    fqn.add(definedType.getParamName());
                }
                JsObject object = ModelUtils.getJsObject(modelBuilder, fqn, true);
                int assignOffset = definedType.getParamName().getOffsetRange().getEnd();
                List<Type> types = definedType.getParamTypes();

                for (Type type : types) {
                    object.addAssignment(new TypeUsage(type.getType(), type.getOffset()), assignOffset);
                }
                List<Type> assignedTypes = comment.getTypes();
                for (Type type : assignedTypes) {
                    object.addAssignment(new TypeUsage(type.getType(), type.getOffset()), assignOffset);
                }
                List<DocParameter> properties = comment.getProperties();
                for (DocParameter docProperty : properties) {
                    JsObject jsProperty = new JsObjectImpl(object, docProperty.getParamName(), docProperty.getParamName().getOffsetRange(), true, JsTokenId.JAVASCRIPT_MIME_TYPE, null);
                    object.addProperty(jsProperty.getName(), jsProperty);
                    types = docProperty.getParamTypes();
                    jsProperty.setDocumentation(Documentation.create(docProperty.getParamDescription()));
                    assignOffset = docProperty.getParamName().getOffsetRange().getEnd();
                    for (Type type : types) {
                        jsProperty.addAssignment(new TypeUsage(type.getType(), type.getOffset()), assignOffset);
                    }
                }
            }
            Type callBack = comment.getCallBack();
            if (callBack != null) {
                List<Identifier> fqn = fqnFromType(callBack);
                markOccurrences(fqn);
                List<Identifier> parentFqn = new ArrayList<Identifier>();
                for (int i = 0; i < fqn.size() - 1; i++) {
                    parentFqn.add(fqn.get(i));
                }
                JsObject parentObject = parentFqn.isEmpty() ? getGlobalObject() : ModelUtils.getJsObject(modelBuilder, parentFqn, true);
                JsFunctionImpl callBackFunction = new JsFunctionImpl(
                        parentObject instanceof DeclarationScope ? (DeclarationScope) parentObject : ModelUtils.getDeclarationScope(parentObject),
                        parentObject, fqn.get(fqn.size() - 1), Collections.EMPTY_LIST,
                        callBack.getOffset() > -1 ? new OffsetRange(callBack.getOffset(), callBack.getOffset() + callBack.getType().length()) : OffsetRange.NONE,
                        JsTokenId.JAVASCRIPT_MIME_TYPE, null);
                parentObject.addProperty(callBackFunction.getName(), callBackFunction);
                callBackFunction.setDocumentation(Documentation.create(comment.getDocumentation()));
                callBackFunction.setJsKind(JsElement.Kind.CALLBACK);
                List<DocParameter> docParameters = comment.getParameters();
                for (DocParameter docParameter : docParameters) {
                    ParameterObject parameter = new ParameterObject(callBackFunction, docParameter.getParamName(), JsTokenId.JAVASCRIPT_MIME_TYPE, null);
                    for (Type type : docParameter.getParamTypes()) {
                        parameter.addAssignment(new TypeUsage(type.getType(), type.getOffset(), true), parameter.getOffset());
                    }
                    addDocNameOccurence(parameter);
                    callBackFunction.addParameter(parameter);
                }
            }
        }
    }
    
    private void processModifiersFromJsDoc(JsFunctionImpl jsFunction, FunctionNode fn, JsDocumentationHolder docHolder) {
        if (!fn.isProgram() && !fn.isModule() && docHolder != null) {
            Set<JsModifier> modifiers = docHolder.getModifiers(fn);
            if (modifiers != null && !modifiers.isEmpty()) {
                Set<Modifier> fnModifiers = jsFunction.getModifiers();
                if (modifiers.contains(JsModifier.PRIVATE)) {
                    fnModifiers.remove(Modifier.PUBLIC);
                    fnModifiers.remove(Modifier.PROTECTED);
                    fnModifiers.add(Modifier.PRIVATE);
                }
                if (modifiers.contains(JsModifier.PUBLIC)) {
                    fnModifiers.remove(Modifier.PRIVATE);
                    fnModifiers.remove(Modifier.PROTECTED);
                    fnModifiers.add(Modifier.PUBLIC);
                }
                if (modifiers.contains(JsModifier.STATIC)) {
                    fnModifiers.add(Modifier.STATIC);
                }
            }
        }
    }
    
    private void  processDeclarations(final JsFunctionImpl parentFn, final FunctionNode inNode) {
        LOGGER.log(Level.FINEST, "in function: " + inNode.getName() + ", ident: " + inNode.getIdent());
        final JsDocumentationHolder docHolder = JsDocumentationSupport.getDocumentationHolder(parserResult);
        
        Block block = inNode.getBody();
        PathNodeVisitor visitor = new PathNodeVisitor(lc)  {
            
            DeclarationScopeImpl currentBlockScope = parentFn;
            private boolean isParameterBlock = false;
            private List<FunctionNode> declaredFunctions = new ArrayList<>();
            private List<VarNode> declaredVars = new ArrayList<>();

            private void handleDeclarations() {
                if (!declaredFunctions.isEmpty() || !declaredVars.isEmpty()) {
                    for (FunctionNode fnNode : declaredFunctions) {
                        handleDeclaredFunction(currentBlockScope, parentFn, fnNode);
                    }
                    for (VarNode varNode : declaredVars) {
                        if (varNode.isLet()) {
                            // block scope variable
                            handleDeclaredVariable(currentBlockScope, parentFn, varNode, docHolder);
                        } else {
                            handleDeclaredVariable(parentFn, parentFn, varNode, docHolder);
                        }
                    }
                    declaredFunctions.clear();
                    declaredVars.clear();
                }
            }
            
            @Override
            public boolean enterBlock(Block block) {
                handleDeclarations();
                if (inNode.isStrict()) {
                    if (getPath().size() > 0) {
                        // we are in strict mode -> possible block scope declaration
                        currentBlockScope = new DeclarationScopeImpl(currentBlockScope, currentBlockScope, 
                                new Identifier(BLOCK_OBJECT_NAME_PREFIX + block.getStart(), OffsetRange.NONE), new OffsetRange(block.getStart(), block.getFinish()), currentBlockScope.getMimeType() , currentBlockScope.getSourceLabel());
                        currentBlockScope.setJsKind(JsElement.Kind.BLOCK);
                    }
                }
                isParameterBlock = block.isParameterBlock();
                return super.enterBlock(block);
            }

            @Override
            public Node leaveBlock(Block block) {
                if (inNode.isStrict() || getPath().size() == 1) {
                    handleDeclarations();
                    if (getPath().size() > 1) {
                        DeclarationScopeImpl parentScope = (DeclarationScopeImpl)currentBlockScope.getParentScope();
                        if (!((JsObject)currentBlockScope).getProperties().isEmpty()) {
                            // don't keep this empty scope in model
                            parentScope.addDeclaredScope(currentBlockScope);
                            parentScope.addProperty(currentBlockScope.getName(), currentBlockScope);
                        }
                        currentBlockScope = parentScope;
                    }
                }
                return super.leaveBlock(block);
            }

            @Override
            public Node leaveExportNode(ExportNode exportNode) {
                handleDeclarations();
                return super.leaveExportNode(exportNode);
            }
            
            
            @Override
            public boolean enterClassNode(ClassNode classNode) {
                if (classNode.getConstructor() != null) {
                    classNode.getConstructor().accept(this);
                }
                if (classNode.getClassElements() != null) {
                    for (PropertyNode pn : classNode.getClassElements()) {
                        pn.accept(this);
                    }
                }
                return false;
            }

            
            @Override
            public boolean enterFunctionNode(FunctionNode fnNode) {
                declaredFunctions.add(fnNode);
                return false;
            }
            
            @Override
            public boolean enterVarNode(VarNode varNode) {
                if (!isParameterBlock) {
                    declaredVars.add(varNode);
                }
                return super.enterVarNode(varNode);
            }

        };
        if (inNode.isModule() && inNode.getModule().getExports() != null) {
            for(ExportNode export :inNode.getModule().getExports()) {
                if (!export.isDefault()) {
                    // don't go through the default export node, it appears also as *default* varible node
                    export.accept(visitor); 
                } else {
                    Expression expression = export.getExpression();
                    if ((expression instanceof ClassNode && ((ClassNode)expression).getIdent() != null)
                            || (expression instanceof FunctionNode && ((FunctionNode)expression).getIdent() != null)) {
                        export.accept(visitor); 
                    }
                }
            }
        }
        block.accept(visitor);
    }
    
    private void handleDeclaredFunction(DeclarationScopeImpl inScope, JsObject parent,  FunctionNode fnNode) {
        LOGGER.log(Level.FINEST, "       function: " + debugInfo(fnNode)); // NOI18N
        String name = fnNode.isAnonymous() ? modelBuilder.getFunctionName(fnNode) : fnNode.getIdent().getName();
        Identifier fnName = new Identifier(name, new OffsetRange(fnNode.getIdent().getStart(), fnNode.getIdent().getFinish()));
        if (fnNode.isClassConstructor() && !ModelUtils.CONSTRUCTOR.equals(fnName.getName())) {
            // skip artifical/ syntetic constructor nodes, that are created
            // when a class extends different class
            return;
        }
        // process parameters
        List<Identifier> parameters = new ArrayList<>(fnNode.getParameters().size());
        for(IdentNode node: fnNode.getParameters()) {
            Identifier param = create(parserResult, node);
            if (param != null && !node.isDestructuredParameter()) {
                // can be null, if it's a generated embeding. 
                parameters.add(param);
            }
        }
        // The parent can be changed in the later processing
        JsFunctionImpl declaredFn = new JsFunctionImpl(inScope, parent, fnName, parameters, getOffsetRange(fnNode), inScope.getMimeType(), inScope.getSourceLabel());
        inScope.addProperty(modelBuilder.getFunctionName(fnNode), declaredFn);
        if (fnName.getOffsetRange().getLength() > 0 && !fnNode.isNamedFunctionExpression()) {
            declaredFn.addOccurrence(fnName.getOffsetRange());
        }
    }
    
    private void handleDeclaredVariable(DeclarationScopeImpl parentFn, JsObject parent,  VarNode varNode, JsDocumentationHolder docHolder) {
        LOGGER.log(Level.FINEST, "       variable: " + debugInfo(varNode)); // NOI18N
        Expression init = varNode.getInit();
        boolean createVariable = true;
        if (!varNode.isFunctionDeclaration() // we skip syntetic variables created from case: function f1(){}
                && !varNode.isExport()) { // we skip syntetic variables created from export expression
            if (init instanceof FunctionNode && !((FunctionNode) init).isNamedFunctionExpression()) {
                    // case: var f1 = function () {}
                // the function here is already, need to be just fixed the name offsets
                createVariable = false;
            } else if (init instanceof BinaryNode) {
                BinaryNode bNode = (BinaryNode) init;
                if (bNode.isLogical()
                        && ((bNode.rhs() instanceof JoinPredecessorExpression && ((JoinPredecessorExpression) bNode.rhs()).getExpression() instanceof FunctionNode)
                        || (bNode.lhs() instanceof JoinPredecessorExpression && ((JoinPredecessorExpression) bNode.lhs()).getExpression() instanceof FunctionNode))) {
                        // case: var f1 = xxx || function () {}
                    // the function here is already, need to be just fixed the name offsets
                    createVariable = false;
                } else if (bNode.isAssignment()) {
                    createVariable = false;
                    if (parentFn.getProperty(varNode.getName().getName()) == null) {
                        while (bNode.rhs() instanceof BinaryNode && bNode.rhs().isAssignment()) {
                                // the cycle is trying to find out a FunctionNode at the end of assignements
                            // case var f1 = f2 = f3 = f4 = function () {}
                            bNode = (BinaryNode) bNode.rhs();
                        }
                        if (bNode.rhs() instanceof FunctionNode) {
                                // case var f1 = f2 = function (){};
                            // -> the variable will be reference fo the function
                            FunctionNode fNode = (FunctionNode) bNode.rhs();
                            JsObject original = parentFn.getProperty(modelBuilder.getFunctionName(fNode));
                            if (original != null) {
                                Identifier varName = new Identifier(varNode.getName().getName(), getOffsetRange(varNode.getName()));
                                OffsetRange range = varName.getOffsetRange();
                                JsFunctionReference variable = new JsFunctionReference(parentFn, varName, (JsFunction) original, true, original.getModifiers());
                                variable.addOccurrence(varName.getOffsetRange());
                                parentFn.addProperty(varName.getName(), variable);
                            }
                        }
                    }
                }
            } else if (parentFn.getProperty(varNode.getName().getName()) != null) {
                // the name is already used by a function. 
                if (!(init instanceof CallNode) && !(init instanceof UnaryNode)) {
                        // we skip the var declaration basically, but has to be added occuerences for the existing property 
                    // with the same name
                    parentFn.getProperty(varNode.getName().getName()).addOccurrence(getOffsetRange(varNode.getName()));
                }
                createVariable = false;
            }
            if (createVariable) {
                // skip the variables that are syntetic 
                Identifier varName = new Identifier(varNode.getName().getName(), getOffsetRange(varNode.getName()));
                OffsetRange range = varNode.getInit() instanceof ObjectNode ? new OffsetRange(varNode.getName().getStart(), ((ObjectNode) varNode.getInit()).getFinish())
                        : varName.getOffsetRange();
                JsObject variable = handleArrayCreation(varNode.getInit(), parentFn, varName);
                if (variable == null) {
                    JsObjectImpl newObject = new JsObjectImpl(parentFn, varName, range, parserResult.getSnapshot().getMimeType(), null);
                    variable = newObject;
                }
                variable.addOccurrence(varName.getOffsetRange());
                parentFn.addProperty(varName.getName(), variable);
                variable.addOccurrence(varName.getOffsetRange());

                if (docHolder != null) {
                    ((JsObjectImpl) variable).setDocumentation(docHolder.getDocumentation(varNode));
                    ((JsObjectImpl) variable).setDeprecated(docHolder.isDeprecated(varNode));
                }
            }
        }
    }
     

    private List<Identifier> fqnFromType (final Type type) {
        List<Identifier> fqn = new ArrayList<Identifier>();
        String typeName = type.getType();
        int offset = type.getOffset();
        if (typeName.indexOf('.') > -1) {
            String[] parts = typeName.split("\\.");
            int delta = 0;
            for (int i = 0; i < parts.length; i++) {
                fqn.add(new Identifier(parts[i], offset + delta));
                delta = delta + parts[i].length() + 1;
            }
        } else {
            fqn.add(new Identifier(typeName, offset));
        }
        return fqn;
    }
    
    private void markOccurrences (List<Identifier> fqn) {
        JsObject whereOccurrence = getGlobalObject();
        for (Identifier iden: fqn) {
            whereOccurrence = whereOccurrence.getProperty(iden.getName());
            if (whereOccurrence != null) {
                whereOccurrence.addOccurrence(iden.getOffsetRange());
            } else {
                break;
            }
        }
    }
    
    private JsArray handleArrayCreation(Node initNode, JsObject parent, Identifier name) {
        if (initNode instanceof UnaryNode && parent != null) {
            UnaryNode uNode = (UnaryNode)initNode;
            if (uNode.tokenType() == TokenType.NEW && uNode.getExpression() instanceof CallNode) {
                CallNode cNode = (CallNode)uNode.getExpression();
                if (cNode.getFunction() instanceof IdentNode && "Array".equals(((IdentNode)cNode.getFunction()).getName())) {
                    List<TypeUsage> itemTypes = new ArrayList<TypeUsage>();
                    for (Node node : cNode.getArgs()) {
                        itemTypes.addAll(ModelUtils.resolveSemiTypeOfExpression(modelBuilder, node));
                    }
                    EnumSet<Modifier> modifiers = parent.getJSKind() != JsElement.Kind.FILE ? EnumSet.of(Modifier.PRIVATE) : EnumSet.of(Modifier.PUBLIC);
                    JsArrayImpl result = new JsArrayImpl(parent, name, name.getOffsetRange(), true, modifiers, parserResult.getSnapshot().getMimeType(), null);
                    result.addTypesInArray(itemTypes);
                    return result;
                }
            }
        }
        return null;
    }
    
    @Override
    public boolean enterLiteralNode(LiteralNode lNode) {
        Node lastVisited = getPreviousFromPath(1);
        if (lNode instanceof LiteralNode.ArrayLiteralNode) {
            LiteralNode.ArrayLiteralNode aNode = (LiteralNode.ArrayLiteralNode)lNode;
            List<Identifier> fqName = null;
            int pathSize = getPath().size();
            boolean isDeclaredInParent = false;
            boolean isPrivate = false;
            boolean treatAsAnonymous = false;
            JsObject parent = null;
            
            if (lastVisited instanceof TernaryNode && pathSize > 1) {
                lastVisited = getPath().get(pathSize - 2);
            } 
            int pathIndex = 1;
            
            while(lastVisited instanceof BinaryNode 
                    && (pathSize > pathIndex)
                    && ((BinaryNode)lastVisited).tokenType() != TokenType.ASSIGN) {
                pathIndex++;
                lastVisited = getPath().get(pathSize - pathIndex);
            }
            if ( lastVisited instanceof VarNode) {
                fqName = getName((VarNode)lastVisited, parserResult);
                isDeclaredInParent = true;
                JsObject declarationScope = ((VarNode)lastVisited).isLet() ? modelBuilder.getCurrentDeclarationScope() : modelBuilder.getCurrentDeclarationFunction();
                parent = declarationScope;
                if (fqName.size() == 1 && !ModelUtils.isGlobal(declarationScope)) {
                    isPrivate = true;
                }
            } else if (lastVisited instanceof PropertyNode) {
                fqName = getName((PropertyNode) lastVisited);
                isDeclaredInParent = true;
            } else if (lastVisited instanceof BinaryNode) {
                BinaryNode binNode = (BinaryNode) lastVisited;
                if (binNode.lhs() instanceof IndexNode) {
                    Node index =  ((IndexNode)binNode.lhs()).getIndex();
                    if (!(index instanceof LiteralNode && ((LiteralNode)index).isString())) {
                        treatAsAnonymous = true;
                    }
                } 
                if (!treatAsAnonymous) {
                    if (getPath().size() > 1) {
                        lastVisited = getPath().get(getPath().size() - pathIndex - 1);
                    }
                    fqName = getName(binNode, parserResult);
                    if ((binNode.lhs() instanceof IdentNode)
                            || (binNode.lhs() instanceof AccessNode
                            && ((AccessNode) binNode.lhs()).getBase() instanceof IdentNode
                            && ((IdentNode) ((AccessNode) binNode.lhs()).getBase()).getName().equals(ModelUtils.THIS))) { //NOI18N
                        if (lastVisited instanceof ExpressionStatement && !fqName.get(0).getName().equals(ModelUtils.THIS)) { //NOI18N
                            // try to catch the case: pool = [];
                            List<Identifier> objectName = fqName.size() > 1 ? fqName.subList(0, fqName.size() - 1) : fqName;
                            JsObject existingArray = ModelUtils.getJsObject(modelBuilder, objectName, false);
                            if (existingArray != null) {
                                existingArray.addOccurrence(fqName.get(fqName.size() - 1).getOffsetRange());
                                return super.enterLiteralNode(lNode);
                            }
                        } else {
                            isDeclaredInParent = true;
                            if (!(binNode.lhs() instanceof IdentNode)) {
                                parent = resolveThis(modelBuilder.getCurrentObject());
                            }
                        }
                    }
                }
            } else if (lastVisited instanceof CallNode || lastVisited instanceof LiteralNode.ArrayLiteralNode
                    || lastVisited instanceof ReturnNode || lastVisited instanceof AccessNode) {
                // probably an anonymous array as a parameter of a function call
                // or array in an array: var a = [['a', 10], ['b', 20]];
                // or [1,2,3].join();
                treatAsAnonymous = true;
            }
            if (!isDeclaredInParent) {
                if (lastVisited instanceof FunctionNode) {
                    isDeclaredInParent = ((FunctionNode) lastVisited).getKind() == FunctionNode.Kind.SCRIPT;
                }
            }
            JsArrayImpl array = null;
            if (!treatAsAnonymous) {
//                if (fqName == null || fqName.isEmpty()) {
//                    fqName = new ArrayList<Identifier>(1);
//                    fqName.add(new Identifier("UNKNOWN", //NOI18N
//                            new OffsetRange(lNode.getStart(), lNode.getFinish())));
//                }
                
                if (fqName != null && !fqName.isEmpty() && fqName.get(0) != null) {
                    if (ModelUtils.THIS.equals(fqName.get(0).getName())) {
                        parent = resolveThis(modelBuilder.getCurrentObject());
                        fqName.remove(0);
                        JsObject tmpObject = parent;
                        while (tmpObject.getParent() != null) {
                            Identifier dName = tmpObject.getDeclarationName();
                            fqName.add(0, dName != null ? tmpObject.getDeclarationName() : new Identifier(tmpObject.getName(), OffsetRange.NONE));
                            tmpObject = tmpObject.getParent();
                        }
                    }
                    array = ModelElementFactory.create(parserResult, aNode, fqName, modelBuilder, isDeclaredInParent, parent);
                    if (array != null && isPrivate) {
                        array.getModifiers().remove(Modifier.PUBLIC);
                        array.getModifiers().add(Modifier.PRIVATE);
                    }
                }
            } else {
                array = ModelElementFactory.createAnonymousObject(parserResult, aNode, modelBuilder);
            }
            if (array != null) {
                int aOffset = fqName == null ? lastVisited.getStart() : fqName.get(fqName.size() - 1).getOffsetRange().getEnd();
                array.addAssignment(ModelUtils.resolveSemiTypeOfExpression(modelBuilder, lNode), aOffset);
                for (Node item : aNode.getElementExpressions()) {
                    array.addTypesInArray(ModelUtils.resolveSemiTypeOfExpression(modelBuilder, item));
                }
                if (!functionArgumentStack.isEmpty()) {
                    functionArgumentStack.peek().add(array);
                }
            }
        } 
        return super.enterLiteralNode(lNode);
    }

    @Override
    public boolean enterObjectNode(ObjectNode objectNode) {
        Node previousVisited = getPath().get(getPath().size() - 1);
        if(previousVisited instanceof CallNode
                || previousVisited instanceof LiteralNode.ArrayLiteralNode
                || previousVisited instanceof ExpressionStatement) {
            // TODO there should be handled anonymous object that are going as parameter to a funciton
            //create anonymous object
            JsObjectImpl object = ModelElementFactory.createAnonymousObject(parserResult, objectNode,  modelBuilder);
            modelBuilder.setCurrentObject(object);
            object.setJsKind(JsElement.Kind.OBJECT_LITERAL);
            if (!functionArgumentStack.isEmpty()) {
                functionArgumentStack.peek().add(object);
            }
            return super.enterObjectNode(objectNode);
        } else if (previousVisited instanceof ReturnNode
                 || (previousVisited instanceof BinaryNode && ((BinaryNode)previousVisited).tokenType() == TokenType.COMMARIGHT)) {
            JsObjectImpl objectScope = ModelElementFactory.createAnonymousObject(parserResult, objectNode, modelBuilder);
            modelBuilder.setCurrentObject(objectScope);
            objectScope.setJsKind(JsElement.Kind.OBJECT_LITERAL);
        } else if (previousVisited instanceof ExportNode && ((ExportNode)previousVisited).isDefault()) { 
            // we are handling case: export default {}
            // the node should be visible in navigator
            List<Identifier> fqName = new ArrayList<>(1);
            fqName.add(new Identifier("default", OffsetRange.NONE)); // NOI18N
            JsObjectImpl objectScope = ModelElementFactory.create(parserResult, objectNode, fqName, modelBuilder, true); //ModelElementFactory.createAnonymousObject(parserResult, objectNode, modelBuilder);
            modelBuilder.setCurrentObject(objectScope);
            objectScope.setJsKind(JsElement.Kind.OBJECT_LITERAL);
        } else {
            List<Identifier> fqName = null;
            int pathSize = getPath().size();
            boolean isDeclaredInParent = false;
            boolean isDeclaredThroughThis = false;
            boolean isPrivate = false;
            boolean treatAsAnonymous = false;
            
            int pathIndex = 1;
            Node lastVisited = getPath().get(pathSize - pathIndex);
            VarNode varNode = null;
            
            if (lastVisited instanceof JoinPredecessorExpression) {
                pathIndex++;
                lastVisited = getPath().get(pathSize - pathIndex);
            }
            if (lastVisited instanceof TernaryNode && pathSize > 1) {
                TernaryNode tNode = (TernaryNode)lastVisited;
                lastVisited = getPath().get(pathSize - pathIndex - 1);
                if (lastVisited instanceof ExpressionStatement || lastVisited instanceof BinaryNode) {
                    JoinPredecessorExpression trueExpression = tNode.getTrueExpression();
                    JoinPredecessorExpression falseExpression = tNode.getFalseExpression();
                    if (trueExpression.getExpression().equals(objectNode) || falseExpression.getExpression().equals(objectNode)) {
                        // now we have to find out, whether we are in parameter block
                        int blockIndex = pathIndex + 1;
                        Block block = null;
                        while (blockIndex < getPath().size() && block == null) {
                            if (getPreviousFromPath(++blockIndex) instanceof Block) {
                                block = (Block)getPreviousFromPath(blockIndex);
                            }
                        }
                        // this is can be case when the object literal is a part of destructure assignman pattern used as parameter
                        // function drawES6Chart({size = 'big', cords = { x: 0, y: 0 , z: 0}, radius = 25} = {}) {}
                        treatAsAnonymous = block != null && block.isParameterBlock();
                    }
                } 
            } 
            if (lastVisited instanceof BinaryNode) {
                BinaryNode bNode = (BinaryNode)lastVisited;
                if (bNode.lhs().equals(objectNode)) {
                    // case of destructuring assignment { a, b} = ....
                    // we should not create object in the model. 
                    return super.enterObjectNode(objectNode);
                } else if (bNode.lhs() instanceof ObjectNode && bNode.rhs().equals(objectNode)) {
                    // case of destructuring assignment {a, b} = {a:1, b:2}
                    // do nothing/ already processed in binary node. 
                    return false;
                }
            }
            
            while(lastVisited instanceof BinaryNode 
                    && (pathSize > pathIndex)
                    && ((BinaryNode)lastVisited).tokenType() != TokenType.ASSIGN) {
                pathIndex++;
                lastVisited = getPath().get(pathSize - pathIndex);
            }
            if ( lastVisited instanceof VarNode) {
                fqName = getName((VarNode)lastVisited, parserResult);
                isDeclaredInParent = true;
                JsObject declarationScope = modelBuilder.getCurrentDeclarationFunction();
                varNode = (VarNode)lastVisited;
                if (fqName.size() == 1 && !ModelUtils.isGlobal(declarationScope)) {
                    isPrivate = true;
                }
            } else if (lastVisited instanceof PropertyNode) {
                fqName = getName((PropertyNode) lastVisited);
                isDeclaredInParent = true;
            } else if (lastVisited instanceof AccessNode) {
                treatAsAnonymous = true;
            } else if (lastVisited instanceof BinaryNode) {
                BinaryNode binNode = (BinaryNode) lastVisited;
                Node binLhs = binNode.lhs();
                if (binLhs instanceof IndexNode) {
                    Node index =  ((IndexNode)binLhs).getIndex();
                    if (!(index instanceof LiteralNode && ((LiteralNode)index).isString())) {
                        treatAsAnonymous = true;
                    }
                } 
                if (!treatAsAnonymous) {
                    if (getPath().size() > 1) {
                        lastVisited = getPath().get(getPath().size() - pathIndex - 1);
                        if (lastVisited instanceof VarNode) {
                            varNode = (VarNode) lastVisited;
                        }
                    }
                    fqName = getName(binNode, parserResult);
                    if (binLhs instanceof IdentNode || (binLhs instanceof AccessNode
                            && ((AccessNode) binLhs).getBase() instanceof IdentNode
                            && ((IdentNode) ((AccessNode) binLhs).getBase()).getName().equals(ModelUtils.THIS))) {
                        // if it's not declared throgh the var node, then the variable doesn't have to be declared here
                        isDeclaredInParent = (binLhs instanceof IdentNode &&  varNode != null);
                        if (binLhs instanceof AccessNode) {
                            isDeclaredInParent = true;
                            isDeclaredThroughThis = true;
                        }
                    }
                }
            }
            if (!isDeclaredInParent) {
                if (lastVisited instanceof FunctionNode) {
                    isDeclaredInParent = ((FunctionNode) lastVisited).getKind() == FunctionNode.Kind.SCRIPT;
                }
            }
            if (!treatAsAnonymous) {
                if (fqName == null || fqName.isEmpty()) {
                    fqName = new ArrayList<Identifier>(1);
                    fqName.add(new Identifier("UNKNOWN", //NOI18N
                            new OffsetRange(objectNode.getStart(), objectNode.getFinish())));
                }
                JsObjectImpl objectScope;
                if (varNode != null) {
                    objectScope = modelBuilder.getCurrentObject();
                } else {
                    Identifier name = fqName.get(fqName.size() - 1);
                    JsObject alreadyThere = null;
                    if (isDeclaredThroughThis) {
                        JsObject thisIs = resolveThis(modelBuilder.getCurrentObject());
                        alreadyThere = thisIs.getProperty(name.getName());
                    } else {
                        if (isDeclaredInParent) {
                            if (lastVisited instanceof PropertyNode) {
                                alreadyThere = modelBuilder.getCurrentObject().getProperty(name.getName());
                            } else {
                                alreadyThere = ModelUtils.getJsObjectByName(modelBuilder.getCurrentDeclarationFunction(), name.getName());
                            }
                        } else {
                            if (fqName.size() == 1) {
                                alreadyThere = ModelUtils.getScopeVariable(modelBuilder.getCurrentDeclarationScope(), name.getName());
                            }
                            if (alreadyThere == null) {
                                alreadyThere = ModelUtils.getJsObject(modelBuilder, fqName, true);
                            }
                        }
                    }

                    objectScope = (alreadyThere == null) 
                            ? ModelElementFactory.create(parserResult, objectNode, fqName, modelBuilder, isDeclaredInParent)
                            : (JsObjectImpl)alreadyThere;
                    if (alreadyThere != null) {
                        ((JsObjectImpl)alreadyThere).addOccurrence(name.getOffsetRange());
                    }
                }
                if (objectScope != null) {
                    objectScope.setJsKind(JsElement.Kind.OBJECT_LITERAL);
                    if (!objectScope.isDeclared()) {
                        // the objec literal is always declared
                        objectScope.setDeclared(true);
                    }
                    modelBuilder.setCurrentObject(objectScope);
                    if (isPrivate) {
                        objectScope.getModifiers().remove(Modifier.PUBLIC);
                        objectScope.getModifiers().add(Modifier.PRIVATE);
                    }
                }
            } else {
                JsObjectImpl objectScope = ModelElementFactory.createAnonymousObject(parserResult, objectNode, modelBuilder);
                modelBuilder.setCurrentObject(objectScope);
            }
            
        }

        return super.enterObjectNode(objectNode);
    }

    @Override
    public Node leaveObjectNode(ObjectNode objectNode) {
        Node lastVisited = getPreviousFromPath(2);
        
        if (lastVisited instanceof BinaryNode) {
            BinaryNode bNode = (BinaryNode)lastVisited;
            if (bNode.lhs().equals(objectNode)) {
                // case of destructuring assignment { a, b} = ....
                // we dob't create object in the model, but process the property nodes -> skip reseting modelBuilder
                return super.leaveObjectNode(objectNode);
            }
        }
        modelBuilder.reset();
        return super.leaveObjectNode(objectNode);
    }

    @Override
    public boolean enterPropertyNode(PropertyNode propertyNode) {
        final Expression key = propertyNode.getKey();
        final Expression value = propertyNode.getValue();
        List<Expression> decorators = propertyNode.getDecorators();
        if (decorators != null && !decorators.isEmpty()) {
            for (Expression decorator : decorators) {
                if (decorator instanceof IdentNode) {
                    // in such case, this is probaly a function
                    addOccurence((IdentNode)decorator, false, true);
                } else {
                    decorator.accept(this);
                }
            }
        }
        if ((key instanceof IdentNode || key instanceof LiteralNode)
                && !(value instanceof ObjectNode
                || value instanceof FunctionNode)
                && !propertyNode.isComputed()) {
            final JsObjectImpl parent = modelBuilder.getCurrentObject();
            Identifier name = null;
            if (key instanceof IdentNode) {
                name = ModelElementFactory.create(parserResult, (IdentNode)key);
            } else if (key instanceof LiteralNode) {
                name = ModelElementFactory.create(parserResult, (LiteralNode)key);
            }
            if (name != null) {
                if (key instanceof IdentNode && value instanceof IdentNode) {
                    IdentNode iKey = (IdentNode)key;
                    IdentNode iValue = (IdentNode)value;
                    if (iKey.getName().equals(iValue.getName()) && iKey.getStart() == iValue.getStart() && iKey.getFinish() == iValue.getFinish()) {
                        // it's object initializer shorthand property names
                        // (ES6) var o = { a, b, c }; The variables a, b and c has to exists and properties are references to the orig var
                        JsObject variable = ModelUtils.getScopeVariable(modelBuilder.getCurrentDeclarationScope(), name.getName());
                        if (variable != null) {
                            parent.addProperty(variable.getName(), variable);
                            variable.addOccurrence(name.getOffsetRange());
                            // don't continue. 
                            return false;
                        }
                    }
                }
                JsObjectImpl property = (JsObjectImpl)parent.getProperty(name.getName());
                if (property == null) {
                    if (parent.getJSKind() == JsElement.Kind.OBJECT_LITERAL || parent.getJSKind() == JsElement.Kind.ANONYMOUS_OBJECT) {
                        property = ModelElementFactory.create(parserResult, propertyNode, name, modelBuilder, true);
                    } else {
                        // the object literal was not created before property node,
                        // so it can be destructive assignment on the left side
                        
                        // find the block node to decide whether's the property node are not
                        // parameters defined via destructive assignment
                        // case function drawES6Chart({size = 'big', cords = { x: 0, y: 0 }, radius = 25} = test) {}
                        int index = 1;
                        Node node = getPreviousFromPath(index);
                        BinaryNode bNode = null;
                        ObjectNode oNode = null;
                        while (index < getPath().size() && !(node instanceof Block)) {
                            if (bNode == null && node instanceof BinaryNode) {
                                bNode = (BinaryNode)node;
                            } else if (oNode == null && node instanceof ObjectNode) {
                                oNode = (ObjectNode)node;
                            }
                            node = getPreviousFromPath(++index);
                        }
                        boolean isDestructiveParam = false;
                        if (node instanceof Block) {
                            Block block = (Block)node;
                            if (block.isParameterBlock() && oNode != null && bNode != null && bNode.lhs().equals(oNode) ) {
                                // we are in parameters defined via destructive assignment
                                JsFunction currentFnImpl = modelBuilder.getCurrentDeclarationFunction();
                                property = (JsObjectImpl)currentFnImpl.getParameter(name.getName());
                                isDestructiveParam = true;
                            }
                        }
                        if (!isDestructiveParam) {
                            property = ModelElementFactory.create(parserResult, propertyNode, name, modelBuilder, true);
                        }
                    }
                } else {
                    // The property can be already defined, via a usage before declaration (see testfiles/model/simpleObject.js - called property)
                    JsObjectImpl newProperty = ModelElementFactory.create(parserResult, propertyNode, name, modelBuilder, true);
                    if (newProperty != null) {
                        newProperty.addOccurrence(property.getDeclarationName().getOffsetRange());
                        for(Occurrence occurrence : property.getOccurrences()) {
                            newProperty.addOccurrence(occurrence.getOffsetRange());
                        }
                        property = newProperty;
                    }
                }

                if (property != null) {
//                    if (propertyNode.getGetter() != null) {
//                        FunctionNode getter = ((FunctionNode)((ReferenceNode)propertyNode.getGetter()).getReference());
//                        property.addOccurrence(new OffsetRange(getter.getIdent().getStart(), getter.getIdent().getFinish()));
//                    }
//
//                    if (propertyNode.getSetter() != null) {
//                        FunctionNode setter = ((FunctionNode)((ReferenceNode)propertyNode.getSetter()).getReference());
//                        property.addOccurrence(new OffsetRange(setter.getIdent().getStart(), setter.getIdent().getFinish()));
//                    }
                    property.getParent().addProperty(name.getName(), property);
                    property.setDeclared(true);
                    if(value instanceof CallNode) {
                        // TODO for now, don't continue. There shoudl be handled cases liek
                        // in the testFiles/model/property02.js file
                        //return null;
                    } else {
                        Collection<TypeUsage> types = ModelUtils.resolveSemiTypeOfExpression(modelBuilder, value);
                        if (!types.isEmpty()) {
                            property.addAssignment(types, name.getOffsetRange().getStart());
                        }
                        if (value instanceof IdentNode) {
                            IdentNode iNode = (IdentNode)value;
                            if (!iNode.getPropertyName().equals(name.getName())) {
                                addOccurence((IdentNode)value, false);
                            } else {
                                // handling case like property: property
                                if (parent.getParent() != null) {
                                    occurrenceBuilder.addOccurrence(name.getName(), getOffsetRange(iNode), modelBuilder.getCurrentDeclarationScope(), parent.getParent(), modelBuilder.getCurrentWith(), false, false);
                                }
                            }
                        }
                    }
                }
            }
        } if (propertyNode.isComputed()) {
            propertyNode.getKey().accept(this);
        }
        return super.enterPropertyNode(propertyNode);
    }
//
//    @Override
//    public Node enter(ReferenceNode referenceNode) {
//        FunctionNode reference = referenceNode.getReference();
//        if (reference != null) {
//            Node lastNode = getPreviousFromPath(1);
//            if (!((lastNode instanceof VarNode) && !reference.isAnonymous())) {
//                if (lastNode instanceof BinaryNode && !reference.isAnonymous()) {
//                    Node lhs = ((BinaryNode)lastNode).lhs();
//                    List<Identifier> nodeName = getNodeName(lhs, parserResult);
//                    if (nodeName != null && !nodeName.isEmpty()) {
//                        JsObject jsObject = null;
//                        if (ModelUtils.THIS.equals(nodeName.get(0).getName())) { //NOI18N
//                            jsObject = resolveThis(modelBuilder.getCurrentObject());
//                            for (int i = 1; jsObject != null && i < nodeName.size(); i++ ) {
//                                jsObject = jsObject.getProperty(nodeName.get(i).getName());
//                            }
//                        } else {
//                            jsObject = ModelUtils.getJsObject(modelBuilder, nodeName, true);
//                        }
//                        if (jsObject != null) {
//                            Identifier name = nodeName.get(nodeName.size() - 1);
//                            DeclarationScopeImpl ds = modelBuilder.getCurrentDeclarationScope();
//                            String referenceName = reference.getIdent().getName();
//                            JsObject originalFnc = ds.getProperty(referenceName);
//                            while (originalFnc != null && !(originalFnc instanceof JsFunction)) {
//                                if (ds.getParentScope() != null) {
//                                    ds = (DeclarationScopeImpl)ds.getParentScope();
//                                    originalFnc = ds.getProperty(referenceName);
//                                } else {
//                                    originalFnc = null;
//                                }
//                            }
//                            if (originalFnc != null && originalFnc instanceof JsFunction) {
//                                //property contains the definition of the function
//                                JsObject newRef = new JsFunctionReference(jsObject.getParent(), name, (JsFunction)originalFnc, true, jsObject.getModifiers());
//                                jsObject.getParent().addProperty(jsObject.getName(), newRef);
//                                for (Occurrence occurence : jsObject.getOccurrences()) {
//                                    newRef.addOccurrence(occurence.getOffsetRange());
//                                }
//                                if (originalFnc instanceof JsFunctionImpl) {
////                                    ((JsFunctionImpl)originalFnc).setAnonymous(true);
//                                    JsObject parent = jsObject.getParent();
//                                    if (ModelUtils.PROTOTYPE.equals(parent.getName())) {
//                                        parent = parent.getParent();
//                                    }
//                                    if (parent != null) {
//                                        Collection<JsObject> propertiesCopy = new ArrayList(originalFnc.getProperties().values());
//                                        for (JsObject property : propertiesCopy) {
//                                            if (!property.getModifiers().contains(Modifier.PRIVATE)) {
//                                                ModelUtils.moveProperty(parent, property);
//                                            }
//                                        }
//                                    }
//                                }
//                                
//                            }
//                            
//                        }
//                    }
//                } else {
//                    addToPath(referenceNode);
//                    reference.accept(this);
//                    removeFromPathTheLast();
//                }
//            } 
//            return null;
//        }
//        return super.enter(referenceNode);
//    }
//
    @Override
    public boolean enterReturnNode(ReturnNode returnNode) {
        Node expression = returnNode.getExpression();
        Collection<TypeUsage> types = ModelUtils.resolveSemiTypeOfExpression(modelBuilder, expression);
        if (expression == null) {
            types.add(new TypeUsage(Type.UNDEFINED, returnNode.getStart(), true));
        } else {
            if (expression instanceof IdentNode) {
                addOccurence((IdentNode)expression, false);
            }
            if(types.isEmpty()) {
               types.add(new TypeUsage(Type.UNRESOLVED, returnNode.getStart(), true));
            }
        }
        JsFunctionImpl function = modelBuilder.getCurrentDeclarationFunction();
        function.addReturnType(types);
        return super.enterReturnNode(returnNode);
    }

    @Override
    public boolean enterTernaryNode(TernaryNode ternaryNode) {
        if (ternaryNode.getTest() instanceof IdentNode) {
            addOccurence((IdentNode)ternaryNode.getTest(), false);
        }
        if (ternaryNode.getTrueExpression().getExpression() instanceof IdentNode) {
            addOccurence((IdentNode)ternaryNode.getTrueExpression().getExpression(), false);
        }
        if (ternaryNode.getFalseExpression().getExpression() instanceof IdentNode) {
            addOccurence((IdentNode)ternaryNode.getFalseExpression().getExpression(), false);
        }
        return super.enterTernaryNode(ternaryNode);
    }

    @Override
    public boolean enterUnaryNode(UnaryNode unaryNode) {
        if (unaryNode.getExpression() instanceof IdentNode) {
            addOccurence((IdentNode) unaryNode.getExpression(), false);
        }
        return super.enterUnaryNode(unaryNode);
    }

    @Override
    public boolean enterVarNode(VarNode varNode) {        
        Node init = varNode.getInit();
        FunctionNode rNode = null;
        if (init instanceof FunctionNode) {
            rNode = (FunctionNode)init;
        } else if (init instanceof BinaryNode) {
            // this should handle cases like 
            // var prom  = another.prom = function prom() {}
            BinaryNode bNode = (BinaryNode)init;
            while (bNode.rhs() instanceof BinaryNode ) {
                bNode = (BinaryNode)bNode.rhs();
            }
            if (bNode.rhs() instanceof FunctionNode) {
                 rNode = (FunctionNode) bNode.rhs();
            }
        } else if (init instanceof UnaryNode && ((UnaryNode)init).getExpression() instanceof CallNode
                    && ((CallNode)((UnaryNode)init).getExpression()).getFunction() instanceof FunctionNode) {
            rNode = (FunctionNode)((CallNode)((UnaryNode)init).getExpression()).getFunction();
//            Identifier varName = new Identifier(varNode.getName().getName(), getOffsetRange(varNode.getName()));
//            OffsetRange range = varNode.getInit() instanceof ObjectNode ? new OffsetRange(varNode.getName().getStart(), ((ObjectNode)varNode.getInit()).getFinish()) 
//                    : varName.getOffsetRange();
//            JsObjectImpl parentFn = modelBuilder.getCurrentDeclarationFunction();
//            JsObject variable = handleArrayCreation(varNode.getInit(), parentFn, varName);
//            if (variable == null) {
//                JsObjectImpl newObject = new JsObjectImpl(parentFn, varName, range, parserResult.getSnapshot().getMimeType(), null);
//                variable = newObject;
//            }
//            variable.addOccurrence(varName.getOffsetRange());
//            JsObject property = parentFn.getProperty(varName.getName());
//            parentFn.addProperty(varName.getName(), variable);
//            variable.addProperty(property.getName(), property);
//            Collection<TypeUsage> returns = ModelUtils.resolveSemiTypeOfExpression(modelBuilder, init);
//            for (TypeUsage type : returns) {
//                variable.addAssignment(type, init.getStart());
//            }
//            if (rNode.isNamedFunctionExpression() && rNode.getName().equals(varName.getName())) {
//                // the name of function is the same as the variable
//                // var MyLib = new function MyLib() {};
//                ModelUtils.copyOccurrences(property, variable);
//            }
                        
        }
         if (!(init instanceof ObjectNode || rNode != null
                 || init instanceof LiteralNode.ArrayLiteralNode
                 || init instanceof ClassNode
                 || varNode.isExport())) {
            JsObject parent = modelBuilder.getCurrentObject();
            //parent = canBeSingletonPattern(1) ? resolveThis(parent) : parent;
            if (parent instanceof CatchBlockImpl) {
                parent = parent.getParent();
            }
            while (parent instanceof JsWith) {
                parent = parent.getParent();
            }
            JsObjectImpl variable = (JsObjectImpl)parent.getProperty(varNode.getName().getName());
            Identifier name = ModelElementFactory.create(parserResult, varNode.getName());
            if (name != null) {
                if (variable == null) {
                    // variable si not defined, so it has to be from global scope
                    // or from a code structure like for cycle
                    // or it can be from parameter block

                    Node lastVisited = getPreviousFromPath(1);
                    if (parent instanceof JsFunctionImpl && lastVisited instanceof Block && ((Block)lastVisited).isParameterBlock()) {
                        // it's a parameter definition
                        variable = new ParameterObject(parent, name, parent.getMimeType(), parent.getSourceLabel());
                        ((JsFunctionImpl)parent).addParameter(variable);
                    } else {
                        variable = new JsObjectImpl(parent, name, name.getOffsetRange(),
                            true, parserResult.getSnapshot().getMimeType(), null);
                        parent.addProperty(name.getName(), variable);
                    }
                    if (parent.getJSKind() != JsElement.Kind.FILE) {
                        variable.getModifiers().remove(Modifier.PUBLIC);
                        variable.getModifiers().add(Modifier.PRIVATE);
                    }
                    variable.addOccurrence(name.getOffsetRange());
                } else if (!variable.isDeclared()){
                    // the variable was probably created as temporary before, now we
                    // need to replace it with the real one
                    JsObjectImpl newVariable = new JsObjectImpl(parent, name, name.getOffsetRange(),
                            true, parserResult.getSnapshot().getMimeType(), null);
                    newVariable.addOccurrence(name.getOffsetRange());
                    for(String propertyName: variable.getProperties().keySet()) {
                        JsObject property = variable.getProperty(propertyName);
                        if (property instanceof JsObjectImpl) {
                            ((JsObjectImpl)property).setParent(newVariable);
                        }
                        newVariable.addProperty(propertyName, property);
                    }
                    if (parent.getJSKind() != JsElement.Kind.FILE) {
                        newVariable.getModifiers().remove(Modifier.PUBLIC);
                        newVariable.getModifiers().add(Modifier.PRIVATE);
                    }
                    for(TypeUsage type : variable.getAssignments()) {
                        newVariable.addAssignment(type, type.getOffset());
                    }
                    for(Occurrence occurrence: variable.getOccurrences()){
                        newVariable.addOccurrence(occurrence.getOffsetRange());
                    }
                    parent.addProperty(name.getName(), newVariable);
                    variable = newVariable;
                } 
                JsDocumentationHolder docHolder = JsDocumentationSupport.getDocumentationHolder(parserResult);
                variable.setDeprecated(docHolder.isDeprecated(varNode));
                variable.setDocumentation(docHolder.getDocumentation(varNode));
                if (docHolder.isConstant(varNode)) {
                    variable.setJsKind(JsElement.Kind.CONSTANT);
                }
                if (init instanceof IdentNode) {
                    IdentNode iNode = (IdentNode)init;
                    if (!iNode.getName().equals(variable.getName())) {
                        addOccurrence((IdentNode)init, variable.getName());
                    } else {
                        // the name of variable is the same as already existing function or var or parameter
                        JsFunctionImpl currentFunction = modelBuilder.getCurrentDeclarationFunction();
                        if (currentFunction != null && currentFunction.getParameter(variable.getName()) != null) {
                            // it's a parameter
                            addOccurrence((IdentNode)init, variable.getName());
                        } else {
                            variable.addOccurrence(getOffsetRange(iNode));
                        }
                    }
                    
                }
                modelBuilder.setCurrentObject(variable);
                Collection<TypeUsage> types = ModelUtils.resolveSemiTypeOfExpression(modelBuilder, init);
                if (modelBuilder.getCurrentWith() != null) {
                    ((JsWithObjectImpl)modelBuilder.getCurrentWith()).addObjectWithAssignment(variable);
                }
                for (TypeUsage type : types) {
                    variable.addAssignment(type, varNode.getName().getFinish());
                }
                List<Type> returnTypes = docHolder.getReturnType(varNode);
                if (returnTypes != null && !returnTypes.isEmpty()) {
                    for (Type type : returnTypes) {
                        variable.addAssignment(new TypeUsage(type.getType(), type.getOffset(), true), varNode.getName().getFinish());
                    }
                }
                if (varNode.isConst()) {
                    variable.setJsKind(JsElement.Kind.CONSTANT);
                }
            }
        } else if(init instanceof ObjectNode && !varNode.isExport()) {
            JsObjectImpl function = modelBuilder.getCurrentDeclarationFunction();
            Identifier name = ModelElementFactory.create(parserResult, varNode.getName());
            if (name != null) {
                JsObjectImpl variable = (JsObjectImpl)function.getProperty(name.getName());
                if (variable != null) {
                    variable.setDeclared(true);
                } else {
                    List<Identifier> fqName = getName(varNode, parserResult);
                    variable = ModelElementFactory.create(parserResult, (ObjectNode)varNode.getInit(), fqName, modelBuilder, true);
                }
                if (variable != null) {
                    variable.setJsKind(JsElement.Kind.OBJECT_LITERAL);
                    modelBuilder.setCurrentObject(variable);
                }
            }
        } else if(init instanceof ObjectNode && varNode.isExport()) {
            // we are expecting here that the var node is artificial and is created due to: export default {}
            return false;
        } else if (init instanceof ClassNode) {
            ClassNode cNode = (ClassNode) init;
            // process decorators
            List<Expression> decorators = cNode.getDecorators();
            if (decorators != null && !decorators.isEmpty()) {
                for (Expression decorator : decorators) {
                    if (decorator instanceof IdentNode) {
                        // in such case, this is probaly a function
                        addOccurence((IdentNode)decorator, false, true);
                    } else {
                        decorator.accept(this);
                    }
                }
            }
        }
        return super.enterVarNode(varNode);
    }

    @Override
    public Node leaveVarNode(VarNode varNode) {
        Node init = varNode.getInit();
        FunctionNode rNode = null;
        if (init instanceof BinaryNode) {
            // this should handle cases like 
            // var prom  = another.prom = function prom() {}
            BinaryNode bNode = (BinaryNode)init;
            while (bNode.rhs() instanceof BinaryNode ) {
                bNode = (BinaryNode)bNode.rhs();
            }
            if (bNode.rhs() instanceof FunctionNode) {
                // this should handle cases like 
                // var prom  = another.prom = function prom() {}
                rNode = (FunctionNode) bNode.rhs();
                List<Identifier> name = getNodeName(bNode.lhs(), parserResult);
                if (name != null && !name.isEmpty()) {
                    boolean isPriviliged = name.get(0).getName().equals(ModelUtils.THIS);
                    JsObject parent =  isPriviliged ? resolveThis(modelBuilder.getCurrentObject()) : modelBuilder.getCurrentObject();
                    for (int i = isPriviliged ? 1 : 0; parent != null && i < name.size(); i++) {
                        parent = parent.getProperty(name.get(i).getName());
                    }
                    if (parent!= null && parent instanceof JsFunction) {
                        Identifier propertyName = create(parserResult, varNode.getName());
                        Set<Modifier> modifiers;
                        if (isPriviliged) {
                            modifiers = EnumSet.of(Modifier.PROTECTED);
                        } else if (modelBuilder.getCurrentDeclarationFunction().getJSKind() == JsElement.Kind.FILE) {
                            modifiers = EnumSet.of(Modifier.PUBLIC);
                        } else {
                            modifiers = EnumSet.of(Modifier.PRIVATE);
                        }
                        JsObject property = new JsFunctionReference(modelBuilder.getCurrentObject(), propertyName, (JsFunction)parent, true, modifiers);
                        modelBuilder.getCurrentObject().addProperty(propertyName.getName(), property);
                        property.addOccurrence(propertyName.getOffsetRange());
                    }
                }

            }
//            if (bNode.rhs() instanceof ReferenceNode /*&& bNode.tokenType() == TokenType.ASSIGN*/) {
//                 init = (ReferenceNode) bNode.rhs();
//            }
        } else if (init instanceof FunctionNode) {
            rNode = (FunctionNode)init;
        } else if (init instanceof UnaryNode && ((UnaryNode)init).getExpression() instanceof CallNode
                    && ((CallNode)((UnaryNode)init).getExpression()).getFunction() instanceof FunctionNode) {
            rNode = (FunctionNode)((CallNode)((UnaryNode)init).getExpression()).getFunction();
        }
        if (!(rNode != null || init instanceof LiteralNode.ArrayLiteralNode)
                // XXX can we avoid creation of object ?
                && ModelElementFactory.create(parserResult, varNode.getName()) != null) {
            JsDocumentationHolder docHolder = JsDocumentationSupport.getDocumentationHolder(parserResult);
            List<DocParameter> properties = docHolder.getProperties(varNode);
            for (DocParameter docProperty : properties) {
                String propertyName = docProperty.getParamName().getName();
                String names[];
                int delta = 0;
                if (propertyName.indexOf('.') > 0) {
                    names = propertyName.split("\\.");
                } else {
                    names = new String[]{propertyName};
                }
                JsObject parent = modelBuilder.getCurrentObject();
                for (int i = 0; i < names.length; i++) {
                    String name = names[i];
                    JsObject property = parent.getProperty(name);
                    int startOffset = docProperty.getParamName().getOffsetRange().getStart() + delta;
                    int endOffset = startOffset + name.length();
                    OffsetRange offsetRange = new OffsetRange(startOffset, endOffset);
                    if (property == null) {
                        Identifier iden = new Identifier(name, offsetRange);
                        property = new JsObjectImpl(parent, iden, offsetRange, true, JsTokenId.JAVASCRIPT_MIME_TYPE, null);
                        parent.addProperty(name, property);
                    }
                    property.addOccurrence(offsetRange);
                     if (i == names.length - 1) {
                        for (Type type : docProperty.getParamTypes()) {
                            property.addAssignment(new TypeUsage(type.getType(), endOffset), endOffset);
                        }
                    }
                    delta = delta + name.length() + 1;
                    parent = property;
                    
                }


            }
            modelBuilder.reset();
        }
        return super.leaveVarNode(varNode);
    }

    @Override
    public boolean enterWithNode(WithNode withNode) {
        JsObjectImpl currentObject = modelBuilder.getCurrentObject();
        Collection<TypeUsage> types = ModelUtils.resolveSemiTypeOfExpression(modelBuilder, withNode.getExpression());
        JsWithObjectImpl withObject = new JsWithObjectImpl(currentObject, modelBuilder.getUnigueNameForWithObject(), types, new OffsetRange(withNode.getStart(), withNode.getFinish()), 
                        new OffsetRange(withNode.getExpression().getStart(), withNode.getExpression().getFinish()), modelBuilder.getCurrentWith(), parserResult.getSnapshot().getMimeType(), null);
        currentObject.addProperty(withObject.getName(), withObject);
//        withNode.getExpression().accept(this); // expression should be visted when the with object is the current object.
        modelBuilder.setCurrentObject(withObject);
        withNode.getBody().accept(this);
        modelBuilder.reset();
        return false;
    }

//--------------------------------End of visit methods--------------------------------------

    public Map<FunctionInterceptor, Collection<FunctionCall>> getCallsForProcessing() {
        return functionCalls;
    }

    private boolean fillName(AccessNode node, List<String> result) {
        List<Identifier> fqn = getName(node, parserResult);
        if (fqn != null) {
            for (int i = fqn.size() - 1; i >= 0; i--) {
                result.add(0, fqn.get(i).getName());
            }
        }

        JsObject current = modelBuilder.getCurrentObject();
        while (current != null && current.getDeclarationName() != null) {
            if (current != modelBuilder.getGlobal()) {
                result.add(0, current.getDeclarationName().getName());
            }
            current = current.getParent();
        }
        return true;
    }

    private boolean fillName(IndexNode node, List<String> result) {
        Node index = node.getIndex();
        Node base = node.getBase();
        if (index instanceof LiteralNode && base instanceof AccessNode) {
            LiteralNode literal = (LiteralNode) index;
            if (literal.isString()) {
                result.add(0, literal.getString());
                List<Identifier> fqn = getName((AccessNode) base, parserResult);
                for (int i = fqn.size() - 1; i >= 0; i--) {
                    result.add(0, fqn.get(i).getName());
                }
                return true;
            }
        }
        return false;
    }

    private List<Identifier> getName(PropertyNode propertyNode) {
        List<Identifier> name = new ArrayList<>(1);
        if (propertyNode.getGetter() != null || propertyNode.getSetter() != null) {
            // check whether this is not defining getter or setter of a property.
            Node previousNode = getPreviousFromPath(1);
            if (previousNode instanceof FunctionNode) {
                FunctionNode fNode = (FunctionNode)previousNode;
                String fName = fNode.getIdent().getName();
                if (fName.startsWith("get ") || fName.startsWith("set ")) { //NOI18N
                    name.add(new Identifier(fName,
                        new OffsetRange(fNode.getIdent().getStart(), fNode.getIdent().getFinish())));
                    return name;
                }
            }
        }
        return getName(propertyNode, parserResult);
    }

    private static List<Identifier> getName(PropertyNode propertyNode, ParserResult parserResult) {
        List<Identifier> name = new ArrayList<>(1);
        if (propertyNode.getKey() instanceof IdentNode) {
            IdentNode ident = (IdentNode) propertyNode.getKey();
            name.add(new Identifier(ident.getName(), getOffsetRange(ident)));
        } else if (propertyNode.getKey() instanceof LiteralNode){
            LiteralNode lNode = (LiteralNode)propertyNode.getKey();
            name.add(new Identifier(lNode.getString(),
                    new OffsetRange(lNode.getStart(), lNode.getFinish())));
        }
        return name;
    }

    private static List<Identifier> getName(VarNode varNode, ParserResult parserResult) {
        List<Identifier> name = new ArrayList<>();
        name.add(new Identifier(varNode.getName().getName(),
                new OffsetRange(varNode.getName().getStart(), varNode.getName().getFinish())));
        return name;
    }

    private static List<Identifier> getName(BinaryNode binaryNode, ParserResult parserResult) {
        List<Identifier> name = new ArrayList<>();
        Node lhs = binaryNode.lhs();
        if (lhs instanceof AccessNode) {
            name = getName((AccessNode)lhs, parserResult);
        } else if (lhs instanceof IdentNode) {
            IdentNode ident = (IdentNode) lhs;
            name.add(new Identifier(ident.getName(), getOffsetRange(ident)));
        } else if (lhs instanceof IndexNode) {
            IndexNode indexNode = (IndexNode)lhs;
            if (indexNode.getBase() instanceof AccessNode) {
                List<Identifier> aName = getName((AccessNode)indexNode.getBase(), parserResult);
                if (aName != null) {
                    name.addAll(getName((AccessNode)indexNode.getBase(), parserResult));
                }
                else {
                    return null;
                }
            } else if (indexNode.getBase() instanceof IdentNode) {
                name.add(create(parserResult, (IdentNode)indexNode.getBase()));
            }
            if (indexNode.getIndex() instanceof LiteralNode) {
                LiteralNode lNode = (LiteralNode)indexNode.getIndex();
                name.add(new Identifier(lNode.getPropertyName(), 
                        new OffsetRange(lNode.getStart(), lNode.getFinish())));
            } else if (indexNode.getIndex() instanceof IdentNode) {
                // this is case test[variable] where we don't know the name -> return null
                return null;
            }
        }
        return name;
    }

    private static List<Identifier> getName(AccessNode aNode, ParserResult parserResult) {
        List<Identifier> name = new ArrayList<>();
        name.add(new Identifier(aNode.getProperty(),
                new OffsetRange(aNode.getFinish() - aNode.getProperty().length(), aNode.getFinish())));
        Node base = aNode.getBase();
        while (base instanceof AccessNode || base instanceof CallNode || base instanceof IndexNode) {
            if (base instanceof CallNode) {
                CallNode cNode = (CallNode)base;
                base = cNode.getFunction();
            } else if (base instanceof IndexNode) {
                IndexNode iNode = (IndexNode) base;
                if (iNode.getIndex() instanceof LiteralNode) {
                    LiteralNode lNode = (LiteralNode)iNode.getIndex();
                    if (lNode.isString()) {
                        name.add(new Identifier(lNode.getPropertyName(), 
                                new OffsetRange(lNode.getStart(), lNode.getFinish())));
                    }
                } else {
                    return null;
                } 
                base = iNode.getBase();
            }
            if (base instanceof AccessNode) {
                AccessNode aaNode = (AccessNode)base;
                base = aaNode.getBase();
                name.add(new Identifier(aaNode.getProperty(),
                        new OffsetRange(aaNode.getFinish() - aaNode.getProperty().length(), aaNode.getFinish())));
            }
        }
        Identifier baseIdent = null;
        if (base instanceof IdentNode) {
            IdentNode ident = (IdentNode) base;
            baseIdent = new Identifier(ident.getName(), getOffsetRange(ident));
        } else if (base instanceof LiteralNode) {
            // we fake Number object to handel mark occurrences
            LiteralNode lNode= (LiteralNode) base;
            if (lNode.isNumeric()) {
                baseIdent = new Identifier("Number", OffsetRange.NONE); //NOI8N
            }
        } 
        
        
        if (baseIdent != null) {
            name.add(baseIdent);
            Collections.reverse(name);
            return name;
        } else {
            return null;
        }
    }
    
    private JsObject createJsObject(AccessNode accessNode, ParserResult parserResult, ModelBuilder modelBuilder) {
        List<Identifier> fqn = getName(accessNode, parserResult);
        if (fqn == null) {
            return null;
        }
        JsObject object = null;

        Identifier name = fqn.get(0);
        if (!ModelUtils.THIS.equals(fqn.get(0).getName())) { 
            if (modelBuilder.getCurrentWith() == null) {
                DeclarationScopeImpl currentDS = modelBuilder.getCurrentDeclarationScope();
                JsObject variable = ModelUtils.getScopeVariable(currentDS, name.getName());
                if (variable != null) {
                    if (variable instanceof ParameterObject || variable.getModifiers().contains(Modifier.PRIVATE)) {
                        object = (JsObjectImpl) variable;
                    } else {
                        DeclarationScope variableDS = ModelUtils.getDeclarationScope(variable);
                        if (!variableDS.equals(currentDS)) {
                            object = (JsObjectImpl) variable;
                        } else if (currentDS.getProperty(name.getName()) != null) {
                            Node lastNode = getPreviousFromPath(2);
                            if (lastNode instanceof BinaryNode) {
                                BinaryNode bNode = (BinaryNode) lastNode;
                                if (bNode.lhs().equals(accessNode)) {
                                    object = (JsObjectImpl) variable;
                                }
                            }
                        }
                    }
                }
                if (object == null) {
                    JsObject global = modelBuilder.getGlobal();
                    object = (JsObjectImpl)global.getProperty(name.getName());
                    if (object == null) {
                        object = new JsObjectImpl(global, name, name.getOffsetRange(), false, global.getMimeType(), global.getSourceLabel());
                        global.addProperty(name.getName(), object);
                    }
                } 
            } else {
                JsObject withObject = modelBuilder.getCurrentWith();
                object = (JsObjectImpl)withObject.getProperty(name.getName());
                if (object == null) {
                    object = new JsObjectImpl(withObject, name, name.getOffsetRange(), false, parserResult.getSnapshot().getMimeType(), null);
                    withObject.addProperty(name.getName(), object);
                }
            }       
            object.addOccurrence(name.getOffsetRange());
        } else {
            JsObject current = modelBuilder.getCurrentDeclarationFunction();
            object = (JsObjectImpl)resolveThis(current);
            if (object != null) {
                // find out, whether is not defined in prototype
                if (object.getProperty(fqn.get(1).getName()) == null) {
                    JsObject prototype = object.getProperty(ModelUtils.PROTOTYPE);
                    if (prototype != null && prototype.getProperty(fqn.get(1).getName()) != null) {
                        object = prototype;
                    }
                }
            }
            if (object != null && fqn.size() == 2) {
                // try to handle case
                // function MyF() {
                //      this.f1 = f1;
                //      function f1() {};
                // }
                // in such case the name after this has to be equal to the declared function. 
                // -> in the model, just change  the f1 from private to privilaged. 
                String lastName = fqn.get(1).getName();
                JsObjectImpl property = (JsObjectImpl)object.getProperty(lastName);
                Node lastVisited = getPreviousFromPath(2);
                if (property != null && lastName.equals(property.getName()) && (property.getModifiers().contains(Modifier.PRIVATE) && property.getModifiers().size() == 1)
                        && !(lastVisited instanceof CallNode)) {
                    // if there is CallNode, then it like this.xxx() -> don't change modifiers
                    property.getModifiers().remove(Modifier.PRIVATE);
                    property.getModifiers().add(Modifier.PROTECTED);
                }
            }
        }
        
        if (object != null) {
            JsObjectImpl property = null;
            for (int i = 1; i < fqn.size(); i++) {
                property = (JsObjectImpl)object.getProperty(fqn.get(i).getName());
                if (property != null) {
                    object = property;
                }
            }
            int pathSize = getPath().size();
            Node lastVisited =  pathSize > 1 ? getPath().get(pathSize - 2) : getPath().get(0);
            boolean onLeftSite = false;
            if (lastVisited instanceof BinaryNode) {
                BinaryNode bNode = (BinaryNode)lastVisited;
                onLeftSite = bNode.tokenType() == TokenType.ASSIGN && bNode.lhs().equals(accessNode);       
            }
            String propertyName = accessNode.getProperty();
            // there is a problem in the parser. When there is a line comment after access node, then the finish of access node is finish of the line comment
            int propertyOffsetStart = accessNode.getBase().getFinish() + 1;
            int propertyOffsetEnd = propertyOffsetStart + propertyName.length();
            if (property != null) {
                OffsetRange range = new OffsetRange(propertyOffsetStart, propertyOffsetEnd);
                if(onLeftSite && !property.isDeclared()) {
                    property.setDeclared(true);
                    property.setDeclarationName(new Identifier(property.getName(), range));
                }
                property.addOccurrence(range);
            } else {
                name = ModelElementFactory.create(parserResult, propertyName, propertyOffsetStart, propertyOffsetEnd);
                if (name != null) {
                    if (pathSize > 1 && getPath().get(pathSize - 2) instanceof CallNode) {
                        CallNode cNode = (CallNode)getPath().get(pathSize - 2);
                        if (!cNode.getArgs().contains(accessNode)) {
                            property = ModelElementFactory.createVirtualFunction(parserResult, object, name, cNode.getArgs().size());
                            //property.addOccurrence(name.getOffsetRange());
                        } else {
                            property = new JsObjectImpl(object, name, name.getOffsetRange(), onLeftSite, parserResult.getSnapshot().getMimeType(), null);
                            property.addOccurrence(name.getOffsetRange());
                        }
                    } else {
                        boolean setDocumentation = false;
                        if (isPriviliged(accessNode) && getPath().size() > 1 && (getPreviousFromPath(2) instanceof ExpressionStatement || getPreviousFromPath(1) instanceof ExpressionStatement)) {
                            // google style declaration of properties:  this.buildingID;    
                            onLeftSite = true;
                            setDocumentation = true;
                        }
                        property = new JsObjectImpl(object, name, name.getOffsetRange(), onLeftSite, parserResult.getSnapshot().getMimeType(), null);
                        property.addOccurrence(name.getOffsetRange());
                        if (setDocumentation) {
                            JsDocumentationHolder docHolder = JsDocumentationSupport.getDocumentationHolder(parserResult);
                            if (docHolder != null) {    
                                property.setDocumentation(docHolder.getDocumentation(accessNode));
                                property.setDeprecated(docHolder.isDeprecated(accessNode));
                                List<Type> returnTypes = docHolder.getReturnType(accessNode);
                                if (!returnTypes.isEmpty()) {
                                    for (Type type : returnTypes) {
                                        property.addAssignment(new TypeUsage(type.getType(), type.getOffset(), true), accessNode.getFinish());
                                    }
                                }
                                setModifiersFromDoc(property, docHolder.getModifiers(accessNode));
                            }
                        }
                    }
                    object.addProperty(name.getName(), property);
                    object = property;
                }
            }
        }
        return object;
    }

    /**
     * Gets the node name if it has any (case of AccessNode, BinaryNode, VarNode, PropertyNode).
     *
     * @param node examined node for getting its name
     * @return name of the node if it supports it
     */
    public static List<Identifier> getNodeName(Node node, ParserResult parserResult) {
        if (node instanceof AccessNode) {
            return getName((AccessNode) node, parserResult);
        } else if (node instanceof BinaryNode) {
            return getName((BinaryNode) node, parserResult);
        } else if (node instanceof VarNode) {
            return getName((VarNode) node, parserResult);
        } else if (node instanceof PropertyNode) {
            return getName((PropertyNode) node, parserResult);
        } else if (node instanceof IdentNode) {
            IdentNode ident = ((IdentNode) node);
            return Arrays.<Identifier>asList(new Identifier(
                    ident.getName(), getOffsetRange(ident)));
        } else if (node instanceof FunctionNode) {
            if (((FunctionNode) node).getKind() == FunctionNode.Kind.SCRIPT) {
                return Collections.<Identifier>emptyList();
            }
            IdentNode ident = ((FunctionNode) node).getIdent();
            return Arrays.<Identifier>asList(new Identifier(
                    ident.getName(), getOffsetRange(ident)));
        } else {
            return Collections.<Identifier>emptyList();
        }
    }
//
////    private Variable findVarWithName(final Scope scope, final String name) {
////        Variable result = null;
////        Collection<Variable> variables = ScopeImpl.filter(scope.getElements(), new ScopeImpl.ElementFilter() {
////
////            @Override
////            public boolean isAccepted(ModelElement element) {
////                return element.getJSKind().equals(JsElement.Kind.VARIABLE)
////                        && element.getName().equals(name);
////            }
////        });
////
////        if (!variables.isEmpty()) {
////            result = variables.iterator().next();
////        } else {
////            if (!(scope instanceof FileScope)) {
////                result = findVarWithName((Scope)scope.getInElement(), name);
////            }
////        }
////
////        return result;
////    }
////
////    private Field findFieldWithName(FunctionScope function, final String name) {
////        Field result = null;
////        Collection<? extends Field> fields = function.getFields();
////        result = ModelUtils.getFirst(ModelUtils.getFirst(fields, name));
////        if (result == null && function.getInElement() instanceof FunctionScope) {
////            FunctionScope parent = (FunctionScope)function.getInElement();
////            fields = parent.getFields();
////            result = ModelUtils.getFirst(ModelUtils.getFirst(fields, name));
////        }
////        return result;
////    }
//
    private boolean isInPropertyNode() {
        boolean inFunction = false;
        for (int i = getPath().size() - 1; i > 0 ; i--) {
            final Node node = getPath().get(i);
            if(node instanceof FunctionNode) {
                if (!inFunction) {
                    inFunction = true;
                } else {
                    return false;
                }
            } else if (node instanceof PropertyNode) {
                return true;
            }
        }
        return false;
    }

    private void addOccurence(IdentNode iNode, boolean leftSite) {
        addOccurence(iNode, leftSite, false);
    }

    private void addOccurence(IdentNode iNode, boolean leftSite, boolean isFunction) {
        if (!iNode.isDestructuredParameter()) {
            // skip names of destructured param (it's syntetic)
            addOccurrence(iNode.getName(), getOffsetRange(iNode), leftSite, isFunction);
        }
    }
    
    private void addOccurrence(String name, OffsetRange range, boolean leftSite, boolean isFunction) {
        if (ModelUtils.THIS.equals(name) || Type.UNDEFINED.equals(name)) {
            // don't process this node and undefined
            return;
        }
        occurrenceBuilder.addOccurrence(name, range, modelBuilder.getCurrentDeclarationScope(), modelBuilder.getCurrentObject(), modelBuilder.getCurrentWith(), isFunction, leftSite);
//        DeclarationScope scope = modelBuilder.getCurrentDeclarationScope();
//        JsObject property = null;
//        JsObject parameter = null;
//        JsObject parent = modelBuilder.getCurrentObject();
//        if (!(parent instanceof JsWith || (parent.getParent() != null && parent.getParent() instanceof JsWith))) {
//            while (scope != null && property == null && parameter == null) {
//                JsFunction function = (JsFunction)scope;
//                property = function.getProperty(name);
//                parameter = function.getParameter(name);
//                scope = scope.getParentScope();
//            }
//            if(parameter != null) {
//                if (property == null) {
//                    property = parameter;
//                } else {
//                    if(property.getJSKind() != JsElement.Kind.VARIABLE) {
//                        property = parameter;
//                    }
//                }
//            }
//        } else {
//            if (!(parent instanceof JsWith) && (parent.getParent() != null && parent.getParent() instanceof JsWith)) {
//                parent = parent.getParent();
//            }
//            property = parent.getProperty(name);
//        }
//
//        if (property != null) {
//
//            // occurence in the doc
//            addDocNameOccurence(((JsObjectImpl)property));
//            addDocTypesOccurence(((JsObjectImpl)property));
//
//            ((JsObjectImpl)property).addOccurrence(range);
//        } else {
//            // it's a new global variable?
//            Identifier nameIden = ModelElementFactory.create(parserResult, name, range.getStart(), range.getEnd());
//            if (nameIden != null) {
//                JsObjectImpl newObject;
//                if (!(parent instanceof JsWith)) {
//                        parent = modelBuilder.getGlobal();
//                }
//                if (!isFunction) {
//                    newObject = new JsObjectImpl(parent, nameIden, nameIden.getOffsetRange(),
//                            leftSite, parserResult.getSnapshot().getMimeType(), null);
//                } else {
//                    FileObject fo = parserResult.getSnapshot().getSource().getFileObject();
//                    newObject = new JsFunctionImpl(fo, parent, nameIden, Collections.EMPTY_LIST,
//                            parserResult.getSnapshot().getMimeType(), null);
//                }
//                newObject.addOccurrence(nameIden.getOffsetRange());
//                parent.addProperty(nameIden.getName(), newObject);
//            }
//        }
    }
    
    /**
     * Handles adding occurrences in expression like var xxx = xxx or this.xxx = xxx;
     * @param iNode
     * @param name 
     */
    private void addOccurrence(IdentNode iNode, String name) {
        String valueName = iNode.getName();
        if (!name.equals(valueName)) {
            addOccurence(iNode, false);
        } else {
            DeclarationScope scope = modelBuilder.getCurrentDeclarationScope();
            JsObject parameter = null;
            if (scope instanceof JsFunction) {
                JsFunction function = (JsFunction)scope;
                parameter = function.getParameter(iNode.getName());
            }
            if (parameter != null) {
                parameter.addOccurrence(getOffsetRange(iNode));
            } else {
                boolean found = false;
                JsObject jsProperty = ((JsObject)scope).getProperty(valueName);
                if (jsProperty != null && jsProperty.isDeclared()) {
                    found = true;
                    jsProperty.addOccurrence(new OffsetRange(iNode.getStart(), iNode.getFinish()));
                } else {
                    JsObject jsObject = ModelUtils.getScopeVariable(scope.getParentScope(), valueName);
                    if (jsObject != null) {
                        jsObject.addOccurrence(new OffsetRange(iNode.getStart(), iNode.getFinish()));
                        found = true;
                    }
                }
                if (!found) {
                    // new global var?
                    Identifier nameI = ModelElementFactory.create(parserResult, iNode);
                    if (nameI != null) {
                        JsObjectImpl newObject;
                        newObject = new JsObjectImpl(modelBuilder.getGlobal(), nameI, nameI.getOffsetRange(),
                                false, parserResult.getSnapshot().getMimeType(), null);
                        newObject.addOccurrence(nameI.getOffsetRange());
                        modelBuilder.getGlobal().addProperty(nameI.getName(), newObject);
                    }
                }
            }
        }
    }
    
    private void addDocNameOccurence(JsObjectImpl jsObject) {
        JsDocumentationHolder holder = JsDocumentationSupport.getDocumentationHolder(parserResult);
        JsComment comment = holder.getCommentForOffset(jsObject.getOffset(), holder.getCommentBlocks());
        if (comment != null) {
            for (DocParameter docParameter : comment.getParameters()) {
                Identifier paramName = docParameter.getParamName();
                String name = (docParameter.getParamName() == null) ? "" : docParameter.getParamName().getName(); //NOI18N
                if (name.equals(jsObject.getName())) {
                    jsObject.addOccurrence(paramName.getOffsetRange());
                }
            }
        }
    }

    private void addDocTypesOccurence(JsObjectImpl jsObject) {
        JsDocumentationHolder holder = JsDocumentationSupport.getDocumentationHolder(parserResult);
        if (holder.getOccurencesMap().containsKey(jsObject.getName())) {
            for (OffsetRange offsetRange : holder.getOccurencesMap().get(jsObject.getName())) {
                ((JsObjectImpl)jsObject).addOccurrence(offsetRange);
            }
        }
    }

    private boolean belongsTo(JsObject parent, String property) {
        boolean result = parent.getProperty(property) != null;
        if (!result && parent instanceof JsFunction) {
            result = ((JsFunction)parent).getParameter(property) != null;
        }
        
        return result;
    }
    
    private JsObject processLhs(Identifier name, JsObject parent, boolean lastOnLeft) {
        JsObject lObject = null;
        if (name != null) {
            if (ModelUtils.THIS.equals(name.getName())) {
                return null;
            }
            final String newVarName = name.getName();
            boolean hasParent = belongsTo(parent, newVarName);
            boolean hasGrandParent = parent.getJSKind() == JsElement.Kind.METHOD && belongsTo(parent.getParent(), newVarName);
            if (!hasParent && !hasGrandParent && modelBuilder.getGlobal().getProperty(newVarName) == null) {
                addOccurrence(name.getName(), name.getOffsetRange(), lastOnLeft, false);
            } else {
                if (hasParent) {
                    lObject = parent.getProperty(newVarName);
                    if(lObject == null && parent instanceof JsFunction) {
                        lObject = ((JsFunction)parent).getParameter(newVarName);
                    }
                } else if (hasGrandParent) {
                    lObject = parent.getParent().getProperty(newVarName);
                    if(lObject == null && parent.getParent() instanceof JsFunction) {
                        lObject = ((JsFunction)parent.getParent()).getParameter(newVarName);
                    }
                }
                if (lObject != null) {
                    ((JsObjectImpl)lObject).addOccurrence(name.getOffsetRange());
                } else {
                    addOccurrence(name.getName(), name.getOffsetRange(), lastOnLeft, false);
                }
            }
//            lObject = (JsObjectImpl)parent.getProperty(newVarName);
            if (lObject == null) {
                // it's not a property of the parent -> try to find in different context
                // FIXME why is model visitor requesting model from PR
                Model model = Model.getModel(parserResult, false);
                Collection<? extends JsObject> variables = model.getVariables(name.getOffsetRange().getStart());
                for(JsObject variable : variables) {
                    if(variable.getName().equals(newVarName)) {
                        lObject = (JsObjectImpl)variable;
                        break;
                    }
                }
                if (lObject == null) {
                    // the object with the name wasn't find yet -> create in global scope
                    JsObject where = modelBuilder.getCurrentWith() == null ? model.getGlobalObject() : modelBuilder.getCurrentWith();
                    lObject = new JsObjectImpl( where, name,
                            name.getOffsetRange(), lastOnLeft, parserResult.getSnapshot().getMimeType(), null);
                    where.addProperty(name.getName(), lObject);
                }
            }
        }
        return lObject;
    }
    
    public static OffsetRange getOffsetRange(IdentNode node) {
        // because the truffle parser doesn't set correctly the finish offset, when there are comments after the indent node
        return new OffsetRange(node.getStart(), node.getStart() + node.getName().length());
    }
    
    public static OffsetRange getOffsetRange(Node node) {
        return new OffsetRange(node.getStart(), node.getFinish());
    }
    
    public static OffsetRange getOffsetRange(FunctionNode node) {
        return new OffsetRange(Token.descPosition(node.getFirstToken()),
                Token.descPosition(node.getLastToken()) + Token.descLength(node.getLastToken()));
    }
    
    // TODO move this method to the ModelUtils
    /**
     * 
     * @param where the declaration context, where this is used
     * @return JsObject that should represent this. 
     */
    public JsObject resolveThis(JsObject where) {
        JsElement.Kind whereKind = where.getJSKind();
//        if (canBeSingletonPattern()) {
//            JsObject result = resolveThisInSingletonPattern(where);
//            if (result != null) {
//                return result;
//            }
//        }
        if (whereKind == JsElement.Kind.FILE) {
            // this is used in global context
            return where;
        }
        if (whereKind.isFunction() && where.getModifiers().contains(Modifier.PRIVATE)) {
            // the case where is defined private function in another function
            return where;
        }
        JsObject parent = where.getParent();
        if (parent == null) {
            return where;
        }
        JsElement.Kind parentKind = parent.getJSKind();
        if (parentKind == JsElement.Kind.FILE && !where.isAnonymous()) {
            // this is used in a function that is in the global context
            return where;
        }
        if (ModelUtils.PROTOTYPE.equals(parent.getName())) {
            // this is used in a function defined in prototype object
            return where.getParent().getParent();
        }
        if (whereKind == JsElement.Kind.CONSTRUCTOR) {
            if (parentKind == JsElement.Kind.CLASS) {
                return parent;
            } else {
                return where;
            }
        }
        if (whereKind.isFunction() && !where.getModifiers().contains(Modifier.PRIVATE) && !where.isAnonymous()) {
            // public or protected method
            if (parent.getJSKind() == JsElement.Kind.OBJECT_LITERAL) {
                if (Character.isUpperCase(where.getName().charAt(0))) {
                    return where;
                }
                if (Character.isUpperCase(parent.getName().charAt(0))) {
                    return parent;
                }
            } else {
                if (parent.isDeclared() || modelBuilder.getCurrentWith() != null) {
                    return parent;
                } else {
                    return where;
                }
            }
        }
        if (isInPropertyNode()) {
            // this is used in a method of an object -> this is the object
            return parent;
        }
//        if (where.isAnonymous()) {
//            JsObject result = resolveThisInSingletonPattern(where);
//            if (result != null) {
//                return result;
//            }
//        }
        return where;
    }
    
    private JsObject resolveThisInSingletonPattern(JsObject where) {
        int pathIndex = 1;
        Node lastNode = getPreviousFromPath(1);
        if (lastNode instanceof FunctionNode && !canBeSingletonPattern(pathIndex)) {
            pathIndex++;
        }
        while (pathIndex < getPath().size() && !(getPreviousFromPath(pathIndex) instanceof FunctionNode)) {
            pathIndex++;
        }
        // trying to find out that it corresponds with patter, where an object is defined via new function:
        // exp: this.pro = new function () { this.field = "";}
        if (canBeSingletonPattern(pathIndex)) {
            UnaryNode uNode = (UnaryNode) getPreviousFromPath(pathIndex + 2);
            if (uNode.tokenType() == TokenType.NEW) {

                String name = null;
                boolean simpleName = true;
                if (getPreviousFromPath(pathIndex + 3) instanceof BinaryNode) {
                    BinaryNode bNode = (BinaryNode) getPreviousFromPath(pathIndex + 3);
                    if (bNode.tokenType() == TokenType.ASSIGN) {
                        if (bNode.lhs() instanceof AccessNode) {
                            List<Identifier> identifier = getName((AccessNode) bNode.lhs(), parserResult);
                            if (identifier != null) {
                                if (!identifier.isEmpty() && ModelUtils.THIS.equals(identifier.get(0).getName())) {
                                    identifier.remove(0);
                                }
                                if (identifier.size() == 1) {
                                    name = identifier.get(0).getName();
                                } else {
                                    StringBuilder sb = new StringBuilder();
                                    for (Identifier part : identifier) {
                                        sb.append(part.getName()).append('.');
                                    }
                                    name = sb.toString().substring(0, sb.length() - 1);
                                    simpleName = false;
                                }
                            }
                        } else if (bNode.lhs() instanceof IdentNode) {
                            name = ((IdentNode) bNode.lhs()).getName();
                        }
                    }
                } else if (getPreviousFromPath(pathIndex + 3) instanceof VarNode) {
                    VarNode vNode = (VarNode)getPreviousFromPath(pathIndex + 3);
                    name = vNode.getName().getName();
                }
                
                JsObject parent = where.getParent() == null ? where : where.getParent();
                if (name != null) {
                    if (simpleName) {
                        parent = where;
                        while (parent != null && parent.getProperty(name) == null) {
                            parent = parent.getParent();
                        }
                        if (parent != null && parent.getProperty(name) != null) {
                            if (parent.getName().equals(name) && parent.getProperty(name).getJSKind().isFunction()) {
                                return parent;
                            }
                            return parent.getProperty(name);
                        }
                    } else {
                        JsObject property = ModelUtils.findJsObjectByName(ModelUtils.getGlobalObject(parent), name);
                        if (property != null) {
                            return property;
                        }
                    }

                }
            }
        }
        return null;
    }
    
    private  boolean canBeSingletonPattern() {
        int pathIndex = 1;
        Node lastNode = getPreviousFromPath(1);
        if (lastNode instanceof FunctionNode && !canBeSingletonPattern(pathIndex)) {
            pathIndex++;
        } 
        while (pathIndex < getPath().size() && !(getPreviousFromPath(pathIndex) instanceof FunctionNode)) {
            pathIndex++;
        }
        return canBeSingletonPattern(pathIndex);
    }
    
    private boolean canBeSingletonPattern(int pathIndex) {
       return  (getPath().size() > pathIndex + 3 && getPreviousFromPath(pathIndex) instanceof FunctionNode
                    && getPreviousFromPath(pathIndex + 1) instanceof CallNode
                    && ((CallNode)getPreviousFromPath(pathIndex + 1)).getFunction().equals(getPreviousFromPath(pathIndex))
                    && getPreviousFromPath(pathIndex + 2) instanceof UnaryNode
                    && (getPreviousFromPath(pathIndex + 3) instanceof BinaryNode
                        || getPreviousFromPath(pathIndex + 3) instanceof VarNode));
    }
    
    private boolean isPriviliged(AccessNode aNode) {
        Node node = aNode.getBase();
        while (node instanceof AccessNode) {
            node = ((AccessNode)node).getBase();
        }
        if (node instanceof IdentNode && ModelUtils.THIS.endsWith(((IdentNode)node).getName())) {
            return true;
        }
        return false;
    }
    
    private void setModifiersFromDoc(JsObject object, Set<JsModifier> modifiers) {
        if (modifiers != null && !modifiers.isEmpty()) {
            for (JsModifier jsModifier : modifiers) {
                switch (jsModifier) {
                    case PRIVATE:
                        // if the modifier from doc is PRIVATE, keep information about the privilaged or public method anyway.
                        object.getModifiers().add(Modifier.PRIVATE);
                        break;
                    case PUBLIC:
                        object.getModifiers().remove(Modifier.PROTECTED);
                        object.getModifiers().remove(Modifier.PRIVATE);
                        object.getModifiers().add(Modifier.PUBLIC);
                        break;
                    case STATIC:
                        object.getModifiers().add(Modifier.STATIC);
                        break;
                }
            }
        }
    }
    
    private void processObjectPropertyAssignment(CallNode cNode) {
        if (!(cNode.getFunction() instanceof AccessNode)) {
            return;
        }
        
        AccessNode aNode = (AccessNode)cNode.getFunction();
        if ("assign".equals(aNode.getProperty()) 
                && aNode.getBase() instanceof IdentNode
                && "Object".equals(((IdentNode)aNode.getBase()).getName())) {
            // the function call is Object.assign ...
            final List<Expression> args = cNode.getArgs();
            if (args != null && !args.isEmpty()) {
                // first param is the target object
                List<Identifier> targetName = getNodeName(args.get(0), parserResult);
                if (targetName != null && !targetName.isEmpty()) {
                    JsObjectImpl targetObject = ModelUtils.getJsObject(modelBuilder, targetName, false);
                    if (targetObject != null) {
                        for (int i = 1; i < args.size(); i++) {
                            Expression expression = args.get(i);
                            List<Identifier> argName = getNodeName(expression, parserResult);
                            if (argName != null && !argName.isEmpty()) {
                                JsObjectImpl argObject = ModelUtils.getJsObject(modelBuilder, argName, false);
                                if (argObject != null) {
                                    for(JsObject property : argObject.getProperties().values()) {
                                        JsObject copyProperty;
                                        if (property.getJSKind().isFunction()) {
                                            copyProperty = new JsFunctionReference(targetObject, property.getDeclarationName(), (JsFunction)property, true, property.getModifiers());
                                        } else {
                                            copyProperty = new JsObjectReference(targetObject, property.getDeclarationName(), property, true, property.getModifiers());
                                        }
                                        targetObject.addProperty(copyProperty.getName(), copyProperty);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            
            
        }
    }
    
    public static class FunctionCall {

        private final String name;

        private final DeclarationScope scope;

        private final Collection<FunctionArgument> arguments;
        
        private final int callOffset;

        public FunctionCall(String name, DeclarationScope scope,
                Collection<FunctionArgument> arguments, int callOffset) {
            this.name = name;
            this.scope = scope;
            this.arguments = arguments;
            this.callOffset = callOffset;
        }

        public String getName() {
            return name;
        }

        public DeclarationScope getScope() {
            return scope;
        }

        public Collection<FunctionArgument> getArguments() {
            return arguments;
        }

        public int getCallOffset() {
            return callOffset;
        }
        
        
    }
    
    // for loging purposes
    private int indent = 0;
    private String createSpaces(int indent) {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < indent; i++) {
            sb.append(' ');
        }
        return sb.toString();
    }
    
    private void log(String text) {
        System.out.print(createSpaces(indent));
        System.out.println(text);
    }
    
    private String debugInfo(Node node) {
        StringBuilder sb = new StringBuilder();
        if (node instanceof FunctionNode) {
            FunctionNode fn = (FunctionNode)node;
            sb.append("FunctionNode name: ").append(fn.getName());
            sb.append(", Ident: ").append(fn.getIdent());
            if (fn.allVarsInScope()) sb.append(", allVarsInScope");
            if (fn.isAnonymous()) sb.append(", isAnonymous");
            if (fn.isDeclared()) sb.append(", isDeclared");
            if (fn.isMethod()) sb.append(", isMethod");
            if (fn.isNamedFunctionExpression()) sb.append(", isNamedFunctionExpression");
            if (fn.isVarArg()) sb.append(", isVarArg");
            if (fn.hasDeclaredFunctions()) sb.append(", hasDeclaredFunctions");
            if (fn.hasDirectSuper()) sb.append(", hasDirectSuper");
//            if (fn.hasScopeBlock()) sb.append(", hasScoprBlock");
        } else if (node instanceof VarNode) {
            VarNode vn = (VarNode)node;
            sb.append("VarNode ").append(vn.getName());
            if (vn.isBlockScoped()) sb.append(", isBlockScoped");
            if (vn.isConst()) sb.append(", isConst");
            if (vn.isFunctionDeclaration()) sb.append(", isFunctionDeclaration");
            if (vn.isLet()) sb.append(", isLet");
        } else {
            sb.append(node.getClass().getName());
        }
        return sb.toString();
    }


    @ServiceProvider(service = ModelResolver.Provider.class, position = 10_000)
    public static final class Provider implements ModelResolver.Provider {

        @Override
        public ModelResolver create(ParserResult result, OccurrenceBuilder occurrenceBuilder) {
            final ModelVisitor visitor = new ModelVisitor(result, occurrenceBuilder);
            return visitor;
        }

    }
}
