public static SemanticRuleViolation TypeOrNamespaceDoesNotExist(INode subject, NameSyntax name) { return new SemanticRuleViolation( RuleCodes.TypeOrNamespaceDoesNotExist, String.Format("The type or namespace '{0}' could not be found.", name), subject); }
public SymbolResolution Resolve(ISymbol context, NameSyntax name) { var builtInType = _builtInTypes.TryGetValue(name); if(builtInType.HasValue) return new SymbolResolution(builtInType.Value); var fullName = context.FullName + name; var symbol = _map.TryGetValue(fullName); if(symbol.HasValue) return new SymbolResolution(symbol.Value); var parent = context.Parent as ISymbol; var typeWithBase = context as ITypeWithBase; if (parent != null && typeWithBase != null && typeWithBase.Base.HasValue) { var @base = Resolve(parent, typeWithBase.Base.Value); if (@base.Status == SymbolResolutionStatus.Found) { var baseResolution = Resolve(@base.Symbol, name); if (baseResolution.Status != SymbolResolutionStatus.NotFound) return baseResolution; } } var usingsContainer = context as IUsingsContainer; if (usingsContainer != null) { var resolution = ResolveViaUsings(context.FullName, name, usingsContainer); if (resolution.Status != SymbolResolutionStatus.NotFound) return resolution; } var contextualResolution = context.FullName .Recurse(x => x.Parent) .Skip(1) .SelectMaybe(x => _map.TryGetValue(x + name)) .Select(x => new SymbolResolution(x)) .TryFirst(x => x.Status != SymbolResolutionStatus.NotFound) .ValueOrDefault(); if (contextualResolution.Status != SymbolResolutionStatus.NotFound) return contextualResolution; var parentSymbol = context.Parent as ISymbol; if (parentSymbol != null) return Resolve(parentSymbol, name); var parentUsings = context.Parent as IUsingsContainer; if (parentUsings != null) return ResolveViaUsings(null, name, parentUsings); return default(SymbolResolution); }
public static SemanticRuleViolation TypeReferenceIsAmbiguous(INode subject, NameSyntax name, SymbolResolution resolution) { var symbols = resolution.Symbols.ToArray(); string ambiguousTypes = symbols.Take(symbols.Length - 1).Delimit(", ", x => String.Format("'{0}'", x.FullName)) + String.Format(" and '{0}'", symbols[symbols.Length - 1].FullName); return new SemanticRuleViolation( RuleCodes.TypeReferenceIsAmbiguous, String.Format("'{0}' is an ambiguous reference between {1}.", name, ambiguousTypes), subject); }
private async Task <Document> IntroduceLocalDeclarationIntoBlockAsync( SemanticDocument document, BlockSyntax block, ExpressionSyntax expression, NameSyntax newLocalName, LocalDeclarationStatementSyntax declarationStatement, bool allOccurrences, CancellationToken cancellationToken) { declarationStatement = declarationStatement.WithAdditionalAnnotations(Formatter.Annotation); SyntaxNode scope = block; // If we're within a non-static local function, our scope for the new local declaration is expanded to include the enclosing member. var localFunction = block.GetAncestor <LocalFunctionStatementSyntax>(); if (localFunction != null && !localFunction.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.StaticKeyword))) { scope = block.GetAncestor <MemberDeclarationSyntax>(); } var matches = FindMatches(document, expression, document, scope, allOccurrences, cancellationToken); Debug.Assert(matches.Contains(expression)); (document, matches) = await ComplexifyParentingStatements(document, matches, cancellationToken).ConfigureAwait(false); // Our original expression should have been one of the matches, which were tracked as part // of complexification, so we can retrieve the latest version of the expression here. expression = document.Root.GetCurrentNode(expression); var root = document.Root; ISet <StatementSyntax> allAffectedStatements = new HashSet <StatementSyntax>(matches.SelectMany(expr => expr.GetAncestorsOrThis <StatementSyntax>())); SyntaxNode innermostCommonBlock; var innermostStatements = new HashSet <StatementSyntax>(matches.Select(expr => expr.GetAncestorOrThis <StatementSyntax>())); if (innermostStatements.Count == 1) { // if there was only one match, or all the matches came from the same statement var statement = innermostStatements.Single(); // and the statement is an embedded statement without a block, we want to generate one // around this statement rather than continue going up to find an actual block if (!IsBlockLike(statement.Parent)) { root = root.TrackNodes(allAffectedStatements.Concat(new SyntaxNode[] { expression, statement })); root = root.ReplaceNode(root.GetCurrentNode(statement), SyntaxFactory.Block(root.GetCurrentNode(statement)).WithAdditionalAnnotations(Formatter.Annotation)); expression = root.GetCurrentNode(expression); allAffectedStatements = allAffectedStatements.Select(root.GetCurrentNode).ToSet(); statement = root.GetCurrentNode(statement); } innermostCommonBlock = statement.Parent; } else { innermostCommonBlock = innermostStatements.FindInnermostCommonNode(IsBlockLike); } var firstStatementAffectedIndex = GetStatements(innermostCommonBlock).IndexOf(allAffectedStatements.Contains); var newInnerMostBlock = Rewrite( document, expression, newLocalName, document, innermostCommonBlock, allOccurrences, cancellationToken); var statements = InsertWithinTriviaOfNext(GetStatements(newInnerMostBlock), declarationStatement, firstStatementAffectedIndex); var finalInnerMostBlock = WithStatements(newInnerMostBlock, statements); var newRoot = root.ReplaceNode(innermostCommonBlock, finalInnerMostBlock); return(document.Document.WithSyntaxRoot(newRoot)); }
public static QualifiedNameSyntax Qualified(this NameSyntax left, string ident) { return(SyntaxFactory.QualifiedName(left, SyntaxFactory.IdentifierName(ident))); }
/// <summary> /// Returns qualified name syntax. /// </summary> /// <param name="instance"> /// The instance. /// </param> /// <param name="member"> /// The member. /// </param> /// <returns> /// The resulting <see cref="MemberAccessExpressionSyntax"/>. /// </returns> public static QualifiedNameSyntax Qualify(this NameSyntax instance, string member) { return(instance.Qualify(member.ToIdentifierName())); }
private async Task <IEnumerable <CompletionItem> > GetCompletionsOffOfExplicitInterfaceAsync( Document document, SemanticModel semanticModel, int position, NameSyntax name, CancellationToken cancellationToken) { // Bind the interface name which is to the left of the dot var syntaxTree = semanticModel.SyntaxTree; var nameBinding = semanticModel.GetSymbolInfo(name, cancellationToken); var context = CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken); var symbol = nameBinding.Symbol as ITypeSymbol; if (symbol == null || symbol.TypeKind != TypeKind.Interface) { return(SpecializedCollections.EmptyEnumerable <CompletionItem>()); } var members = semanticModel.LookupSymbols( position: name.SpanStart, container: symbol) .Where(s => !s.IsStatic) .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation); // We're going to create a entry for each one, including the signature var completions = new List <CompletionItem>(); var signatureDisplayFormat = new SymbolDisplayFormat( genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, memberOptions: SymbolDisplayMemberOptions.IncludeParameters, parameterOptions: SymbolDisplayParameterOptions.IncludeName | SymbolDisplayParameterOptions.IncludeType | SymbolDisplayParameterOptions.IncludeParamsRefOut, miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | SymbolDisplayMiscellaneousOptions.UseSpecialTypes); var namePosition = name.SpanStart; var text = await context.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, context.Position); foreach (var member in members) { var displayString = member.ToMinimalDisplayString(semanticModel, namePosition, signatureDisplayFormat); var memberCopied = member; var insertionText = displayString; completions.Add(new SymbolCompletionItem( this, displayString, insertionText: insertionText, filterSpan: textChangeSpan, position: position, symbols: new List <ISymbol> { member }, context: context)); } return(completions); }
protected override TypeSyntax GetTypeName() { NameSyntax ns = Context.NamespaceProvider.GetNamespace(Element); return(QualifiedName(ns, IdentifierName(GetClassName()))); }
private UsingDirectiveSyntax QualifyUsingDirective(UsingDirectiveSyntax usingDirective) { NameSyntax originalName = usingDirective.Name; NameSyntax rewrittenName; switch (originalName.Kind()) { case SyntaxKind.QualifiedName: case SyntaxKind.IdentifierName: case SyntaxKind.GenericName: if (originalName.Parent.IsKind(SyntaxKind.UsingDirective) || originalName.Parent.IsKind(SyntaxKind.TypeArgumentList)) { var symbol = this.semanticModel.GetSymbolInfo(originalName, cancellationToken: CancellationToken.None).Symbol; if (symbol == null) { rewrittenName = originalName; break; } if (symbol is INamespaceSymbol) { // TODO: Preserve inner trivia string fullName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); NameSyntax replacement = SyntaxFactory.ParseName(fullName); if (!originalName.DescendantNodesAndSelf().OfType <AliasQualifiedNameSyntax>().Any()) { replacement = replacement.ReplaceNodes( replacement.DescendantNodesAndSelf().OfType <AliasQualifiedNameSyntax>(), (originalNode2, rewrittenNode2) => rewrittenNode2.Name); } rewrittenName = replacement.WithTriviaFrom(originalName); break; } else if (symbol is INamedTypeSymbol namedTypeSymbol) { // TODO: Preserve inner trivia // TODO: simplify after qualification string fullName; if (SpecialTypeHelper.IsPredefinedType(namedTypeSymbol.OriginalDefinition.SpecialType)) { fullName = "global::System." + symbol.Name; } else if (namedTypeSymbol.IsTupleType()) { fullName = namedTypeSymbol.TupleUnderlyingType().ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); } else { fullName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); } NameSyntax replacement = SyntaxFactory.ParseName(fullName); if (!originalName.DescendantNodesAndSelf().OfType <AliasQualifiedNameSyntax>().Any()) { replacement = replacement.ReplaceNodes( replacement.DescendantNodesAndSelf().OfType <AliasQualifiedNameSyntax>(), (originalNode2, rewrittenNode2) => rewrittenNode2.Name); } rewrittenName = replacement.WithTriviaFrom(originalName); break; } else { rewrittenName = originalName; break; } } else { rewrittenName = originalName; break; } case SyntaxKind.AliasQualifiedName: case SyntaxKind.PredefinedType: default: rewrittenName = originalName; break; } if (rewrittenName == originalName) { return(usingDirective); } return(usingDirective.ReplaceNode(originalName, rewrittenName)); }
public ContractInvocationInfo(SimpleNameSyntax className, SimpleNameSyntax methodName, NameSyntax exceptionType, ExpressionSyntax condition, ExpressionSyntax message, ExpressionSyntax conditionString, ArgumentListSyntax allArguments) { ClassName = className; MethodName = methodName; ExceptionType = exceptionType; Condition = condition; Message = message; ConditionString = conditionString; AllArguments = allArguments; }
private TypeDefinition(string @name, string @namespace, ImmutableList <UsingDirectiveSyntax> @usings, ImmutableList <PropertyDefinition> @properties, NameSyntax @validateMethodName) { Name = @name; Namespace = @namespace; Usings = @usings; Properties = @properties; ValidateMethodName = @validateMethodName; }
private static IEnumerable <ISymbol> GetSymbolsOffOfName( CSharpSyntaxContext context, NameSyntax name, CancellationToken cancellationToken) { // Check if we're in an interesting situation like this: // // int i = 5; // i. // <-- here // List<string> ml = new List<string>(); // The problem is that "i.List<string>" gets parsed as a type. In this case we need to // try binding again as if "i" is an expression and not a type. In order to do that, we // need to speculate as to what 'i' meant if it wasn't part of a local declaration's // type. if (name.IsFoundUnder <LocalDeclarationStatementSyntax>(d => d.Declaration.Type)) { var speculativeBinding = context.SemanticModel.GetSpeculativeSymbolInfo(name.SpanStart, name, SpeculativeBindingOption.BindAsExpression); var container = context.SemanticModel.GetSpeculativeTypeInfo(name.SpanStart, name, SpeculativeBindingOption.BindAsExpression).Type; return(GetSymbolsOffOfBoundExpression(context, name, name, speculativeBinding, container, cancellationToken)); } // We're in a name-only context, since if we were an expression we'd be a // MemberAccessExpressionSyntax. Thus, let's do other namespaces and types. var nameBinding = context.SemanticModel.GetSymbolInfo(name, cancellationToken); var symbol = nameBinding.Symbol as INamespaceOrTypeSymbol; if (symbol != null) { IEnumerable <ISymbol> symbols = context.SemanticModel.LookupNamespacesAndTypes( position: name.SpanStart, container: symbol); // Filter the types when in a using directive, but not an alias. // // Cases: // using | -- Show namespaces (and static types in C# v6) // using A = B.| -- Show namespace and types var usingDirective = name.GetAncestorOrThis <UsingDirectiveSyntax>(); if (usingDirective != null && usingDirective.Alias == null) { // Do we also have inclusion of static types? if (((CSharpParseOptions)context.SyntaxTree.Options).LanguageVersion >= LanguageVersion.CSharp6) { symbols = symbols.Where(s => s.IsNamespace() || s.IsStaticType()).ToList(); } else { symbols = symbols.Where(s => s.IsNamespace()).ToList(); } } if (symbols.Any()) { return(symbols); } } return(SpecializedCollections.EmptyEnumerable <ISymbol>()); }
private BuiltInType(NameSyntax alias, Type actualType) { _alias = alias; _actualType = actualType; _fullName = Parser.Name.Parse(actualType.FullName); }
private FunctionInvocationExpressionSyntax ParseFunctionInvocationExpression(NameSyntax name) { var arguments = ParseParenthesizedArgumentList(false); return(new FunctionInvocationExpressionSyntax(name, arguments)); }
public static bool ParseInvocation(InvocationExpressionSyntax invocation, out ContractInvocationInfo invocationInfo) { if (invocation.ArgumentList.Arguments.Count >= 1 && invocation.ArgumentList.Arguments.Count <= 3 && invocation.Expression is MemberAccessExpressionSyntax memberAccess && memberAccess.Name is SimpleNameSyntax methodNameSyntax) { SimpleNameSyntax className = memberAccess.Expression as SimpleNameSyntax; if (className == null && memberAccess.Expression is MemberAccessExpressionSyntax classMemberAccess) { className = classMemberAccess.Name as SimpleNameSyntax; } if (className != null && ValidContractClasses.Contains(className.Identifier.ValueText)) { SimpleNameSyntax methodName = methodNameSyntax; NameSyntax genericExceptionType = null; if (methodNameSyntax is GenericNameSyntax genericName && genericName.TypeArgumentList.Arguments.Count == 1) { genericExceptionType = genericName.TypeArgumentList.Arguments[0] as NameSyntax; } ExpressionSyntax condition = invocation.ArgumentList.Arguments[0].Expression; ExpressionSyntax message = null; ExpressionSyntax conditionString = null; if (invocation.ArgumentList.Arguments.Count >= 2) { if (invocation.ArgumentList.Arguments[1].NameColon != null) { if (invocation.ArgumentList.Arguments[1].NameColon.Name.Identifier.ValueText == "conditionString") { conditionString = invocation.ArgumentList.Arguments[1].Expression; } else { message = invocation.ArgumentList.Arguments[1].Expression; } } else { message = invocation.ArgumentList.Arguments[1].Expression; } } if (invocation.ArgumentList.Arguments.Count == 3) { if (invocation.ArgumentList.Arguments[2].NameColon != null) { if (invocation.ArgumentList.Arguments[2].NameColon.Name.Identifier.ValueText == "message" || invocation.ArgumentList.Arguments[2].NameColon.Name.Identifier.ValueText == "userMessage") { message = invocation.ArgumentList.Arguments[2].Expression; } else { conditionString = invocation.ArgumentList.Arguments[2].Expression; } } else { conditionString = invocation.ArgumentList.Arguments[2].Expression; } } if (className != null && methodName != null && condition != null) { invocationInfo = new ContractInvocationInfo(className, methodName, genericExceptionType, condition, message, conditionString, invocation.ArgumentList); return(true); } } } invocationInfo = null; return(false); }
public static Imports FromGlobalUsings(CSharpCompilation compilation) { var usings = compilation.Options.Usings; if (usings.Length == 0 && compilation.PreviousSubmission == null) { return(Empty); } var diagnostics = new DiagnosticBag(); var usingsBinder = new InContainerBinder(compilation.GlobalNamespace, new BuckStopsHereBinder(compilation)); var boundUsings = ArrayBuilder <NamespaceOrTypeAndUsingDirective> .GetInstance(); var uniqueUsings = PooledHashSet <NamespaceOrTypeSymbol> .GetInstance(); foreach (string @using in usings) { if ([email protected]()) { continue; } string[] identifiers = @using.Split('.'); NameSyntax qualifiedName = SyntaxFactory.IdentifierName(identifiers[0]); for (int j = 1; j < identifiers.Length; j++) { qualifiedName = SyntaxFactory.QualifiedName(left: qualifiedName, right: SyntaxFactory.IdentifierName(identifiers[j])); } var imported = usingsBinder.BindNamespaceOrTypeSymbol(qualifiedName, diagnostics); if (uniqueUsings.Add(imported)) { boundUsings.Add(new NamespaceOrTypeAndUsingDirective(imported, null)); } } if (diagnostics.IsEmptyWithoutResolution) { diagnostics = null; } var previousSubmissionImports = compilation.PreviousSubmission?.GlobalImports; if (previousSubmissionImports != null) { // Currently, only usings are supported. Debug.Assert(previousSubmissionImports.UsingAliases.IsEmpty); Debug.Assert(previousSubmissionImports.ExternAliases.IsEmpty); var expandedImports = ExpandPreviousSubmissionImports(previousSubmissionImports, compilation); foreach (var previousUsing in expandedImports.Usings) { if (uniqueUsings.Add(previousUsing.NamespaceOrType)) { boundUsings.Add(previousUsing); } } } uniqueUsings.Free(); if (boundUsings.Count == 0) { boundUsings.Free(); return(Empty); } return(new Imports(compilation, ImmutableDictionary <string, AliasAndUsingDirective> .Empty, boundUsings.ToImmutableAndFree(), ImmutableArray <AliasAndExternAliasDirective> .Empty, diagnostics)); }
// Private Methods private static QualifiedNameVisitor.R _Name(NameSyntax node) { return(new QualifiedNameVisitor().Visit(node)); }
internal static NameSyntax PrependExternAlias(IdentifierNameSyntax externAliasSyntax, NameSyntax nameSyntax) { if (nameSyntax is QualifiedNameSyntax qualifiedNameSyntax) { return(SyntaxFactory.QualifiedName( PrependExternAlias(externAliasSyntax, qualifiedNameSyntax.Left), qualifiedNameSyntax.Right)); } else { return(SyntaxFactory.AliasQualifiedName(externAliasSyntax, (SimpleNameSyntax)nameSyntax)); } }
public static IList <NameSyntax> GetNameParts(this NameSyntax nameSyntax) => new NameSyntaxIterator(nameSyntax).ToList();
private bool CompareNames(NameSyntax oldName, NameSyntax newName) { if (oldName.Kind() != newName.Kind()) { return(false); } switch (oldName.Kind()) { case SyntaxKind.IdentifierName: var oldIdentifierName = (IdentifierNameSyntax)oldName; var newIdentifierName = (IdentifierNameSyntax)newName; return(StringComparer.Ordinal.Equals( oldIdentifierName.Identifier.ToString(), newIdentifierName.Identifier.ToString() )); case SyntaxKind.QualifiedName: var oldQualifiedName = (QualifiedNameSyntax)oldName; var newQualifiedName = (QualifiedNameSyntax)newName; return(CompareNames(oldQualifiedName.Left, newQualifiedName.Left) && CompareNames(oldQualifiedName.Right, oldQualifiedName.Right)); case SyntaxKind.GenericName: var oldGenericName = (GenericNameSyntax)oldName; var newGenericName = (GenericNameSyntax)newName; if ( !StringComparer.Ordinal.Equals( oldGenericName.Identifier.ToString(), newGenericName.Identifier.ToString() ) ) { return(false); } if (oldGenericName.Arity != newGenericName.Arity) { return(false); } for (var i = 0; i < oldGenericName.Arity; i++) { if ( !CompareTypes( oldGenericName.TypeArgumentList.Arguments[i], newGenericName.TypeArgumentList.Arguments[i] ) ) { return(false); } } return(true); case SyntaxKind.AliasQualifiedName: var oldAliasQualifiedName = (AliasQualifiedNameSyntax)oldName; var newAliasQualifiedName = (AliasQualifiedNameSyntax)newName; return(CompareNames( oldAliasQualifiedName.Alias, newAliasQualifiedName.Alias ) && CompareNames(oldAliasQualifiedName.Name, newAliasQualifiedName.Name)); } Debug.Fail("Unknown kind: " + oldName.Kind()); return(false); }
public static NameSyntax GetLastDottedName(this NameSyntax nameSyntax) { var parts = nameSyntax.GetNameParts(); return(parts[parts.Count - 1]); }
static string Ser(NameSyntax nameSyn) => nameSyn switch {
private static void CheckNamespaceNameSyntax(SyntaxNodeAnalysisContext context, NameSyntax nameSyntax, StyleCopSettings settings) { if (nameSyntax == null || nameSyntax.IsMissing) { return; } if (nameSyntax is QualifiedNameSyntax qualifiedNameSyntax) { CheckNamespaceNameSyntax(context, qualifiedNameSyntax.Left, settings); CheckNamespaceNameSyntax(context, qualifiedNameSyntax.Right, settings); return; } if (nameSyntax is SimpleNameSyntax simpleNameSyntax && !settings.NamingRules.AllowedNamespaceComponents.Contains(simpleNameSyntax.Identifier.ValueText)) { CheckElementNameToken(context, simpleNameSyntax.Identifier); return; } // TODO: any other cases? }
private ImmutableArray <ISymbol> GetSymbolsOffOfName(NameSyntax name) { // Check if we're in an interesting situation like this: // // int i = 5; // i. // <-- here // List<string> ml = new List<string>(); // // The problem is that "i.List<string>" gets parsed as a type. In this case we need // to try binding again as if "i" is an expression and not a type. In order to do // that, we need to speculate as to what 'i' meant if it wasn't part of a local // declaration's type. // // Another interesting case is something like: // // stringList. // await Test2(); // // Here "stringList.await" is thought of as the return type of a local function. if (name.IsFoundUnder <LocalFunctionStatementSyntax>(d => d.ReturnType) || name.IsFoundUnder <LocalDeclarationStatementSyntax>(d => d.Declaration.Type) || name.IsFoundUnder <FieldDeclarationSyntax>(d => d.Declaration.Type)) { var speculativeBinding = _context.SemanticModel.GetSpeculativeSymbolInfo( name.SpanStart, name, SpeculativeBindingOption.BindAsExpression); var container = _context.SemanticModel.GetSpeculativeTypeInfo( name.SpanStart, name, SpeculativeBindingOption.BindAsExpression).Type; var speculativeResult = GetSymbolsOffOfBoundExpression(name, name, speculativeBinding, container); return(speculativeResult); } // We're in a name-only context, since if we were an expression we'd be a // MemberAccessExpressionSyntax. Thus, let's do other namespaces and types. var nameBinding = _context.SemanticModel.GetSymbolInfo(name, _cancellationToken); if (nameBinding.Symbol is INamespaceOrTypeSymbol symbol) { if (_context.IsNameOfContext) { return(_context.SemanticModel.LookupSymbols(position: name.SpanStart, container: symbol)); } var symbols = _context.SemanticModel.LookupNamespacesAndTypes( position: name.SpanStart, container: symbol); if (_context.IsNamespaceDeclarationNameContext) { var declarationSyntax = name.GetAncestorOrThis <NamespaceDeclarationSyntax>(); return(symbols.WhereAsArray(s => IsNonIntersectingNamespace(s, declarationSyntax))); } // Filter the types when in a using directive, but not an alias. // // Cases: // using | -- Show namespaces // using A.| -- Show namespaces // using static | -- Show namespace and types // using A = B.| -- Show namespace and types var usingDirective = name.GetAncestorOrThis <UsingDirectiveSyntax>(); if (usingDirective != null && usingDirective.Alias == null) { return(usingDirective.StaticKeyword.IsKind(SyntaxKind.StaticKeyword) ? symbols.WhereAsArray(s => !s.IsDelegateType() && !s.IsInterfaceType()) : symbols.WhereAsArray(s => s.IsNamespace())); } return(symbols); } return(ImmutableArray <ISymbol> .Empty); }
private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings) { NameSyntax nameSyntax = ((NamespaceDeclarationSyntax)context.Node).Name; CheckNamespaceNameSyntax(context, nameSyntax, settings); }
/// <summary> /// Returns member access syntax. /// </summary> /// <param name="instance"> /// The instance. /// </param> /// <param name="member"> /// The member. /// </param> /// <returns> /// The resulting <see cref="MemberAccessExpressionSyntax"/>. /// </returns> public static QualifiedNameSyntax Qualify(this NameSyntax instance, IdentifierNameSyntax member) { return(SyntaxFactory.QualifiedName(instance, member).WithDotToken(SyntaxFactory.Token(SyntaxKind.DotToken))); }
public Func <string, IEnumerable <StatementSyntax> > GetStatement(IBeforeCompileContext context, INamedTypeSymbol symbol, ClassDeclarationSyntax declaration) { var attributeSymbol = symbol.GetAttributes().Single(x => x.AttributeClass.Name.ToString().Contains("ServiceDescriptorAttribute")); var attributeDeclaration = declaration.AttributeLists .SelectMany(z => z.Attributes) .Single(z => z.Name.ToString().Contains("ServiceDescriptor")); // This appears safe to call on all types, generic or otherwise var implementationType = symbol.ConstructUnboundGenericType().ToDisplayString(); var implementationQualifiedName = BuildQualifiedName(implementationType); string serviceType = null; IEnumerable <NameSyntax> serviceQualifiedNames = symbol.AllInterfaces .Select(z => BuildQualifiedName(z.ConstructUnboundGenericType().ToDisplayString())); if (declaration.Modifiers.Any(z => z.RawKind == (int)SyntaxKind.PublicKeyword)) { // TODO: Should this include all base types? Should it be the lowest base type (HttpContext for example)? serviceQualifiedNames = serviceQualifiedNames.Union(new NameSyntax[] { implementationQualifiedName }); } if (attributeSymbol.ConstructorArguments.Count() > 0 && attributeSymbol.ConstructorArguments[0].Value != null) { var serviceNameTypedSymbol = (INamedTypeSymbol)attributeSymbol.ConstructorArguments[0].Value; if (serviceNameTypedSymbol == null) { throw new Exception("Could not infer service symbol"); } serviceType = serviceNameTypedSymbol.ConstructUnboundGenericType().ToString(); serviceQualifiedNames = new NameSyntax[] { BuildQualifiedName(serviceType) }; } var baseTypes = new List <string>(); var impType = symbol; while (impType != null) { baseTypes.Add(impType.ToDisplayString()); impType = impType.BaseType; } // TODO: Enforce implementation is assignable to service // Diagnostic error? var potentialBaseTypes = baseTypes.Concat( symbol.AllInterfaces.Select(z => z.ConstructUnboundGenericType().ToDisplayString()) ); // This is where some of the power comes out. // We now have the ability to throw compile time errors if we believe something is wrong. // This could be extended to support generic types, and potentially matching compatible open generic types together to build a list. if (serviceType != null && !potentialBaseTypes.Any(z => serviceType.Equals(z, StringComparison.OrdinalIgnoreCase))) { var serviceName = serviceType.Split('.').Last(); var implementationName = implementationType.Split('.').Last(); context.Diagnostics.Add( Diagnostic.Create( new DiagnosticDescriptor( "DI0001", "Implementation miss-match", "The implementation '{0}' does not implement the service '{1}'", "DependencyInjection", DiagnosticSeverity.Error, true ), Location.Create(attributeDeclaration.SyntaxTree, attributeDeclaration.Span), implementationName, serviceName ) ); } var hasLifecycle = attributeSymbol.NamedArguments.Any(z => z.Key == "Lifecycle"); var lifecycle = "Transient"; if (hasLifecycle) { lifecycle = GetLifecycle((int)attributeSymbol.NamedArguments.Single(z => z.Key == "Lifecycle").Value.Value); } // Build the Statement return(GetCollectionExpressionStatement(lifecycle, serviceQualifiedNames, implementationQualifiedName)); }
private Document RewriteExpressionBodiedMemberAndIntroduceLocalDeclaration( SemanticDocument document, ArrowExpressionClauseSyntax arrowExpression, ExpressionSyntax expression, NameSyntax newLocalName, LocalDeclarationStatementSyntax declarationStatement, bool allOccurrences, CancellationToken cancellationToken) { var oldBody = arrowExpression; var oldParentingNode = oldBody.Parent; var leadingTrivia = oldBody.GetLeadingTrivia() .AddRange(oldBody.ArrowToken.TrailingTrivia); var newStatement = Rewrite(document, expression, newLocalName, document, oldBody.Expression, allOccurrences, cancellationToken); var newBody = SyntaxFactory.Block(declarationStatement, SyntaxFactory.ReturnStatement(newStatement)) .WithLeadingTrivia(leadingTrivia) .WithTrailingTrivia(oldBody.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); SyntaxNode newParentingNode = null; if (oldParentingNode is BasePropertyDeclarationSyntax baseProperty) { var getAccessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, newBody); var accessorList = SyntaxFactory.AccessorList(SyntaxFactory.List(new[] { getAccessor })); newParentingNode = baseProperty.RemoveNode(oldBody, SyntaxRemoveOptions.KeepNoTrivia); if (newParentingNode.IsKind(SyntaxKind.PropertyDeclaration)) { var propertyDeclaration = ((PropertyDeclarationSyntax)newParentingNode); newParentingNode = propertyDeclaration .WithAccessorList(accessorList) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) .WithTrailingTrivia(propertyDeclaration.SemicolonToken.TrailingTrivia); } else if (newParentingNode.IsKind(SyntaxKind.IndexerDeclaration)) { var indexerDeclaration = ((IndexerDeclarationSyntax)newParentingNode); newParentingNode = indexerDeclaration .WithAccessorList(accessorList) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) .WithTrailingTrivia(indexerDeclaration.SemicolonToken.TrailingTrivia); } } else if (oldParentingNode is BaseMethodDeclarationSyntax baseMethod) { newParentingNode = baseMethod.RemoveNode(oldBody, SyntaxRemoveOptions.KeepNoTrivia) .WithBody(newBody); if (newParentingNode.IsKind(SyntaxKind.MethodDeclaration)) { var methodDeclaration = ((MethodDeclarationSyntax)newParentingNode); newParentingNode = methodDeclaration .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) .WithTrailingTrivia(methodDeclaration.SemicolonToken.TrailingTrivia); } else if (newParentingNode.IsKind(SyntaxKind.OperatorDeclaration)) { var operatorDeclaration = ((OperatorDeclarationSyntax)newParentingNode); newParentingNode = operatorDeclaration .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) .WithTrailingTrivia(operatorDeclaration.SemicolonToken.TrailingTrivia); } else if (newParentingNode.IsKind(SyntaxKind.ConversionOperatorDeclaration)) { var conversionOperatorDeclaration = ((ConversionOperatorDeclarationSyntax)newParentingNode); newParentingNode = conversionOperatorDeclaration .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) .WithTrailingTrivia(conversionOperatorDeclaration.SemicolonToken.TrailingTrivia); } } var newRoot = document.Root.ReplaceNode(oldParentingNode, newParentingNode); return(document.Document.WithSyntaxRoot(newRoot)); }
public Func <string, IEnumerable <StatementSyntax> > GetCollectionExpressionStatement(string lifecycle, IEnumerable <NameSyntax> serviceQualifiedNames, NameSyntax implementationQualifiedName) { // I hear there is a better way to do this... that will be released sometime. return((string identifierName) => { return serviceQualifiedNames.Select(serviceName => SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(identifierName), name: SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("Add" + lifecycle)) ), SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList( new[] { SyntaxFactory.Argument(SyntaxFactory.TypeOfExpression(serviceName)), SyntaxFactory.Argument(SyntaxFactory.TypeOfExpression(implementationQualifiedName)) }) ) ) ) ); }); }
private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context) { NameSyntax nameSyntax = ((NamespaceDeclarationSyntax)context.Node).Name; CheckNameSyntax(context, nameSyntax); }
/// <remarks> /// We don't want to use the real lexer because we want to treat keywords as identifiers. /// Since the inputs are so simple, we'll just do the lexing ourselves. /// </remarks> internal static bool TryParseDottedName(string input, out NameSyntax output) { var pooled = PooledStringBuilder.GetInstance(); try { var builder = pooled.Builder; output = null; foreach (var ch in input) { if (builder.Length == 0) { if (!SyntaxFacts.IsIdentifierStartCharacter(ch)) { output = null; return(false); } builder.Append(ch); } else if (ch == '.') { var identifierName = SyntaxFactory.IdentifierName(builder.ToString()); builder.Clear(); output = output == null ? (NameSyntax)identifierName : SyntaxFactory.QualifiedName(output, identifierName); } else if (SyntaxFacts.IsIdentifierPartCharacter(ch)) { builder.Append(ch); } else { output = null; return(false); } } // There must be at least one character in the last identifier. if (builder.Length == 0) { output = null; return(false); } var finalIdentifierName = SyntaxFactory.IdentifierName(builder.ToString()); output = output == null ? (NameSyntax)finalIdentifierName : SyntaxFactory.QualifiedName(output, finalIdentifierName); return(true); } finally { pooled.Free(); } }
private bool IsInVarContext(NameSyntax name) { return (name.CheckParent <VariableDeclarationSyntax>(v => v.Type == name) || name.CheckParent <ForEachStatementSyntax>(f => f.Type == name)); }
private bool TryClassifySymbol( NameSyntax name, [NotNullWhen(returnValue: true)] ISymbol?symbol, SemanticModel semanticModel, CancellationToken cancellationToken, out ClassifiedSpan classifiedSpan) { // For Namespace parts, we want don't want to classify the QualifiedNameSyntax // nodes, we instead wait for the each IdentifierNameSyntax node to avoid // creating overlapping ClassifiedSpans. if (symbol is INamespaceSymbol namespaceSymbol && name is IdentifierNameSyntax identifierNameSyntax) { // Do not classify the global:: namespace. It is already syntactically classified as a keyword. var isGlobalNamespace = namespaceSymbol.IsGlobalNamespace && identifierNameSyntax.Identifier.IsKind(SyntaxKind.GlobalKeyword); if (isGlobalNamespace) { classifiedSpan = default; return(false); } // Classifies both extern aliases and namespaces. classifiedSpan = new ClassifiedSpan(name.Span, ClassificationTypeNames.NamespaceName); return(true); } if (name.IsVar && IsInVarContext(name)) { var alias = semanticModel.GetAliasInfo(name, cancellationToken); if (alias == null || alias.Name != "var") { if (!IsSymbolWithName(symbol, "var")) { // We bound to a symbol. If we bound to a symbol called "var" then we want to // classify this appropriately as a type. Otherwise, we want to classify this as // a keyword. classifiedSpan = new ClassifiedSpan(name.Span, ClassificationTypeNames.Keyword); return(true); } } } if (name.IsNint || name.IsNuint) { if (symbol is ITypeSymbol type && type.IsNativeIntegerType) { classifiedSpan = new ClassifiedSpan(name.Span, ClassificationTypeNames.Keyword); return(true); } } if ((name.IsUnmanaged || name.IsNotNull) && name.Parent.IsKind(SyntaxKind.TypeConstraint)) { var nameToCheck = name.IsUnmanaged ? "unmanaged" : "notnull"; var alias = semanticModel.GetAliasInfo(name, cancellationToken); if (alias == null || alias.Name != nameToCheck) { if (!IsSymbolWithName(symbol, nameToCheck)) { // We bound to a symbol. If we bound to a symbol called "unmanaged"/"notnull" then we want to // classify this appropriately as a type. Otherwise, we want to classify this as // a keyword. classifiedSpan = new ClassifiedSpan(name.Span, ClassificationTypeNames.Keyword); return(true); } } } // Use .Equals since we can't rely on object identity for constructed types. SyntaxToken token; switch (symbol) { case ITypeSymbol typeSymbol: var classification = GetClassificationForType(typeSymbol); if (classification != null) { token = name.GetNameToken(); classifiedSpan = new ClassifiedSpan(token.Span, classification); return(true); } break; case IFieldSymbol fieldSymbol: token = name.GetNameToken(); classifiedSpan = new ClassifiedSpan(token.Span, GetClassificationForField(fieldSymbol)); return(true); case IMethodSymbol methodSymbol: token = name.GetNameToken(); classifiedSpan = new ClassifiedSpan(token.Span, GetClassificationForMethod(methodSymbol)); return(true); case IPropertySymbol propertySymbol: token = name.GetNameToken(); classifiedSpan = new ClassifiedSpan(token.Span, ClassificationTypeNames.PropertyName); return(true); case IEventSymbol eventSymbol: token = name.GetNameToken(); classifiedSpan = new ClassifiedSpan(token.Span, ClassificationTypeNames.EventName); return(true); case IParameterSymbol parameterSymbol: if (parameterSymbol.IsImplicitlyDeclared && parameterSymbol.Name == "value") { break; } token = name.GetNameToken(); classifiedSpan = new ClassifiedSpan(token.Span, ClassificationTypeNames.ParameterName); return(true); case ILocalSymbol localSymbol: token = name.GetNameToken(); classifiedSpan = new ClassifiedSpan(token.Span, GetClassificationForLocal(localSymbol)); return(true); case ILabelSymbol labelSymbol: token = name.GetNameToken(); classifiedSpan = new ClassifiedSpan(token.Span, ClassificationTypeNames.LabelName); return(true); } classifiedSpan = default; return(false); }
private static void ComputeDeclarations( SemanticModel model, SyntaxNode node, Func <SyntaxNode, int?, bool> shouldSkip, bool getSymbol, List <DeclarationInfo> builder, int?levelsToCompute, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (shouldSkip(node, levelsToCompute)) { return; } var newLevel = DecrementLevel(levelsToCompute); switch (node.Kind()) { case SyntaxKind.NamespaceDeclaration: { var ns = (NamespaceDeclarationSyntax)node; foreach (var decl in ns.Members) { ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } var declInfo = GetDeclarationInfo(model, node, getSymbol, cancellationToken); builder.Add(declInfo); NameSyntax name = ns.Name; INamespaceSymbol nsSymbol = declInfo.DeclaredSymbol as INamespaceSymbol; while (name.Kind() == SyntaxKind.QualifiedName) { name = ((QualifiedNameSyntax)name).Left; var declaredSymbol = getSymbol ? nsSymbol?.ContainingNamespace : null; builder.Add(new DeclarationInfo(name, ImmutableArray <SyntaxNode> .Empty, declaredSymbol)); nsSymbol = declaredSymbol; } return; } case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: { var t = (TypeDeclarationSyntax)node; foreach (var decl in t.Members) { ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken)); return; } case SyntaxKind.EnumDeclaration: { var t = (EnumDeclarationSyntax)node; foreach (var decl in t.Members) { ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken)); return; } case SyntaxKind.EnumMemberDeclaration: { var t = (EnumMemberDeclarationSyntax)node; builder.Add(GetDeclarationInfo(model, node, getSymbol, t.EqualsValue, cancellationToken)); return; } case SyntaxKind.DelegateDeclaration: { builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken)); return; } case SyntaxKind.EventDeclaration: { var t = (EventDeclarationSyntax)node; foreach (var decl in t.AccessorList.Accessors) { ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken)); return; } case SyntaxKind.EventFieldDeclaration: case SyntaxKind.FieldDeclaration: { var t = (BaseFieldDeclarationSyntax)node; foreach (var decl in t.Declaration.Variables) { builder.Add(GetDeclarationInfo(model, decl, getSymbol, decl.Initializer, cancellationToken)); } return; } case SyntaxKind.ArrowExpressionClause: { // Arrow expression clause declares getter symbol for properties and indexers. var parentProperty = node.Parent as BasePropertyDeclarationSyntax; if (parentProperty != null) { builder.Add(GetExpressionBodyDeclarationInfo(parentProperty, (ArrowExpressionClauseSyntax)node, model, getSymbol, cancellationToken)); } return; } case SyntaxKind.PropertyDeclaration: { var t = (PropertyDeclarationSyntax)node; if (t.AccessorList != null) { foreach (var decl in t.AccessorList.Accessors) { ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } } if (t.ExpressionBody != null) { ComputeDeclarations(model, t.ExpressionBody, shouldSkip, getSymbol, builder, levelsToCompute, cancellationToken); } builder.Add(GetDeclarationInfo(model, node, getSymbol, cancellationToken, t.Initializer)); return; } case SyntaxKind.IndexerDeclaration: { var t = (IndexerDeclarationSyntax)node; if (t.AccessorList != null) { foreach (var decl in t.AccessorList.Accessors) { ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } } if (t.ExpressionBody != null) { ComputeDeclarations(model, t.ExpressionBody, shouldSkip, getSymbol, builder, levelsToCompute, cancellationToken); } var codeBlocks = t.ParameterList != null?t.ParameterList.Parameters.Select(p => p.Default) : SpecializedCollections.EmptyEnumerable <SyntaxNode>(); builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken)); return; } case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.GetAccessorDeclaration: { var t = (AccessorDeclarationSyntax)node; builder.Add(GetDeclarationInfo(model, node, getSymbol, t.Body, cancellationToken)); return; } case SyntaxKind.ConstructorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: case SyntaxKind.DestructorDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.OperatorDeclaration: { var t = (BaseMethodDeclarationSyntax)node; var codeBlocks = t.ParameterList != null?t.ParameterList.Parameters.Select(p => p.Default) : SpecializedCollections.EmptyEnumerable <SyntaxNode>(); codeBlocks = codeBlocks.Concat(t.Body); var ctorDecl = t as ConstructorDeclarationSyntax; if (ctorDecl != null && ctorDecl.Initializer != null) { codeBlocks = codeBlocks.Concat(ctorDecl.Initializer); } var expressionBody = GetExpressionBodySyntax(t); if (expressionBody != null) { codeBlocks = codeBlocks.Concat(expressionBody); } builder.Add(GetDeclarationInfo(model, node, getSymbol, codeBlocks, cancellationToken)); return; } case SyntaxKind.CompilationUnit: { var t = (CompilationUnitSyntax)node; foreach (var decl in t.Members) { ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); } return; } default: return; } }
private SymbolResolution ResolveViaUsings(NameSyntax baseName, NameSyntax name, IUsingsContainer usingsContainer) { if (!(name is SimpleNameSyntax)) return default(SymbolResolution); if (baseName != null) { return baseName.Recurse(x => x.Parent) .Select(ns => usingsContainer.UsingStatements .SelectMaybe(u => { var n = ns + u.Namespace + name; return _map.TryGetValue(n); }) .Select(x => new SymbolResolution(x)) .Aggregate(default(SymbolResolution), (l, r) => l & r)) .TryFirst(x => x.Status != SymbolResolutionStatus.NotFound) .ValueOrDefault(); } return usingsContainer.UsingStatements .SelectMaybe(u => { var n = u.Namespace + name; return _map.TryGetValue(n); }) .Select(x => new SymbolResolution(x)) .Aggregate(default(SymbolResolution), (l, r) => l & r); }