private void InitializeFullQualifierSymbol(BoundQualifier qualifier) { if (qualifier.IsInitialized()) { return; } var result = ArrayBuilder <object> .GetInstance(); var identifiers = qualifier.Identifiers; NamespaceOrTypeSymbol qualifierOpt = null; for (int i = 0; i < identifiers.Length; i++) { bool last = i == identifiers.Length - 1; var types = last ? _types : _nestingTypes; var identifier = identifiers[i]; LookupResult lookupResult = LookupResult.GetInstance(); this.LookupSymbolsSimpleName(lookupResult, new LookupConstraints(identifier.Name, identifier.MetadataName, types, qualifierOpt)); var symbol = this.ResultSymbol(lookupResult, identifier.Name, identifier.MetadataName, identifier.Syntax, identifier.BoundTree.DiagnosticBag, false, out bool wasError, qualifierOpt, LookupOptions.Default); Debug.Assert(symbol != null); result.Add(symbol); lookupResult.Free(); qualifierOpt = symbol as NamespaceOrTypeSymbol; } qualifier.InitializeValues(identifiers, result.ToImmutableAndFree()); }
protected override void LookupSymbolsInSingleBinder(LookupResult result, string name, int arity, ConsList <Symbol> basesBeingResolved, LookupOptions options, bool diagnose) { LookupResult tmp = LookupResult.GetInstance(); LookupResult nonViable = LookupResult.GetInstance(); // Member definitions of different kinds hide each other (field defs hide method defs, etc.). // So even if the caller asks only for invocable members find any member first and then reject the result if a non-invokable is found. LookupOptions anyMemberLookupOptions = options & ~LookupOptions.MustBeInvocableMember; // TODO: optimize lookup (there might be many interactions in the chain) for (ICompilation commonSubmission = Compilation.PreviousSubmission; commonSubmission != null; commonSubmission = commonSubmission.PreviousSubmission) { // TODO (tomat): cross-language binding - for now, skip non-C# submissions Compilation submission = commonSubmission as Compilation; if (submission == null) { continue; } tmp.Clear(); Imports imports = GetImports(submission); imports.LookupSymbolInAliases(this, tmp, name, arity, basesBeingResolved, anyMemberLookupOptions, diagnose); // If a viable using alias and a matching member are both defined in the submission an error is reported elsewhere. // Ignore the member in such case. if (!tmp.IsMultiViable && (options & LookupOptions.NamespaceAliasesOnly) == 0) { this.LookupMembers(tmp, submission.ScriptClass, name, arity, basesBeingResolved, anyMemberLookupOptions, diagnose); } // found a non-method in the current submission: if (tmp.Symbols.Count > 0 && tmp.Symbols.First().Kind != SymbolKind.Method) { if (!tmp.IsMultiViable) { // skip non-viable members, but remember them in case no viable members are found in previous submissions: nonViable.MergePrioritized(tmp); continue; } if (result.Symbols.Count == 0) { result.MergeEqual(tmp); } break; } // merge overloads: Debug.Assert(result.Symbols.Count == 0 || result.Symbols.All(s => s.Kind == SymbolKind.Method)); result.MergeEqual(tmp); } // Set a proper error if we found a symbol that is not invocable but were asked for invocable only. // Only a single non-method can be present in the result; methods are always invocable. if ((options & LookupOptions.MustBeInvocableMember) != 0 && result.Symbols.Count == 1) { Symbol symbol = result.Symbols.First(); AliasSymbol alias = symbol as AliasSymbol; if (alias != null) { symbol = alias.GetAliasTarget(basesBeingResolved); } if (IsNonInvocableMember(symbol)) { result.SetFrom(LookupResult.NotInvocable(symbol, result.Symbols.First(), diagnose)); } } else if (result.Symbols.Count == 0) { result.SetFrom(nonViable); } tmp.Free(); nonViable.Free(); }