/// <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; }
/// <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); }
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; }
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); }