示例#1
0
        /// <summary>
        /// Clones the stack object and also clones the highest item on the context stack (only!)
        /// </summary>
        public ResolverContextStack Clone()
        {
            var rc = new ResolverContext();

            rc.ApplyFrom(CurrentContext);

            return(new ResolverContextStack(ParseCache, rc));
        }
示例#2
0
        public void ApplyFrom(ResolverContext other)
        {
            if (other == null)
                return;

            ScopedBlock = other.ScopedBlock;
            ScopedStatement = other.ScopedStatement;
        }
示例#3
0
        public void ApplyFrom(ResolverContext other)
        {
            if (other == null)
            {
                return;
            }

            ScopedBlock     = other.ScopedBlock;
            ScopedStatement = other.ScopedStatement;
        }
示例#4
0
        public ResolverContext PushNewScope(IBlockNode scope)
        {
            var ctxtOverride = new ResolverContext();

            ctxtOverride.ScopedBlock     = scope;
            ctxtOverride.ScopedStatement = null;

            stack.Push(ctxtOverride);

            return(ctxtOverride);
        }
示例#5
0
 public void Push(ResolverContext c)
 {
     stack.Push(c);
 }
示例#6
0
        public static ArgumentsResolutionResult ResolveArgumentContext(
			string code,
			int caretOffset,
			CodeLocation caretLocation,
			DMethod MethodScope,
			IEnumerable<IAbstractSyntaxTree> parseCache, IEnumerable<IAbstractSyntaxTree> ImportCache)
        {
            var ctxt = new ResolverContext { ScopedBlock = MethodScope, ParseCache = parseCache, ImportCache=ImportCache };

            #region Parse the code between the last block opener and the caret

            var curMethodBody = MethodScope.GetSubBlockAt(caretLocation);

            if (curMethodBody == null && MethodScope.Parent is DMethod)
            {
                MethodScope = MethodScope.Parent as DMethod;
                curMethodBody = MethodScope.GetSubBlockAt(caretLocation);
            }

            if (curMethodBody == null)
                return null;

            var blockOpenerLocation = curMethodBody.StartLocation;
            var blockOpenerOffset = blockOpenerLocation.Line <= 0 ? blockOpenerLocation.Column :
                DocumentHelper.LocationToOffset(code, blockOpenerLocation);

            if (blockOpenerOffset >= 0 && caretOffset - blockOpenerOffset > 0)
            {
                var codeToParse = code.Substring(blockOpenerOffset, caretOffset - blockOpenerOffset);

                curMethodBody = DParser.ParseBlockStatement(codeToParse, blockOpenerLocation, MethodScope);

                if (curMethodBody != null)
                    ctxt.ScopedStatement = curMethodBody.SearchStatementDeeply(caretLocation);
            }

            if (curMethodBody == null || ctxt.ScopedStatement == null)
                return null;
            #endregion

            // Scan statement for method calls or template instantiations
            var e = DResolver.SearchForMethodCallsOrTemplateInstances(ctxt.ScopedStatement, caretLocation);

            /*
             * 1) foo(			-- normal arguments only
             * 2) foo!(...)(	-- normal arguments + template args
             * 3) foo!(		-- template args only
             * 4) new myclass(  -- ctor call
             * 5) new myclass!( -- ditto
             * 6) new myclass!(...)(
             * 7) mystruct(		-- opCall call
             */
            var res = new ArgumentsResolutionResult() { ParsedExpression = e };

            ITypeDeclaration methodIdentifier = null;

            // 1), 2)
            if (e is PostfixExpression_MethodCall)
            {
                res.IsMethodArguments = true;
                var call = e as PostfixExpression_MethodCall;

                if (call.Arguments != null)
                {
                    int i = 0;
                    foreach (var arg in call.Arguments)
                    {
                        if (caretLocation >= arg.Location && caretLocation <= arg.EndLocation)
                        {
                            res.CurrentlyTypedArgumentIndex = i;
                            break;
                        }
                        i++;
                    }
                }

                methodIdentifier = call.PostfixForeExpression.ExpressionTypeRepresentation;

            }
            // 3)
            else if (e is TemplateInstanceExpression)
            {
                var templ = e as TemplateInstanceExpression;

                res.IsTemplateInstanceArguments = true;

                if (templ.Arguments != null)
                {
                    int i = 0;
                    foreach (var arg in templ.Arguments)
                    {
                        if (caretLocation >= arg.Location && caretLocation <= arg.EndLocation)
                        {
                            res.CurrentlyTypedArgumentIndex = i;
                            break;
                        }
                        i++;
                    }
                }

                methodIdentifier = new IdentifierDeclaration(templ.TemplateIdentifier.Value) { InnerDeclaration=templ.InnerDeclaration };
            }
            else if (e is NewExpression)
            {
                var ne = e as NewExpression;

                if (ne.Arguments != null)
                {
                    int i = 0;
                    foreach (var arg in ne.Arguments)
                    {
                        if (caretLocation >= arg.Location && caretLocation <= arg.EndLocation)
                        {
                            res.CurrentlyTypedArgumentIndex = i;
                            break;
                        }
                        i++;
                    }
                }

                methodIdentifier = ne.ExpressionTypeRepresentation;
            }

            if (methodIdentifier == null)
                return null;

            // Resolve all types, methods etc. which belong to the methodIdentifier
            res.ResolvedTypesOrMethods = ResolveType(methodIdentifier, ctxt);

            if (res.ResolvedTypesOrMethods == null)
                return res;

            // 4),5),6)
            if (e is NewExpression)
            {
                var substitutionList = new List<ResolveResult>();
                foreach (var rr in res.ResolvedTypesOrMethods)
                    if (rr is TypeResult)
                    {
                        var classDef = (rr as TypeResult).ResolvedTypeDefinition as DClassLike;

                        if (classDef == null)
                            continue;

                        //TODO: Regard protection attributes for ctor members
                        foreach (var i in classDef)
                            if (i is DMethod && (i as DMethod).SpecialType == DMethod.MethodType.Constructor)
                                substitutionList.Add(HandleNodeMatch(i, ctxt, resultBase: rr));
                    }

                if (substitutionList.Count > 0)
                    res.ResolvedTypesOrMethods = substitutionList.ToArray();
            }

            // 7)
            else if (e is PostfixExpression_MethodCall)
            {
                var substitutionList = new List<ResolveResult>();

                var nonAliases=TryRemoveAliasesFromResult(res.ResolvedTypesOrMethods);

                foreach (var rr in nonAliases)
                    if (rr is TypeResult)
                    {
                        var classDef = (rr as TypeResult).ResolvedTypeDefinition as DClassLike;

                        if (classDef == null)
                            continue;

                        //TODO: Regard protection attributes for opCall members
                        foreach (var i in classDef)
                            if (i is DMethod && i.Name == "opCall")
                                substitutionList.Add(HandleNodeMatch(i, ctxt, resultBase: rr));
                    }

                if (substitutionList.Count > 0)
                    nonAliases = substitutionList.ToArray();

                res.ResolvedTypesOrMethods = nonAliases;
            }

            return res;
        }
示例#7
0
        static ResolveResult[] HandleIdDeclaration(IdentifierDeclaration typeId,
			ResolverContext lastResCtxt,
			IAbstractSyntaxTree SyntaxTree,
			CodeScanResult csr, 
			Dictionary<string, ResolveResult> compDict)
        {
            var typeString = typeId.ToString();

            bool WasAlreadyResolved = false;
            ResolveResult[] allCurrentResults = null;
            ResolveResult rr = null;

            /*
             * string,wstring,dstring are highlighted by the editor's syntax definition automatically..
             * Anyway, allow to resolve e.g. "object.string"
             */
            if (typeString == "" || typeString == "string" || typeString == "wstring" || typeString == "dstring")
                return null;

            lastResCtxt.ScopedBlock = DResolver.SearchBlockAt(SyntaxTree, typeId.Location, out lastResCtxt.ScopedStatement);
            if (typeString == "th" && typeId.Location.Line == 114)
            {

            }
            if (!(WasAlreadyResolved = compDict.TryGetValue(typeString, out rr)))
            {
                allCurrentResults = DResolver.ResolveType(typeId, lastResCtxt);

                if (allCurrentResults != null && allCurrentResults.Length > 0)
                    rr = allCurrentResults[0];
            }

            if (rr == null)
            {
                if (typeId is IdentifierDeclaration)
                    csr.UnresolvedIdentifiers.Add(typeId as IdentifierDeclaration);
            }
            else
            {
                /*
                 * Note: It is of course possible to highlight more than one type in one type declaration!
                 * So, we scan down the result hierarchy for TypeResults and highlight all of them later.
                 */
                var curRes = rr;

                /*
                 * Note: Since we want to use results multiple times,
                 * we at least have to 'update' their type declarations
                 * to ensure that the second, third, fourth etc. occurence of this result
                 * are also highlit (and won't(!) cause an Already-Added-Exception of our finalDict-Array)
                 */
                var curTypeDeclBase = typeId as ITypeDeclaration;

                while (curRes != null)
                {
                    if (curRes is MemberResult)
                    {
                        var mr = curRes as MemberResult;

                        // If curRes is an alias or a template parameter, highlight it
                        if (mr.ResolvedMember is TemplateParameterNode ||
                            (mr.ResolvedMember is DVariable &&
                            (mr.ResolvedMember as DVariable).IsAlias))
                        {
                            try
                            {
                                csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes);
                            }
                            catch { }

                            // See performance reasons
                            //if (curRes != rr && !WasAlreadyResolved && !) compDict.Add(curTypeDeclBase.ToString(), curRes);
                        }
                    }

                    else if (curRes is TypeResult)
                    {
                        // Yeah, in quite all cases we do identify a class via its name ;-)
                        if (curTypeDeclBase is IdentifierDeclaration &&
                            !(curTypeDeclBase is DTokenDeclaration) &&
                            !csr.ResolvedIdentifiers.ContainsKey(curTypeDeclBase as IdentifierDeclaration))
                        {
                            csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes);

                            // See performance reasons
                            //if (curRes != rr && !WasAlreadyResolved) compDict.Add(curTypeDeclBase.ToString(), curRes);
                        }
                    }

                    else if (curRes is ModuleResult)
                    {
                        if (curTypeDeclBase is IdentifierDeclaration &&
                            !csr.ResolvedIdentifiers.ContainsKey(curTypeDeclBase as IdentifierDeclaration))
                            csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes);
                    }

                    curRes = curRes.ResultBase;
                    curTypeDeclBase = curTypeDeclBase.InnerDeclaration;
                }
            }
            return allCurrentResults;
        }
示例#8
0
        /// <summary>
        /// Scans the syntax tree for all kinds of identifier declarations, 
        /// tries to resolve them,
        /// adds them to a dictionary. If not found, 
        /// they will be added to a second, special array.
        /// 
        /// Note: For performance reasons, it's recommended to disable 'ResolveAliases' in the ResolverContext parameter
        /// </summary>
        /// <param name="lastResCtxt"></param>
        /// <param name="SyntaxTree"></param>
        /// <returns></returns>
        public static CodeScanResult ScanSymbols(ResolverContext lastResCtxt,IAbstractSyntaxTree SyntaxTree)
        {
            var csr = new CodeScanResult();

            var compDict = new Dictionary<string, ResolveResult>();

            // Step 1: Enum all existing type id's that shall become resolved'n displayed
            var typeObjects = CodeScanner.ScanForTypeIdentifiers(SyntaxTree);

            foreach (var o in typeObjects)
            {
                if (o == null)
                    continue;

                #region Identifier Declarations
                if (o is IdentifierDeclaration)
                {
                    HandleIdDeclaration(o as IdentifierDeclaration,
                        lastResCtxt,
                        SyntaxTree,
                        csr,
                        compDict);
                }
                #endregion
                    /*
                #region Method call check
                else if (o is PostfixExpression_MethodCall)
                {
                    var mc=o as PostfixExpression_MethodCall;

                    int argc = mc.ArgumentCount;

                    var methodOverloads=HandleIdDeclaration(mc.ExpressionTypeRepresentation as IdentifierDeclaration,
                        lastResCtxt,
                        SyntaxTree,
                        csr,
                        compDict);

                    // Important: Also check template parameters and arguments!
                    IExpression[] TemplateArguments=null;

                    if (mc.PostfixForeExpression is TemplateInstanceExpression)
                        TemplateArguments = (mc.PostfixForeExpression as TemplateInstanceExpression).Arguments;

                    int TemplateArgCount = TemplateArguments == null ? 0 : TemplateArguments.Length;

                    // Note: If no method members were found, we already show the semantic error as a generically missing symbol
                    if (methodOverloads != null)
                    {
                        var l1 = new List<DMethod>();
                        var l2 = new List<DMethod>();

                        #region First add all available method overloads
                        foreach (var rr_ in methodOverloads)
                        {
                            // Like every time, remove unnecessary aliasing
                            var rr = DResolver.TryRemoveAliasesFromResult(rr_);

                            // Can be either 1) a normal method OR 2) a type related opCall

                            // 1)
                            if (rr is MemberResult)
                            {
                                var mr = rr as MemberResult;

                                //FIXME: What about delegate aliases'n stuff?
                                if (!(mr.ResolvedMember is DMethod))
                                    continue;

                                var dm = mr.ResolvedMember as DMethod;

                                // Even before checking argument types etc, pre-select possibly chosen overloads
                                // by comparing the method's parameter count with the call's argument count
                                if (dm.Parameters.Count == argc && (dm.TemplateParameters==null?true:
                                    dm.TemplateParameters.Length==TemplateArgCount))
                                    l1.Add(dm);
                            }

                            // 2)
                            else if (rr is TypeResult)
                            {
                                var tr = rr as TypeResult;

                                // Scan the type for opCall members
                                var opCalls=DResolver.ScanNodeForIdentifier(tr.ResolvedTypeDefinition, "opCall", lastResCtxt);

                                if (opCalls != null)
                                    foreach (var n in opCalls)
                                    {
                                        var dm = n as DMethod;

                                        // Also pre-filter opCall members by param count comparison
                                        if (dm!=null &&
                                            dm.Parameters.Count == argc && (dm.TemplateParameters == null ? true :
                                            dm.TemplateParameters.Length == TemplateArgCount))
                                            l1.Add(dm);
                                    }
                            }
                        }
                        #endregion

                        // Must be a semantic error - no method fits in any way
                        if(l1.Count<1)
                        {
                            csr.ParameterActions.Add(o as IExpression, null);
                            continue;
                        }

                        // Compare template arguments first
                    }
                }
                #endregion
                */
            }

            return csr;
        }
示例#9
0
        static ResolveResult[] HandleIdDeclaration(IdentifierDeclaration typeId,
                                                   ResolverContext lastResCtxt,
                                                   IAbstractSyntaxTree SyntaxTree,
                                                   CodeScanResult csr,
                                                   Dictionary <string, ResolveResult> compDict)
        {
            var typeString = typeId.ToString();

            bool WasAlreadyResolved = false;

            ResolveResult[] allCurrentResults = null;
            ResolveResult   rr = null;

            /*
             * string,wstring,dstring are highlighted by the editor's syntax definition automatically..
             * Anyway, allow to resolve e.g. "object.string"
             */
            if (typeString == "" || typeString == "string" || typeString == "wstring" || typeString == "dstring")
            {
                return(null);
            }

            lastResCtxt.ScopedBlock = DResolver.SearchBlockAt(SyntaxTree, typeId.Location, out lastResCtxt.ScopedStatement);
            if (typeString == "th" && typeId.Location.Line == 114)
            {
            }
            if (!(WasAlreadyResolved = compDict.TryGetValue(typeString, out rr)))
            {
                allCurrentResults = DResolver.ResolveType(typeId, lastResCtxt);

                if (allCurrentResults != null && allCurrentResults.Length > 0)
                {
                    rr = allCurrentResults[0];
                }
            }

            if (rr == null)
            {
                if (typeId is IdentifierDeclaration)
                {
                    csr.UnresolvedIdentifiers.Add(typeId as IdentifierDeclaration);
                }
            }
            else
            {
                /*
                 * Note: It is of course possible to highlight more than one type in one type declaration!
                 * So, we scan down the result hierarchy for TypeResults and highlight all of them later.
                 */
                var curRes = rr;

                /*
                 * Note: Since we want to use results multiple times,
                 * we at least have to 'update' their type declarations
                 * to ensure that the second, third, fourth etc. occurence of this result
                 * are also highlit (and won't(!) cause an Already-Added-Exception of our finalDict-Array)
                 */
                var curTypeDeclBase = typeId as ITypeDeclaration;

                while (curRes != null)
                {
                    if (curRes is MemberResult)
                    {
                        var mr = curRes as MemberResult;

                        // If curRes is an alias or a template parameter, highlight it
                        if (mr.ResolvedMember is TemplateParameterNode ||
                            (mr.ResolvedMember is DVariable &&
                             (mr.ResolvedMember as DVariable).IsAlias))
                        {
                            try
                            {
                                csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes);
                            }
                            catch { }

                            // See performance reasons
                            //if (curRes != rr && !WasAlreadyResolved && !) compDict.Add(curTypeDeclBase.ToString(), curRes);
                        }
                    }

                    else if (curRes is TypeResult)
                    {
                        // Yeah, in quite all cases we do identify a class via its name ;-)
                        if (curTypeDeclBase is IdentifierDeclaration &&
                            !(curTypeDeclBase is DTokenDeclaration) &&
                            !csr.ResolvedIdentifiers.ContainsKey(curTypeDeclBase as IdentifierDeclaration))
                        {
                            csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes);

                            // See performance reasons
                            //if (curRes != rr && !WasAlreadyResolved) compDict.Add(curTypeDeclBase.ToString(), curRes);
                        }
                    }

                    else if (curRes is ModuleResult)
                    {
                        if (curTypeDeclBase is IdentifierDeclaration &&
                            !csr.ResolvedIdentifiers.ContainsKey(curTypeDeclBase as IdentifierDeclaration))
                        {
                            csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes);
                        }
                    }

                    curRes          = curRes.ResultBase;
                    curTypeDeclBase = curTypeDeclBase.InnerDeclaration;
                }
            }
            return(allCurrentResults);
        }
示例#10
0
        /// <summary>
        /// Scans the syntax tree for all kinds of identifier declarations,
        /// tries to resolve them,
        /// adds them to a dictionary. If not found,
        /// they will be added to a second, special array.
        ///
        /// Note: For performance reasons, it's recommended to disable 'ResolveAliases' in the ResolverContext parameter
        /// </summary>
        /// <param name="lastResCtxt"></param>
        /// <param name="SyntaxTree"></param>
        /// <returns></returns>
        public static CodeScanResult ScanSymbols(ResolverContext lastResCtxt, IAbstractSyntaxTree SyntaxTree)
        {
            var csr = new CodeScanResult();

            var compDict = new Dictionary <string, ResolveResult>();

            // Step 1: Enum all existing type id's that shall become resolved'n displayed
            var typeObjects = CodeScanner.ScanForTypeIdentifiers(SyntaxTree);

            foreach (var o in typeObjects)
            {
                if (o == null)
                {
                    continue;
                }

                #region Identifier Declarations
                if (o is IdentifierDeclaration)
                {
                    HandleIdDeclaration(o as IdentifierDeclaration,
                                        lastResCtxt,
                                        SyntaxTree,
                                        csr,
                                        compDict);
                }
                #endregion

                /*
                 #region Method call check
                 * else if (o is PostfixExpression_MethodCall)
                 * {
                 * var mc=o as PostfixExpression_MethodCall;
                 *
                 * int argc = mc.ArgumentCount;
                 *
                 * var methodOverloads=HandleIdDeclaration(mc.ExpressionTypeRepresentation as IdentifierDeclaration,
                 *      lastResCtxt,
                 *      SyntaxTree,
                 *      csr,
                 *      compDict);
                 *
                 * // Important: Also check template parameters and arguments!
                 * IExpression[] TemplateArguments=null;
                 *
                 * if (mc.PostfixForeExpression is TemplateInstanceExpression)
                 *      TemplateArguments = (mc.PostfixForeExpression as TemplateInstanceExpression).Arguments;
                 *
                 * int TemplateArgCount = TemplateArguments == null ? 0 : TemplateArguments.Length;
                 *
                 * // Note: If no method members were found, we already show the semantic error as a generically missing symbol
                 * if (methodOverloads != null)
                 * {
                 *      var l1 = new List<DMethod>();
                 *      var l2 = new List<DMethod>();
                 *
                 #region First add all available method overloads
                 *      foreach (var rr_ in methodOverloads)
                 *      {
                 *              // Like every time, remove unnecessary aliasing
                 *              var rr = DResolver.TryRemoveAliasesFromResult(rr_);
                 *
                 *              // Can be either 1) a normal method OR 2) a type related opCall
                 *
                 *              // 1)
                 *              if (rr is MemberResult)
                 *              {
                 *                      var mr = rr as MemberResult;
                 *
                 *                      //FIXME: What about delegate aliases'n stuff?
                 *                      if (!(mr.ResolvedMember is DMethod))
                 *                              continue;
                 *
                 *                      var dm = mr.ResolvedMember as DMethod;
                 *
                 *                      // Even before checking argument types etc, pre-select possibly chosen overloads
                 *                      // by comparing the method's parameter count with the call's argument count
                 *                      if (dm.Parameters.Count == argc && (dm.TemplateParameters==null?true:
                 *                              dm.TemplateParameters.Length==TemplateArgCount))
                 *                              l1.Add(dm);
                 *              }
                 *
                 *              // 2)
                 *              else if (rr is TypeResult)
                 *              {
                 *                      var tr = rr as TypeResult;
                 *
                 *                      // Scan the type for opCall members
                 *                      var opCalls=DResolver.ScanNodeForIdentifier(tr.ResolvedTypeDefinition, "opCall", lastResCtxt);
                 *
                 *                      if (opCalls != null)
                 *                              foreach (var n in opCalls)
                 *                              {
                 *                                      var dm = n as DMethod;
                 *
                 *                                      // Also pre-filter opCall members by param count comparison
                 *                                      if (dm!=null &&
                 *                                              dm.Parameters.Count == argc && (dm.TemplateParameters == null ? true :
                 *                                              dm.TemplateParameters.Length == TemplateArgCount))
                 *                                              l1.Add(dm);
                 *                              }
                 *              }
                 *      }
                 #endregion
                 *
                 *      // Must be a semantic error - no method fits in any way
                 *      if(l1.Count<1)
                 *      {
                 *              csr.ParameterActions.Add(o as IExpression, null);
                 *              continue;
                 *      }
                 *
                 *      // Compare template arguments first
                 * }
                 * }
                 #endregion
                 */
            }

            return(csr);
        }
示例#11
0
        public static ResolveResult[] ResolveType(IEditorData editor,
			ResolverContext ctxt,
			bool alsoParseBeyondCaret = false,
			bool onlyAssumeIdentifierList = false)
        {
            var code = editor.ModuleCode;

            // First check if caret is inside a comment/string etc.
            int lastNonNormalStart = 0;
            int lastNonNormalEnd = 0;
            var caretContext = CommentSearching.GetTokenContext(code, editor.CaretOffset, out lastNonNormalStart,out lastNonNormalEnd);

            // Return if comment etc. found
            if (caretContext != CommentSearching.TokenContext.None)
                return null;

            var start = ReverseParsing.SearchExpressionStart(code,editor.CaretOffset-1,
                /*FIXME: Only backward-parse code until the last comment -
                 * this can be provoking errors e.g.
                 * on MyType /* Some comment * / .myProp
                 * But: In quite all cases this shouldn't occur - so it's still acceptable
                 */
                (lastNonNormalEnd>0 && lastNonNormalEnd<editor.CaretOffset)?lastNonNormalEnd:0);

            if (start < 0 || editor.CaretOffset<=start)
                return null;

            var expressionCode = code.Substring(start, alsoParseBeyondCaret ? code.Length - start : editor.CaretOffset - start);

            var parser = DParser.Create(new StringReader(expressionCode));
            parser.Lexer.SetInitialLocation(DocumentHelper.OffsetToLocation(editor.ModuleCode,start));
            parser.Step();

            if (onlyAssumeIdentifierList && parser.Lexer.LookAhead.Kind == DTokens.Identifier)
                return ResolveType(parser.IdentifierList(), ctxt);
            else if (parser.IsAssignExpression())
            {
                var expr = parser.AssignExpression();

                if (expr != null)
                {
                    expr = ExpressionHelper.SearchExpressionDeeply(expr, editor.CaretLocation);

                    var ret = ResolveType(expr.ExpressionTypeRepresentation, ctxt);

                    if (ret == null && expr != null && !(expr is TokenExpression))
                        ret = new[] { new ExpressionResult() { Expression = expr } };

                    return ret;
                }
            }
            else
                return ResolveType(parser.Type(), ctxt);

            return null;
        }
示例#12
0
        public static ResolveResult[] ResolveType(ITypeDeclaration declaration,
		                                          ResolverContext ctxt,
												  IBlockNode currentScopeOverride = null)
        {
            if (ctxt == null)
                return null;

            var ctxtOverride=ctxt;

            if(currentScopeOverride!=null && currentScopeOverride!=ctxt.ScopedBlock){
                ctxtOverride=new ResolverContext();
                ctxtOverride.ApplyFrom(ctxt);
                ctxtOverride.ScopedBlock = currentScopeOverride;
                ctxtOverride.ScopedStatement = null;
            }

            if(ctxtOverride.ScopedBlock!=null &&( ctxtOverride.ImportCache==null || ctxtOverride.ScopedBlock.NodeRoot!=ctxt.ScopedBlock.NodeRoot))
            {
                ctxtOverride.ImportCache=ResolveImports(ctxtOverride.ScopedBlock.NodeRoot as DModule,ctxt.ParseCache);
            }

            if (currentScopeOverride == null)
                currentScopeOverride = ctxt.ScopedBlock;

            if (ctxt == null || declaration == null)
                return null;

            ResolveResult[] preRes = null;
            object scopeObj = null;

            if (ctxtOverride.ScopedStatement != null)
            {
                var curStmtLevel=ctxtOverride.ScopedStatement;

                while (curStmtLevel != null && !(curStmtLevel is BlockStatement))
                    curStmtLevel = curStmtLevel.Parent;

                if(curStmtLevel is BlockStatement)
                    scopeObj = curStmtLevel;
            }

            if (scopeObj == null)
                scopeObj = ctxtOverride.ScopedBlock;

            // Check if already resolved once
            if (ctxtOverride.TryGetAlreadyResolvedType(declaration.ToString(), out preRes, scopeObj))
                return preRes;

            var returnedResults = new List<ResolveResult>();

            // Walk down recursively to resolve everything from the very first to declaration's base type declaration.
            ResolveResult[] rbases = null;
            if (declaration.InnerDeclaration != null)
                rbases = ResolveType(declaration.InnerDeclaration, ctxtOverride);

            // If it's a template, resolve the template id first
            if (declaration is TemplateInstanceExpression)
                declaration = (declaration as TemplateInstanceExpression).TemplateIdentifier;

            /*
             * If there is no parent resolve context (what usually means we are searching the type named like the first identifier in the entire declaration),
             * search the very first type declaration by walking along the current block scope hierarchy.
             * If there wasn't any item found in that procedure, search in the global parse cache
             */
            #region Search initial member/type/module/whatever
            if (rbases == null)
            {
                #region IdentifierDeclaration
                if (declaration is IdentifierDeclaration)
                {
                    string searchIdentifier = (declaration as IdentifierDeclaration).Value as string;

                    if (string.IsNullOrEmpty(searchIdentifier))
                        return null;

                    // Try to convert the identifier into a token
                    int searchToken = string.IsNullOrEmpty(searchIdentifier) ? 0 : DTokens.GetTokenID(searchIdentifier);

                    // References current class scope
                    if (searchToken == DTokens.This)
                    {
                        var classDef = ctxt.ScopedBlock;

                        while (!(classDef is DClassLike) && classDef != null)
                            classDef = classDef.Parent as IBlockNode;

                        if (classDef is DClassLike)
                        {
                            var res = HandleNodeMatch(classDef, ctxtOverride, typeBase: declaration);

                            if (res != null)
                                returnedResults.Add(res);
                        }
                    }
                    // References super type of currently scoped class declaration
                    else if (searchToken == DTokens.Super)
                    {
                        var classDef = currentScopeOverride;

                        while (!(classDef is DClassLike) && classDef != null)
                            classDef = classDef.Parent as IBlockNode;

                        if (classDef != null)
                        {
                            var baseClassDefs = ResolveBaseClass(classDef as DClassLike, ctxtOverride);

                            if (baseClassDefs != null)
                            {
                                // Important: Overwrite type decl base with 'super' token
                                foreach (var bc in baseClassDefs)
                                    bc.TypeDeclarationBase = declaration;

                                returnedResults.AddRange(baseClassDefs);
                            }
                        }
                    }
                    // If we found a base type, return a static-type-result
                    else if (searchToken > 0)
                    {
                        if (DTokens.BasicTypes[searchToken])
                            returnedResults.Add(new StaticTypeResult()
                            {
                                BaseTypeToken = searchToken,
                                TypeDeclarationBase = declaration
                            });
                        // anything else is just a key word, not a type
                    }
                    // (As usual) Go on searching in the local&global scope(s)
                    else
                    {
                        var matches = new List<INode>();

                        // Search in current statement's declarations (if possible)
                        var decls = BlockStatement.GetItemHierarchy(ctxt.ScopedStatement, declaration.Location);

                        if(decls!=null)
                            foreach (var decl in decls)
                                if (decl != null && decl.Name == searchIdentifier)
                                    matches.Add(decl);

                        // First search along the hierarchy in the current module
                        var curScope = ctxtOverride.ScopedBlock;
                        while (curScope != null)
                        {
                            /*
                             * If anonymous enum, skip that one, because in the following ScanForNodeIdentifier call,
                             * its children already become added to the match list
                             */
                            if (curScope is DEnum && curScope.Name == "")
                                curScope = curScope.Parent as IBlockNode;

                            if (curScope is DMethod)
                            {
                                var dm = curScope as DMethod;

                                // If the method is a nested method,
                                // this method won't be 'linked' to the parent statement tree directly -
                                // so, we've to gather the parent method and add its locals to the return list
                                if (dm.Parent is DMethod)
                                {
                                    var parDM = dm.Parent as DMethod;
                                    var nestedBlock = parDM.GetSubBlockAt(declaration.Location);
                                    if (nestedBlock != null)
                                    {
                                        // Search for the deepest statement scope and test all declarations done in the entire scope hierarchy
                                        decls = BlockStatement.GetItemHierarchy(nestedBlock.SearchStatementDeeply(declaration.Location), declaration.Location);

                                        foreach (var decl in decls)
                                            // ... Add them if match was found
                                            if (decl != null && decl.Name == searchIdentifier)
                                                matches.Add(decl);
                                    }
                                }

                                // Do not check further method's children but its (template) parameters
                                foreach (var p in dm.Parameters)
                                    if (p.Name == searchIdentifier)
                                        matches.Add(p);

                                if (dm.TemplateParameters != null)
                                    foreach (var tp in dm.TemplateParameterNodes)
                                        if (tp.Name == searchIdentifier)
                                            matches.Add(tp);
                            }
                            else
                            {
                                var m = ScanNodeForIdentifier(curScope, searchIdentifier, ctxtOverride);

                                if (m != null)
                                    matches.AddRange(m);

                                var mod = curScope as IAbstractSyntaxTree;
                                if (mod != null)
                                {
                                    var modNameParts = mod.ModuleName.Split('.');
                                    if (!string.IsNullOrEmpty(mod.ModuleName) && modNameParts[0] == searchIdentifier)
                                        matches.Add(curScope);
                                }
                            }
                            curScope = curScope.Parent as IBlockNode;
                        }

                        // Then go on searching in the global scope
                        var ThisModule =
                            currentScopeOverride is IAbstractSyntaxTree ?
                                currentScopeOverride as IAbstractSyntaxTree :
                                currentScopeOverride.NodeRoot as IAbstractSyntaxTree;
                        if (ctxt.ParseCache != null)
                            foreach (var mod in ctxt.ParseCache)
                            {
                                if (mod == ThisModule)
                                    continue;

                                var modNameParts = mod.ModuleName.Split('.');

                                if (modNameParts[0] == searchIdentifier)
                                    matches.Add(mod);
                            }

                        if (ctxtOverride.ImportCache != null)
                            foreach (var mod in ctxtOverride.ImportCache)
                            {
                                var m = ScanNodeForIdentifier(mod, searchIdentifier, null);
                                if (m != null)
                                    matches.AddRange(m);
                            }

                        var results = HandleNodeMatches(matches, ctxtOverride, TypeDeclaration: declaration);
                        if (results != null)
                            returnedResults.AddRange(results);
                    }
                }
                #endregion

                #region TypeOfDeclaration
                else if(declaration is TypeOfDeclaration)
                {
                    var typeOf=declaration as TypeOfDeclaration;

                    // typeof(return)
                    if(typeOf.InstanceId is TokenExpression && (typeOf.InstanceId as TokenExpression).Token==DTokens.Return)
                    {
                        var m= HandleNodeMatch(currentScopeOverride,ctxt,currentScopeOverride,null,declaration);
                        if(m!=null)
                            returnedResults.Add(m);
                    }
                    // typeOf(myInt) === int
                    else if(typeOf.InstanceId!=null)
                    {
                        var wantedTypes=ResolveType(typeOf.InstanceId.ExpressionTypeRepresentation,ctxt,currentScopeOverride);

                        // Scan down for variable's base types
                        var c1=new List<ResolveResult>(wantedTypes);
                        var c2=new List<ResolveResult>();

                        while(c1.Count>0)
                        {
                            foreach(var t in c1)
                            {
                                if(t is MemberResult)
                                    c2.AddRange((t as MemberResult).MemberBaseTypes);
                                else
                                    returnedResults.Add(t);
                            }

                            c1.Clear();
                            c1.AddRange(c2);
                            c2.Clear();
                        }
                    }
                }
                #endregion

                else
                    returnedResults.Add(new StaticTypeResult() { TypeDeclarationBase = declaration });
            }
            #endregion

            #region Search in further, deeper levels
            else foreach (var rbase in rbases)
                {
                    #region Identifier
                    if (declaration is IdentifierDeclaration)
                    {
                        string searchIdentifier = (declaration as IdentifierDeclaration).Value as string;

                        // Scan for static properties
                        var staticProp = StaticPropertyResolver.TryResolveStaticProperties(
                            rbase,
                            declaration as IdentifierDeclaration,
                            ctxtOverride);
                        if (staticProp != null)
                        {
                            returnedResults.Add(staticProp);
                            continue;
                        }

                        var scanResults = new List<ResolveResult>();
                        scanResults.Add(rbase);
                        var nextResults = new List<ResolveResult>();

                        while (scanResults.Count > 0)
                        {
                            foreach (var scanResult in scanResults)
                            {
                                // First filter out all alias and member results..so that there will be only (Static-)Type or Module results left..
                                if (scanResult is MemberResult)
                                {
                                    var _m = (scanResult as MemberResult).MemberBaseTypes;
                                    if (_m != null) nextResults.AddRange(_m);
                                }

                                else if (scanResult is TypeResult)
                                {
                                    var tr=scanResult as TypeResult;
                                    var nodeMatches=ScanNodeForIdentifier(tr.ResolvedTypeDefinition, searchIdentifier, ctxtOverride);

                                    var results = HandleNodeMatches(
                                        nodeMatches,
                                        ctxtOverride,
                                        tr.ResolvedTypeDefinition,
                                        resultBase: rbase,
                                        TypeDeclaration: declaration);

                                    if (results != null)
                                        returnedResults.AddRange(results);
                                }
                                else if (scanResult is ModuleResult)
                                {
                                    var modRes = (scanResult as ModuleResult);

                                    if (modRes.IsOnlyModuleNamePartTyped())
                                    {
                                        var modNameParts = modRes.ResolvedModule.ModuleName.Split('.');

                                        if (modNameParts[modRes.AlreadyTypedModuleNameParts] == searchIdentifier)
                                        {
                                            returnedResults.Add(new ModuleResult()
                                            {
                                                ResolvedModule = modRes.ResolvedModule,
                                                AlreadyTypedModuleNameParts = modRes.AlreadyTypedModuleNameParts + 1,
                                                ResultBase = modRes,
                                                TypeDeclarationBase = declaration
                                            });
                                        }
                                    }
                                    else
                                    {
                                        var results = HandleNodeMatches(
                                        ScanNodeForIdentifier((scanResult as ModuleResult).ResolvedModule, searchIdentifier, ctxtOverride),
                                        ctxtOverride, currentScopeOverride, rbase, TypeDeclaration: declaration);
                                        if (results != null)
                                            returnedResults.AddRange(results);
                                    }
                                }
                                else if (scanResult is StaticTypeResult)
                                {

                                }
                            }

                            scanResults = nextResults;
                            nextResults = new List<ResolveResult>();
                        }
                    }
                    #endregion

                    else if (declaration is ArrayDecl || declaration is PointerDecl)
                    {
                        returnedResults.Add(new StaticTypeResult() { TypeDeclarationBase = declaration, ResultBase = rbase });
                    }

                    else if (declaration is DExpressionDecl)
                    {
                        var expr = (declaration as DExpressionDecl).Expression;

                        /*
                         * Note: Assume e.g. foo.bar.myArray in foo.bar.myArray[0] has been resolved!
                         * So, we just have to take the last postfix expression
                         */

                        /*
                         * After we've done this, we reduce the stack..
                         * Target of this action is to retrieve the value type:
                         *
                         * int[string][] myArray; // Is an array that holds an associative array, whereas the value type is 'int', and key type is 'string'
                         *
                         * auto mySubArray=myArray[0]; // returns a reference to an int[string] array
                         *
                         * auto myElement=mySubArray["abcd"]; // returns the most basic value type: 'int'
                         */
                        if (rbase is StaticTypeResult)
                        {
                            var str = rbase as StaticTypeResult;

                            if (str.TypeDeclarationBase is ArrayDecl && expr is PostfixExpression_Index)
                            {
                                returnedResults.Add(new StaticTypeResult() { TypeDeclarationBase = (str.TypeDeclarationBase as ArrayDecl).ValueType });
                            }
                        }
                        else if (rbase is MemberResult)
                        {
                            var mr = rbase as MemberResult;
                            if (mr.MemberBaseTypes != null && mr.MemberBaseTypes.Length > 0)
                                foreach (var memberType in TryRemoveAliasesFromResult(mr.MemberBaseTypes))
                                {
                                    if (expr is PostfixExpression_Index)
                                    {
                                        var str = (memberType as StaticTypeResult);
                                        /*
                                         * If the member's type is an array, and if our expression contains an index-expression (e.g. myArray[0]),
                                         * take the value type of the
                                         */
                                        // For array and pointer declarations, the StaticTypeResult object contains the array's value type / pointer base type.
                                        if (str != null && (str.TypeDeclarationBase is ArrayDecl || str.TypeDeclarationBase is PointerDecl))
                                            returnedResults.AddRange(TryRemoveAliasesFromResult(str.ResultBase));
                                    }
                                    else
                                        returnedResults.Add(memberType);
                                }
                        }
                    }
                }
            #endregion

            if (returnedResults.Count > 0)
            {
                ctxt.TryAddResults(declaration.ToString(), returnedResults.ToArray(), ctxtOverride.ScopedBlock);

                return returnedResults.ToArray();
            }

            return null;
        }
示例#13
0
        /// <summary>
        /// Scans through the node. Also checks if n is a DClassLike or an other kind of type node and checks their specific child and/or base class nodes.
        /// </summary>
        /// <param name="n"></param>
        /// <param name="name"></param>
        /// <param name="parseCache">Needed when trying to search base classes</param>
        /// <returns></returns>
        public static INode[] ScanNodeForIdentifier(IBlockNode curScope, string name, ResolverContext ctxt)
        {
            var matches = new List<INode>();

            if (curScope.Count > 0)
                foreach (var n in curScope)
                {
                    // Scan anonymous enums
                    if (n is DEnum && n.Name == "")
                    {
                        foreach (var k in n as DEnum)
                            if (k.Name == name)
                                matches.Add(k);
                    }

                    if (n.Name == name)
                        matches.Add(n);
                }

            // If our current Level node is a class-like, also attempt to search in its baseclass!
            if (curScope is DClassLike)
            {
                var baseClasses = ResolveBaseClass(curScope as DClassLike, ctxt);
                if (baseClasses != null)
                    foreach (var i in baseClasses)
                    {
                        var baseClass = i as TypeResult;
                        if (baseClass == null)
                            continue;
                        // Search for items called name in the base class(es)
                        var r = ScanNodeForIdentifier(baseClass.ResolvedTypeDefinition, name, ctxt);

                        if (r != null)
                            matches.AddRange(r);
                    }
            }

            // Check parameters
            if (curScope is DMethod)
            {
                var dm = curScope as DMethod;
                foreach (var ch in dm.Parameters)
                {
                    if (name == ch.Name)
                        matches.Add(ch);
                }
            }

            // and template parameters
            if (curScope is DNode && (curScope as DNode).TemplateParameters != null)
                foreach (var ch in (curScope as DNode).TemplateParameters)
                {
                    if (name == ch.Name)
                        matches.Add(new TemplateParameterNode(ch));
                }

            return matches.Count > 0 ? matches.ToArray() : null;
        }
示例#14
0
        public static ResolveResult[] HandleNodeMatches(IEnumerable<INode> matches,
			ResolverContext ctxt,
			IBlockNode currentlyScopedNode = null,
			ResolveResult resultBase = null,
			ITypeDeclaration TypeDeclaration = null)
        {
            var rl = new List<ResolveResult>();
            if (matches != null)
                foreach (var m in matches)
                {
                    if (m == null)
                        continue;
                    var res = HandleNodeMatch(m, ctxt, currentlyScopedNode, resultBase, typeBase: TypeDeclaration);
                    if (res != null)
                        rl.Add(res);
                }
            return rl.ToArray();
        }
示例#15
0
        /// <summary>
        /// The variable's or method's base type will be resolved (if auto type, the intializer's type will be taken).
        /// A class' base class will be searched.
        /// etc..
        /// </summary>
        /// <returns></returns>
        public static ResolveResult HandleNodeMatch(
			INode m,
			ResolverContext ctxt,
			IBlockNode currentlyScopedNode = null,
			ResolveResult resultBase = null, ITypeDeclaration typeBase = null)
        {
            if (currentlyScopedNode == null)
                currentlyScopedNode = ctxt.ScopedBlock;

            stackNum_HandleNodeMatch++;

            //HACK: Really dirty stack overflow prevention via manually counting call depth
            var DoResolveBaseType =
                stackNum_HandleNodeMatch > 5 ?
                false : ctxt.ResolveBaseTypes;
            // Prevent infinite recursion if the type accidently equals the node's name
            if (m.Type != null && m.Type.ToString(false) == m.Name)
                DoResolveBaseType = false;

            if (m is DVariable)
            {
                var v = m as DVariable;

                var memberbaseTypes = DoResolveBaseType ? ResolveType(v.Type, ctxt, currentlyScopedNode) : null;

                // For auto variables, use the initializer to get its type
                if (memberbaseTypes == null && DoResolveBaseType && v.ContainsAttribute(DTokens.Auto) && v.Initializer != null)
                {
                    var init = v.Initializer;
                    memberbaseTypes = ResolveType(init.ExpressionTypeRepresentation, ctxt, currentlyScopedNode);
                }

                // Resolve aliases if wished
                if (ctxt.ResolveAliases && memberbaseTypes != null)
                {
                    /*
                     * To ensure that absolutely all kinds of alias definitions became resolved (includes aliased alias definitions!),
                     * loop through the resolution process again, after at least one aliased type has been found.
                     */
                    while (memberbaseTypes.Length > 0)
                    {
                        bool hadAliasResolution = false;
                        var memberBaseTypes_Override = new List<ResolveResult>();

                        foreach (var type in memberbaseTypes)
                        {
                            var mr = type as MemberResult;
                            if (mr != null && mr.ResolvedMember is DVariable)
                            {
                                var dv = mr.ResolvedMember as DVariable;
                                // Note: Normally, a variable's base type mustn't be an other variable but an alias defintion...
                                if (dv.IsAlias)
                                {
                                    var newRes = ResolveType(dv.Type, ctxt, currentlyScopedNode);
                                    if (newRes != null)
                                        memberBaseTypes_Override.AddRange(newRes);
                                    hadAliasResolution = true;
                                    continue;
                                }
                            }

                            // If no alias found, re-add it to our override list again
                            memberBaseTypes_Override.Add(type);
                        }
                        memberbaseTypes = memberBaseTypes_Override.ToArray();

                        if (!hadAliasResolution)
                            break;
                    }
                }

                // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type
                stackNum_HandleNodeMatch--;
                return new MemberResult()
                {
                    ResolvedMember = m,
                    MemberBaseTypes = memberbaseTypes,
                    ResultBase = resultBase,
                    TypeDeclarationBase = typeBase
                };
            }
            else if (m is DMethod)
            {
                var method = m as DMethod;

                var methodType = method.Type;

                /*
                 * If a method's type equals null, assume that it's an 'auto' function..
                 * 1) Search for a return statement
                 * 2) Resolve the returned expression
                 * 3) Use that one as the method's type
                 */
                //TODO: What about handling 'null'-returns?
                if (methodType == null && method.Body != null)
                {
                    ReturnStatement returnStmt = null;
                    var list = new List<IStatement> { method.Body };
                    var list2 = new List<IStatement>();

                    while (returnStmt == null && list.Count > 0)
                    {
                        foreach (var stmt in list)
                        {
                            if (stmt is ReturnStatement)
                            {
                                returnStmt = stmt as ReturnStatement;
                                break;
                            }

                            if (stmt is StatementContainingStatement)
                                list2.AddRange((stmt as StatementContainingStatement).SubStatements);
                        }

                        list = list2;
                        list2 = new List<IStatement>();
                    }

                    if (returnStmt != null && returnStmt.ReturnExpression != null)
                    {
                        currentlyScopedNode = method;
                        methodType = returnStmt.ReturnExpression.ExpressionTypeRepresentation;
                    }
                }

                var ret = new MemberResult()
                {
                    ResolvedMember = m,
                    MemberBaseTypes = DoResolveBaseType ? ResolveType(methodType, ctxt, currentlyScopedNode) : null,
                    ResultBase = resultBase,
                    TypeDeclarationBase = typeBase
                };
                stackNum_HandleNodeMatch--;
                return ret;
            }
            else if (m is DClassLike)
            {
                var Class = m as DClassLike;

                var bc = DoResolveBaseType ? ResolveBaseClass(Class, ctxt) : null;

                stackNum_HandleNodeMatch--;
                return new TypeResult()
                {
                    ResolvedTypeDefinition = Class,
                    BaseClass = bc,
                    ResultBase = resultBase,
                    TypeDeclarationBase = typeBase
                };
            }
            else if (m is IAbstractSyntaxTree)
            {
                stackNum_HandleNodeMatch--;
                return new ModuleResult()
                {
                    ResolvedModule = m as IAbstractSyntaxTree,
                    AlreadyTypedModuleNameParts = 1,
                    ResultBase = resultBase,
                    TypeDeclarationBase = typeBase
                };
            }
            else if (m is DEnum)
            {
                stackNum_HandleNodeMatch--;
                return new TypeResult()
                {
                    ResolvedTypeDefinition = m as IBlockNode,
                    ResultBase = resultBase,
                    TypeDeclarationBase = typeBase
                };
            }
            else if (m is TemplateParameterNode)
            {
                stackNum_HandleNodeMatch--;
                return new MemberResult()
                {
                    ResolvedMember = m,
                    TypeDeclarationBase = typeBase,
                    ResultBase = resultBase
                };
            }

            stackNum_HandleNodeMatch--;
            // This never should happen..
            return null;
        }
示例#16
0
        public void ApplyFrom(ResolverContext other)
        {
            if (other == null)
                return;

            ScopedBlock = other.ScopedBlock;
            ScopedStatement = other.ScopedStatement;
            ParseCache = other.ParseCache;
            ImportCache = other.ImportCache;

            ResolveBaseTypes = other.ResolveBaseTypes;
            ResolveAliases = other.ResolveAliases;

            resolvedTypes = other.resolvedTypes;
        }
示例#17
0
            /// <summary>
            /// Tries to resolve a static property's name.
            /// Returns a result describing the theoretical member (".init"-%gt;MemberResult; ".typeof"-&gt;TypeResult etc).
            /// Returns null if nothing was found.
            /// </summary>
            /// <param name="InitialResult"></param>
            /// <returns></returns>
            public static ResolveResult TryResolveStaticProperties(ResolveResult InitialResult, IdentifierDeclaration Identifier, ResolverContext ctxt = null)
            {
                if (InitialResult == null || Identifier == null || InitialResult is ModuleResult)
                {
                    return null;
                }

                var propertyName = Identifier.Value as string;
                if (propertyName == null)
                    return null;

                INode relatedNode = null;

                if (InitialResult is MemberResult)
                    relatedNode = (InitialResult as MemberResult).ResolvedMember;
                else if (InitialResult is TypeResult)
                    relatedNode = (InitialResult as TypeResult).ResolvedTypeDefinition;

                #region init
                if (propertyName == "init")
                {
                    var prop_Init = new DVariable
                    {
                        Name = "init",
                        Description = "Initializer"
                    };

                    if (relatedNode != null)
                    {
                        if (!(relatedNode is DVariable))
                        {
                            prop_Init.Parent = relatedNode.Parent;
                            prop_Init.Type = new IdentifierDeclaration(relatedNode.Name);
                        }
                        else
                        {
                            prop_Init.Parent = relatedNode;
                            prop_Init.Initializer = (relatedNode as DVariable).Initializer;
                            prop_Init.Type = relatedNode.Type;
                        }
                    }

                    return new MemberResult
                    {
                        ResultBase = InitialResult,
                        MemberBaseTypes = new[] { InitialResult },
                        TypeDeclarationBase = Identifier,
                        ResolvedMember = prop_Init
                    };
                }
                #endregion

                #region sizeof
                if (propertyName == "sizeof")
                    return new MemberResult
                    {
                        ResultBase = InitialResult,
                        TypeDeclarationBase = Identifier,
                        ResolvedMember = new DVariable
                        {
                            Name = "sizeof",
                            Type = new DTokenDeclaration(DTokens.Int),
                            Initializer = new IdentifierExpression(4),
                            Description = "Size in bytes (equivalent to C's sizeof(type))"
                        }
                    };
                #endregion

                #region alignof
                if (propertyName == "alignof")
                    return new MemberResult
                    {
                        ResultBase = InitialResult,
                        TypeDeclarationBase = Identifier,
                        ResolvedMember = new DVariable
                        {
                            Name = "alignof",
                            Type = new DTokenDeclaration(DTokens.Int),
                            Description = "Alignment size"
                        }
                    };
                #endregion

                #region mangleof
                if (propertyName == "mangleof")
                    return new MemberResult
                    {
                        ResultBase = InitialResult,
                        TypeDeclarationBase = Identifier,
                        ResolvedMember = new DVariable
                        {
                            Name = "mangleof",
                            Type = new IdentifierDeclaration("string"),
                            Description = "String representing the ‘mangled’ representation of the type"
                        },
                        MemberBaseTypes = ResolveType(new IdentifierDeclaration("string"), ctxt)
                    };
                #endregion

                #region stringof
                if (propertyName == "stringof")
                    return new MemberResult
                    {
                        ResultBase = InitialResult,
                        TypeDeclarationBase = Identifier,
                        ResolvedMember = new DVariable
                        {
                            Name = "stringof",
                            Type = new IdentifierDeclaration("string"),
                            Description = "String representing the source representation of the type"
                        },
                        MemberBaseTypes = ResolveType(new IdentifierDeclaration("string"), ctxt)
                    };
                #endregion

                bool
                    isArray = false,
                    isAssocArray = false,
                    isInt = false,
                    isFloat = false;

                #region See AbsractCompletionSupport.StaticPropertyAddition
                if (InitialResult is StaticTypeResult)
                {
                    var srr = InitialResult as StaticTypeResult;

                    var type = srr.TypeDeclarationBase;

                    // on things like immutable(char), pass by the surrounding attribute..
                    while (type is MemberFunctionAttributeDecl)
                        type = (type as MemberFunctionAttributeDecl).InnerType;

                    if (type is ArrayDecl)
                    {
                        var ad = type as ArrayDecl;

                        // Normal array
                        if (ad.KeyType is DTokenDeclaration && DTokens.BasicTypes_Integral[(ad.KeyType as DTokenDeclaration).Token])
                            isArray = true;
                        // Associative array
                        else
                            isAssocArray = true;
                    }
                    else if (!(type is PointerDecl))
                    {
                        int TypeToken = srr.BaseTypeToken;

                        if (TypeToken <= 0 && type is DTokenDeclaration)
                            TypeToken = (type as DTokenDeclaration).Token;

                        if (TypeToken > 0)
                        {
                            // Determine whether float by the var's base type
                            isInt = DTokens.BasicTypes_Integral[srr.BaseTypeToken];
                            isFloat = DTokens.BasicTypes_FloatingPoint[srr.BaseTypeToken];
                        }
                    }
                }
                else if (InitialResult is ExpressionResult)
                {
                    var err = InitialResult as ExpressionResult;
                    var expr = err.Expression;

                    // 'Skip' surrounding parentheses
                    while (expr is SurroundingParenthesesExpression)
                        expr = (expr as SurroundingParenthesesExpression).Expression;

                    var idExpr = expr as IdentifierExpression;
                    if (idExpr != null)
                    {
                        // Char literals, Integrals types & Floats
                        if ((idExpr.Format & LiteralFormat.Scalar) == LiteralFormat.Scalar || idExpr.Format == LiteralFormat.CharLiteral)
                        {
                            // Floats also imply integral properties
                            isInt = true;
                            isFloat = (idExpr.Format & LiteralFormat.FloatingPoint) == LiteralFormat.FloatingPoint;
                        }
                        // String literals
                        else if (idExpr.Format == LiteralFormat.StringLiteral || idExpr.Format == LiteralFormat.VerbatimStringLiteral)
                        {
                            isArray = true;
                        }
                    }
                    // Pointer conversions (e.g. (myInt*).sizeof)
                }
                #endregion

                //TODO: Resolve static [assoc] array props
                if (isArray || isAssocArray)
                {

                }

                return null;
            }
示例#18
0
        public ResolverContextStack(ParseCacheList ParseCache, ResolverContext initialContext)
        {
            this.ParseCache = ParseCache;

            stack.Push(initialContext);
        }
示例#19
0
        public static TypeResult[] ResolveBaseClass(DClassLike ActualClass, ResolverContext ctxt)
        {
            if (bcStack > 8)
            {
                bcStack--;
                return null;
            }

            if (ActualClass == null || ((ActualClass.BaseClasses == null || ActualClass.BaseClasses.Count < 1) && ActualClass.Name != null && ActualClass.Name.ToLower() == "object"))
                return null;

            var ret = new List<TypeResult>();
            // Implicitly set the object class to the inherited class if no explicit one was done
            var type = (ActualClass.BaseClasses == null || ActualClass.BaseClasses.Count < 1) ? new IdentifierDeclaration("Object") : ActualClass.BaseClasses[0];

            // A class cannot inherit itself
            if (type == null || type.ToString(false) == ActualClass.Name || ActualClass.NodeRoot == ActualClass)
                return null;

            bcStack++;

            /*
             * If the ActualClass is defined in an other module (so not in where the type resolution has been started),
             * we have to enable access to the ActualClass's module's imports!
             *
             * module modA:
             * import modB;
             *
             * class A:B{
             *
             *		void bar()
             *		{
             *			fooC(); // Note that modC wasn't imported publically! Anyway, we're still able to access this method!
             *			// So, the resolver must know that there is a class C.
             *		}
             * }
             *
             * -----------------
             * module modB:
             * import modC;
             *
             * // --> When being about to resolve B's base class C, we have to use the imports of modB(!), not modA
             * class B:C{}
             * -----------------
             * module modC:
             *
             * class C{
             *
             * void fooC();
             *
             * }
             */
            ResolveResult[] results = null;

            if (ctxt != null)
            {
                var ctxtOverride = new ResolverContext();

                // Take ctxt's parse cache etc.
                ctxtOverride.ApplyFrom(ctxt);

                // First override the scoped block
                ctxtOverride.ScopedBlock = ActualClass.Parent as IBlockNode;

                // Then override the import cache with imports of the ActualClass's module
                if (ctxt.ScopedBlock != null &&
                    ctxt.ScopedBlock.NodeRoot != ActualClass.NodeRoot)
                    ctxtOverride.ImportCache = ResolveImports(ActualClass.NodeRoot as DModule, ctxt.ParseCache);

                results = ResolveType(type, ctxtOverride);
            }
            else
            {
                results = ResolveType(type, null, ActualClass.Parent as IBlockNode);
            }

            if (results != null)
                foreach (var i in results)
                    if (i is TypeResult)
                        ret.Add(i as TypeResult);
            bcStack--;

            return ret.Count > 0 ? ret.ToArray() : null;
        }