private void ValidateScope(ILanguageScope scope) { // collect duplicate identifiers at this scope // declaring a variable in a local scope hides the parent scope variables, // so we don't need to look at other levels var outputDeclarations = scope.Declarations.Where(decl => decl is OutputSymbol); var nonOutputDeclarations = scope.Declarations.Where(decl => decl is not OutputSymbol); // all symbols apart from outputs are in the same namespace, so check for uniqueness. this.Diagnostics.AddRange( FindDuplicateNamedSymbols(nonOutputDeclarations) .Select(decl => DiagnosticBuilder.ForPosition(decl.NameSyntax).IdentifierMultipleDeclarations(decl.Name))); // output symbols cannot be referenced, so the names declared by them do not need to be unique in the scope. // we still need to ensure that they unique among other outputs. this.Diagnostics.AddRange( FindDuplicateNamedSymbols(outputDeclarations) .Select(decl => DiagnosticBuilder.ForPosition(decl.NameSyntax).OutputMultipleDeclarations(decl.Name))); // imported namespaces are reserved in all the scopes // otherwise the user could accidentally hide a namespace which would remove the ability // to fully qualify a function this.Diagnostics.AddRange(nonOutputDeclarations .Where(decl => decl.NameSyntax.IsValid && this.importedNamespaces.ContainsKey(decl.Name)) .Select(reservedSymbol => DiagnosticBuilder.ForPosition(reservedSymbol.NameSyntax).SymbolicNameCannotUseReservedNamespaceName(reservedSymbol.Name, this.importedNamespaces.Keys))); }
private void ValidateScope(ILanguageScope scope) { // collect duplicate identifiers at this scope // declaring a variable in a local scope hides the parent scope variables, // so we don't need to look at other levels this.Diagnostics.AddRange(scope.AllDeclarations .Where(decl => decl.NameSyntax.IsValid) .GroupBy(decl => decl.Name, LanguageConstants.IdentifierComparer) .Where(group => group.Count() > 1) .SelectMany(group => group) .Select(decl => DiagnosticBuilder.ForPosition(decl.NameSyntax).IdentifierMultipleDeclarations(decl.Name))); // imported namespaces are reserved in all the scopes // otherwise the user could accidentally hide a namespace which would remove the ability // to fully qualify a function this.Diagnostics.AddRange(scope.AllDeclarations .Where(decl => decl.NameSyntax.IsValid && this.importedNamespaces.ContainsKey(decl.Name)) .Select(reservedSymbol => DiagnosticBuilder.ForPosition(reservedSymbol.NameSyntax).SymbolicNameCannotUseReservedNamespaceName(reservedSymbol.Name, this.importedNamespaces.Keys))); }
private static ResourceSymbol?LookupResourceSymbolByName(ILanguageScope scope, IdentifierSyntax identifierSyntax) => scope.Declarations .OfType <ResourceSymbol>() .FirstOrDefault(symbol => string.Equals(identifierSyntax.IdentifierName, symbol.Name, LanguageConstants.IdentifierComparison));